コード例 #1
0
        private void UpdateDependenciesSnapshotAsync(
            ImmutableDictionary <ITargetFramework, IDependenciesChanges> changes,
            IProjectCatalogSnapshot catalogs,
            ITargetFramework activeTargetFramework)
        {
            DependenciesSnapshot newSnapshot;
            bool anyChanges = false;

            HashSet <string> projectItemSpecs = GetProjectItemSpecsFromSnapshot(catalogs);

            // Note: we are updating existing snapshot, not receivig a complete new one. Thus we must
            // ensure incremental updates are done in the correct order. This lock ensures that here.
            lock (_snapshotLock)
            {
                newSnapshot = DependenciesSnapshot.FromChanges(
                    CommonServices.Project.FullPath,
                    _currentSnapshot,
                    changes,
                    catalogs,
                    activeTargetFramework,
                    SnapshotFilters.Select(x => x.Value),
                    SubTreeProviders.Select(x => x.Value),
                    projectItemSpecs,
                    out anyChanges);
                _currentSnapshot = newSnapshot;
            }

            if (anyChanges)
            {
                // avoid unnecessary tree updates
                ScheduleDependenciesUpdate();
            }
        }
コード例 #2
0
        private HashSet <string> GetProjectItemSpecsFromSnapshot(IProjectCatalogSnapshot catalogs)
        {
            // We don't have catalog snapshot, we're likely updating because one of our project
            // dependencies changed. Just return 'no data'
            if (catalogs == null)
            {
                return(null);
            }

            var projectItemSpecs = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            foreach (ProjectItemInstance item in catalogs.Project.ProjectInstance.Items)
            {
                if (item.IsImported())
                {
                    continue;
                }

                // Returns unescaped evaluated include
                string itemSpec = item.EvaluatedInclude;
                if (itemSpec.Length > 0)
                {
                    projectItemSpecs.Add(itemSpec);
                }
            }

            return(projectItemSpecs);
        }
コード例 #3
0
        public IRule GetRule(IDependency dependency, IProjectCatalogSnapshot catalogs)
        {
            var mockRule = new Mock <IRule>(MockBehavior.Strict);

            mockRule.Setup(x => x.Name).Returns(dependency.SchemaItemType);
            return(mockRule.Object);
        }
        private string GetUnresolvedReferenceItemType(
            string unresolvedItemSpec,
            IEnumerable <IProjectRuleSnapshot> unresolvedReferenceSnapshots,
            IProjectCatalogSnapshot catalogs,
            out IProjectRuleSnapshot unresolvedReferenceSnapshot)
        {
            Requires.NotNull(unresolvedItemSpec, nameof(unresolvedItemSpec));
            Requires.NotNull(unresolvedReferenceSnapshots, nameof(unresolvedReferenceSnapshots));
            Requires.NotNull(catalogs, nameof(catalogs));

            unresolvedReferenceSnapshot = null;
            foreach (var referenceSnapshot in unresolvedReferenceSnapshots)
            {
                if (referenceSnapshot.Items.ContainsKey(unresolvedItemSpec))
                {
                    var itemType = GetItemTypeFromRuleName(referenceSnapshot.RuleName, catalogs, true);
                    if (itemType != null)
                    {
                        unresolvedReferenceSnapshot = referenceSnapshot;
                        return(itemType);
                    }
                }
            }

            return(null);
        }
