private void ProcessSharedProjectsUpdates( IProjectSharedFoldersSnapshot sharedFolders, ITargetedProjectContext targetContext, DependenciesRuleChangeContext dependencyChangeContext) { Requires.NotNull(sharedFolders, nameof(sharedFolders)); Requires.NotNull(targetContext, nameof(targetContext)); Requires.NotNull(dependencyChangeContext, nameof(dependencyChangeContext)); IDependenciesSnapshot snapshot = _dependenciesSnapshotProvider.CurrentSnapshot; if (!snapshot.Targets.TryGetValue(targetContext.TargetFramework, out ITargetedDependenciesSnapshot targetedSnapshot)) { return; } IEnumerable <string> sharedFolderProjectPaths = sharedFolders.Value.Select(sf => sf.ProjectPath); var currentSharedImportNodes = targetedSnapshot.TopLevelDependencies .Where(x => x.Flags.Contains(DependencyTreeFlags.SharedProjectFlags)) .ToList(); IEnumerable <string> currentSharedImportNodePaths = currentSharedImportNodes.Select(x => x.Path); // process added nodes IEnumerable <string> addedSharedImportPaths = sharedFolderProjectPaths.Except(currentSharedImportNodePaths); foreach (string addedSharedImportPath in addedSharedImportPaths) { IDependencyModel added = new SharedProjectDependencyModel( addedSharedImportPath, addedSharedImportPath, isResolved: true, isImplicit: false, properties: ImmutableStringDictionary <string> .EmptyOrdinal); dependencyChangeContext.IncludeAddedChange(targetContext.TargetFramework, added); } // process removed nodes IEnumerable <string> removedSharedImportPaths = currentSharedImportNodePaths.Except(sharedFolderProjectPaths); foreach (string removedSharedImportPath in removedSharedImportPaths) { bool exists = currentSharedImportNodes.Any(node => PathHelper.IsSamePath(node.Path, removedSharedImportPath)); if (exists) { dependencyChangeContext.IncludeRemovedChange( targetContext.TargetFramework, ProjectRuleHandler.ProviderTypeString, dependencyId: removedSharedImportPath); } } }
private void ProcessSharedProjectsUpdates( IProjectSharedFoldersSnapshot sharedFolders, TargetFramework targetFramework, DependenciesChangesBuilder changesBuilder) { Requires.NotNull(sharedFolders, nameof(sharedFolders)); Requires.NotNull(targetFramework, nameof(targetFramework)); Requires.NotNull(changesBuilder, nameof(changesBuilder)); DependenciesSnapshot snapshot = _dependenciesSnapshotProvider.CurrentSnapshot; if (!snapshot.DependenciesByTargetFramework.TryGetValue(targetFramework, out TargetedDependenciesSnapshot? targetedSnapshot)) { return; } IEnumerable <string> sharedFolderProjectPaths = sharedFolders.Value.Select(sf => sf.ProjectPath); var currentSharedImportNodePaths = targetedSnapshot.Dependencies .Where(pair => pair.Flags.Contains(DependencyTreeFlags.SharedProjectDependency)) .Select(pair => pair.FilePath !) .ToList(); var diff = new SetDiff <string>(currentSharedImportNodePaths, sharedFolderProjectPaths); // process added nodes foreach (string addedSharedImportPath in diff.Added) { IDependencyModel added = new SharedProjectDependencyModel( addedSharedImportPath, addedSharedImportPath, isResolved: true, isImplicit: false, properties: ImmutableStringDictionary <string> .EmptyOrdinal); changesBuilder.Added(targetFramework, added); } // process removed nodes foreach (string removedSharedImportPath in diff.Removed) { bool exists = currentSharedImportNodePaths.Any(nodePath => PathHelper.IsSamePath(nodePath, removedSharedImportPath)); if (exists) { changesBuilder.Removed( targetFramework, ProjectRuleHandler.ProviderTypeString, dependencyId: removedSharedImportPath); } } }
private void ProcessSharedProjectsUpdates( IProjectSharedFoldersSnapshot sharedFolders, ITargetedProjectContext targetContext, DependenciesRuleChangeContext dependencyChangeContext) { Requires.NotNull(sharedFolders, nameof(sharedFolders)); Requires.NotNull(targetContext, nameof(targetContext)); Requires.NotNull(dependencyChangeContext, nameof(dependencyChangeContext)); IDependenciesSnapshot snapshot = _dependenciesSnapshotProvider.CurrentSnapshot; if (!snapshot.Targets.TryGetValue(targetContext.TargetFramework, out ITargetedDependenciesSnapshot targetedSnapshot)) { return; } IEnumerable <string> sharedFolderProjectPaths = sharedFolders.Value.Select(sf => sf.ProjectPath); var currentSharedImportNodes = targetedSnapshot.TopLevelDependencies .Where(x => x.Flags.Contains(DependencyTreeFlags.SharedProjectFlags)) .ToList(); IEnumerable <string> currentSharedImportNodePaths = currentSharedImportNodes.Select(x => x.Path); // process added nodes IEnumerable <string> addedSharedImportPaths = sharedFolderProjectPaths.Except(currentSharedImportNodePaths); foreach (string addedSharedImportPath in addedSharedImportPaths) { IDependencyModel added = CreateDependencyModel(addedSharedImportPath, targetContext.TargetFramework, resolved: true); dependencyChangeContext.IncludeAddedChange(targetContext.TargetFramework, added); } // process removed nodes IEnumerable <string> removedSharedImportPaths = currentSharedImportNodePaths.Except(sharedFolderProjectPaths); foreach (string removedSharedImportPath in removedSharedImportPaths) { IDependency existingImportNode = currentSharedImportNodes .Where(node => PathHelper.IsSamePath(node.Path, removedSharedImportPath)) .FirstOrDefault(); if (existingImportNode != null) { IDependencyModel removed = CreateDependencyModel(removedSharedImportPath, targetContext.TargetFramework, resolved: true); dependencyChangeContext.IncludeRemovedChange(targetContext.TargetFramework, removed); } } }
/// <summary> /// Updates the shared project import nodes that are shown under the 'Dependencies/Projects' node. /// </summary> /// <param name="sharedFolders">Snapshot of shared folders.</param> /// <param name="dependenciesChange"></param> /// <returns></returns> protected override void ProcessSharedProjectImportNodes(IProjectSharedFoldersSnapshot sharedFolders, DependenciesChange dependenciesChange) { Requires.NotNull(sharedFolders, nameof(sharedFolders)); Requires.NotNull(dependenciesChange, nameof(dependenciesChange)); var sharedFolderProjectPaths = sharedFolders.Value.Select(sf => sf.ProjectPath); var rootNodeChildren = RootNode.Children; var currentSharedImportNodes = rootNodeChildren .Where(x => x.Flags.Contains(ProjectTreeFlags.Common.SharedProjectImportReference)); var currentSharedImportNodePaths = currentSharedImportNodes.Select(x => x.Id.ItemSpec); // process added nodes IEnumerable <string> addedSharedImportPaths = sharedFolderProjectPaths.Except(currentSharedImportNodePaths); var itemType = ResolvedProjectReference.PrimaryDataSourceItemType; foreach (string addedSharedImportPath in addedSharedImportPaths) { rootNodeChildren = RootNode.Children; var node = rootNodeChildren.FindNode(addedSharedImportPath, itemType); if (node == null) { var sharedFlags = ProjectTreeFlags.Create(ProjectTreeFlags.Common.SharedProjectImportReference); var id = new DependencyNodeId(ProviderType, addedSharedImportPath, itemType); node = new SharedProjectDependencyNode(id, flags: sharedFlags); dependenciesChange.AddedNodes.Add(node); } } // process removed nodes var removedSharedImportPaths = currentSharedImportNodePaths.Except(sharedFolderProjectPaths); foreach (string removedSharedImportPath in removedSharedImportPaths) { var existingImportNode = currentSharedImportNodes .Where(node => PathHelper.IsSamePath(node.Id.ItemSpec, removedSharedImportPath)) .FirstOrDefault(); if (existingImportNode != null) { dependenciesChange.RemovedNodes.Add(existingImportNode); } } }
protected override void Handle( AggregateCrossTargetProjectContext currentAggregateContext, TargetFramework targetFrameworkToUpdate, EventData e) { IProjectSharedFoldersSnapshot sharedProjectsUpdate = e.Item2; IProjectCatalogSnapshot catalogs = e.Item3; var changesBuilder = new DependenciesChangesBuilder(); ProcessSharedProjectsUpdates(sharedProjectsUpdate, targetFrameworkToUpdate, changesBuilder); IDependenciesChanges?changes = changesBuilder.TryBuildChanges(); if (changes != null) { RaiseDependenciesChanged(targetFrameworkToUpdate, changes, currentAggregateContext, catalogs); } }
private async Task HandleAsync(Tuple <IProjectSubscriptionUpdate, IProjectSharedFoldersSnapshot, IProjectCatalogSnapshot> e) { AggregateCrossTargetProjectContext currentAggregateContext = await _host.GetCurrentAggregateProjectContext(); if (currentAggregateContext == null) { return; } IProjectSubscriptionUpdate projectUpdate = e.Item1; IProjectSharedFoldersSnapshot sharedProjectsUpdate = e.Item2; IProjectCatalogSnapshot catalogs = e.Item3; // We need to process the update within a lock to ensure that we do not release this context during processing. // TODO: Enable concurrent execution of updates themselves, i.e. two separate invocations of HandleAsync // should be able to run concurrently. using (await _gate.DisposableWaitAsync()) { // Get the inner workspace project context to update for this change. ITargetedProjectContext projectContextToUpdate = currentAggregateContext .GetInnerProjectContext(projectUpdate.ProjectConfiguration, out bool isActiveContext); if (projectContextToUpdate == null) { return; } var dependencyChangeContext = new DependenciesRuleChangeContext( currentAggregateContext.ActiveProjectContext.TargetFramework, catalogs); ProcessSharedProjectsUpdates(sharedProjectsUpdate, projectContextToUpdate, dependencyChangeContext); if (dependencyChangeContext.AnyChanges) { DependenciesChanged?.Invoke(this, new DependencySubscriptionChangedEventArgs(dependencyChangeContext)); } } }
private async Task HandleAsync(Tuple <IProjectSubscriptionUpdate, IProjectSharedFoldersSnapshot, IProjectCatalogSnapshot> e) { AggregateCrossTargetProjectContext?currentAggregateContext = await _host !.GetCurrentAggregateProjectContextAsync(); if (currentAggregateContext == null) { return; } IProjectSubscriptionUpdate projectUpdate = e.Item1; IProjectSharedFoldersSnapshot sharedProjectsUpdate = e.Item2; IProjectCatalogSnapshot catalogs = e.Item3; // Get the target framework to update for this change. ITargetFramework?targetFrameworkToUpdate = currentAggregateContext.GetProjectFramework(projectUpdate.ProjectConfiguration); if (targetFrameworkToUpdate == null) { return; } var changesBuilder = new CrossTargetDependenciesChangesBuilder(); ProcessSharedProjectsUpdates(sharedProjectsUpdate, targetFrameworkToUpdate, changesBuilder); ImmutableDictionary <ITargetFramework, IDependenciesChanges>?changes = changesBuilder.TryBuildChanges(); if (changes != null) { DependenciesChanged?.Invoke( this, new DependencySubscriptionChangedEventArgs( currentAggregateContext.TargetFrameworks, currentAggregateContext.ActiveTargetFramework, catalogs, changes)); } }
/// <summary> /// Updates the shared project import nodes that are shown under the 'Dependencies/Projects' node. /// </summary> /// <param name="sharedFolders">Snapshot of shared folders.</param> /// <param name="dependenciesChange"></param> /// <returns></returns> protected virtual void ProcessSharedProjectImportNodes(IProjectSharedFoldersSnapshot sharedFolders, DependenciesChange dependenciesChange) { // does nothing by default }