예제 #1
0
        protected virtual void HandleChangedItem(
            string changedItem,
            bool resolved,
            IProjectChangeDescription projectChange,
            DependenciesChangesBuilder changesBuilder,
            ITargetFramework targetFramework,
            Func <string, bool>?isEvaluatedItemSpec)
        {
            IDependencyModel model = CreateDependencyModelForRule(changedItem, projectChange.After, resolved);

            if (isEvaluatedItemSpec == null || isEvaluatedItemSpec(model.Id))
            {
                // 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.
                changesBuilder.Added(model);
            }
        }
예제 #2
0
        public async Task ApplyProjectBuildAsync(IProjectVersionedValue <IProjectSubscriptionUpdate> update, bool isActiveContext, CancellationToken cancellationToken)
        {
            Requires.NotNull(update, nameof(update));

            VerifyInitializedAndNotDisposed();

            IProjectChangeDescription projectChange = update.Value.ProjectChanges[ProjectBuildRuleName];

            if (projectChange.Difference.AnyChanges)
            {
                IComparable version = GetConfiguredProjectVersion(update);

                ProcessOptions(projectChange.After);
                await ProcessCommandLineAsync(version, projectChange.Difference, isActiveContext, cancellationToken);

                ProcessProjectBuildFailure(projectChange.After);
            }
        }
        private HostDocument[] GetChangedAndRemovedDocuments(IProjectSubscriptionUpdate update)
        {
            IProjectChangeDescription rule = null;

            var documents = new List <HostDocument>();

            if (update.ProjectChanges.TryGetValue(Rules.RazorComponentWithTargetPath.SchemaName, out rule))
            {
                foreach (var key in rule.Difference.RemovedItems.Concat(rule.Difference.ChangedItems))
                {
                    if (rule.Before.Items.TryGetValue(key, out var value))
                    {
                        if (value.TryGetValue(Rules.RazorComponentWithTargetPath.TargetPathProperty, out var targetPath) &&
                            !string.IsNullOrWhiteSpace(key) &&
                            !string.IsNullOrWhiteSpace(targetPath))
                        {
                            var filePath = CommonServices.UnconfiguredProject.MakeRooted(key);
                            var fileKind = FileKinds.GetComponentFileKindFromFilePath(filePath);

                            documents.Add(new HostDocument(filePath, targetPath, fileKind));
                        }
                    }
                }
            }

            if (update.ProjectChanges.TryGetValue(Rules.RazorGenerateWithTargetPath.SchemaName, out rule))
            {
                foreach (var key in rule.Difference.RemovedItems.Concat(rule.Difference.ChangedItems))
                {
                    if (rule.Before.Items.TryGetValue(key, out var value))
                    {
                        if (value.TryGetValue(Rules.RazorGenerateWithTargetPath.TargetPathProperty, out var targetPath) &&
                            !string.IsNullOrWhiteSpace(key) &&
                            !string.IsNullOrWhiteSpace(targetPath))
                        {
                            var filePath = CommonServices.UnconfiguredProject.MakeRooted(key);
                            documents.Add(new HostDocument(filePath, targetPath, FileKinds.Legacy));
                        }
                    }
                }
            }

            return(documents.ToArray());
        }
        public void Handle(
            IProjectChangeDescription evaluation,
            IProjectChangeDescription?projectBuild,
            TargetFramework targetFramework,
            DependenciesChangesBuilder changesBuilder)
        {
            HandleChangesForRule(
                resolved: false,
                projectChange: evaluation,
                isEvaluatedItemSpec: null);

            // We only have resolved data if the update came via the JointRule data source.
            if (projectBuild != null)
            {
                Func <string, bool>?isEvaluatedItemSpec = ResolvedItemRequiresEvaluatedItem ? evaluation.After.Items.ContainsKey : (Func <string, bool>?)null;

                HandleChangesForRule(
                    resolved: true,
                    projectChange: projectBuild,
                    isEvaluatedItemSpec);
            }

            return;

            void HandleChangesForRule(bool resolved, IProjectChangeDescription projectChange, Func <string, bool>?isEvaluatedItemSpec)
            {
                foreach (string removedItem in projectChange.Difference.RemovedItems)
                {
                    HandleRemovedItem(removedItem, resolved, projectChange, changesBuilder, targetFramework, isEvaluatedItemSpec);
                }

                foreach (string changedItem in projectChange.Difference.ChangedItems)
                {
                    HandleChangedItem(changedItem, resolved, projectChange, changesBuilder, targetFramework, isEvaluatedItemSpec);
                }

                foreach (string addedItem in projectChange.Difference.AddedItems)
                {
                    HandleAddedItem(addedItem, resolved, projectChange, changesBuilder, targetFramework, isEvaluatedItemSpec);
                }

                System.Diagnostics.Debug.Assert(projectChange.Difference.RenamedItems.Count == 0, "Project rule diff should not contain renamed items");
            }
        }