コード例 #5
0
        private async Task OnProjectChangedAsync(
            IProjectSubscriptionUpdate projectUpdate,
            IProjectCatalogSnapshot catalogSnapshot,
            IProjectCapabilitiesSnapshot capabilities,
            ConfiguredProject configuredProject,
            RuleHandlerType handlerType)
        {
            if (IsDisposing || IsDisposed)
            {
                return;
            }

            // Ensure updates don't overlap and that we aren't disposed during the update without cleaning up properly
            await ExecuteUnderLockAsync(async token =>
            {
                // Ensure the project doesn't unload during the update
                await _tasksService.LoadedProjectAsync(async() =>
                {
                    // TODO pass _tasksService.UnloadCancellationToken into handler to reduce redundant work on unload

                    // Ensure the project's capabilities don't change during the update
                    using (ProjectCapabilitiesContext.CreateIsolatedContext(configuredProject, capabilities))
                    {
                        await HandleAsync(projectUpdate, catalogSnapshot, handlerType);
                    }
                });
            });
        }
        /// <summary>
        /// Gets the item type for a given rule.
        /// </summary>
        /// <param name="ruleName">The name of the rule to get an item type for.</param>
        /// <param name="catalogs">The catalog snapshot to use to find the item type.</param>
        /// <param name="allowNull">Whether or not to allow a null result for a missing or malformed rule.</param>
        /// <returns>The matching item type.</returns>
        public string GetItemTypeFromRuleName(string ruleName,
                                              IProjectCatalogSnapshot catalogs,
                                              bool allowNull = false)
        {
            Requires.NotNullOrEmpty(ruleName, nameof(ruleName));
            Requires.NotNull(catalogs, nameof(catalogs));

            string itemType;

            lock (_syncObject)
            {
                if (!_ruleNameToItemType.TryGetValue(ruleName, out itemType))
                {
                    var rule = catalogs.GetSchema(PropertyPageContexts.Project, ruleName)
                               ?? catalogs.GetSchema(PropertyPageContexts.File, ruleName);
                    itemType = rule != null ? rule.DataSource.ItemType : null;

                    if (itemType != null)
                    {
                        _ruleNameToItemType[ruleName] = itemType;
                        _itemTypeToRuleName[itemType] = ruleName;
                    }
                }
            }

            ProjectErrorUtilities.VerifyThrowProjectException(
                itemType != null || allowNull, VSResources.NoItemTypeForRule, ruleName);

            return(itemType);
        }
コード例 #7
0
        private async Task OnProjectChangedAsync(
            IProjectSubscriptionUpdate projectUpdate,
            IProjectCatalogSnapshot catalogSnapshot,
            IProjectCapabilitiesSnapshot capabilities,
            ConfiguredProject configuredProject,
            RuleHandlerType handlerType)
        {
            if (IsDisposing || IsDisposed)
            {
                return;
            }

            await _tasksService.LoadedProjectAsync(async() =>
            {
                if (_tasksService.UnloadCancellationToken.IsCancellationRequested)
                {
                    return;
                }

                using (ProjectCapabilitiesContext.CreateIsolatedContext(configuredProject, capabilities))
                {
                    await HandleAsync(projectUpdate, catalogSnapshot, handlerType);
                }
            });
        }
