Пример #1
0
        public override Task HandleAsync(
            IProjectVersionedValue <Tuple <IProjectSubscriptionUpdate, IProjectCatalogSnapshot> > e,
            IImmutableDictionary <string, IProjectChangeDescription> projectChanges,
            ITargetedProjectContext context,
            bool isActiveContext,
            DependenciesRuleChangeContext ruleChangeContext)
        {
            if (projectChanges.TryGetValue(UnresolvedRuleName, out IProjectChangeDescription unresolvedChanges) &&
                unresolvedChanges.Difference.AnyChanges)
            {
                HandleChangesForRule(
                    unresolvedChanges,
                    ruleChangeContext,
                    context.TargetFramework,
                    resolved: false);
            }

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

            caseInsensitiveUnresolvedChanges.AddRange(unresolvedChanges.After.Items.Keys);

            if (projectChanges.TryGetValue(ResolvedRuleName, out IProjectChangeDescription resolvedChanges) &&
                resolvedChanges.Difference.AnyChanges)
            {
                HandleChangesForRule(
                    resolvedChanges,
                    ruleChangeContext,
                    context.TargetFramework,
                    resolved: true,
                    unresolvedChanges: caseInsensitiveUnresolvedChanges);
            }

            return(Task.CompletedTask);
        }
 private void AddConfiguredProjectState(ConfiguredProject configuredProject, ITargetedProjectContext projectContext)
 {
     lock (_gate)
     {
         _configuredProjectContextsMap.Add(configuredProject, projectContext);
     }
 }
 public async Task OnContextReleasedAsync(ITargetedProjectContext innerContext)
 {
     foreach (var handler in Handlers)
     {
         await handler.Value.OnContextReleasedAsync(innerContext).ConfigureAwait(false);
     }
 }
Пример #4
0
 public async Task OnContextReleasedAsync(ITargetedProjectContext innerContext)
 {
     foreach (Lazy <ICrossTargetRuleHandler <T>, IOrderPrecedenceMetadataView> handler in Handlers)
     {
         await handler.Value.OnContextReleasedAsync(innerContext).ConfigureAwait(false);
     }
 }
        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);
                }
            }
        }
Пример #6
0
        public void SetProjectFilePathAndDisplayName(string projectFilePath, string displayName)
        {
            // Update the project file path and display name for all the inner project contexts.
            foreach (KeyValuePair <ITargetFramework, ITargetedProjectContext> innerProjectContextKvp in _configuredProjectContextsByTargetFramework)
            {
                ITargetFramework        targetFramework     = innerProjectContextKvp.Key;
                ITargetedProjectContext innerProjectContext = innerProjectContextKvp.Value;

                // For cross targeting projects, we ensure that the display name is unique per every target framework.
                innerProjectContext.DisplayName     = IsCrossTargeting ? $"{displayName}({targetFramework})" : displayName;
                innerProjectContext.ProjectFilePath = projectFilePath;
            }
        }
Пример #7
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));
                }
            }
        }
Пример #9
0
        private void HandleChangesForRule(
            bool resolved,
            IProjectChangeDescription projectChange,
            ITargetedProjectContext context,
            bool isActiveContext,
            DependenciesRuleChangeContext ruleChangeContext,
            Func <IDependencyModel, bool> shouldProcess)
        {
            foreach (var removedItem in projectChange.Difference.RemovedItems)
            {
                var model = CreateDependencyModelForRule(removedItem, resolved, projectChange.Before, context.TargetFramework);
                if (shouldProcess(model))
                {
                    ruleChangeContext.IncludeRemovedChange(context.TargetFramework, model);
                }
            }

            foreach (var changedItem in projectChange.Difference.ChangedItems)
            {
                var model = CreateDependencyModelForRule(changedItem, resolved, projectChange.After, context.TargetFramework);
                if (shouldProcess(model))
                {
                    // For changes we try to add new dependency. If it is a resolved dependency, it would just override
                    // old one with new properties. If it is unresolved dependency, it would be added only when there no
                    // resolved version in the snapshot.
                    ruleChangeContext.IncludeAddedChange(context.TargetFramework, model);
                }
            }

            foreach (var addedItem in projectChange.Difference.AddedItems)
            {
                var model = CreateDependencyModelForRule(addedItem, resolved, projectChange.After, context.TargetFramework);
                if (shouldProcess(model))
                {
                    ruleChangeContext.IncludeAddedChange(context.TargetFramework, model);
                }
            }
        }