예제 #5
0
 protected override void HandleAddedItem(
     string addedItem,
     bool resolved,
     IProjectChangeDescription projectChange,
     DependenciesChangesBuilder changesBuilder,
     ITargetFramework targetFramework,
     Func <string, bool>?isEvaluatedItemSpec)
 {
     if (TryCreatePackageDependencyModel(
             addedItem,
             resolved,
             properties: projectChange.After.GetProjectItemProperties(addedItem) !,
             isEvaluatedItemSpec,
             targetFramework,
             out PackageDependencyModel? dependencyModel))
     {
         changesBuilder.Added(dependencyModel);
     }
 }
        protected virtual void HandleRemovedItem(
            string projectFullPath,
            string removedItem,
            bool resolved,
            IProjectChangeDescription projectChange,
            IProjectRuleSnapshot evaluationRuleSnapshot,
            DependenciesChangesBuilder changesBuilder,
            TargetFramework targetFramework,
            Func <string, bool>?isEvaluatedItemSpec)
        {
            string dependencyId = resolved
                ? projectChange.Before.GetProjectItemProperties(removedItem) !.GetStringProperty(ProjectItemMetadata.OriginalItemSpec) ?? removedItem
                : removedItem;

            if (isEvaluatedItemSpec == null || isEvaluatedItemSpec(dependencyId))
            {
                changesBuilder.Removed(ProviderType, removedItem);
            }
        }
예제 #7
0
        public void Handle(
            string projectFullPath,
            IProjectChangeDescription evaluationProjectChange,
            IProjectChangeDescription?buildProjectChange,
            TargetFramework targetFramework,
            DependenciesChangesBuilder changesBuilder)
        {
            bool hasResolvedData = buildProjectChange is not null;

            HandleChangesForRule(evaluationProjectChange, isResolvedItem: false);

            // We only have resolved data if the update came via the JointRule data source.
            if (hasResolvedData)
            {
                Func <string, bool>?isEvaluatedItemSpec = ResolvedItemRequiresEvaluatedItem ? evaluationProjectChange.After.Items.ContainsKey : null;

                HandleChangesForRule(evaluationProjectChange, isResolvedItem: true, buildProjectChange, isEvaluatedItemSpec);
            }

            return;

            void HandleChangesForRule(IProjectChangeDescription evaluationProjectChange, bool isResolvedItem, IProjectChangeDescription?buildProjectChange = null, Func <string, bool>?isEvaluatedItemSpec = null)
            {
                IProjectChangeDescription projectChange = buildProjectChange ?? evaluationProjectChange;

                foreach (string removedItem in projectChange.Difference.RemovedItems)
                {
                    HandleRemovedItem(projectFullPath, removedItem, isResolvedItem, projectChange, evaluationProjectChange.After, changesBuilder, targetFramework, isEvaluatedItemSpec);
                }

                foreach (string changedItem in projectChange.Difference.ChangedItems)
                {
                    HandleAddedItem(projectFullPath, changedItem, isResolvedItem, projectChange, evaluationProjectChange.After, changesBuilder, targetFramework, isEvaluatedItemSpec);
                }

                foreach (string addedItem in projectChange.Difference.AddedItems)
                {
                    HandleAddedItem(projectFullPath, addedItem, isResolvedItem, projectChange, evaluationProjectChange.After, changesBuilder, targetFramework, isEvaluatedItemSpec);
                }

                System.Diagnostics.Debug.Assert(projectChange.Difference.RenamedItems.Count == 0, "Project rule diff should not contain renamed items");
            }
        }