コード例 #8
0
        /// <summary>
        /// Updates or creates new node
        /// </summary>
        private async Task <IProjectTree> CreateOrUpdateNodeAsync(
            IProjectTree node,
            IDependency dependency,
            ITargetedDependenciesSnapshot targetedSnapshot,
            IProjectCatalogSnapshot catalogs,
            bool isProjectItem,
            ProjectTreeFlags?additionalFlags = null,
            ProjectTreeFlags?excludedFlags   = null)
        {
            IRule rule = null;

            if (dependency.Flags.Contains(DependencyTreeFlags.SupportsRuleProperties))
            {
                rule = await TreeServices.GetRuleAsync(dependency, catalogs)
                       .ConfigureAwait(false);
            }

            return(CreateOrUpdateNode(
                       node,
                       dependency.ToViewModel(targetedSnapshot),
                       rule,
                       isProjectItem,
                       additionalFlags,
                       excludedFlags));
        }
        /// <summary>
        /// Gets the rule name for an item type.
        /// </summary>
        /// <param name="itemType">The item type to get a rule name for.</param>
        /// <param name="catalogs">The catalog snapshot to use to find the rule name.</param>
        /// <param name="allowNull">Whether or not to allow a null result for a missing or malformed rule.</param>
        /// <returns>The matching rule name.</returns>
        public string GetRuleNameFromItemType(string itemType,
                                              IProjectCatalogSnapshot catalogs,
                                              bool allowNull = false)
        {
            Requires.NotNullOrEmpty(itemType, nameof(itemType));
            Requires.NotNull(catalogs, nameof(catalogs));

            string ruleName;

            lock (_syncObject)
            {
                if (!_itemTypeToRuleName.TryGetValue(itemType, out ruleName))
                {
                    ruleName = GetRuleNameByItemType(catalogs, PropertyPageContexts.Project, itemType)
                               ?? GetRuleNameByItemType(catalogs, PropertyPageContexts.File, itemType);

                    if (ruleName != null)
                    {
                        _ruleNameToItemType[ruleName] = itemType;
                        _itemTypeToRuleName[itemType] = ruleName;
                    }
                }
            }

            ProjectErrorUtilities.VerifyThrowProjectException(ruleName != null || allowNull,
                                                              VSResources.NoItemTypeForRule,
                                                              itemType);

            return(ruleName);
        }
        /// <summary>
        /// Gets an IRule to attach to a project item so that browse object properties will be displayed.
        /// </summary>
        private IRule GetRuleForUnresolvableReference(IProjectPropertiesContext unresolvedContext,
                                                      IProjectCatalogSnapshot catalogs,
                                                      ConfiguredProjectExports configuredProjectExports)
        {
            Requires.NotNull(unresolvedContext, nameof(unresolvedContext));
            Requires.NotNull(configuredProjectExports, nameof(configuredProjectExports));

            var namedCatalogs = GetNamedCatalogs(catalogs);
            var schemas       = GetSchemaForReference(unresolvedContext.ItemType, false, namedCatalogs).ToList();

            if (schemas.Count == 1)
            {
                Requires.NotNull(namedCatalogs, nameof(namedCatalogs));
                var browseObjectCatalog = namedCatalogs[PropertyPageContexts.BrowseObject];
                return(browseObjectCatalog.BindToContext(schemas[0].Name, unresolvedContext));
            }

            if (schemas.Count > 1)
            {
                TraceUtilities.TraceWarning(
                    "Too many rule schemas ({0}) in the BrowseObject context were found. Only 1 is allowed.",
                    schemas.Count);
            }

            // Since we have no browse object, we still need to create *something* so that standard property
            // pages can pop up.
            var emptyRule = RuleExtensions.SynthesizeEmptyRule(unresolvedContext.ItemType);

            return(configuredProjectExports.PropertyPagesDataModelProvider.GetRule(
                       emptyRule,
                       unresolvedContext.File,
                       unresolvedContext.ItemType,
                       unresolvedContext.ItemName));
        }
コード例 #11
0
        public Task <IRule> GetBrowseObjectRuleAsync(IDependency dependency, IProjectCatalogSnapshot catalogs)
        {
            var mockRule = new Mock <IRule>(MockBehavior.Strict);

            mockRule.Setup(x => x.Name).Returns(dependency.SchemaItemType);
            return(Task.FromResult(mockRule.Object));
        }
