Skip to content

Commit

Permalink
Merge pull request #8493 from drewnoakes/fix-1597866-no-active-workspace
Browse files Browse the repository at this point in the history
Workaround incorrect active configured project data
  • Loading branch information
drewnoakes authored Sep 16, 2022
2 parents ffc4f51 + a97769f commit 2fc22ff
Showing 1 changed file with 28 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ internal sealed class LanguageServiceHost : OnceInitializedOnceDisposedUnderLock
private readonly ILanguageServiceHostEnvironment? _languageServiceHostEnvironment;

private DisposableBag? _disposables;

/// <summary>
/// Gets the "primary" workspace. Each slice represents a single implicitly active configuration.
/// This workspace is from the slice that VS considers "active".
/// </summary>
private Workspace? _primaryWorkspace;

[ImportingConstructor]
Expand Down Expand Up @@ -146,13 +151,16 @@ protected override async Task InitializeCoreAsync(CancellationToken cancellation
async Task OnSlicesChanged(IProjectVersionedValue<(ConfiguredProject ActiveConfiguredProject, ConfigurationSubscriptionSources Sources)> update, CancellationToken cancellationToken)
{
ProjectConfiguration activeProjectConfiguration = update.Value.ActiveConfiguredProject.ProjectConfiguration;
IReadOnlyDictionary<ProjectConfigurationSlice, IActiveConfigurationSubscriptionSource> sources = update.Value.Sources;
ConfigurationSubscriptionSources sources = update.Value.Sources;

// Check off existing slices. An unseen at the end must be disposed.
var checklist = new Dictionary<ProjectConfigurationSlice, Workspace>(workspaceBySlice);

// TODO currently this loops through each slice, initializing them serially. can we do this in parallel, or can we do the active slice first?

// Remember the first slice's workspace. We may use it later, if the active workspace is removed.
Workspace? firstWorkspace = null;

foreach ((ProjectConfigurationSlice slice, IActiveConfigurationSubscriptionSource source) in sources)
{
if (!workspaceBySlice.TryGetValue(slice, out Workspace? workspace))
Expand All @@ -178,6 +186,8 @@ async Task OnSlicesChanged(IProjectVersionedValue<(ConfiguredProject ActiveConfi
Assumes.True(checklist.Remove(slice));
}

firstWorkspace ??= workspace;

workspace.IsPrimary = IsPrimaryActiveSlice(slice, activeProjectConfiguration);

if (workspace.IsPrimary)
Expand All @@ -187,19 +197,35 @@ async Task OnSlicesChanged(IProjectVersionedValue<(ConfiguredProject ActiveConfi
}
}

bool removedPrimary = false;

// Dispose workspaces for unseen slices
foreach ((_, Workspace workspace) in checklist)
{
if (ReferenceEquals(_primaryWorkspace, workspace))
{
_primaryWorkspace = null;
removedPrimary = true;
}

workspace.IsPrimary = false;

// Disposes asynchronously on the thread pool, without awaiting completion.
workspace.Dispose();
}

if (removedPrimary)
{
// We removed the primary workspace

// If we have a new primary workspace, use it.
if (firstWorkspace is not null)
{
firstWorkspace.IsPrimary = true;
}

// Set the new primary workspace (or theoretically null if no slices exist).
_primaryWorkspace = firstWorkspace;
}
}

static bool IsPrimaryActiveSlice(ProjectConfigurationSlice slice, ProjectConfiguration activeProjectConfiguration)
Expand Down

0 comments on commit 2fc22ff

Please sign in to comment.