예제 #8
0
 protected override void HandleRemovedItem(
     string removedItem,
     bool resolved,
     IProjectChangeDescription projectChange,
     DependenciesChangesBuilder changesBuilder,
     ITargetFramework targetFramework,
     Func <string, bool>?isEvaluatedItemSpec)
 {
     if (TryCreatePackageDependencyModel(
             removedItem,
             resolved,
             properties: projectChange.Before.GetProjectItemProperties(removedItem) !,
             isEvaluatedItemSpec,
             targetFramework,
             out PackageDependencyModel? dependencyModel))
     {
         changesBuilder.Removed(ProviderTypeString, dependencyModel.OriginalItemSpec);
     }
 }
        internal void OnNamespaceImportChanged(IProjectVersionedValue <IProjectSubscriptionUpdate> e)
        {
            IProjectChangeDescription projectChange = e.Value.ProjectChanges[NamespaceImport.SchemaName];

            if (projectChange.Difference.AnyChanges)
            {
                lock (_lock)
                {
                    IOrderedEnumerable <string> sortedItems = projectChange.After.Items.Keys.OrderBy(s => s, StringComparer.OrdinalIgnoreCase);
                    int newListCount = sortedItems.Count();
                    int oldListCount = _list.Count;

                    int trackingIndex = 0;

                    while (trackingIndex < oldListCount && trackingIndex < newListCount)
                    {
                        string incomingItem = sortedItems.ElementAt(trackingIndex);
                        if (string.Compare(_list[trackingIndex], incomingItem, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            trackingIndex++;
                            continue;
                        }

                        _list[trackingIndex] = incomingItem;
                        trackingIndex++;
                    }

                    if (oldListCount == newListCount)
                    {
                        return;
                    }
                    else if (oldListCount < newListCount)
                    {
                        _list.AddRange(sortedItems.Skip(trackingIndex));
                    }
                    else
                    {
                        _list.RemoveRange(trackingIndex, oldListCount - trackingIndex);
                    }
                }
            }
        }
        private async Task HandleAsync(IProjectVersionedValue <IProjectSubscriptionUpdate> update, RuleHandlerType handlerType)
        {
            var handlers = Handlers.Select(h => h.Value)
                           .Where(h => h.HandlerType == 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.
            await ExecuteWithinLockAsync(async() =>
            {
                // TODO: https://github.com/dotnet/roslyn-project-system/issues/353
                await _commonServices.ThreadingService.SwitchToUIThread();

                // Get the inner workspace project context to update for this change.
                var projectContextToUpdate = _currentAggregateProjectContext.GetInnerProjectContext(update.Value.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.Value.ProjectChanges.Count == 0)
                {
                    if (handlerType == RuleHandlerType.DesignTimeBuild)
                    {
                        projectContextToUpdate.LastDesignTimeBuildSucceeded = false;
                    }

                    return;
                }

                foreach (var handler in handlers)
                {
                    IProjectChangeDescription projectChange = update.Value.ProjectChanges[handler.RuleName];
                    if (handler.ReceiveUpdatesWithEmptyProjectChange || projectChange.Difference.AnyChanges)
                    {
                        await handler.HandleAsync(update, projectChange, projectContextToUpdate, isActiveContext).ConfigureAwait(true);
                    }
                }
            });
        }
예제 #11
0
        public void Handle(IComparable version, IProjectChangeDescription projectChange, ContextState state, IProjectLogger logger)
        {
            Requires.NotNull(version, nameof(version));
            Requires.NotNull(projectChange, nameof(projectChange));
            Requires.NotNull(logger, nameof(logger));

            VerifyInitialized();

            if (projectChange.Difference.ChangedProperties.Contains(ConfigurationGeneral.MSBuildProjectFullPathProperty) &&
                projectChange.After.Properties.TryGetValue(ConfigurationGeneral.MSBuildProjectFullPathProperty, out string projectFilePath))
            {
                string displayName = GetDisplayName(projectFilePath);

                logger.WriteLine("DisplayName: {0}", displayName);
                logger.WriteLine("ProjectFilePath: {0}", projectFilePath);

                Context.ProjectFilePath = projectFilePath;
                Context.DisplayName     = displayName;
            }
        }
        protected virtual void HandleChangedItem(
            string projectFullPath,
            string changedItem,
            bool resolved,
            IProjectChangeDescription projectChange,
            IProjectRuleSnapshot evaluationRuleSnapshot,
            DependenciesChangesBuilder changesBuilder,
            TargetFramework targetFramework,
            Func <string, bool>?isEvaluatedItemSpec)
        {
            IDependencyModel?model = CreateDependencyModelForRule(changedItem, evaluationRuleSnapshot, projectChange.After, resolved, projectFullPath);

            if (model != null && (isEvaluatedItemSpec == null || isEvaluatedItemSpec(model.Id)))
            {
                // 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 is
                // no resolved version in the snapshot (due to UnresolvedDependenciesSnapshotFilter).
                changesBuilder.Added(model);
            }
        }
예제 #13
0
        private Task ProcessProjectEvaluationHandlersAsync(IComparable version, IProjectVersionedValue <IProjectSubscriptionUpdate> update, bool isActiveContext, CancellationToken cancellationToken)
        {
            foreach (ExportLifetimeContext <IWorkspaceContextHandler> handler in _handlers)
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (handler.Value is IProjectEvaluationHandler evaluationHandler)
                {
                    IProjectChangeDescription projectChange = update.Value.ProjectChanges[evaluationHandler.ProjectEvaluationRule];
                    if (!projectChange.Difference.AnyChanges)
                    {
                        continue;
                    }

                    evaluationHandler.Handle(version, projectChange, isActiveContext, _logger);
                }
            }

            return(Task.CompletedTask);
        }
        public void ApplyDesignTime(IProjectVersionedValue <IProjectSubscriptionUpdate> update, bool isActiveContext, CancellationToken cancellationToken)
        {
            Requires.NotNull(update, nameof(update));

            lock (SyncObject)
            {
                VerifyInitializedAndNotDisposed();

                IProjectChangeDescription projectChange = update.Value.ProjectChanges[DesignTimeRuleName];

                if (projectChange.Difference.AnyChanges)
                {
                    IComparable version = GetConfiguredProjectVersion(update);

                    ProcessOptions(projectChange.After);
                    ProcessCommandLine(version, projectChange.Difference, isActiveContext, cancellationToken);
                    ProcessDesignTimeBuildFailure(projectChange.After);
                }
            }
        }
예제 #15
0
 protected override void HandleChangedItem(
     string changedItem,
     bool resolved,
     IProjectChangeDescription projectChange,
     DependenciesChangesBuilder changesBuilder,
     ITargetFramework targetFramework,
     Func <string, bool>?isEvaluatedItemSpec)
 {
     if (PackageDependencyMetadata.TryGetMetadata(
             changedItem,
             resolved,
             properties: projectChange.After.GetProjectItemProperties(changedItem) !,
             isEvaluatedItemSpec,
             targetFramework,
             _targetFrameworkProvider,
             out PackageDependencyMetadata metadata))
     {
         changesBuilder.Removed(ProviderTypeString, metadata.OriginalItemSpec);
         changesBuilder.Added(metadata.CreateDependencyModel());
     }
 }
예제 #16
0
        private void ProcessProjectEvaluationHandlers(IComparable version, IProjectVersionedValue <IProjectSubscriptionUpdate> update, bool isActiveContext, CancellationToken cancellationToken)
        {
            foreach (ExportLifetimeContext <IWorkspaceContextHandler> handler in _handlers)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                if (handler.Value is IProjectEvaluationHandler evaluationHandler)
                {
                    IProjectChangeDescription projectChange = update.Value.ProjectChanges[evaluationHandler.ProjectEvaluationRule];
                    if (!projectChange.Difference.AnyChanges)
                    {
                        continue;
                    }

                    evaluationHandler.Handle(version, projectChange, isActiveContext, _logger);
                }
            }
        }