コード例 #12
0
        public async Task <IRule> GetRuleAsync(IDependency dependency, IProjectCatalogSnapshot catalogs)
        {
            Requires.NotNull(dependency, nameof(dependency));

            ConfiguredProject project = null;

            if (dependency.TargetFramework.Equals(TargetFramework.Any))
            {
                project = ActiveConfiguredProject;
            }
            else
            {
                project = await DependenciesHost.GetConfiguredProject(dependency.TargetFramework)
                          .ConfigureAwait(false) ?? ActiveConfiguredProject;
            }

            ConfiguredProjectExports configuredProjectExports = GetActiveConfiguredProjectExports(project);
            IImmutableDictionary <string, IPropertyPagesCatalog> namedCatalogs = await GetNamedCatalogsAsync(catalogs).ConfigureAwait(false);

            Requires.NotNull(namedCatalogs, nameof(namedCatalogs));

            IPropertyPagesCatalog browseObjectsCatalog = namedCatalogs[PropertyPageContexts.BrowseObject];
            Rule   schema   = browseObjectsCatalog.GetSchema(dependency.SchemaName);
            string itemSpec = string.IsNullOrEmpty(dependency.OriginalItemSpec) ? dependency.Path : dependency.OriginalItemSpec;
            var    context  = ProjectPropertiesContext.GetContext(UnconfiguredProject,
                                                                  itemType: dependency.SchemaItemType,
                                                                  itemName: itemSpec);

            IRule rule = null;

            if (schema != null)
            {
                if (dependency.Resolved)
                {
                    rule = configuredProjectExports.RuleFactory.CreateResolvedReferencePageRule(
                        schema,
                        context,
                        dependency.Name,
                        dependency.Properties);
                }
                else
                {
                    rule = browseObjectsCatalog.BindToContext(schema.Name, context);
                }
            }
            else
            {
                // Since we have no browse object, we still need to create *something* so
                // that standard property pages can pop up.
                Rule emptyRule = RuleExtensions.SynthesizeEmptyRule(context.ItemType);
                return(configuredProjectExports.PropertyPagesDataModelProvider.GetRule(
                           emptyRule,
                           context.File,
                           context.ItemType,
                           context.ItemName));
            }

            return(rule);
        }
コード例 #13
0
        private async Task HandleAsync(
            IProjectSubscriptionUpdate projectUpdate,
            IProjectCatalogSnapshot catalogSnapshot,
            RuleSource source)
        {
            AggregateCrossTargetProjectContext?currentAggregateContext = await _host !.GetCurrentAggregateProjectContextAsync();

            if (currentAggregateContext == null || _currentProjectContext != currentAggregateContext)
            {
                return;
            }

            // Get the inner workspace project context to update for this change.
            ITargetFramework?targetFrameworkToUpdate = currentAggregateContext.GetProjectFramework(projectUpdate.ProjectConfiguration);

            if (targetFrameworkToUpdate == null)
            {
                return;
            }

            // Broken design time builds sometimes cause updates with no project changes and sometimes
            // cause updates with a project change that has no difference.
            // We handle the former case here, and the latter case is handled in the CommandLineItemHandler.
            if (projectUpdate.ProjectChanges.Count == 0)
            {
                return;
            }

            if (!projectUpdate.ProjectChanges.Any(x => x.Value.Difference.AnyChanges))
            {
                return;
            }

            // Create an object to track dependency changes.
            var changesBuilder = new CrossTargetDependenciesChangesBuilder();

            // Give each handler a chance to register dependency changes.
            foreach (Lazy <IDependenciesRuleHandler, IOrderPrecedenceMetadataView> handler in _handlers)
            {
                handler.Value.Handle(projectUpdate.ProjectChanges, targetFrameworkToUpdate, changesBuilder);
            }

            ImmutableDictionary <ITargetFramework, IDependenciesChanges>?changes = changesBuilder.TryBuildChanges();

            if (changes != null)
            {
                // Notify subscribers of a change in dependency data
                DependenciesChanged?.Invoke(
                    this,
                    new DependencySubscriptionChangedEventArgs(
                        currentAggregateContext.TargetFrameworks,
                        currentAggregateContext.ActiveTargetFramework,
                        catalogSnapshot,
                        changes));
            }

            // record all the rules that have occurred
            _treeTelemetryService.ObserveTargetFrameworkRules(targetFrameworkToUpdate, projectUpdate.ProjectChanges.Keys);
        }
コード例 #14
0
 public TestableTargetedDependenciesSnapshot(
     string projectPath,
     ITargetFramework targetFramework,
     ITargetedDependenciesSnapshot previousSnapshot = null,
     IProjectCatalogSnapshot catalogs = null)
     : base(projectPath, targetFramework, previousSnapshot, catalogs)
 {
 }
コード例 #15
0
 public DependenciesChangedEventArgs(
     IProjectDependenciesSubTreeProvider provider,
     string?targetShortOrFullName,
     IDependenciesChanges changes,
     IProjectCatalogSnapshot catalogs,
     IImmutableDictionary <NamedIdentity, IComparable> dataSourceVersions)
     : this(provider, targetShortOrFullName, changes, CancellationToken.None)
 {
 }
