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(); } }
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); }
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); }
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); }
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); } }); }
/// <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)); }
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)); }
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); }
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); }
public TestableTargetedDependenciesSnapshot( string projectPath, ITargetFramework targetFramework, ITargetedDependenciesSnapshot previousSnapshot = null, IProjectCatalogSnapshot catalogs = null) : base(projectPath, targetFramework, previousSnapshot, catalogs) { }
public DependenciesChangedEventArgs( IProjectDependenciesSubTreeProvider provider, string?targetShortOrFullName, IDependenciesChanges changes, IProjectCatalogSnapshot catalogs, IImmutableDictionary <NamedIdentity, IComparable> dataSourceVersions) : this(provider, targetShortOrFullName, changes, CancellationToken.None) { }
public DependenciesChangedEventArgs(IProjectDependenciesSubTreeProvider provider, IDependenciesChangeDiff changes, IProjectCatalogSnapshot catalogs, IImmutableDictionary <NamedIdentity, IComparable> dataSourceVersions) { Provider = provider; Changes = changes; Catalogs = catalogs; DataSourceVersions = dataSourceVersions; }
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); }
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; }
public DependenciesChangedEventArgs(IProjectDependenciesSubTreeProvider provider, string targetShortOrFullName, IDependenciesChanges changes, IProjectCatalogSnapshot catalogs, IImmutableDictionary <NamedIdentity, IComparable> dataSourceVersions) { Provider = provider; TargetShortOrFullName = targetShortOrFullName; Changes = changes; Catalogs = catalogs; DataSourceVersions = dataSourceVersions; }
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()); } }
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); }
/// <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); } }
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); }
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); }
/// <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); }
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; }
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; }
// 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(); }
/// <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); } }