예제 #17
0
        public void Handle(IComparable version, IProjectChangeDescription projectChange, bool isActiveContext, IProjectLogger logger)
        {
            Requires.NotNull(version, nameof(version));
            Requires.NotNull(projectChange, nameof(projectChange));
            Requires.NotNull(logger, nameof(logger));

            VerifyInitialized();

            IProjectChangeDiff difference = HandlerServices.NormalizeRenames(projectChange.Difference);

            foreach (string includePath in difference.RemovedItems)
            {
                if (IsDynamicFile(includePath))
                {
                    RemoveFromContextIfPresent(includePath, logger);
                }
            }

            foreach (string includePath in difference.AddedItems)
            {
                if (IsDynamicFile(includePath))
                {
                    IImmutableDictionary <string, string> metadata = projectChange.After.Items.GetValueOrDefault(includePath, ImmutableStringDictionary <string> .EmptyOrdinal);

                    AddToContextIfNotPresent(includePath, metadata, logger);
                }
            }

            // We Remove then Add changed items to pick up the Linked metadata
            foreach (string includePath in difference.ChangedItems)
            {
                if (IsDynamicFile(includePath))
                {
                    IImmutableDictionary <string, string> metadata = projectChange.After.Items.GetValueOrDefault(includePath, ImmutableStringDictionary <string> .EmptyOrdinal);

                    RemoveFromContextIfPresent(includePath, logger);
                    AddToContextIfNotPresent(includePath, metadata, logger);
                }
            }
        }
        private void HandleChangesForRule(
            bool resolved,
            IProjectChangeDescription projectChange,
            ITargetFramework targetFramework,
            DependenciesRuleChangeContext ruleChangeContext,
            Func <string, bool> shouldProcess)
        {
            foreach (string removedItem in projectChange.Difference.RemovedItems)
            {
                string dependencyId = resolved
                    ? projectChange.Before.GetProjectItemProperties(removedItem).GetStringProperty(OriginalItemSpecPropertyName)
                    : removedItem;

                if (shouldProcess(dependencyId))
                {
                    ruleChangeContext.IncludeRemovedChange(targetFramework, ProviderType, removedItem);
                }
            }

            foreach (string changedItem in projectChange.Difference.ChangedItems)
            {
                IDependencyModel model = CreateDependencyModelForRule(changedItem, resolved, projectChange.After);
                if (shouldProcess(model.Id))
                {
                    // 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(targetFramework, model);
                }
            }

            foreach (string addedItem in projectChange.Difference.AddedItems)
            {
                IDependencyModel model = CreateDependencyModelForRule(addedItem, resolved, projectChange.After);
                if (shouldProcess(model.Id))
                {
                    ruleChangeContext.IncludeAddedChange(targetFramework, model);
                }
            }
        }
        protected override void Handle(
            string projectFullPath,
            AggregateCrossTargetProjectContext currentAggregateContext,
            TargetFramework targetFrameworkToUpdate,
            EventData e)
        {
            IProjectSubscriptionUpdate projectUpdate   = e.Item1;
            IProjectCatalogSnapshot    catalogSnapshot = e.Item2;

            // Broken design-time builds can produce updates containing no rule data.
            // Later code assumes that the requested rules are available.
            // If we see no rule data, return now.
            if (projectUpdate.ProjectChanges.Count == 0)
            {
                return;
            }

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

            // Give each handler a chance to register dependency changes.
            foreach (Lazy <IDependenciesRuleHandler, IOrderPrecedenceMetadataView> handler in _handlers)
            {
                IProjectChangeDescription evaluation = projectUpdate.ProjectChanges[handler.Value.EvaluatedRuleName];
                IProjectChangeDescription?build      = projectUpdate.ProjectChanges.GetValueOrDefault(handler.Value.ResolvedRuleName);

                handler.Value.Handle(projectFullPath, evaluation, build, targetFrameworkToUpdate, changesBuilder);
            }

            IDependenciesChanges?changes = changesBuilder.TryBuildChanges();

            // Notify subscribers of a change in dependency data.
            // NOTE even if changes is null, it's possible the catalog has changed. If we don't take the newer
            // catalog we end up retaining a reference to an old catalog, which in turn retains an old project
            // instance which can be very large.
            RaiseDependenciesChanged(targetFrameworkToUpdate, changes, currentAggregateContext, catalogSnapshot);

            // Record all the rules that have occurred
            _treeTelemetryService.ObserveTargetFrameworkRules(targetFrameworkToUpdate, projectUpdate.ProjectChanges.Keys);
        }