コード例 #16
0
 public DependenciesChangedEventArgs(IProjectDependenciesSubTreeProvider provider,
                                     IDependenciesChangeDiff changes,
                                     IProjectCatalogSnapshot catalogs,
                                     IImmutableDictionary <NamedIdentity, IComparable> dataSourceVersions)
 {
     Provider           = provider;
     Changes            = changes;
     Catalogs           = catalogs;
     DataSourceVersions = dataSourceVersions;
 }
コード例 #17
0
        public static Mock <ITargetedDependenciesSnapshot> ImplementMock(
            string projectPath = null,
            ITargetFramework targetFramework            = null,
            IEnumerable <IDependency> dependenciesWorld = null,
            bool?hasUnresolvedDependency     = null,
            IProjectCatalogSnapshot catalogs = null,
            IEnumerable <IDependency> topLevelDependencies = null,
            bool?checkForUnresolvedDependencies            = null,
            MockBehavior?mockBehavior = null)
        {
            var behavior = mockBehavior ?? MockBehavior.Default;
            var mock     = new Mock <ITargetedDependenciesSnapshot>(behavior);

            if (projectPath != null)
            {
                mock.Setup(x => x.ProjectPath).Returns(projectPath);
            }

            if (targetFramework != null)
            {
                mock.Setup(x => x.TargetFramework).Returns(targetFramework);
            }

            if (dependenciesWorld != null)
            {
                mock.Setup(x => x.DependenciesWorld)
                .Returns(dependenciesWorld.ToImmutableDictionary(d => d.Id, StringComparer.OrdinalIgnoreCase));
            }

            if (hasUnresolvedDependency.HasValue)
            {
                mock.Setup(x => x.HasUnresolvedDependency).Returns(hasUnresolvedDependency.Value);
            }

            if (catalogs != null)
            {
                mock.Setup(x => x.Catalogs).Returns(catalogs);
            }

            if (topLevelDependencies != null)
            {
                Assert.True(topLevelDependencies.All(d => d.TopLevel));

                mock.Setup(x => x.TopLevelDependencies)
                .Returns(ImmutableHashSet.CreateRange(topLevelDependencies));
            }

            if (checkForUnresolvedDependencies.HasValue)
            {
                mock.Setup(x => x.CheckForUnresolvedDependencies(It.IsAny <string>())).Returns(checkForUnresolvedDependencies.Value);
                mock.Setup(x => x.CheckForUnresolvedDependencies(It.IsAny <IDependency>())).Returns(checkForUnresolvedDependencies.Value);
            }

            return(mock);
        }
コード例 #18
0
        public DependencySubscriptionChangedEventArgs(
            ITargetFramework activeTarget,
            IProjectCatalogSnapshot catalogs,
            ImmutableDictionary <ITargetFramework, IDependenciesChanges> changes)
        {
            Requires.Argument(changes.Count != 0, nameof(changes), "Must not be zero.");

            ActiveTarget = activeTarget;
            Catalogs     = catalogs;
            Changes      = changes;
        }
コード例 #19
0
 public DependenciesChangedEventArgs(IProjectDependenciesSubTreeProvider provider,
                                     string targetShortOrFullName,
                                     IDependenciesChanges changes,
                                     IProjectCatalogSnapshot catalogs,
                                     IImmutableDictionary <NamedIdentity, IComparable> dataSourceVersions)
 {
     Provider = provider;
     TargetShortOrFullName = targetShortOrFullName;
     Changes            = changes;
     Catalogs           = catalogs;
     DataSourceVersions = dataSourceVersions;
 }
