public void Handle(IComparable version, BuildOptions added, BuildOptions removed, bool isActiveContext)
        {
            Requires.NotNull(version, nameof(version));
            Requires.NotNull(added, nameof(added));
            Requires.NotNull(removed, nameof(removed));

            IProjectChangeDiff difference = ConvertToProjectDiff(added, removed);

            ApplyDesignTimeChanges(version, difference, isActiveContext);
        }
        private static IProjectChangeDiff ResolveConflicts(IProjectChangeDiff evaluationDifferences, IProjectChangeDiff projectBuildDifferences)
        {
            // Remove added items that were removed by later evaluations, and vice versa
            IImmutableSet <string> added   = projectBuildDifferences.AddedItems.Except(evaluationDifferences.RemovedItems);
            IImmutableSet <string> removed = projectBuildDifferences.RemovedItems.Except(evaluationDifferences.AddedItems);

            Assumes.True(projectBuildDifferences.ChangedItems.Count == 0, "We should never see ChangedItems during project builds.");

            return(new ProjectChangeDiff(added, removed, projectBuildDifferences.ChangedItems));
        }
Exemple #3
0
        private Task ProcessCommandLineAsync(IComparable version, IProjectChangeDiff differences, bool isActiveContext, CancellationToken cancellationToken)
        {
            ICommandLineParserService?parser = CommandLineParsers.FirstOrDefault()?.Value;

            Assumes.Present(parser);

            string baseDirectory = Path.GetDirectoryName(_project.UnconfiguredProject.FullPath);

            BuildOptions added   = parser !.Parse(differences.AddedItems, baseDirectory);
            BuildOptions removed = parser.Parse(differences.RemovedItems, baseDirectory);

            return(ProcessCommandLineHandlersAsync(version, added, removed, isActiveContext, cancellationToken));
        }
        public void Handle(IComparable version, BuildOptions added, BuildOptions removed, ContextState state, IProjectDiagnosticOutputService logger)
        {
            Requires.NotNull(version, nameof(version));
            Requires.NotNull(added, nameof(added));
            Requires.NotNull(removed, nameof(removed));
            Requires.NotNull(logger, nameof(logger));

            VerifyInitialized();

            IProjectChangeDiff difference = ConvertToProjectDiff(added, removed);

            ApplyProjectBuild(version, difference, state.IsActiveEditorContext, logger);
        }
        public void Handle(IComparable version, BuildOptions added, BuildOptions removed, bool isActiveContext, IProjectLogger logger)
        {
            Requires.NotNull(version, nameof(version));
            Requires.NotNull(added, nameof(added));
            Requires.NotNull(removed, nameof(removed));
            Requires.NotNull(logger, nameof(logger));

            VerifyInitialized();

            IProjectChangeDiff difference = ConvertToProjectDiff(added, removed);

            ApplyProjectBuild(version, difference, isActiveContext, logger);
        }
        public static IProjectChangeDiff NormalizeRenames(IProjectChangeDiff difference)
        {
            // Optimize for common case
            if (difference.RenamedItems.Count == 0)
                return difference;

            // Treat renamed items as just as an Add and Remove, makes finding conflicts easier
            IEnumerable<string> renamedNewNames = difference.RenamedItems.Select(r => r.Value);
            IEnumerable<string> renamedOldNames = difference.RenamedItems.Select(e => e.Key);

            IImmutableSet<string> added = difference.AddedItems.Union(renamedNewNames);
            IImmutableSet<string> removed = difference.RemovedItems.Union(renamedOldNames);

            return new ProjectChangeDiff(added, removed, difference.ChangedItems);
        }