예제 #20
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);
                }
            }
        }
        protected virtual void HandleRemovedItem(
            string projectFullPath,
            string removedItem,
            IProjectChangeDescription projectChange,
            IProjectRuleSnapshot evaluationRuleSnapshot,
            DependenciesChangesBuilder changesBuilder,
            TargetFramework targetFramework,
            Func <string, bool>?isEvaluatedItemSpec)
        {
            if (isEvaluatedItemSpec is not null)
            {
                // The item is resolved
                string dependencyId = projectChange.Before.GetProjectItemProperties(removedItem) !.GetStringProperty(ProjectItemMetadata.OriginalItemSpec) ?? removedItem;

                if (!isEvaluatedItemSpec(dependencyId))
                {
                    // Skip any items returned by build that were not present in evaluation
                    return;
                }
            }

            changesBuilder.Removed(targetFramework, ProviderType, removedItem);
        }
        public void Handle(IComparable version, IProjectChangeDescription projectChange, bool isActiveContext, IProjectLogger logger)
        {
            Requires.NotNull(version, nameof(version));
            Requires.NotNull(projectChange, nameof(projectChange));
            Requires.NotNull(logger, nameof(logger));

            // The language service wants both the intermediate (bin\obj) and output (bin\debug)) paths
            // so that it can automatically hook up project-to-project references. It does this by matching the
            // bin output path with the another project's /reference argument, if they match, then it automatically
            // introduces a project reference between the two. We pass the intermediate path via the /out
            // command-line argument and set via one of the other handlers, where as the latter is calculated via
            // the TargetPath property and explictly set on the context.

            if (projectChange.Difference.ChangedProperties.Contains(ConfigurationGeneral.TargetPathProperty))
            {
                string newBinOutputPath = projectChange.After.Properties[ConfigurationGeneral.TargetPathProperty];
                if (!string.IsNullOrEmpty(newBinOutputPath))
                {
                    logger.WriteLine("BinOutputPath: {0}", newBinOutputPath);
                    _context.BinOutputPath = newBinOutputPath;
                }
            }
        }
예제 #23
0
        public void Handle(IComparable version, IProjectChangeDescription projectChange, bool isActiveContext, IProjectLogger logger)
        {
            Requires.NotNull(version, nameof(version));
            Requires.NotNull(projectChange, nameof(projectChange));
            Requires.NotNull(logger, nameof(logger));

            VerifyInitialized();

            foreach (string name in projectChange.Difference.ChangedProperties)
            {
                string value = projectChange.After.Properties[name];

                // Is it a property we're specifically aware of?
                if (TryHandleSpecificProperties(name, value, logger))
                {
                    continue;
                }

                // Otherwise, just pass it through
                logger.WriteLine("{0}: {1}", name, value);
                Context.SetProperty(name, value);
            }
        }