コード例 #20
0
        private void UpdateDependenciesSnapshot(
            ImmutableDictionary <ITargetFramework, IDependenciesChanges> changes,
            IProjectCatalogSnapshot catalogs,
            ITargetFramework activeTargetFramework,
            CancellationToken token)
        {
            IImmutableSet <string> projectItemSpecs = GetProjectItemSpecsFromSnapshot();

            TryUpdateSnapshot(
                snapshot => DependenciesSnapshot.FromChanges(
                    _commonServices.Project.FullPath,
                    snapshot,
                    changes,
                    catalogs,
                    activeTargetFramework,
                    _snapshotFilters.ToImmutableValueArray(),
                    _subTreeProviders.ToValueDictionary(p => p.ProviderType),
                    projectItemSpecs),
                token);

            return;

            // Gets the set of items defined directly the project, and not included by imports.
            IImmutableSet <string> GetProjectItemSpecsFromSnapshot()
            {
                // We don't have catalog snapshot, we're likely updating because one of our project
                // dependencies changed. Just return 'no data'
                if (catalogs == null)
                {
                    return(null);
                }

                ImmutableHashSet <string> .Builder itemSpecs = ImmutableHashSet.CreateBuilder(StringComparer.OrdinalIgnoreCase);

                foreach (ProjectItemInstance item in catalogs.Project.ProjectInstance.Items)
                {
                    if (item.IsImported())
                    {
                        continue;
                    }

                    // Returns unescaped evaluated include
                    string itemSpec = item.EvaluatedInclude;
                    if (itemSpec.Length != 0)
                    {
                        itemSpecs.Add(itemSpec);
                    }
                }

                return(itemSpecs.ToImmutable());
            }
        }
コード例 #21
0
        private static ImmutableDictionary <TargetFramework, TargetedDependenciesSnapshot> CreateDependenciesByTargetFramework(
            IProjectCatalogSnapshot catalogs,
            params TargetFramework[] targetFrameworks)
        {
            var dic = ImmutableDictionary <TargetFramework, TargetedDependenciesSnapshot> .Empty;

            foreach (var targetFramework in targetFrameworks)
            {
                dic = dic.Add(targetFramework, TargetedDependenciesSnapshot.CreateEmpty(targetFramework, catalogs));
            }

            return(dic);
        }
        public static Mock <ITargetedDependenciesSnapshot> ImplementMock(
            ITargetFramework targetFramework = null,
            Dictionary <string, IDependency> dependenciesWorld = null,
            bool?hasUnresolvedDependency     = null,
            IProjectCatalogSnapshot catalogs = null,
            IEnumerable <IDependency> topLevelDependencies = null,
            bool?checkForUnresolvedDependencies            = null,
            MockBehavior?mockBehavior = null)
        {
            var behavior = mockBehavior ?? MockBehavior.Default;
            var mock     = new Mock <ITargetedDependenciesSnapshot>(behavior);

            if (targetFramework != null)
            {
                mock.Setup(x => x.TargetFramework).Returns(targetFramework);
            }

            if (dependenciesWorld != null)
            {
                mock.Setup(x => x.DependenciesWorld)
                .Returns(ImmutableStringDictionary <IDependency> .EmptyOrdinalIgnoreCase.AddRange(dependenciesWorld));
            }

            if (hasUnresolvedDependency.HasValue)
            {
                mock.Setup(x => x.HasUnresolvedDependency).Returns(hasUnresolvedDependency.Value);
            }

            if (catalogs != null)
            {
                mock.Setup(x => x.Catalogs).Returns(catalogs);
            }

            if (topLevelDependencies != null)
            {
                var dependencies = ImmutableHashSet <IDependency> .Empty;
                foreach (var d in topLevelDependencies)
                {
                    dependencies = dependencies.Add(d);
                }

                mock.Setup(x => x.TopLevelDependencies).Returns(dependencies);
            }

            if (checkForUnresolvedDependencies.HasValue)
            {
                mock.Setup(x => x.CheckForUnresolvedDependencies(It.IsAny <string>())).Returns(checkForUnresolvedDependencies.Value);
            }

            return(mock);
        }
