-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #34564 from jasonmalinowski/raise-precise-workspac…
…e-changes Be smarter for how we raise WorkspaceChange events when completing batches
- Loading branch information
Showing
7 changed files
with
330 additions
and
33 deletions.
There are no files selected for viewing
106 changes: 106 additions & 0 deletions
106
src/VisualStudio/Core/Def/Implementation/ProjectSystem/SolutionChangeAccumulator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. | ||
|
||
using System.Collections.Generic; | ||
using Microsoft.CodeAnalysis; | ||
|
||
namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem | ||
{ | ||
/// <summary> | ||
/// A little helper type to hold onto the <see cref="Solution"/> being updated in a batch, which also | ||
/// keeps track of the right <see cref="CodeAnalysis.WorkspaceChangeKind"/> to raise when we are done. | ||
/// </summary> | ||
internal class SolutionChangeAccumulator | ||
{ | ||
/// <summary> | ||
/// The kind that encompasses all the changes we've made. It's null if no changes have been made, | ||
/// and <see cref="WorkspaceChangeKind.ProjectChanged"/> or | ||
/// <see cref="WorkspaceChangeKind.SolutionChanged"/> if we can't give a more precise type. | ||
/// </summary> | ||
private WorkspaceChangeKind? _workspaceChangeKind; | ||
|
||
public SolutionChangeAccumulator(Solution startingSolution) | ||
{ | ||
Solution = startingSolution; | ||
} | ||
|
||
public Solution Solution { get; private set; } | ||
|
||
public bool HasChange => _workspaceChangeKind.HasValue; | ||
public WorkspaceChangeKind WorkspaceChangeKind => _workspaceChangeKind.Value; | ||
|
||
public ProjectId WorkspaceChangeProjectId { get; private set; } | ||
public DocumentId WorkspaceChangeDocumentId { get; private set; } | ||
|
||
public void UpdateSolutionForDocumentAction(Solution newSolution, WorkspaceChangeKind changeKind, IEnumerable<DocumentId> documentIds) | ||
{ | ||
// If the newSolution is the same as the current solution, there's nothing to actually do | ||
if (Solution == newSolution) | ||
{ | ||
return; | ||
} | ||
|
||
Solution = newSolution; | ||
|
||
foreach (var documentId in documentIds) | ||
{ | ||
// If we don't previously have change, this is our new change | ||
if (!_workspaceChangeKind.HasValue) | ||
{ | ||
_workspaceChangeKind = changeKind; | ||
WorkspaceChangeProjectId = documentId.ProjectId; | ||
WorkspaceChangeDocumentId = documentId; | ||
} | ||
else | ||
{ | ||
// We do have a new change. At this point, the change is spanning multiple documents or projects we | ||
// will coalesce accordingly | ||
if (documentId.ProjectId == WorkspaceChangeProjectId) | ||
{ | ||
// It's the same project, at least, so project change it is | ||
_workspaceChangeKind = WorkspaceChangeKind.ProjectChanged; | ||
WorkspaceChangeDocumentId = null; | ||
} | ||
else | ||
{ | ||
// Multiple projects have changed, so it's a generic solution change. At this point | ||
// we can bail from the loop, because this is already our most general case. | ||
_workspaceChangeKind = WorkspaceChangeKind.SolutionChanged; | ||
WorkspaceChangeProjectId = null; | ||
WorkspaceChangeDocumentId = null; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Should be called to update the solution if there isn't a specific document change kind that should be | ||
/// given to <see cref="UpdateSolutionForDocumentAction"/> | ||
/// </summary> | ||
public void UpdateSolutionForProjectAction(ProjectId projectId, Solution newSolution) | ||
{ | ||
// If the newSolution is the same as the current solution, there's nothing to actually do | ||
if (Solution == newSolution) | ||
{ | ||
return; | ||
} | ||
|
||
Solution = newSolution; | ||
|
||
// Since we're changing a project, we definitely have no DocumentId anymore | ||
WorkspaceChangeDocumentId = null; | ||
|
||
if (!_workspaceChangeKind.HasValue || WorkspaceChangeProjectId == projectId) | ||
{ | ||
// We can count this as a generic project change | ||
_workspaceChangeKind = WorkspaceChangeKind.ProjectChanged; | ||
WorkspaceChangeProjectId = projectId; | ||
} | ||
else | ||
{ | ||
_workspaceChangeKind = WorkspaceChangeKind.SolutionChanged; | ||
WorkspaceChangeProjectId = null; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.