예제 #24
0
 protected bool DoesUnresolvedProjectItemExist(string itemSpec, IProjectChangeDescription unresolvedChanges)
 {
     return(unresolvedChanges != null && unresolvedChanges.After.Items.ContainsKey(itemSpec));
 }
예제 #25
0
        public Task HandleAsync(IProjectVersionedValue <IProjectSubscriptionUpdate> e, IProjectChangeDescription projectChange)
        {
            Requires.NotNull(e, nameof(e));
            Requires.NotNull(projectChange, nameof(projectChange));

            if (projectChange.Difference.ChangedProperties.Contains(ConfigurationGeneral.ProjectGuidProperty))
            {
                Guid result;
                if (Guid.TryParse(projectChange.After.Properties[ConfigurationGeneral.ProjectGuidProperty], out result))
                {
                    _context.Guid = result;
                }
            }

            // The language service wants both the intermediate (bin\obj) and output (bin\debug)) paths
            // so that it can automatically hook up project-to-project references. It does this by matching the
            // bin output path with the another project's /reference argument, if they match, then it automatically
            // introduces a project reference between the two. We pass the intermediate path via the /out
            // command-line argument and set via one of the other handlers, where as the latter is calculate via
            // the TargetPath property and explictly set on the context.

            if (projectChange.Difference.ChangedProperties.Contains(ConfigurationGeneral.TargetPathProperty))
            {
                _context.BinOutputPath = projectChange.After.Properties[ConfigurationGeneral.TargetPathProperty];
            }

            return(Task.CompletedTask);
        }
예제 #26
0
        public override async Task HandleAsync(IProjectVersionedValue <IProjectSubscriptionUpdate> e, IProjectChangeDescription projectChange, IWorkspaceProjectContext context, bool isActiveContext)
        {
            Requires.NotNull(e, nameof(e));
            Requires.NotNull(projectChange, nameof(projectChange));

            IProjectChangeDiff diff = projectChange.Difference;

            foreach (string filePath in diff.RemovedItems)
            {
                RemoveSourceFile(filePath, context);
            }

            if (diff.AddedItems.Count > 0 || diff.RenamedItems.Count > 0 || diff.ChangedItems.Count > 0)
            {
                // Make sure the tree matches the same version of the evaluation that we're handling
                IProjectTreeServiceState treeState = await PublishTreeAsync(e).ConfigureAwait(true); // TODO: https://github.com/dotnet/roslyn-project-system/issues/353

                foreach (string filePath in diff.AddedItems)
                {
                    AddSourceFile(filePath, context, isActiveContext, treeState);
                }

                foreach (KeyValuePair <string, string> filePaths in diff.RenamedItems)
                {
                    RemoveSourceFile(filePaths.Key, context);
                    AddSourceFile(filePaths.Value, context, isActiveContext, treeState);
                }

                foreach (string filePath in diff.ChangedItems)
                {
                    // We add and then remove ChangedItems to handle Linked metadata changes
                    RemoveSourceFile(filePath, context);
                    AddSourceFile(filePath, context, isActiveContext);
                }
            }
        }
        public override Task HandleAsync(IProjectVersionedValue <IProjectSubscriptionUpdate> e, IProjectChangeDescription projectChange, IWorkspaceProjectContext context, bool isActiveContext)
        {
            Requires.NotNull(e, nameof(e));
            Requires.NotNull(projectChange, nameof(projectChange));

            if (!ProcessDesignTimeBuildFailure(projectChange, context))
            {
                ProcessOptions(projectChange, context);
                ProcessItems(projectChange, context, isActiveContext);
            }

            return(Task.CompletedTask);
        }