コード例 #23
0
 /// <summary>
 /// Gets the rule from the specified catalog, if such a catalog and rule exist.
 /// </summary>
 /// <param name="snapshot">The snapshot to read from.</param>
 /// <param name="catalogName">The name of the catalog.</param>
 /// <param name="ruleName">The name of the rule.</param>
 /// <returns>The rule, if found; otherwise <c>null</c>.</returns>
 internal static Rule GetSchema(this IProjectCatalogSnapshot snapshot, string catalogName, string ruleName)
 {
     Requires.NotNull(snapshot, nameof(snapshot));
     Requires.NotNull(catalogName, nameof(catalogName));
     Requires.NotNullOrEmpty(ruleName, nameof(ruleName));
     if (snapshot.NamedCatalogs.TryGetValue(catalogName, out IPropertyPagesCatalog catalog))
     {
         return(catalog.GetSchema(ruleName));
     }
     else
     {
         return(null);
     }
 }
コード例 #24
0
        public static DependenciesSnapshot FromChanges(
            string projectPath,
            DependenciesSnapshot previousSnapshot,
            ImmutableDictionary <ITargetFramework, IDependenciesChanges> changes,
            IProjectCatalogSnapshot catalogs,
            ITargetFramework activeTargetFramework,
            IEnumerable <IDependenciesSnapshotFilter> snapshotFilters,
            out bool anyChanges)
        {
            var newSnapshot = new DependenciesSnapshot(projectPath, activeTargetFramework, previousSnapshot);

            anyChanges = newSnapshot.MergeChanges(changes, catalogs, snapshotFilters);
            return(newSnapshot);
        }
コード例 #25
0
        public static TargetedDependenciesSnapshot FromChanges(
            string projectPath,
            ITargetFramework targetFramework,
            ITargetedDependenciesSnapshot previousSnapshot,
            IDependenciesChanges changes,
            IProjectCatalogSnapshot catalogs,
            IEnumerable <IDependenciesSnapshotFilter> snapshotFilters,
            out bool anyChanges)
        {
            var newSnapshot = new TargetedDependenciesSnapshot(projectPath, targetFramework, previousSnapshot, catalogs);

            anyChanges = newSnapshot.MergeChanges(changes, snapshotFilters);
            return(newSnapshot);
        }
コード例 #26
0
        /// <summary>
        /// Builds a sub tree under root: target framework or Dependencies node when there is only one target.
        /// </summary>
        private async Task <IProjectTree> BuildSubTreeAsync(
            IProjectTree rootNode,
            ITargetedDependenciesSnapshot targetedSnapshot,
            IEnumerable <IDependency> dependencies,
            IProjectCatalogSnapshot catalogs,
            bool isActiveTarget,
            bool shouldCleanup)
        {
            var currentNodes = new List <IProjectTree>();

            foreach (IDependency dependency in dependencies)
            {
                IProjectTree dependencyNode      = rootNode.FindNodeByCaption(dependency.Caption);
                bool         isNewDependencyNode = dependencyNode == null;

                if (!isNewDependencyNode &&
                    dependency.Flags.Contains(DependencyTreeFlags.SupportsHierarchy))
                {
                    if ((dependency.Resolved && dependencyNode.Flags.Contains(DependencyTreeFlags.UnresolvedFlags)) ||
                        (!dependency.Resolved && dependencyNode.Flags.Contains(DependencyTreeFlags.ResolvedFlags)))
                    {
                        // when transition from unresolved to resolved or vise versa - remove old node
                        // and re-add new  one to allow GraphProvider to recalculate children
                        isNewDependencyNode = true;
                        rootNode            = dependencyNode.Remove();
                        dependencyNode      = null;
                    }
                }

                dependencyNode = await CreateOrUpdateNodeAsync(dependencyNode, dependency, targetedSnapshot, catalogs, isActiveTarget);

                currentNodes.Add(dependencyNode);

                if (isNewDependencyNode)
                {
                    rootNode = rootNode.Add(dependencyNode).Parent;
                }
                else
                {
                    rootNode = dependencyNode.Parent;
                }
            }

            if (shouldCleanup)
            {
                rootNode = CleanupOldNodes(rootNode, currentNodes);
            }

            return(rootNode);
        }
