Skip to content

Commit

Permalink
Adding async helpers.
Browse files Browse the repository at this point in the history
  • Loading branch information
CyrusNajmabadi committed Feb 14, 2021
1 parent fb502c2 commit 05a3950
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public VisualStudioProject CreateAndAddToWorkspace(string projectSystemName, str
w.OnProjectAdded(projectInfo);
}
_visualStudioWorkspaceImpl.RefreshProjectExistsUIContextForLanguage(language);
_visualStudioWorkspaceImpl.RefreshProjectExistsUIContextForLanguage_NoLock(language);
});

return project;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1523,6 +1523,15 @@ public void ApplyChangeToWorkspace(Action<Workspace> action)
}
}

/// <inheritdoc cref="ApplyChangeToWorkspace(Action{Workspace})"/>
public async Task ApplyChangeToWorkspaceAsync(Func<Workspace, Task> action)
{
using (await _gate.DisposableWaitAsync().ConfigureAwait(false))
{
await action(this).ConfigureAwait(false);
}
}

/// <summary>
/// Applies a solution transformation to the workspace and triggers workspace changed event for specified <paramref name="projectId"/>.
/// The transformation shall only update the project of the solution with the specified <paramref name="projectId"/>.
Expand All @@ -1547,26 +1556,43 @@ public void ApplyBatchChangeToWorkspace(Func<CodeAnalysis.Solution, SolutionChan
var oldSolution = this.CurrentSolution;
var solutionChangeAccumulator = mutation(oldSolution);

if (!solutionChangeAccumulator.HasChange)
{
return;
}
ApplyBatchChangeToWorkspaceWorker(oldSolution, solutionChangeAccumulator);
}
}

foreach (var documentId in solutionChangeAccumulator.DocumentIdsRemoved)
{
this.ClearDocumentData(documentId);
}
/// <inheritdoc cref="ApplyBatchChangeToWorkspace"/>
public async Task ApplyBatchChangeToWorkspaceAsync(Func<CodeAnalysis.Solution, Task<SolutionChangeAccumulator>> mutation)
{
using (await _gate.DisposableWaitAsync().ConfigureAwait(false))
{
var oldSolution = this.CurrentSolution;
var solutionChangeAccumulator = await mutation(oldSolution).ConfigureAwait(false);

SetCurrentSolution(solutionChangeAccumulator.Solution);
RaiseWorkspaceChangedEventAsync(
solutionChangeAccumulator.WorkspaceChangeKind,
oldSolution,
solutionChangeAccumulator.Solution,
solutionChangeAccumulator.WorkspaceChangeProjectId,
solutionChangeAccumulator.WorkspaceChangeDocumentId);
ApplyBatchChangeToWorkspaceWorker(oldSolution, solutionChangeAccumulator);
}
}

private void ApplyBatchChangeToWorkspaceWorker(CodeAnalysis.Solution oldSolution, SolutionChangeAccumulator solutionChangeAccumulator)
{
if (!solutionChangeAccumulator.HasChange)
{
return;
}

foreach (var documentId in solutionChangeAccumulator.DocumentIdsRemoved)
{
this.ClearDocumentData(documentId);
}

SetCurrentSolution(solutionChangeAccumulator.Solution);
RaiseWorkspaceChangedEventAsync(
solutionChangeAccumulator.WorkspaceChangeKind,
oldSolution,
solutionChangeAccumulator.Solution,
solutionChangeAccumulator.WorkspaceChangeProjectId,
solutionChangeAccumulator.WorkspaceChangeDocumentId);
}

private readonly Dictionary<ProjectId, ProjectReferenceInformation> _projectReferenceInfoMap = new();

private ProjectReferenceInformation GetReferenceInfo_NoLock(ProjectId projectId)
Expand Down Expand Up @@ -1618,7 +1644,7 @@ protected internal override void OnProjectRemoved(ProjectId projectId)
_threadingContext.RunWithShutdownBlockAsync(async cancellationToken =>
{
await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);
RefreshProjectExistsUIContextForLanguage(languageName);
RefreshProjectExistsUIContextForLanguage_NoLock(languageName);
});
}
}
Expand Down Expand Up @@ -1997,23 +2023,22 @@ internal void SetDependencyNodeTargetIdentifier(ProjectId projectId, string targ
}
}

internal void RefreshProjectExistsUIContextForLanguage(string language)
internal void RefreshProjectExistsUIContextForLanguage_NoLock(string language)
{
// We must assert the call is on the foreground as setting UIContext.IsActive would otherwise do a COM RPC.
_foregroundObject.AssertIsForeground();

using (_gate.DisposableWait())
{
var uiContext =
_languageToProjectExistsUIContext.GetOrAdd(
language,
l => Services.GetLanguageServices(l).GetService<IProjectExistsUIContextProviderLanguageService>()?.GetUIContext());
// This can only be called when the caller holds the gate.
Contract.ThrowIfFalse(_gate.CurrentCount == 0);
var uiContext =
_languageToProjectExistsUIContext.GetOrAdd(
language,
l => Services.GetLanguageServices(l).GetService<IProjectExistsUIContextProviderLanguageService>()?.GetUIContext());

// UIContexts can be "zombied" if UIContexts aren't supported because we're in a command line build or in other scenarios.
if (uiContext != null && !uiContext.IsZombie)
{
uiContext.IsActive = CurrentSolution.Projects.Any(p => p.Language == language);
}
// UIContexts can be "zombied" if UIContexts aren't supported because we're in a command line build or in other scenarios.
if (uiContext != null && !uiContext.IsZombie)
{
uiContext.IsActive = CurrentSolution.Projects.Any(p => p.Language == language);
}
}
}
Expand Down

0 comments on commit 05a3950

Please sign in to comment.