예제 #28
0
        internal void ProcessDataflowChanges(IProjectVersionedValue <ValueTuple <DesignTimeInputs, IProjectSubscriptionUpdate> > input)
        {
            DesignTimeInputs          inputs        = input.Value.Item1;
            IProjectChangeDescription configChanges = input.Value.Item2.ProjectChanges[ConfigurationGeneral.SchemaName];

            // This can't change while we're running, but let's use a local so you don't have to take my word for it
            DesignTimeInputsDelta?previousState = _currentState;

            var changedInputs = new List <DesignTimeInputFileChange>();

            // On the first call where we receive design time inputs we queue compilation of all of them, knowing that we'll only compile if the file write date requires it
            if (previousState == null)
            {
                AddAllInputsToQueue(false);
            }
            else
            {
                // If its not the first call...

                // If a new shared design time input is added, we need to recompile everything regardless of source file modified date
                // because it could be an old file that is being promoted to a shared input
                if (inputs.SharedInputs.Except(previousState.SharedInputs, StringComparers.Paths).Any())
                {
                    AddAllInputsToQueue(true);
                }
                // If the namespace or output path inputs have changed, then we recompile every file regardless of date
                else if (configChanges.Difference.ChangedProperties.Contains(ConfigurationGeneral.RootNamespaceProperty) ||
                         configChanges.Difference.ChangedProperties.Contains(ConfigurationGeneral.ProjectDirProperty) ||
                         configChanges.Difference.ChangedProperties.Contains(ConfigurationGeneral.IntermediateOutputPathProperty))
                {
                    AddAllInputsToQueue(true);
                }
                else
                {
                    // Otherwise we just queue any new design time inputs, and still do date checks
                    foreach (string file in inputs.Inputs.Except(previousState.Inputs, StringComparers.Paths))
                    {
                        changedInputs.Add(new DesignTimeInputFileChange(file, ignoreFileWriteTime: false));
                    }
                }
            }

            string tempPEOutputPath;
            // Make sure we have the up to date output path
            string basePath = configChanges.After.Properties[ConfigurationGeneral.ProjectDirProperty];
            string objPath  = configChanges.After.Properties[ConfigurationGeneral.IntermediateOutputPathProperty];

            try
            {
                tempPEOutputPath = Path.Combine(basePath, objPath, "TempPE");
            }
            catch (ArgumentException)
            {
                // if the path is bad, then we presume we wouldn't be able to act on any files anyway
                // so we can just clear _latestDesignTimeInputs to ensure file changes aren't processed, and return.
                // If the path is ever fixed this block will trigger again and all will be right with the world.
                _currentState = null;
                return;
            }

            // This is our only update to current state, and data flow protects us from overlaps. File changes don't update state
            _currentState = new DesignTimeInputsDelta(inputs.Inputs, inputs.SharedInputs, changedInputs, tempPEOutputPath);
            PostToOutput(_currentState);

            void AddAllInputsToQueue(bool ignoreFileWriteTime)
            {
                foreach (string file in inputs.Inputs)
                {
                    changedInputs.Add(new DesignTimeInputFileChange(file, ignoreFileWriteTime));
                }
            }
        }
        private IDependencyModel GetDependencyModel(
            string itemSpec,
            bool resolved,
            IImmutableDictionary <string, string> properties,
            IProjectChangeDescription projectChange,
            HashSet <string> unresolvedChanges,
            ITargetFramework targetFramework)
        {
            PackageDependencyMetadata metadata;
            bool isTopLevel = true;
            bool isTarget   = false;

            if (resolved)
            {
                metadata   = new PackageDependencyMetadata(itemSpec, properties);
                isTopLevel = metadata.IsImplicitlyDefined ||
                             (metadata.DependencyType == DependencyType.Package &&
                              unresolvedChanges != null &&
                              unresolvedChanges.Contains(metadata.Name));
                isTarget = metadata.IsTarget;
                ITargetFramework packageTargetFramework = TargetFrameworkProvider.GetTargetFramework(metadata.Target);
                if (!(packageTargetFramework?.Equals(targetFramework) == true))
                {
                    return(null);
                }
            }
            else
            {
                metadata = CreateUnresolvedMetadata(itemSpec, properties);
            }

            if (isTarget)
            {
                return(null);
            }

            string originalItemSpec = itemSpec;

            if (resolved && isTopLevel)
            {
                originalItemSpec = metadata.Name;
            }

            IDependencyModel dependencyModel = null;

            switch (metadata.DependencyType)
            {
            case DependencyType.Package:
                dependencyModel = new PackageDependencyModel(
                    ProviderType,
                    itemSpec,
                    originalItemSpec,
                    metadata.Name,
                    DependencyTreeFlags.NuGetSubTreeNodeFlags,
                    metadata.Version,
                    resolved,
                    metadata.IsImplicitlyDefined,
                    isTopLevel,
                    !metadata.IsImplicitlyDefined /*visible*/,
                    properties,
                    metadata.DependenciesItemSpecs);
                break;

            case DependencyType.Assembly:
            case DependencyType.FrameworkAssembly:
                dependencyModel = new PackageAssemblyDependencyModel(
                    ProviderType,
                    itemSpec,
                    originalItemSpec,
                    metadata.Name,
                    DependencyTreeFlags.NuGetSubTreeNodeFlags,
                    resolved,
                    properties,
                    metadata.DependenciesItemSpecs);
                break;

            case DependencyType.AnalyzerAssembly:
                dependencyModel = new PackageAnalyzerAssemblyDependencyModel(
                    ProviderType,
                    itemSpec,
                    originalItemSpec,
                    metadata.Name,
                    DependencyTreeFlags.NuGetSubTreeNodeFlags,
                    resolved,
                    properties,
                    metadata.DependenciesItemSpecs);
                break;

            case DependencyType.Diagnostic:
                dependencyModel = new DiagnosticDependencyModel(
                    ProviderType,
                    itemSpec,
                    metadata.Severity,
                    metadata.DiagnosticCode,
                    metadata.Name,
                    DependencyTreeFlags.NuGetSubTreeNodeFlags,
                    isVisible: true,
                    properties: properties);
                break;

            default:
                dependencyModel = new PackageUnknownDependencyModel(
                    ProviderType,
                    itemSpec,
                    originalItemSpec,
                    metadata.Name,
                    DependencyTreeFlags.NuGetSubTreeNodeFlags,
                    resolved,
                    properties,
                    metadata.DependenciesItemSpecs);
                break;
            }

            return(dependencyModel);
        }