コード例 #27
0
        public DependencySubscriptionChangedEventArgs(
            ImmutableArray <ITargetFramework> targetFrameworks,
            ITargetFramework activeTarget,
            IProjectCatalogSnapshot catalogs,
            ImmutableDictionary <ITargetFramework, IDependenciesChanges> changes)
        {
            Requires.Argument(!targetFrameworks.IsDefaultOrEmpty, nameof(targetFrameworks), "Must not be default or empty.");
            Requires.Argument(changes.Count != 0, nameof(changes), "Must not be zero.");

            TargetFrameworks = targetFrameworks;
            ActiveTarget     = activeTarget;
            Catalogs         = catalogs;
            Changes          = changes;
        }
コード例 #28
0
        public DependencySubscriptionChangedEventArgs(
            ImmutableArray <TargetFramework> targetFrameworks,
            TargetFramework activeTarget,
            TargetFramework changedTargetFramework,
            IDependenciesChanges?changes,
            IProjectCatalogSnapshot catalogs)
        {
            Requires.Argument(!targetFrameworks.IsDefaultOrEmpty, nameof(targetFrameworks), "Must not be default or empty.");

            TargetFrameworks       = targetFrameworks;
            ActiveTarget           = activeTarget;
            Catalogs               = catalogs;
            Changes                = changes;
            ChangedTargetFramework = changedTargetFramework;
        }
コード例 #29
0
        // Internal, for test use -- normal code should use the factory methods
        internal TargetedDependenciesSnapshot(
            string projectPath,
            ITargetFramework targetFramework,
            IProjectCatalogSnapshot catalogs,
            ImmutableDictionary <string, IDependency> dependenciesWorld)
        {
            Requires.NotNullOrEmpty(projectPath, nameof(projectPath));
            Requires.NotNull(targetFramework, nameof(targetFramework));
            // catalogs can be null
            Requires.NotNull(dependenciesWorld, nameof(dependenciesWorld));

            ProjectPath       = projectPath;
            TargetFramework   = targetFramework;
            Catalogs          = catalogs;
            DependenciesWorld = dependenciesWorld;

            bool hasUnresolvedDependency = false;

            ImmutableHashSet <IDependency> .Builder topLevelDependencies = ImmutableHashSet.CreateBuilder <IDependency>();

            foreach ((string id, IDependency dependency) in dependenciesWorld)
            {
                System.Diagnostics.Debug.Assert(
                    string.Equals(id, dependency.Id),
                    "dependenciesWorld dictionary entry keys must match their value's ids.");

                if (!dependency.Resolved)
                {
                    hasUnresolvedDependency = true;
                }

                if (dependency.TopLevel)
                {
                    bool added = topLevelDependencies.Add(dependency);
                    System.Diagnostics.Debug.Assert(added, "Duplicate top level dependency found.");

                    if (!string.IsNullOrEmpty(dependency.Path))
                    {
                        _topLevelDependenciesByPathMap.Add(
                            Dependency.GetID(TargetFramework, dependency.ProviderType, dependency.Path),
                            dependency);
                    }
                }
            }

            HasUnresolvedDependency = hasUnresolvedDependency;
            TopLevelDependencies    = topLevelDependencies.ToImmutable();
        }
コード例 #30
0
 /// <summary>
 /// Returns all rule names from the snapshot that match an item type.
 /// </summary>
 /// <remarks>
 /// In the current CPS world, an item type will only match one rule name at most. This may change in the future.
 /// </remarks>
 private static string GetRuleNameByItemType(IProjectCatalogSnapshot snapshot,
                                             string catalogName,
                                             string itemType)
 {
     Requires.NotNull(snapshot, nameof(snapshot));
     Requires.NotNull(catalogName, nameof(catalogName));
     Requires.NotNullOrEmpty(itemType, nameof(itemType));
     if (snapshot.NamedCatalogs.TryGetValue(catalogName, out IPropertyPagesCatalog catalog))
     {
         return(catalog.GetPropertyPagesSchemas(itemType).FirstOrDefault());
     }
     else
     {
         return(null);
     }
 }