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);
                }
            }
        }
Beispiel #2
0
        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);
                }
            }
        }
        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));
                }
            }
        }