예제 #30
0
        internal static IVsProjectRestoreInfo Build(IEnumerable <IProjectVersionedValue <IProjectSubscriptionUpdate> > updates)
        {
            Requires.NotNull(updates, nameof(updates));

            // if none of the underlying subscriptions have any changes
            if (!updates.Any(u => u.Value.ProjectChanges.Any(c => c.Value.Difference.AnyChanges)))
            {
                return(null);
            }

            string msbuildProjectExtensionsPath = null;
            string originalTargetFrameworks     = null;
            var    targetFrameworks             = ImmutableDictionary.Create <string, IVsTargetFrameworkInfo>(StringComparers.ItemNames);
            var    toolReferences = ImmutableDictionary.Create <string, IVsReferenceItem>(StringComparers.ItemNames);

            foreach (IProjectVersionedValue <IProjectSubscriptionUpdate> update in updates)
            {
                IProjectChangeDescription nugetRestoreChanges = update.Value.ProjectChanges[NuGetRestore.SchemaName];
                msbuildProjectExtensionsPath = msbuildProjectExtensionsPath ??
                                               nugetRestoreChanges.After.Properties[NuGetRestore.MSBuildProjectExtensionsPathProperty];
                originalTargetFrameworks = originalTargetFrameworks ??
                                           nugetRestoreChanges.After.Properties[NuGetRestore.TargetFrameworksProperty];
                bool noTargetFramework =
                    !update.Value.ProjectConfiguration.Dimensions.TryGetValue(NuGetRestore.TargetFrameworkProperty, out string targetFramework) &&
                    !nugetRestoreChanges.After.Properties.TryGetValue(NuGetRestore.TargetFrameworkProperty, out targetFramework);

                if (noTargetFramework || string.IsNullOrEmpty(targetFramework))
                {
                    TraceUtilities.TraceWarning("Unable to find TargetFramework Property");
                    continue;
                }

                if (!targetFrameworks.ContainsKey(targetFramework))
                {
                    IProjectChangeDescription projectReferencesChanges = update.Value.ProjectChanges[ProjectReference.SchemaName];
                    IProjectChangeDescription packageReferencesChanges = update.Value.ProjectChanges[PackageReference.SchemaName];

                    targetFrameworks = targetFrameworks.Add(targetFramework, new TargetFrameworkInfo(
                                                                targetFramework,
                                                                RestoreBuilder.ToReferenceItems(projectReferencesChanges.After.Items),
                                                                RestoreBuilder.ToReferenceItems(packageReferencesChanges.After.Items),
                                                                RestoreBuilder.ToProjectProperties(nugetRestoreChanges.After.Properties)
                                                                ));
                }

                IProjectChangeDescription toolReferencesChanges = update.Value.ProjectChanges[DotNetCliToolReference.SchemaName];
                foreach (KeyValuePair <string, IImmutableDictionary <string, string> > item in toolReferencesChanges.After.Items)
                {
                    if (!toolReferences.ContainsKey(item.Key))
                    {
                        toolReferences = toolReferences.Add(item.Key, RestoreBuilder.ToReferenceItem(item.Key, item.Value));
                    }
                }
            }

            // return nominate restore information if any target framework entries are found
            return(targetFrameworks.Count > 0
                ? new ProjectRestoreInfo(
                       // NOTE: We pass MSBuildProjectExtensionsPath as BaseIntermediatePath instead of using
                       // BaseIntermediateOutputPath. This is because NuGet switched from using BaseIntermediateOutputPath
                       // to MSBuildProjectExtensionsPath, since the value of BaseIntermediateOutputPath is often set too
                       // late (after *.g.props files would need to have been imported from it). Instead of modifying the
                       // IVsProjectRestoreInfo interface or introducing something like IVsProjectRestoreInfo with an
                       // MSBuildProjectExtensionsPath property, we opted to leave the interface the same but change the
                       // meaning of its BaseIntermediatePath property. See
                       // https://github.com/dotnet/project-system/issues/3466for for details.
                       msbuildProjectExtensionsPath,
                       originalTargetFrameworks,
                       new TargetFrameworks(targetFrameworks.Values),
                       new ReferenceItems(toolReferences.Values)
                       )
                : null);
        }