Exemple #7
0
        /// <summary>
        ///     Applys the specified version of design-time build <see cref="IProjectChangeDiff"/> to the underlying
        ///     <see cref="IWorkspaceProjectContext"/>, indicating if the context is the currently active one.
        /// </summary>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="version"/> is <see langword="null"/>.
        ///     <para>
        ///         -or-
        ///     </para>
        ///     <paramref name="difference" /> is <see langword="null"/>.
        /// </exception>
        public void ApplyDesignTimeChanges(IComparable version, IProjectChangeDiff difference, bool isActiveContext)
        {
            Requires.NotNull(version, nameof(version));
            Requires.NotNull(difference, nameof(difference));

            if (!difference.AnyChanges)
            {
                return;
            }

            difference = NormalizeDifferences(difference);
            difference = ResolveDesignTimeConflicts(version, difference);

            ApplyChangesToContext(version, difference, ImmutableDictionary <string, IImmutableDictionary <string, string> > .Empty, isActiveContext);
        }
Exemple #8
0
        /// <summary>
        ///     Applys the specified version of evaluation <see cref="IProjectChangeDiff"/> and metadata to the underlying
        ///     <see cref="IWorkspaceProjectContext"/>, indicating if the context is the currently active one.
        /// </summary>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="version"/> is <see langword="null"/>.
        ///     <para>
        ///         -or-
        ///     </para>
        ///     <paramref name="difference" /> is <see langword="null"/>.
        ///     <para>
        ///         -or-
        ///     </para>
        ///     <paramref name="metadata" /> is <see langword="null"/>.
        /// </exception>
        public void ApplyEvaluationChanges(IComparable version, IProjectChangeDiff difference, IImmutableDictionary <string, IImmutableDictionary <string, string> > metadata, bool isActiveContext)
        {
            Requires.NotNull(version, nameof(version));
            Requires.NotNull(version, nameof(version));
            Requires.NotNull(metadata, nameof(metadata));

            if (!difference.AnyChanges)
            {
                return;
            }

            difference = NormalizeDifferences(difference);
            EnqueueEvaluation(version, difference);

            ApplyChangesToContext(version, difference, metadata, isActiveContext);
        }
        public void ApplyProjectBuild(IComparable version, IProjectChangeDiff difference, bool isActiveContext, IProjectLogger logger)
        {
            Requires.NotNull(version, nameof(version));
            Requires.NotNull(difference, nameof(difference));
            Requires.NotNull(logger, nameof(logger));

            if (!difference.AnyChanges)
            {
                return;
            }

            difference = HandlerServices.NormalizeRenames(difference);
            difference = ResolveProjectBuildConflicts(version, difference);

            ApplyChangesToContext(difference, ImmutableStringDictionary <IImmutableDictionary <string, string> > .EmptyOrdinal, isActiveContext, logger);
        }
        public void ApplyProjectEvaluation(IComparable version, IProjectChangeDiff difference, IImmutableDictionary <string, IImmutableDictionary <string, string> > metadata, bool isActiveContext, IProjectLogger logger)
        {
            Requires.NotNull(version, nameof(version));
            Requires.NotNull(difference, nameof(difference));
            Requires.NotNull(metadata, nameof(metadata));
            Requires.NotNull(logger, nameof(logger));

            if (!difference.AnyChanges)
            {
                return;
            }

            difference = HandlerServices.NormalizeRenames(difference);
            EnqueueProjectEvaluation(version, difference);

            ApplyChangesToContext(difference, metadata, isActiveContext, logger);
        }
        public async Task HandleAsync(IProjectVersionedValue <IProjectSubscriptionUpdate> e, IProjectChangeDescription projectChange)
        {
            Requires.NotNull(e, nameof(e));
            Requires.NotNull(projectChange, nameof(projectChange));

            IProjectChangeDiff diff = projectChange.Difference;

            foreach (string filePath in diff.RemovedItems)
            {
                // Item includes are always relative to csproj/vbproj
                string fullPath = _project.MakeRooted(filePath);

                RemoveSourceFile(fullPath);
            }

            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 _projectTree.TreeService.PublishTreeAsync(e.ToRequirements(), blockDuringLoadingTree : true)
                                                     .ConfigureAwait(true);                               // TODO: https://github.com/dotnet/roslyn-project-system/issues/353

                foreach (string filePath in diff.AddedItems)
                {
                    string fullPath = _project.MakeRooted(filePath);

                    AddSourceFile(fullPath, treeState);
                }

                foreach (KeyValuePair <string, string> filePaths in diff.RenamedItems)
                {
                    string beforeFullPath = _project.MakeRooted(filePaths.Key);
                    string afterFullPath  = _project.MakeRooted(filePaths.Value);

                    RemoveSourceFile(beforeFullPath);
                    AddSourceFile(afterFullPath, treeState);
                }

                foreach (string filePath in diff.ChangedItems)
                {   // We add and then remove ChangedItems to handle Linked metadata changes
                    string fullPath = _project.MakeRooted(filePath);

                    RemoveSourceFile(fullPath);
                    AddSourceFile(fullPath);
                }
            }
        }
        /// <summary>
        ///     Applies the specified version of the project evaluation <see cref="IProjectChangeDiff"/> and metadata to the underlying
        ///     <see cref="IWorkspaceProjectContext"/>, indicating if the context is the currently active one.
        /// </summary>
        /// <exception cref="ArgumentNullException">
        ///     <paramref name="version"/> is <see langword="null"/>.
        ///     <para>
        ///         -or-
        ///     </para>
        ///     <paramref name="difference" /> is <see langword="null"/>.
        ///     <para>
        ///         -or-
        ///     </para>
        ///     <paramref name="previousMetadata" /> is <see langword="null"/>.
        ///     <para>
        ///         -or-
        ///     </para>
        ///     <paramref name="currentMetadata" /> is <see langword="null"/>.
        ///     <para>
        ///         -or-
        ///     </para>
        ///     <paramref name="logger" /> is <see langword="null"/>.
        /// </exception>
        public void ApplyProjectEvaluation(IComparable version, IProjectChangeDiff difference, IImmutableDictionary <string, IImmutableDictionary <string, string> > previousMetadata, IImmutableDictionary <string, IImmutableDictionary <string, string> > currentMetadata, bool isActiveContext, IProjectLogger logger)
        {
            Requires.NotNull(version, nameof(version));
            Requires.NotNull(difference, nameof(difference));
            Requires.NotNull(previousMetadata, nameof(previousMetadata));
            Requires.NotNull(currentMetadata, nameof(currentMetadata));
            Requires.NotNull(logger, nameof(logger));

            if (!difference.AnyChanges)
            {
                return;
            }

            IImmutableDictionary <string, string> renamedItems = difference.RenamedItems;

            difference = HandlerServices.NormalizeRenames(difference);
            EnqueueProjectEvaluation(version, difference);

            ApplyChangesToContext(difference, previousMetadata, currentMetadata, renamedItems, isActiveContext, logger, evaluation: true);
        }
        private void ApplyChangesToContext(IComparable version, IProjectChangeDiff difference, IImmutableDictionary <string, IImmutableDictionary <string, string> > metadata, bool isActiveContext, IProjectLogger logger)
        {
            foreach (string includePath in difference.RemovedItems)
            {
                RemoveFromContextIfPresent(includePath, logger);
            }

            foreach (string includePath in difference.AddedItems)
            {
                AddToContextIfNotPresent(includePath, metadata, isActiveContext, logger);
            }

            // We Remove then Add changed items to pick up the Linked metadata
            foreach (string includePath in difference.ChangedItems)
            {
                RemoveFromContextIfPresent(includePath, logger);
                AddToContextIfNotPresent(includePath, metadata, isActiveContext, logger);
            }

            Assumes.True(difference.RenamedItems.Count == 0, "We should have normalized renames.");
        }
        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);
                }
            }
        }