Пример #10
0
        public virtual Task HandleAsync(
            IProjectVersionedValue <Tuple <IProjectSubscriptionUpdate, IProjectCatalogSnapshot, IProjectCapabilitiesSnapshot> > e,
            IImmutableDictionary <string, IProjectChangeDescription> projectChanges,
            ITargetedProjectContext context,
            bool isActiveContext,
            DependenciesRuleChangeContext ruleChangeContext)
        {
            if (projectChanges.TryGetValue(UnresolvedRuleName, out IProjectChangeDescription unresolvedChanges))
            {
                HandleChangesForRule(false /*unresolved*/,
                                     unresolvedChanges, context, isActiveContext, ruleChangeContext,
                                     (itemSpec) => { return(true); });
            }

            if (projectChanges.TryGetValue(ResolvedRuleName, out IProjectChangeDescription resolvedChanges))
            {
                HandleChangesForRule(true /*resolved*/,
                                     resolvedChanges, context, isActiveContext, ruleChangeContext,
                                     (metadata) => { return(DoesUnresolvedProjectItemExist(metadata.OriginalItemSpec, unresolvedChanges)); });
            }

            return(Task.CompletedTask);
        }
Пример #11
0
 public Task OnContextReleasedAsync(ITargetedProjectContext context)
 {
     return(Task.CompletedTask);
 }
 private bool TryGetConfiguredProjectState(ConfiguredProject configuredProject, out ITargetedProjectContext targetedProjectContext)
 {
     lock (_gate)
     {
         if (_configuredProjectContextsMap.TryGetValue(configuredProject, out targetedProjectContext))
         {
             return(true);
         }
         else
         {
             targetedProjectContext = null;
             return(false);
         }
     }
 }
        private async Task HandleAsync(
            IProjectVersionedValue <Tuple <IProjectSubscriptionUpdate, IProjectCatalogSnapshot, IProjectCapabilitiesSnapshot> > e,
            RuleHandlerType handlerType)
        {
            AggregateCrossTargetProjectContext currentAggregateContext = await _host.GetCurrentAggregateProjectContext().ConfigureAwait(false);

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

            IProjectSubscriptionUpdate update   = e.Value.Item1;
            IProjectCatalogSnapshot    catalogs = e.Value.Item2;
            IEnumerable <ICrossTargetRuleHandler <T> > handlers = Handlers.Select(h => h.Value)
                                                                  .Where(h => h.SupportsHandlerType(handlerType));

            // 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 themeselves, i.e. two separate invocations of HandleAsync
            //       should be able to run concurrently.
            using (await _gate.DisposableWaitAsync().ConfigureAwait(true))
            {
                // Get the inner workspace project context to update for this change.
                ITargetedProjectContext projectContextToUpdate = currentAggregateContext
                                                                 .GetInnerProjectContext(update.ProjectConfiguration, out bool isActiveContext);
                if (projectContextToUpdate == 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 (update.ProjectChanges.Count == 0)
                {
                    if (handlerType == RuleHandlerType.DesignTimeBuild)
                    {
                        projectContextToUpdate.LastDesignTimeBuildSucceeded = false;
                    }

                    return;
                }

                T ruleChangeContext = CreateRuleChangeContext(
                    currentAggregateContext.ActiveProjectContext.TargetFramework, catalogs);
                foreach (ICrossTargetRuleHandler <T> handler in handlers)
                {
                    ImmutableDictionary <string, IProjectChangeDescription> .Builder builder = ImmutableDictionary.CreateBuilder <string, IProjectChangeDescription>(StringComparers.RuleNames);
                    ImmutableHashSet <string> handlerRules = handler.GetRuleNames(handlerType);
                    builder.AddRange(update.ProjectChanges.Where(
                                         x => handlerRules.Contains(x.Key)));
                    ImmutableDictionary <string, IProjectChangeDescription> projectChanges = builder.ToImmutable();

                    if (handler.ReceiveUpdatesWithEmptyProjectChange ||
                        projectChanges.Any(x => x.Value.Difference.AnyChanges))
                    {
                        await handler.HandleAsync(e,
                                                  projectChanges,
                                                  projectContextToUpdate,
                                                  isActiveContext,
                                                  ruleChangeContext)
                        .ConfigureAwait(true);
                    }
                }

                await CompleteHandleAsync(ruleChangeContext).ConfigureAwait(false);

                // record all the rules that have occurred
                _treeTelemetryService.ObserveTargetFrameworkRules(projectContextToUpdate.TargetFramework, update.ProjectChanges.Keys);
            }
        }
 private bool TryGetConfiguredProjectState(ConfiguredProject configuredProject, out ITargetedProjectContext targetedProjectContext)
 {
     lock (_gate)
     {
         return(_configuredProjectContextsMap.TryGetValue(configuredProject, out targetedProjectContext));
     }
 }