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)); }
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); }
/// <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); }
/// <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); } } }
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); } } }
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; }