Exemple #15
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 for active project context.
                // If we are dealing with non- active project context, then just use the latest published tree.
                IProjectTreeServiceState treeState = isActiveContext ?
                                                     await PublishTreeAsync(e).ConfigureAwait(true) : // TODO: https://github.com/dotnet/roslyn-project-system/issues/353
                                                     await _projectTree.TreeService.PublishLatestTreeAsync(blockDuringLoadingTree : true).ConfigureAwait(true);

                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);
                }
            }
        }
Exemple #16
0
        public static IProjectChangeDescription Implement(IProjectRuleSnapshot after    = null,
                                                          IProjectRuleSnapshot before   = null,
                                                          IProjectChangeDiff difference = null,
                                                          MockBehavior mockBehavior     = MockBehavior.Default)
        {
            var mock = new Mock <IProjectChangeDescription>(mockBehavior);

            if (after != null)
            {
                mock.Setup(x => x.After).Returns(after);
            }

            if (before != null)
            {
                mock.Setup(x => x.Before).Returns(before);
            }

            if (difference != null)
            {
                mock.Setup(x => x.Difference).Returns(difference);
            }

            return(mock.Object);
        }
        private static void ApplyProjectEvaluation(AbstractEvaluationCommandLineHandler handler, IComparable version, IProjectChangeDiff difference, IImmutableDictionary <string, IImmutableDictionary <string, string> > metadata = null)
        {
            metadata ??= ImmutableDictionary <string, IImmutableDictionary <string, string> > .Empty;
            bool isActiveContext = true;
            var  logger          = IProjectLoggerFactory.Create();

            handler.ApplyProjectEvaluation(version, difference, metadata, isActiveContext, logger);
        }
        private void EnqueueProjectEvaluation(IComparable version, IProjectChangeDiff evaluationDifference)
        {
            Assumes.False(_projectEvaluations.Count > 0 && version.IsEarlierThan(_projectEvaluations.Peek().Version), "Attempted to push a project evaluation that regressed in version.");

            _projectEvaluations.Enqueue(new VersionedProjectChangeDiff(version, evaluationDifference));
        }
        private IProjectChangeDiff ResolveProjectBuildConflicts(IComparable projectBuildVersion, IProjectChangeDiff projectBuildDifference)
        {
            DiscardOutOfDateProjectEvaluations(projectBuildVersion);

            // Walk all evaluations (if any) that occurred since we launched and resolve the conflicts
            foreach (VersionedProjectChangeDiff evaluation in _projectEvaluations)
            {
                Assumes.True(evaluation.Version.IsLaterThan(projectBuildVersion), "Attempted to resolve a conflict between a project build and an earlier project evaluation.");

                projectBuildDifference = ResolveConflicts(evaluation.Difference, projectBuildDifference);
            }

            return(projectBuildDifference);
        }
        private IProjectChangeDiff ResolveDesignTimeConflicts(IComparable designTimeVersion, IProjectChangeDiff designTimeDifference)
        {
            DiscardOutOfDateEvaluations(designTimeVersion);

            // Walk all evaluations (if any) that occurred since we launched and resolve the conflicts
            foreach (VersionedProjectChangeDiff evaluation in _evaluations)
            {
                Assumes.True(evaluation.Version.IsLaterThan(designTimeVersion), "Attempted to resolve a conflict between a design-time build and an earlier evaluation.");

                designTimeDifference = ResolveConflicts(evaluation.Difference, designTimeDifference);
            }

            return(designTimeDifference);
        }
        private static void ApplyProjectBuild(AbstractEvaluationCommandLineHandler handler, IComparable version, IProjectChangeDiff difference)
        {
            bool isActiveContext = true;
            var  logger          = IProjectLoggerFactory.Create();

            handler.ApplyProjectBuild(version, difference, isActiveContext, logger);
        }
 public ActualModel(IProjectRuleSnapshot after, IProjectRuleSnapshot before, IProjectChangeDiff difference)
 {
     After      = after;
     Before     = before;
     Difference = difference;
 }