Update ProjectWorkspaceState and HostProject at the same time (#11191)

Preparation for ongoing work to hook up the Roslyn tokenizer and
https://github.com/dotnet/razor/issues/11182 I suppose.

There were three places that `UpdateProjectWorkspaceState` was called:

1. In `RazorProjectService`, just before calling
`UpdateProjectConfiguration`
2. In `ProjectWorkspaceStateGenerator`, where we will need to add a call
to `UpdateProjectConfiguration` in future, to wire up the tokenizer
3. In our LiveShare bits, in response to events from the above.

Previous attempts to plumb through more things for `RazorConfiguration`
resulted in RPS failures, that appeared to be simply more compilations
of closed files. This makes sense because we were adding another update,
which would have triggered another set of `ProjectChanged` events. I
thought it would make more sense to combine these two updates together,
so no matter which part of the project was being updated, there could be
a single `ProjectChanged` notification. This is that.
This commit is contained in:
David Wengier 2024-11-12 13:43:48 +11:00 коммит произвёл GitHub
Родитель f3aa64757d b36e8925b0
Коммит 95f862d12e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
25 изменённых файлов: 128 добавлений и 313 удалений

Просмотреть файл

@ -76,7 +76,7 @@ public class RazorLanguageServerBenchmarkBase : ProjectSnapshotManagerBenchmarkB
updater.ProjectAdded(hostProject); updater.ProjectAdded(hostProject);
var tagHelpers = CommonResources.LegacyTagHelpers; var tagHelpers = CommonResources.LegacyTagHelpers;
var projectWorkspaceState = ProjectWorkspaceState.Create(tagHelpers, CodeAnalysis.CSharp.LanguageVersion.CSharp11); var projectWorkspaceState = ProjectWorkspaceState.Create(tagHelpers, CodeAnalysis.CSharp.LanguageVersion.CSharp11);
updater.ProjectWorkspaceStateChanged(hostProject.Key, projectWorkspaceState); updater.ProjectChanged(hostProject, projectWorkspaceState);
updater.DocumentAdded(hostProject.Key, hostDocument, textLoader); updater.DocumentAdded(hostProject.Key, hostDocument, textLoader);
}, },
CancellationToken.None); CancellationToken.None);

Просмотреть файл

@ -369,34 +369,21 @@ internal partial class RazorProjectService : IRazorProjectService, IRazorProject
_logger.LogInformation($"Updating project '{project.Key}' TagHelpers ({projectWorkspaceState.TagHelpers.Length}) and C# Language Version ({projectWorkspaceState.CSharpLanguageVersion})."); _logger.LogInformation($"Updating project '{project.Key}' TagHelpers ({projectWorkspaceState.TagHelpers.Length}) and C# Language Version ({projectWorkspaceState.CSharpLanguageVersion}).");
} }
updater.ProjectWorkspaceStateChanged(project.Key, projectWorkspaceState);
var currentConfiguration = project.Configuration; var currentConfiguration = project.Configuration;
var currentRootNamespace = project.RootNamespace; var currentRootNamespace = project.RootNamespace;
if (currentConfiguration.ConfigurationName == configuration?.ConfigurationName &&
currentRootNamespace == rootNamespace)
{
_logger.LogTrace($"Updating project '{project.Key}'. The project is already using configuration '{configuration.ConfigurationName}' and root namespace '{rootNamespace}'.");
return;
}
if (configuration is null) if (configuration is null)
{ {
configuration = FallbackRazorConfiguration.Latest; configuration = FallbackRazorConfiguration.Latest;
_logger.LogInformation($"Updating project '{project.Key}' to use the latest configuration ('{configuration.ConfigurationName}')'."); _logger.LogInformation($"Updating project '{project.Key}' to use the latest configuration ('{configuration.ConfigurationName}')'.");
} }
else if (currentConfiguration.ConfigurationName != configuration.ConfigurationName) else if (currentConfiguration == configuration &&
currentRootNamespace == rootNamespace)
{ {
_logger.LogInformation($"Updating project '{project.Key}' to Razor configuration '{configuration.ConfigurationName}' with language version '{configuration.LanguageVersion}'."); _logger.LogTrace($"Updating project '{project.Key}'. The project is already using configuration '{configuration.ConfigurationName}' and root namespace '{rootNamespace}'.");
}
if (currentRootNamespace != rootNamespace)
{
_logger.LogInformation($"Updating project '{project.Key}''s root namespace to '{rootNamespace}'.");
} }
var hostProject = new HostProject(project.FilePath, project.IntermediateOutputPath, configuration, rootNamespace, displayName); var hostProject = new HostProject(project.FilePath, project.IntermediateOutputPath, configuration, rootNamespace, displayName);
updater.ProjectConfigurationChanged(hostProject); updater.ProjectChanged(hostProject, projectWorkspaceState);
}, },
cancellationToken); cancellationToken);
} }

Просмотреть файл

@ -150,15 +150,6 @@ internal partial class DocumentState
return false; return false;
} }
public virtual DocumentState WithConfigurationChange()
{
var state = new DocumentState(HostDocument, Version + 1, _textAndVersion, _textLoader);
// Do not cache computed state
return state;
}
public virtual DocumentState WithImportsChange() public virtual DocumentState WithImportsChange()
{ {
var state = new DocumentState(HostDocument, Version + 1, _textAndVersion, _textLoader); var state = new DocumentState(HostDocument, Version + 1, _textAndVersion, _textLoader);
@ -169,7 +160,7 @@ internal partial class DocumentState
return state; return state;
} }
public virtual DocumentState WithProjectWorkspaceStateChange() public virtual DocumentState WithProjectChange()
{ {
var state = new DocumentState(HostDocument, Version + 1, _textAndVersion, _textLoader); var state = new DocumentState(HostDocument, Version + 1, _textAndVersion, _textLoader);

Просмотреть файл

@ -1,17 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.
using System;
namespace Microsoft.CodeAnalysis.Razor.ProjectSystem;
[Flags]
internal enum ProjectDifference
{
None = 0,
ConfigurationChanged = 1,
ProjectWorkspaceStateChanged = 2,
DocumentAdded = 4,
DocumentRemoved = 8,
DocumentChanged = 16,
}

Просмотреть файл

@ -50,11 +50,8 @@ internal partial class ProjectSnapshotManager
public void ProjectRemoved(ProjectKey projectKey) public void ProjectRemoved(ProjectKey projectKey)
=> instance.ProjectRemoved(projectKey); => instance.ProjectRemoved(projectKey);
public void ProjectConfigurationChanged(HostProject project) public void ProjectChanged(HostProject project, ProjectWorkspaceState projectWorkspaceState)
=> instance.ProjectConfigurationChanged(project); => instance.ProjectChanged(project, projectWorkspaceState);
public void ProjectWorkspaceStateChanged(ProjectKey projectKey, ProjectWorkspaceState projectWorkspaceState)
=> instance.ProjectWorkspaceStateChanged(projectKey, projectWorkspaceState);
public void SolutionOpened() public void SolutionOpened()
=> instance.SolutionOpened(); => instance.SolutionOpened();

Просмотреть файл

@ -306,7 +306,7 @@ internal partial class ProjectSnapshotManager : IProjectSnapshotManager, IDispos
} }
} }
private void ProjectConfigurationChanged(HostProject hostProject) private void ProjectChanged(HostProject hostProject, ProjectWorkspaceState projectWorkspaceState)
{ {
if (_initialized) if (_initialized)
{ {
@ -316,25 +316,7 @@ internal partial class ProjectSnapshotManager : IProjectSnapshotManager, IDispos
if (TryUpdate( if (TryUpdate(
hostProject.Key, hostProject.Key,
documentFilePath: null, documentFilePath: null,
new HostProjectUpdatedAction(hostProject), new ProjectChangeAction(hostProject, projectWorkspaceState),
out var oldSnapshot,
out var newSnapshot))
{
NotifyListeners(oldSnapshot, newSnapshot, documentFilePath: null, ProjectChangeKind.ProjectChanged);
}
}
private void ProjectWorkspaceStateChanged(ProjectKey projectKey, ProjectWorkspaceState projectWorkspaceState)
{
if (_initialized)
{
_dispatcher.AssertRunningOnDispatcher();
}
if (TryUpdate(
projectKey,
documentFilePath: null,
new ProjectWorkspaceStateChangedAction(projectWorkspaceState),
out var oldSnapshot, out var oldSnapshot,
out var newSnapshot)) out var newSnapshot))
{ {
@ -591,11 +573,8 @@ internal partial class ProjectSnapshotManager : IProjectSnapshotManager, IDispos
} }
} }
case ProjectWorkspaceStateChangedAction(var workspaceState): case ProjectChangeAction(var hostProject, var workspaceState):
return new Entry(originalEntry.State.WithProjectWorkspaceState(workspaceState)); return new Entry(originalEntry.State.WithHostProjectAndWorkspaceState(hostProject, workspaceState));
case HostProjectUpdatedAction(var hostProject):
return new Entry(originalEntry.State.WithHostProject(hostProject));
default: default:
throw new InvalidOperationException($"Unexpected action type {action.GetType()}"); throw new InvalidOperationException($"Unexpected action type {action.GetType()}");

Просмотреть файл

@ -1,7 +1,6 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information. // Licensed under the MIT license. See License.txt in the project root for license information.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.IO; using System.IO;
@ -21,17 +20,6 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem;
// Internal tracker for DefaultProjectSnapshot // Internal tracker for DefaultProjectSnapshot
internal class ProjectState internal class ProjectState
{ {
private const ProjectDifference ClearConfigurationVersionMask = ProjectDifference.ConfigurationChanged;
private const ProjectDifference ClearProjectWorkspaceStateVersionMask =
ProjectDifference.ConfigurationChanged |
ProjectDifference.ProjectWorkspaceStateChanged;
private const ProjectDifference ClearDocumentCollectionVersionMask =
ProjectDifference.ConfigurationChanged |
ProjectDifference.DocumentAdded |
ProjectDifference.DocumentRemoved;
private static readonly ImmutableDictionary<string, DocumentState> s_emptyDocuments = ImmutableDictionary.Create<string, DocumentState>(FilePathNormalizingComparer.Instance); private static readonly ImmutableDictionary<string, DocumentState> s_emptyDocuments = ImmutableDictionary.Create<string, DocumentState>(FilePathNormalizingComparer.Instance);
private static readonly ImmutableDictionary<string, ImmutableArray<string>> s_emptyImportsToRelatedDocuments = ImmutableDictionary.Create<string, ImmutableArray<string>>(FilePathNormalizingComparer.Instance); private static readonly ImmutableDictionary<string, ImmutableArray<string>> s_emptyImportsToRelatedDocuments = ImmutableDictionary.Create<string, ImmutableArray<string>>(FilePathNormalizingComparer.Instance);
private readonly object _lock; private readonly object _lock;
@ -70,7 +58,7 @@ internal class ProjectState
private ProjectState( private ProjectState(
ProjectState older, ProjectState older,
ProjectDifference difference, bool numberOfDocumentsMayHaveChanged,
HostProject hostProject, HostProject hostProject,
ProjectWorkspaceState projectWorkspaceState, ProjectWorkspaceState projectWorkspaceState,
ImmutableDictionary<string, DocumentState> documents, ImmutableDictionary<string, DocumentState> documents,
@ -87,17 +75,19 @@ internal class ProjectState
_lock = new object(); _lock = new object();
if ((difference & ClearDocumentCollectionVersionMask) == 0) if (numberOfDocumentsMayHaveChanged)
{
DocumentCollectionVersion = Version;
}
else
{ {
// Document collection hasn't changed // Document collection hasn't changed
DocumentCollectionVersion = older.DocumentCollectionVersion; DocumentCollectionVersion = older.DocumentCollectionVersion;
} }
else
{
DocumentCollectionVersion = Version;
}
if ((difference & ClearConfigurationVersionMask) == 0 && older._projectEngine != null) if (older._projectEngine != null &&
HostProject.Configuration == older.HostProject.Configuration &&
CSharpLanguageVersion == older.CSharpLanguageVersion)
{ {
// Optimistically cache the RazorProjectEngine. // Optimistically cache the RazorProjectEngine.
_projectEngine = older.ProjectEngine; _projectEngine = older.ProjectEngine;
@ -108,9 +98,7 @@ internal class ProjectState
ConfigurationVersion = Version; ConfigurationVersion = Version;
} }
if ((difference & ClearProjectWorkspaceStateVersionMask) == 0 || if (ProjectWorkspaceState.Equals(older.ProjectWorkspaceState))
ProjectWorkspaceState == older.ProjectWorkspaceState ||
ProjectWorkspaceState.Equals(older.ProjectWorkspaceState))
{ {
ProjectWorkspaceStateVersion = older.ProjectWorkspaceStateVersion; ProjectWorkspaceStateVersion = older.ProjectWorkspaceStateVersion;
} }
@ -118,14 +106,6 @@ internal class ProjectState
{ {
ProjectWorkspaceStateVersion = Version; ProjectWorkspaceStateVersion = Version;
} }
if ((difference & ClearProjectWorkspaceStateVersionMask) != 0 &&
CSharpLanguageVersion != older.CSharpLanguageVersion)
{
// C# language version changed. This impacts the ProjectEngine, reset it.
_projectEngine = null;
ConfigurationVersion = Version;
}
} }
// Internal set for testing. // Internal set for testing.
@ -196,16 +176,6 @@ internal class ProjectState
public ProjectState WithAddedHostDocument(HostDocument hostDocument, TextLoader loader) public ProjectState WithAddedHostDocument(HostDocument hostDocument, TextLoader loader)
{ {
if (hostDocument is null)
{
throw new ArgumentNullException(nameof(hostDocument));
}
if (loader is null)
{
throw new ArgumentNullException(nameof(loader));
}
// Ignore attempts to 'add' a document with different data, we only // Ignore attempts to 'add' a document with different data, we only
// care about one, so it might as well be the one we have. // care about one, so it might as well be the one we have.
if (Documents.ContainsKey(hostDocument.FilePath)) if (Documents.ContainsKey(hostDocument.FilePath))
@ -229,17 +199,12 @@ internal class ProjectState
} }
} }
var state = new ProjectState(this, ProjectDifference.DocumentAdded, HostProject, ProjectWorkspaceState, documents, importsToRelatedDocuments); var state = new ProjectState(this, numberOfDocumentsMayHaveChanged: true, HostProject, ProjectWorkspaceState, documents, importsToRelatedDocuments);
return state; return state;
} }
public ProjectState WithRemovedHostDocument(HostDocument hostDocument) public ProjectState WithRemovedHostDocument(HostDocument hostDocument)
{ {
if (hostDocument is null)
{
throw new ArgumentNullException(nameof(hostDocument));
}
if (!Documents.ContainsKey(hostDocument.FilePath)) if (!Documents.ContainsKey(hostDocument.FilePath))
{ {
return this; return this;
@ -261,17 +226,12 @@ internal class ProjectState
var importTargetPaths = GetImportDocumentTargetPaths(hostDocument); var importTargetPaths = GetImportDocumentTargetPaths(hostDocument);
var importsToRelatedDocuments = RemoveFromImportsToRelatedDocuments(ImportsToRelatedDocuments, hostDocument, importTargetPaths); var importsToRelatedDocuments = RemoveFromImportsToRelatedDocuments(ImportsToRelatedDocuments, hostDocument, importTargetPaths);
var state = new ProjectState(this, ProjectDifference.DocumentRemoved, HostProject, ProjectWorkspaceState, documents, importsToRelatedDocuments); var state = new ProjectState(this, numberOfDocumentsMayHaveChanged: true, HostProject, ProjectWorkspaceState, documents, importsToRelatedDocuments);
return state; return state;
} }
public ProjectState WithChangedHostDocument(HostDocument hostDocument, SourceText sourceText, VersionStamp textVersion) public ProjectState WithChangedHostDocument(HostDocument hostDocument, SourceText sourceText, VersionStamp textVersion)
{ {
if (hostDocument is null)
{
throw new ArgumentNullException(nameof(hostDocument));
}
if (!Documents.TryGetValue(hostDocument.FilePath, out var document)) if (!Documents.TryGetValue(hostDocument.FilePath, out var document))
{ {
return this; return this;
@ -287,17 +247,12 @@ internal class ProjectState
} }
} }
var state = new ProjectState(this, ProjectDifference.DocumentChanged, HostProject, ProjectWorkspaceState, documents, ImportsToRelatedDocuments); var state = new ProjectState(this, numberOfDocumentsMayHaveChanged: false, HostProject, ProjectWorkspaceState, documents, ImportsToRelatedDocuments);
return state; return state;
} }
public ProjectState WithChangedHostDocument(HostDocument hostDocument, TextLoader loader) public ProjectState WithChangedHostDocument(HostDocument hostDocument, TextLoader loader)
{ {
if (hostDocument is null)
{
throw new ArgumentNullException(nameof(hostDocument));
}
if (!Documents.TryGetValue(hostDocument.FilePath, out var document)) if (!Documents.TryGetValue(hostDocument.FilePath, out var document))
{ {
return this; return this;
@ -313,24 +268,20 @@ internal class ProjectState
} }
} }
var state = new ProjectState(this, ProjectDifference.DocumentChanged, HostProject, ProjectWorkspaceState, documents, ImportsToRelatedDocuments); var state = new ProjectState(this, numberOfDocumentsMayHaveChanged: false, HostProject, ProjectWorkspaceState, documents, ImportsToRelatedDocuments);
return state; return state;
} }
public ProjectState WithHostProject(HostProject hostProject) public ProjectState WithHostProjectAndWorkspaceState(HostProject hostProject, ProjectWorkspaceState projectWorkspaceState)
{ {
if (hostProject is null)
{
throw new ArgumentNullException(nameof(hostProject));
}
if (HostProject.Configuration.Equals(hostProject.Configuration) && if (HostProject.Configuration.Equals(hostProject.Configuration) &&
HostProject.RootNamespace == hostProject.RootNamespace) HostProject.RootNamespace == hostProject.RootNamespace &&
ProjectWorkspaceState.Equals(projectWorkspaceState))
{ {
return this; return this;
} }
var documents = Documents.ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.WithConfigurationChange(), FilePathNormalizingComparer.Instance); var documents = Documents.ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.WithProjectChange(), FilePathNormalizingComparer.Instance);
// If the host project has changed then we need to recompute the imports map // If the host project has changed then we need to recompute the imports map
var importsToRelatedDocuments = s_emptyImportsToRelatedDocuments; var importsToRelatedDocuments = s_emptyImportsToRelatedDocuments;
@ -341,25 +292,7 @@ internal class ProjectState
importsToRelatedDocuments = AddToImportsToRelatedDocuments(importsToRelatedDocuments, document.Value.HostDocument.FilePath, importTargetPaths); importsToRelatedDocuments = AddToImportsToRelatedDocuments(importsToRelatedDocuments, document.Value.HostDocument.FilePath, importTargetPaths);
} }
var state = new ProjectState(this, ProjectDifference.ConfigurationChanged, hostProject, ProjectWorkspaceState, documents, importsToRelatedDocuments); var state = new ProjectState(this, numberOfDocumentsMayHaveChanged: true, hostProject, projectWorkspaceState, documents, importsToRelatedDocuments);
return state;
}
public ProjectState WithProjectWorkspaceState(ProjectWorkspaceState projectWorkspaceState)
{
if (ProjectWorkspaceState == projectWorkspaceState)
{
return this;
}
if (ProjectWorkspaceState.Equals(projectWorkspaceState))
{
return this;
}
var difference = ProjectDifference.ProjectWorkspaceStateChanged;
var documents = Documents.ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.WithProjectWorkspaceStateChange(), FilePathNormalizingComparer.Instance);
var state = new ProjectState(this, difference, HostProject, projectWorkspaceState, documents, ImportsToRelatedDocuments);
return state; return state;
} }
@ -372,7 +305,7 @@ internal class ProjectState
{ {
if (!importsToRelatedDocuments.TryGetValue(importTargetPath, out var relatedDocuments)) if (!importsToRelatedDocuments.TryGetValue(importTargetPath, out var relatedDocuments))
{ {
relatedDocuments = ImmutableArray.Create<string>(); relatedDocuments = [];
} }
relatedDocuments = relatedDocuments.Add(documentFilePath); relatedDocuments = relatedDocuments.Add(documentFilePath);

Просмотреть файл

@ -30,6 +30,4 @@ internal record ProjectAddedAction(HostProject HostProject) : IUpdateProjectActi
internal record ProjectRemovedAction(ProjectKey ProjectKey) : IUpdateProjectAction; internal record ProjectRemovedAction(ProjectKey ProjectKey) : IUpdateProjectAction;
internal record HostProjectUpdatedAction(HostProject HostProject) : IUpdateProjectAction; internal record ProjectChangeAction(HostProject HostProject, ProjectWorkspaceState WorkspaceState) : IUpdateProjectAction;
internal record ProjectWorkspaceStateChangedAction(ProjectWorkspaceState WorkspaceState) : IUpdateProjectAction;

Просмотреть файл

@ -85,7 +85,7 @@ internal class ProjectSnapshotSynchronizationService(
if (state.projectWorkspaceState != null) if (state.projectWorkspaceState != null)
{ {
updater.ProjectWorkspaceStateChanged(state.hostProject.Key, state.projectWorkspaceState); updater.ProjectChanged(state.hostProject, state.projectWorkspaceState);
} }
}, },
state: (hostProject, projectWorkspaceState: args.Newer.ProjectWorkspaceState), state: (hostProject, projectWorkspaceState: args.Newer.ProjectWorkspaceState),
@ -108,31 +108,16 @@ internal class ProjectSnapshotSynchronizationService(
} }
else if (args.Kind == ProjectProxyChangeKind.ProjectChanged) else if (args.Kind == ProjectProxyChangeKind.ProjectChanged)
{ {
if (!args.Older!.Configuration.Equals(args.Newer!.Configuration)) if (!args.Older!.Configuration.Equals(args.Newer!.Configuration) ||
!args.Older.ProjectWorkspaceState.Equals(args.Newer.ProjectWorkspaceState))
{ {
var guestPath = ResolveGuestPath(args.Newer.FilePath); var guestPath = ResolveGuestPath(args.Newer.FilePath);
var guestIntermediateOutputPath = ResolveGuestPath(args.Newer.IntermediateOutputPath); var guestIntermediateOutputPath = ResolveGuestPath(args.Newer.IntermediateOutputPath);
var hostProject = new HostProject(guestPath, guestIntermediateOutputPath, args.Newer.Configuration, args.Newer.RootNamespace); var hostProject = new HostProject(guestPath, guestIntermediateOutputPath, args.Newer.Configuration, args.Newer.RootNamespace);
var projectWorkspaceState = args.Newer.ProjectWorkspaceState;
await _projectManager.UpdateAsync( await _projectManager.UpdateAsync(
static (updater, hostProject) => updater.ProjectConfigurationChanged(hostProject), static (updater, state) => updater.ProjectChanged(state.hostProject, state.projectWorkspaceState),
state: hostProject, state: (hostProject, projectWorkspaceState),
CancellationToken.None);
}
else if (args.Older.ProjectWorkspaceState != args.Newer.ProjectWorkspaceState ||
args.Older.ProjectWorkspaceState?.Equals(args.Newer.ProjectWorkspaceState) == false)
{
var guestPath = ResolveGuestPath(args.Newer.FilePath);
await _projectManager.UpdateAsync(
static (updater, state) =>
{
var projectKeys = updater.GetAllProjectKeys(state.guestPath);
foreach (var projectKey in projectKeys)
{
updater.ProjectWorkspaceStateChanged(projectKey, state.projectWorkspaceState);
}
},
state: (guestPath, projectWorkspaceState: args.Newer.ProjectWorkspaceState),
CancellationToken.None); CancellationToken.None);
} }
} }
@ -152,7 +137,7 @@ internal class ProjectSnapshotSynchronizationService(
if (state.projectWorkspaceState is not null) if (state.projectWorkspaceState is not null)
{ {
updater.ProjectWorkspaceStateChanged(state.hostProject.Key, state.projectWorkspaceState); updater.ProjectChanged(state.hostProject, state.projectWorkspaceState);
} }
}, },
state: (hostProject, projectWorkspaceState: projectHandle.ProjectWorkspaceState), state: (hostProject, projectWorkspaceState: projectHandle.ProjectWorkspaceState),

Просмотреть файл

@ -265,7 +265,7 @@ internal abstract partial class WindowsRazorProjectHostBase : OnceInitializedOnc
protected static void UpdateProject(ProjectSnapshotManager.Updater updater, HostProject project) protected static void UpdateProject(ProjectSnapshotManager.Updater updater, HostProject project)
{ {
if (!updater.TryGetLoadedProject(project.Key, out _)) if (!updater.TryGetLoadedProject(project.Key, out var current))
{ {
// Just in case we somehow got in a state where VS didn't tell us that solution close was finished, lets just // Just in case we somehow got in a state where VS didn't tell us that solution close was finished, lets just
// ensure we're going to actually do something with the new project that we've just been told about. // ensure we're going to actually do something with the new project that we've just been told about.
@ -275,7 +275,7 @@ internal abstract partial class WindowsRazorProjectHostBase : OnceInitializedOnc
} }
else else
{ {
updater.ProjectConfigurationChanged(project); updater.ProjectChanged(project, current.ProjectWorkspaceState);
} }
} }

Просмотреть файл

@ -157,17 +157,18 @@ internal sealed partial class ProjectWorkspaceStateGenerator(
.UpdateAsync( .UpdateAsync(
static (updater, state) => static (updater, state) =>
{ {
var (projectKey, workspaceState, logger, cancellationToken) = state; var (projectSnapshot, workspaceState, logger, cancellationToken) = state;
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
{ {
return; return;
} }
logger.LogTrace($"Updating project with {workspaceState.TagHelpers.Length} tag helper(s) for '{projectKey}'"); logger.LogTrace($"Updating project with {workspaceState.TagHelpers.Length} tag helper(s) for '{projectSnapshot.Key}'");
updater.ProjectWorkspaceStateChanged(projectKey, workspaceState); var hostProject = new HostProject(projectSnapshot.FilePath, projectSnapshot.IntermediateOutputPath, projectSnapshot.Configuration, projectSnapshot.RootNamespace);
updater.ProjectChanged(hostProject, workspaceState);
}, },
state: (projectKey, workspaceState, _logger, cancellationToken), state: (projectSnapshot, workspaceState, _logger, cancellationToken),
cancellationToken) cancellationToken)
.ConfigureAwait(false); .ConfigureAwait(false);
} }

Просмотреть файл

@ -135,7 +135,7 @@ public class CodeDocumentReferenceHolderTest(ITestOutputHelper testOutput) : Lan
// Act // Act
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectConfigurationChanged(s_hostProject with { Configuration = RazorConfiguration.Default, RootNamespace = "NewRootNamespace" }); updater.ProjectChanged(s_hostProject with { Configuration = RazorConfiguration.Default, RootNamespace = "NewRootNamespace" }, documentSnapshot.Project.ProjectWorkspaceState);
}); });
PerformFullGC(); PerformFullGC();

Просмотреть файл

@ -46,7 +46,7 @@ public class TextDocumentUriPresentationEndpointTests(ITestOutputHelper testOutp
await projectManager.UpdateAsync(updater => await projectManager.UpdateAsync(updater =>
{ {
updater.ProjectWorkspaceStateChanged(hostProject.Key, ProjectWorkspaceState.Create([builder.Build()])); updater.ProjectChanged(hostProject, ProjectWorkspaceState.Create([builder.Build()]));
}); });
var uri = new Uri(hostDocument1.FilePath); var uri = new Uri(hostDocument1.FilePath);
@ -106,7 +106,7 @@ public class TextDocumentUriPresentationEndpointTests(ITestOutputHelper testOutp
await projectManager.UpdateAsync(updater => await projectManager.UpdateAsync(updater =>
{ {
updater.ProjectWorkspaceStateChanged(hostProject.Key, ProjectWorkspaceState.Create([builder.Build()])); updater.ProjectChanged(hostProject, ProjectWorkspaceState.Create([builder.Build()]));
}); });
var uri = new Uri(hostDocument1.FilePath); var uri = new Uri(hostDocument1.FilePath);
@ -177,7 +177,7 @@ public class TextDocumentUriPresentationEndpointTests(ITestOutputHelper testOutp
await projectManager.UpdateAsync(updater => await projectManager.UpdateAsync(updater =>
{ {
updater.ProjectWorkspaceStateChanged(hostProject.Key, ProjectWorkspaceState.Create([builder.Build()])); updater.ProjectChanged(hostProject, ProjectWorkspaceState.Create([builder.Build()]));
}); });
var uri = new Uri(hostDocument1.FilePath); var uri = new Uri(hostDocument1.FilePath);
@ -332,7 +332,7 @@ public class TextDocumentUriPresentationEndpointTests(ITestOutputHelper testOutp
await projectManager.UpdateAsync(updater => await projectManager.UpdateAsync(updater =>
{ {
updater.ProjectWorkspaceStateChanged(hostProject.Key, ProjectWorkspaceState.Create([builder.Build()])); updater.ProjectChanged(hostProject, ProjectWorkspaceState.Create([builder.Build()]));
}); });
var uri = new Uri(hostDocument1.FilePath); var uri = new Uri(hostDocument1.FilePath);

Просмотреть файл

@ -142,8 +142,7 @@ public class OpenDocumentGeneratorTest(ITestOutputHelper testOutput) : LanguageS
updater.DocumentAdded(_hostProject1.Key, _documents[0], _documents[0].CreateEmptyTextLoader()); updater.DocumentAdded(_hostProject1.Key, _documents[0], _documents[0].CreateEmptyTextLoader());
// Act // Act
updater.ProjectWorkspaceStateChanged(_hostProject1.Key, updater.ProjectChanged(_hostProject1, ProjectWorkspaceState.Create(LanguageVersion.CSharp8));
ProjectWorkspaceState.Create(LanguageVersion.CSharp8));
}); });
// Assert // Assert
@ -166,8 +165,7 @@ public class OpenDocumentGeneratorTest(ITestOutputHelper testOutput) : LanguageS
updater.DocumentOpened(_hostProject1.Key, _documents[0].FilePath, SourceText.From(string.Empty)); updater.DocumentOpened(_hostProject1.Key, _documents[0].FilePath, SourceText.From(string.Empty));
// Act // Act
updater.ProjectWorkspaceStateChanged(_hostProject1.Key, updater.ProjectChanged(_hostProject1, ProjectWorkspaceState.Create(LanguageVersion.CSharp8));
ProjectWorkspaceState.Create(LanguageVersion.CSharp8));
}); });
// Assert // Assert

Просмотреть файл

@ -656,10 +656,11 @@ public class RenameEndpointTest(ITestOutputHelper testOutput) : LanguageServerTe
var projectKey1 = await projectService.GetTestAccessor().AddProjectAsync( var projectKey1 = await projectService.GetTestAccessor().AddProjectAsync(
s_projectFilePath1, s_intermediateOutputPath1, RazorConfiguration.Default, RootNamespace1, displayName: null, DisposalToken); s_projectFilePath1, s_intermediateOutputPath1, RazorConfiguration.Default, RootNamespace1, displayName: null, DisposalToken);
var hostProject1 = new HostProject(s_indexFilePath1, s_intermediateOutputPath1, RazorConfiguration.Default, RootNamespace1, displayName: null);
await projectManager.UpdateAsync(updater => await projectManager.UpdateAsync(updater =>
{ {
updater.ProjectWorkspaceStateChanged(projectKey1, ProjectWorkspaceState.Create(tagHelpers)); updater.ProjectChanged(hostProject1, ProjectWorkspaceState.Create(tagHelpers));
}); });
await projectService.AddDocumentToPotentialProjectsAsync(s_componentFilePath1, DisposalToken); await projectService.AddDocumentToPotentialProjectsAsync(s_componentFilePath1, DisposalToken);
@ -678,10 +679,11 @@ public class RenameEndpointTest(ITestOutputHelper testOutput) : LanguageServerTe
var projectKey2 = await projectService.GetTestAccessor().AddProjectAsync( var projectKey2 = await projectService.GetTestAccessor().AddProjectAsync(
s_projectFilePath2, s_intermediateOutputPath2, RazorConfiguration.Default, RootNamespace2, displayName: null, DisposalToken); s_projectFilePath2, s_intermediateOutputPath2, RazorConfiguration.Default, RootNamespace2, displayName: null, DisposalToken);
var hostProject2 = new HostProject(s_projectFilePath2, s_intermediateOutputPath2, RazorConfiguration.Default, RootNamespace2, displayName: null);
await projectManager.UpdateAsync(updater => await projectManager.UpdateAsync(updater =>
{ {
updater.ProjectWorkspaceStateChanged(projectKey2, ProjectWorkspaceState.Create(tagHelpers)); updater.ProjectChanged(hostProject2, ProjectWorkspaceState.Create(tagHelpers));
}); });
await projectService.AddDocumentToPotentialProjectsAsync(s_componentFilePath3, DisposalToken); await projectService.AddDocumentToPotentialProjectsAsync(s_componentFilePath3, DisposalToken);

Просмотреть файл

@ -63,14 +63,14 @@ public class DocumentStateTest : ToolingTestBase
} }
[Fact] [Fact]
public void DocumentState_WithConfigurationChange_CachesSnapshotText() public void DocumentState_WithProjectChange_CachesSnapshotText()
{ {
// Arrange // Arrange
var original = DocumentState.Create(_hostDocument, DocumentState.EmptyLoader) var original = DocumentState.Create(_hostDocument, DocumentState.EmptyLoader)
.WithText(_text, VersionStamp.Create()); .WithText(_text, VersionStamp.Create());
// Act // Act
var state = original.WithConfigurationChange(); var state = original.WithProjectChange();
// Assert // Assert
Assert.True(state.TryGetText(out _)); Assert.True(state.TryGetText(out _));
@ -78,7 +78,7 @@ public class DocumentStateTest : ToolingTestBase
} }
[Fact] [Fact]
public async Task DocumentState_WithConfigurationChange_CachesLoadedText() public async Task DocumentState_WithProjectChange_CachesLoadedText()
{ {
// Arrange // Arrange
var original = DocumentState.Create(_hostDocument, DocumentState.EmptyLoader) var original = DocumentState.Create(_hostDocument, DocumentState.EmptyLoader)
@ -87,7 +87,7 @@ public class DocumentStateTest : ToolingTestBase
await original.GetTextAsync(DisposalToken); await original.GetTextAsync(DisposalToken);
// Act // Act
var state = original.WithConfigurationChange(); var state = original.WithProjectChange();
// Assert // Assert
Assert.True(state.TryGetText(out _)); Assert.True(state.TryGetText(out _));
@ -125,36 +125,4 @@ public class DocumentStateTest : ToolingTestBase
Assert.True(state.TryGetText(out _)); Assert.True(state.TryGetText(out _));
Assert.True(state.TryGetTextVersion(out _)); Assert.True(state.TryGetTextVersion(out _));
} }
[Fact]
public void DocumentState_WithProjectWorkspaceStateChange_CachesSnapshotText()
{
// Arrange
var original = DocumentState.Create(_hostDocument, DocumentState.EmptyLoader)
.WithText(_text, VersionStamp.Create());
// Act
var state = original.WithProjectWorkspaceStateChange();
// Assert
Assert.True(state.TryGetText(out _));
Assert.True(state.TryGetTextVersion(out _));
}
[Fact]
public async Task DocumentState_WithProjectWorkspaceStateChange_CachesLoadedText()
{
// Arrange
var original = DocumentState.Create(_hostDocument, DocumentState.EmptyLoader)
.WithTextLoader(_textLoader);
await original.GetTextAsync(DisposalToken);
// Act
var state = original.WithProjectWorkspaceStateChange();
// Assert
Assert.True(state.TryGetText(out _));
Assert.True(state.TryGetTextVersion(out _));
}
} }

Просмотреть файл

@ -154,7 +154,7 @@ public class ProjectStateGeneratedOutputTest : WorkspaceTestBase
var changed = ProjectWorkspaceState.Default; var changed = ProjectWorkspaceState.Default;
// Act // Act
var state = original.WithProjectWorkspaceState(changed); var state = original.WithHostProjectAndWorkspaceState(original.HostProject, changed);
// Assert // Assert
var (actualOutput, actualInputVersion) = await GetOutputAsync(state, _hostDocument, DisposalToken); var (actualOutput, actualInputVersion) = await GetOutputAsync(state, _hostDocument, DisposalToken);
@ -175,7 +175,7 @@ public class ProjectStateGeneratedOutputTest : WorkspaceTestBase
var changed = ProjectWorkspaceState.Create(_someTagHelpers); var changed = ProjectWorkspaceState.Create(_someTagHelpers);
// Act // Act
var state = original.WithProjectWorkspaceState(changed); var state = original.WithHostProjectAndWorkspaceState(original.HostProject, changed);
// Assert // Assert
var (actualOutput, actualInputVersion) = await GetOutputAsync(state, _hostDocument, DisposalToken); var (actualOutput, actualInputVersion) = await GetOutputAsync(state, _hostDocument, DisposalToken);
@ -199,7 +199,7 @@ public class ProjectStateGeneratedOutputTest : WorkspaceTestBase
var (originalOutput, originalInputVersion) = await GetOutputAsync(original, _hostDocument, DisposalToken); var (originalOutput, originalInputVersion) = await GetOutputAsync(original, _hostDocument, DisposalToken);
// Act // Act
var state = original.WithProjectWorkspaceState(changedWorkspaceState); var state = original.WithHostProjectAndWorkspaceState(original.HostProject, changedWorkspaceState);
// Assert // Assert
var (actualOutput, actualInputVersion) = await GetOutputAsync(state, _hostDocument, DisposalToken); var (actualOutput, actualInputVersion) = await GetOutputAsync(state, _hostDocument, DisposalToken);
@ -219,7 +219,7 @@ public class ProjectStateGeneratedOutputTest : WorkspaceTestBase
var (originalOutput, originalInputVersion) = await GetOutputAsync(original, _hostDocument, DisposalToken); var (originalOutput, originalInputVersion) = await GetOutputAsync(original, _hostDocument, DisposalToken);
// Act // Act
var state = original.WithHostProject(_hostProjectWithConfigurationChange); var state = original.WithHostProjectAndWorkspaceState(_hostProjectWithConfigurationChange, original.ProjectWorkspaceState);
// Assert // Assert
var (actualOutput, actualInputVersion) = await GetOutputAsync(state, _hostDocument, DisposalToken); var (actualOutput, actualInputVersion) = await GetOutputAsync(state, _hostDocument, DisposalToken);

Просмотреть файл

@ -529,7 +529,7 @@ public class ProjectStateTest : WorkspaceTestBase
} }
[Fact] [Fact]
public void ProjectState_WithHostProject_ConfigurationChange_UpdatesConfigurationState() public void ProjectState_WithHostProjectAndWorkspaceState_ConfigurationChange_UpdatesConfigurationState()
{ {
// Arrange // Arrange
var original = ProjectState.Create(ProjectEngineFactoryProvider, LanguageServerFeatureOptions, _hostProject, _projectWorkspaceState) var original = ProjectState.Create(ProjectEngineFactoryProvider, LanguageServerFeatureOptions, _hostProject, _projectWorkspaceState)
@ -541,7 +541,7 @@ public class ProjectStateTest : WorkspaceTestBase
var originalProjectWorkspaceStateVersion = original.ConfigurationVersion; var originalProjectWorkspaceStateVersion = original.ConfigurationVersion;
// Act // Act
var state = original.WithHostProject(_hostProjectWithConfigurationChange); var state = original.WithHostProjectAndWorkspaceState(_hostProjectWithConfigurationChange, _projectWorkspaceState);
// Assert // Assert
Assert.NotEqual(original.Version, state.Version); Assert.NotEqual(original.Version, state.Version);
@ -567,7 +567,7 @@ public class ProjectStateTest : WorkspaceTestBase
} }
[Fact] [Fact]
public void ProjectState_WithHostProject_RootNamespaceChange_UpdatesConfigurationState() public void ProjectState_WithHostProjectAndWorkspaceState_RootNamespaceChange_UpdatesConfigurationState()
{ {
// Arrange // Arrange
var original = ProjectState.Create(ProjectEngineFactoryProvider, LanguageServerFeatureOptions, _hostProject, _projectWorkspaceState) var original = ProjectState.Create(ProjectEngineFactoryProvider, LanguageServerFeatureOptions, _hostProject, _projectWorkspaceState)
@ -580,14 +580,14 @@ public class ProjectStateTest : WorkspaceTestBase
_ = original.ConfigurationVersion; _ = original.ConfigurationVersion;
// Act // Act
var state = original.WithHostProject(hostProjectWithRootNamespaceChange); var state = original.WithHostProjectAndWorkspaceState(hostProjectWithRootNamespaceChange, _projectWorkspaceState);
// Assert // Assert
Assert.NotSame(original, state); Assert.NotSame(original, state);
} }
[Fact] [Fact]
public void ProjectState_WithHostProject_NoConfigurationChange_Noops() public void ProjectState_WithHostProjectAndWorkspaceState_NoConfigurationChange_Noops()
{ {
// Arrange // Arrange
var original = ProjectState.Create(ProjectEngineFactoryProvider, LanguageServerFeatureOptions, _hostProject, _projectWorkspaceState) var original = ProjectState.Create(ProjectEngineFactoryProvider, LanguageServerFeatureOptions, _hostProject, _projectWorkspaceState)
@ -598,14 +598,14 @@ public class ProjectStateTest : WorkspaceTestBase
_ = original.ProjectWorkspaceStateVersion; _ = original.ProjectWorkspaceStateVersion;
// Act // Act
var state = original.WithHostProject(_hostProject); var state = original.WithHostProjectAndWorkspaceState(_hostProject, _projectWorkspaceState);
// Assert // Assert
Assert.Same(original, state); Assert.Same(original, state);
} }
[Fact] [Fact]
public void ProjectState_WithHostProject_CallsConfigurationChangeOnDocumentState() public void ProjectState_WithHostProjectAndWorkspaceState_CallsConfigurationChangeOnDocumentState()
{ {
// Arrange // Arrange
var callCount = 0; var callCount = 0;
@ -618,7 +618,7 @@ public class ProjectStateTest : WorkspaceTestBase
original.Documents = documents.ToImmutable(); original.Documents = documents.ToImmutable();
// Act // Act
var state = original.WithHostProject(_hostProjectWithConfigurationChange); var state = original.WithHostProjectAndWorkspaceState(_hostProjectWithConfigurationChange, _projectWorkspaceState);
// Assert // Assert
Assert.NotEqual(original.Version, state.Version); Assert.NotEqual(original.Version, state.Version);
@ -627,14 +627,14 @@ public class ProjectStateTest : WorkspaceTestBase
} }
[Fact] [Fact]
public void ProjectState_WithHostProject_ResetsImportedDocuments() public void ProjectState_WithHostProjectAndWorkspaceState_ResetsImportedDocuments()
{ {
// Arrange // Arrange
var original = ProjectState.Create(ProjectEngineFactoryProvider, LanguageServerFeatureOptions, _hostProject, _projectWorkspaceState); var original = ProjectState.Create(ProjectEngineFactoryProvider, LanguageServerFeatureOptions, _hostProject, _projectWorkspaceState);
original = original.WithAddedHostDocument(TestProjectData.SomeProjectFile1, DocumentState.EmptyLoader); original = original.WithAddedHostDocument(TestProjectData.SomeProjectFile1, DocumentState.EmptyLoader);
// Act // Act
var state = original.WithHostProject(_hostProjectWithConfigurationChange); var state = original.WithHostProjectAndWorkspaceState(_hostProjectWithConfigurationChange, _projectWorkspaceState);
// Assert // Assert
var importMap = Assert.Single(state.ImportsToRelatedDocuments); var importMap = Assert.Single(state.ImportsToRelatedDocuments);
@ -643,7 +643,7 @@ public class ProjectStateTest : WorkspaceTestBase
} }
[Fact] [Fact]
public void ProjectState_WithProjectWorkspaceState_Changed() public void ProjectState_WithHostProjectAndWorkspaceState_Changed()
{ {
// Arrange // Arrange
var original = ProjectState.Create(ProjectEngineFactoryProvider, LanguageServerFeatureOptions, _hostProject, _projectWorkspaceState) var original = ProjectState.Create(ProjectEngineFactoryProvider, LanguageServerFeatureOptions, _hostProject, _projectWorkspaceState)
@ -657,7 +657,7 @@ public class ProjectStateTest : WorkspaceTestBase
var changed = ProjectWorkspaceState.Create(_projectWorkspaceState.TagHelpers, LanguageVersion.CSharp6); var changed = ProjectWorkspaceState.Create(_projectWorkspaceState.TagHelpers, LanguageVersion.CSharp6);
// Act // Act
var state = original.WithProjectWorkspaceState(changed); var state = original.WithHostProjectAndWorkspaceState(_hostProject, changed);
// Assert // Assert
Assert.NotEqual(original.Version, state.Version); Assert.NotEqual(original.Version, state.Version);
@ -682,7 +682,7 @@ public class ProjectStateTest : WorkspaceTestBase
} }
[Fact] [Fact]
public void ProjectState_WithProjectWorkspaceState_Changed_TagHelpersChanged() public void ProjectState_WithHostProjectAndWorkspaceState_Changed_TagHelpersChanged()
{ {
// Arrange // Arrange
var original = ProjectState.Create(ProjectEngineFactoryProvider, LanguageServerFeatureOptions, _hostProject, _projectWorkspaceState) var original = ProjectState.Create(ProjectEngineFactoryProvider, LanguageServerFeatureOptions, _hostProject, _projectWorkspaceState)
@ -696,7 +696,7 @@ public class ProjectStateTest : WorkspaceTestBase
var changed = ProjectWorkspaceState.Default; var changed = ProjectWorkspaceState.Default;
// Act // Act
var state = original.WithProjectWorkspaceState(changed); var state = original.WithHostProjectAndWorkspaceState(_hostProject, changed);
// Assert // Assert
Assert.NotEqual(original.Version, state.Version); Assert.NotEqual(original.Version, state.Version);
@ -716,7 +716,7 @@ public class ProjectStateTest : WorkspaceTestBase
} }
[Fact] [Fact]
public void ProjectState_WithProjectWorkspaceState_IdenticalState_Caches() public void ProjectState_WithHostProjectAndWorkspaceState_IdenticalState_Caches()
{ {
// Arrange // Arrange
var original = ProjectState.Create(ProjectEngineFactoryProvider, LanguageServerFeatureOptions, _hostProject, _projectWorkspaceState) var original = ProjectState.Create(ProjectEngineFactoryProvider, LanguageServerFeatureOptions, _hostProject, _projectWorkspaceState)
@ -730,21 +730,21 @@ public class ProjectStateTest : WorkspaceTestBase
var changed = ProjectWorkspaceState.Create(original.TagHelpers, original.CSharpLanguageVersion); var changed = ProjectWorkspaceState.Create(original.TagHelpers, original.CSharpLanguageVersion);
// Act // Act
var state = original.WithProjectWorkspaceState(changed); var state = original.WithHostProjectAndWorkspaceState(_hostProject, changed);
// Assert // Assert
Assert.Same(original, state); Assert.Same(original, state);
} }
[Fact] [Fact]
public void ProjectState_WithProjectWorkspaceState_CallsWorkspaceProjectChangeOnDocumentState() public void ProjectState_WithHostProjectAndWorkspaceState_CallsWorkspaceProjectChangeOnDocumentState()
{ {
// Arrange // Arrange
var callCount = 0; var callCount = 0;
var documents = ImmutableDictionary.CreateBuilder<string, DocumentState>(FilePathComparer.Instance); var documents = ImmutableDictionary.CreateBuilder<string, DocumentState>(FilePathComparer.Instance);
documents[_documents[1].FilePath] = TestDocumentState.Create(_documents[1], onProjectWorkspaceStateChange: () => callCount++); documents[_documents[1].FilePath] = TestDocumentState.Create(_documents[1], onConfigurationChange: () => callCount++);
documents[_documents[2].FilePath] = TestDocumentState.Create(_documents[2], onProjectWorkspaceStateChange: () => callCount++); documents[_documents[2].FilePath] = TestDocumentState.Create(_documents[2], onConfigurationChange: () => callCount++);
var original = ProjectState.Create(ProjectEngineFactoryProvider, LanguageServerFeatureOptions, _hostProject, _projectWorkspaceState); var original = ProjectState.Create(ProjectEngineFactoryProvider, LanguageServerFeatureOptions, _hostProject, _projectWorkspaceState);
original.Documents = documents.ToImmutable(); original.Documents = documents.ToImmutable();
@ -752,7 +752,7 @@ public class ProjectStateTest : WorkspaceTestBase
var changed = ProjectWorkspaceState.Default; var changed = ProjectWorkspaceState.Default;
// Act // Act
var state = original.WithProjectWorkspaceState(changed); var state = original.WithHostProjectAndWorkspaceState(_hostProject, changed);
// Assert // Assert
Assert.NotEqual(original.Version, state.Version); Assert.NotEqual(original.Version, state.Version);
@ -991,8 +991,7 @@ public class ProjectStateTest : WorkspaceTestBase
Action? onTextChange = null, Action? onTextChange = null,
Action? onTextLoaderChange = null, Action? onTextLoaderChange = null,
Action? onConfigurationChange = null, Action? onConfigurationChange = null,
Action? onImportsChange = null, Action? onImportsChange = null)
Action? onProjectWorkspaceStateChange = null)
{ {
return new TestDocumentState( return new TestDocumentState(
hostDocument, hostDocument,
@ -1000,15 +999,13 @@ public class ProjectStateTest : WorkspaceTestBase
onTextChange, onTextChange,
onTextLoaderChange, onTextLoaderChange,
onConfigurationChange, onConfigurationChange,
onImportsChange, onImportsChange);
onProjectWorkspaceStateChange);
} }
private readonly Action? _onTextChange; private readonly Action? _onTextChange;
private readonly Action? _onTextLoaderChange; private readonly Action? _onTextLoaderChange;
private readonly Action? _onConfigurationChange; private readonly Action? _onConfigurationChange;
private readonly Action? _onImportsChange; private readonly Action? _onImportsChange;
private readonly Action? _onProjectWorkspaceStateChange;
private TestDocumentState( private TestDocumentState(
HostDocument hostDocument, HostDocument hostDocument,
@ -1016,15 +1013,13 @@ public class ProjectStateTest : WorkspaceTestBase
Action? onTextChange, Action? onTextChange,
Action? onTextLoaderChange, Action? onTextLoaderChange,
Action? onConfigurationChange, Action? onConfigurationChange,
Action? onImportsChange, Action? onImportsChange)
Action? onProjectWorkspaceStateChange)
: base(hostDocument, version: 1, loader ?? EmptyLoader) : base(hostDocument, version: 1, loader ?? EmptyLoader)
{ {
_onTextChange = onTextChange; _onTextChange = onTextChange;
_onTextLoaderChange = onTextLoaderChange; _onTextLoaderChange = onTextLoaderChange;
_onConfigurationChange = onConfigurationChange; _onConfigurationChange = onConfigurationChange;
_onImportsChange = onImportsChange; _onImportsChange = onImportsChange;
_onProjectWorkspaceStateChange = onProjectWorkspaceStateChange;
} }
public override DocumentState WithText(SourceText sourceText, VersionStamp textVersion) public override DocumentState WithText(SourceText sourceText, VersionStamp textVersion)
@ -1039,10 +1034,10 @@ public class ProjectStateTest : WorkspaceTestBase
return base.WithTextLoader(loader); return base.WithTextLoader(loader);
} }
public override DocumentState WithConfigurationChange() public override DocumentState WithProjectChange()
{ {
_onConfigurationChange?.Invoke(); _onConfigurationChange?.Invoke();
return base.WithConfigurationChange(); return base.WithProjectChange();
} }
public override DocumentState WithImportsChange() public override DocumentState WithImportsChange()
@ -1050,11 +1045,5 @@ public class ProjectStateTest : WorkspaceTestBase
_onImportsChange?.Invoke(); _onImportsChange?.Invoke();
return base.WithImportsChange(); return base.WithImportsChange();
} }
public override DocumentState WithProjectWorkspaceStateChange()
{
_onProjectWorkspaceStateChange?.Invoke();
return base.WithProjectWorkspaceStateChange();
}
} }
} }

Просмотреть файл

@ -56,7 +56,7 @@ public class ProjectAvailabilityTests(ITestOutputHelper testOutput) : ToolingTes
await projectManager.UpdateAsync(updater => await projectManager.UpdateAsync(updater =>
{ {
updater.ProjectAdded(hostProject); updater.ProjectAdded(hostProject);
updater.ProjectWorkspaceStateChanged(hostProject.Key, projectWorkspaceState); updater.ProjectChanged(hostProject, projectWorkspaceState);
updater.DocumentAdded(hostProject.Key, hostDocument, TestMocks.CreateTextLoader(hostDocument.FilePath, text: "")); updater.DocumentAdded(hostProject.Key, hostDocument, TestMocks.CreateTextLoader(hostDocument.FilePath, text: ""));
}); });
@ -101,11 +101,11 @@ public class ProjectAvailabilityTests(ITestOutputHelper testOutput) : ToolingTes
await projectManager.UpdateAsync(updater => await projectManager.UpdateAsync(updater =>
{ {
updater.ProjectAdded(hostProject1); updater.ProjectAdded(hostProject1);
updater.ProjectWorkspaceStateChanged(hostProject1.Key, projectWorkspaceState); updater.ProjectChanged(hostProject1, projectWorkspaceState);
updater.DocumentAdded(hostProject1.Key, hostDocument, TestMocks.CreateTextLoader(hostDocument.FilePath, text: "")); updater.DocumentAdded(hostProject1.Key, hostDocument, TestMocks.CreateTextLoader(hostDocument.FilePath, text: ""));
updater.ProjectAdded(hostProject2); updater.ProjectAdded(hostProject2);
updater.ProjectWorkspaceStateChanged(hostProject2.Key, projectWorkspaceState); updater.ProjectChanged(hostProject2, projectWorkspaceState);
updater.DocumentAdded(hostProject2.Key, hostDocument, TestMocks.CreateTextLoader(hostDocument.FilePath, text: "")); updater.DocumentAdded(hostProject2.Key, hostDocument, TestMocks.CreateTextLoader(hostDocument.FilePath, text: ""));
}); });
@ -150,7 +150,7 @@ public class ProjectAvailabilityTests(ITestOutputHelper testOutput) : ToolingTes
await projectManager.UpdateAsync(updater => await projectManager.UpdateAsync(updater =>
{ {
updater.ProjectAdded(hostProject1); updater.ProjectAdded(hostProject1);
updater.ProjectWorkspaceStateChanged(hostProject1.Key, projectWorkspaceState); updater.ProjectChanged(hostProject1, projectWorkspaceState);
updater.DocumentAdded(hostProject1.Key, hostDocument, TestMocks.CreateTextLoader(hostDocument.FilePath, text: "")); updater.DocumentAdded(hostProject1.Key, hostDocument, TestMocks.CreateTextLoader(hostDocument.FilePath, text: ""));
updater.ProjectAdded(hostProject2); updater.ProjectAdded(hostProject2);

Просмотреть файл

@ -170,7 +170,7 @@ public class ProjectSnapshotSynchronizationServiceTest : VisualStudioWorkspaceTe
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectAdded(hostProject); updater.ProjectAdded(hostProject);
updater.ProjectConfigurationChanged(hostProject); updater.ProjectChanged(hostProject, newHandle.ProjectWorkspaceState);
}); });
var args = new ProjectChangeEventProxyArgs(oldHandle, newHandle, ProjectProxyChangeKind.ProjectChanged); var args = new ProjectChangeEventProxyArgs(oldHandle, newHandle, ProjectProxyChangeKind.ProjectChanged);
@ -214,7 +214,7 @@ public class ProjectSnapshotSynchronizationServiceTest : VisualStudioWorkspaceTe
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectAdded(hostProject); updater.ProjectAdded(hostProject);
updater.ProjectWorkspaceStateChanged(hostProject.Key, oldHandle.ProjectWorkspaceState); updater.ProjectChanged(hostProject, oldHandle.ProjectWorkspaceState);
}); });
var args = new ProjectChangeEventProxyArgs(oldHandle, newHandle, ProjectProxyChangeKind.ProjectChanged); var args = new ProjectChangeEventProxyArgs(oldHandle, newHandle, ProjectProxyChangeKind.ProjectChanged);

Просмотреть файл

@ -44,10 +44,10 @@ public class ProjectSnapshotManagerProxyTest(ITestOutputHelper testOutput) : Vis
await projectManager.UpdateAsync(updater => await projectManager.UpdateAsync(updater =>
{ {
updater.ProjectAdded(_hostProject1); updater.ProjectAdded(_hostProject1);
updater.ProjectWorkspaceStateChanged(_hostProject1.Key, _projectWorkspaceState1); updater.ProjectChanged(_hostProject1, _projectWorkspaceState1);
updater.ProjectAdded(_hostProject2); updater.ProjectAdded(_hostProject2);
updater.ProjectWorkspaceStateChanged(_hostProject2.Key, _projectWorkspaceState2); updater.ProjectChanged(_hostProject2, _projectWorkspaceState2);
}); });
using var proxy = new ProjectSnapshotManagerProxy( using var proxy = new ProjectSnapshotManagerProxy(
@ -77,7 +77,7 @@ public class ProjectSnapshotManagerProxyTest(ITestOutputHelper testOutput) : Vis
await projectManager.UpdateAsync(updater => await projectManager.UpdateAsync(updater =>
{ {
updater.ProjectAdded(_hostProject1); updater.ProjectAdded(_hostProject1);
updater.ProjectWorkspaceStateChanged(_hostProject1.Key, _projectWorkspaceState1); updater.ProjectChanged(_hostProject1, _projectWorkspaceState1);
}); });
using var proxy = new ProjectSnapshotManagerProxy( using var proxy = new ProjectSnapshotManagerProxy(
@ -102,12 +102,13 @@ public class ProjectSnapshotManagerProxyTest(ITestOutputHelper testOutput) : Vis
{ {
// Change the project's configuration to force a changed event to be raised. // Change the project's configuration to force a changed event to be raised.
var project = updater.GetLoadedProject(_hostProject1.Key); var project = updater.GetLoadedProject(_hostProject1.Key);
updater.ProjectConfigurationChanged(new( updater.ProjectChanged(new(
project.FilePath, project.FilePath,
project.IntermediateOutputPath, project.IntermediateOutputPath,
FallbackRazorConfiguration.MVC_1_0, FallbackRazorConfiguration.MVC_1_0,
project.RootNamespace, project.RootNamespace,
project.DisplayName)); project.DisplayName),
_projectWorkspaceState1);
}); });
await proxyAccessor.ProcessingChangedEventTestTask.AssumeNotNull().JoinAsync(); await proxyAccessor.ProcessingChangedEventTestTask.AssumeNotNull().JoinAsync();
@ -125,7 +126,7 @@ public class ProjectSnapshotManagerProxyTest(ITestOutputHelper testOutput) : Vis
await projectManager.UpdateAsync(updater => await projectManager.UpdateAsync(updater =>
{ {
updater.ProjectAdded(_hostProject1); updater.ProjectAdded(_hostProject1);
updater.ProjectWorkspaceStateChanged(_hostProject1.Key, _projectWorkspaceState1); updater.ProjectChanged(_hostProject1, _projectWorkspaceState1);
}); });
var proxy = new ProjectSnapshotManagerProxy( var proxy = new ProjectSnapshotManagerProxy(
@ -143,12 +144,13 @@ public class ProjectSnapshotManagerProxyTest(ITestOutputHelper testOutput) : Vis
{ {
// Change the project's configuration to force a changed event to be raised. // Change the project's configuration to force a changed event to be raised.
var project = updater.GetLoadedProject(_hostProject1.Key); var project = updater.GetLoadedProject(_hostProject1.Key);
updater.ProjectConfigurationChanged(new( updater.ProjectChanged(new(
project.FilePath, project.FilePath,
project.IntermediateOutputPath, project.IntermediateOutputPath,
FallbackRazorConfiguration.MVC_1_0, FallbackRazorConfiguration.MVC_1_0,
project.RootNamespace, project.RootNamespace,
project.DisplayName)); project.DisplayName),
_projectWorkspaceState1);
}); });
// Assert // Assert
@ -164,7 +166,7 @@ public class ProjectSnapshotManagerProxyTest(ITestOutputHelper testOutput) : Vis
await projectManager.UpdateAsync(updater => await projectManager.UpdateAsync(updater =>
{ {
updater.ProjectAdded(_hostProject1); updater.ProjectAdded(_hostProject1);
updater.ProjectWorkspaceStateChanged(_hostProject1.Key, _projectWorkspaceState1); updater.ProjectChanged(_hostProject1, _projectWorkspaceState1);
}); });
using var proxy = new ProjectSnapshotManagerProxy( using var proxy = new ProjectSnapshotManagerProxy(
@ -196,10 +198,10 @@ public class ProjectSnapshotManagerProxyTest(ITestOutputHelper testOutput) : Vis
await projectManager.UpdateAsync(updater => await projectManager.UpdateAsync(updater =>
{ {
updater.ProjectAdded(_hostProject1); updater.ProjectAdded(_hostProject1);
updater.ProjectWorkspaceStateChanged(_hostProject1.Key, _projectWorkspaceState1); updater.ProjectChanged(_hostProject1, _projectWorkspaceState1);
updater.ProjectAdded(_hostProject2); updater.ProjectAdded(_hostProject2);
updater.ProjectWorkspaceStateChanged(_hostProject2.Key, _projectWorkspaceState2); updater.ProjectChanged(_hostProject2, _projectWorkspaceState2);
}); });
using var proxy = new ProjectSnapshotManagerProxy( using var proxy = new ProjectSnapshotManagerProxy(
@ -229,7 +231,7 @@ public class ProjectSnapshotManagerProxyTest(ITestOutputHelper testOutput) : Vis
await projectManager.UpdateAsync(updater => await projectManager.UpdateAsync(updater =>
{ {
updater.ProjectAdded(_hostProject1); updater.ProjectAdded(_hostProject1);
updater.ProjectWorkspaceStateChanged(_hostProject1.Key, _projectWorkspaceState1); updater.ProjectChanged(_hostProject1, _projectWorkspaceState1);
}); });
using var proxy = new ProjectSnapshotManagerProxy( using var proxy = new ProjectSnapshotManagerProxy(

Просмотреть файл

@ -5,6 +5,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language;
using Microsoft.AspNetCore.Razor.ProjectSystem;
using Microsoft.AspNetCore.Razor.Telemetry; using Microsoft.AspNetCore.Razor.Telemetry;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem; using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common.VisualStudio; using Microsoft.AspNetCore.Razor.Test.Common.VisualStudio;
@ -142,7 +143,7 @@ public class FallbackProjectManagerTest : VisualStudioWorkspaceTestBase
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectConfigurationChanged(hostProject); updater.ProjectChanged(hostProject, ProjectWorkspaceState.Default);
}); });
project = Assert.Single(_projectManager.GetProjects()); project = Assert.Single(_projectManager.GetProjects());

Просмотреть файл

@ -268,7 +268,7 @@ public class ProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectAdded(s_hostProject); updater.ProjectAdded(s_hostProject);
updater.ProjectWorkspaceStateChanged(s_hostProject.Key, _projectWorkspaceStateWithTagHelpers); updater.ProjectChanged(s_hostProject, _projectWorkspaceStateWithTagHelpers);
}); });
var originalTagHelpers = await _projectManager.GetLoadedProject(s_hostProject.Key).GetTagHelpersAsync(DisposalToken); var originalTagHelpers = await _projectManager.GetLoadedProject(s_hostProject.Key).GetTagHelpersAsync(DisposalToken);
@ -390,7 +390,7 @@ public class ProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectAdded(s_hostProject); updater.ProjectAdded(s_hostProject);
updater.ProjectWorkspaceStateChanged(s_hostProject.Key, _projectWorkspaceStateWithTagHelpers); updater.ProjectChanged(s_hostProject, _projectWorkspaceStateWithTagHelpers);
updater.DocumentAdded(s_hostProject.Key, s_documents[0], s_documents[0].CreateEmptyTextLoader()); updater.DocumentAdded(s_hostProject.Key, s_documents[0], s_documents[0].CreateEmptyTextLoader());
updater.DocumentAdded(s_hostProject.Key, s_documents[1], s_documents[1].CreateEmptyTextLoader()); updater.DocumentAdded(s_hostProject.Key, s_documents[1], s_documents[1].CreateEmptyTextLoader());
updater.DocumentAdded(s_hostProject.Key, s_documents[2], s_documents[2].CreateEmptyTextLoader()); updater.DocumentAdded(s_hostProject.Key, s_documents[2], s_documents[2].CreateEmptyTextLoader());
@ -640,7 +640,7 @@ public class ProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
// Act // Act
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectConfigurationChanged(s_hostProjectWithConfigurationChange); updater.ProjectChanged(s_hostProjectWithConfigurationChange, ProjectWorkspaceState.Default);
}); });
// Assert // Assert
@ -655,7 +655,7 @@ public class ProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectAdded(s_hostProject); updater.ProjectAdded(s_hostProject);
updater.ProjectWorkspaceStateChanged(s_hostProject.Key, _projectWorkspaceStateWithTagHelpers); updater.ProjectChanged(s_hostProject, _projectWorkspaceStateWithTagHelpers);
}); });
using var listener = _projectManager.ListenToNotifications(); using var listener = _projectManager.ListenToNotifications();
@ -663,7 +663,7 @@ public class ProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
// Act // Act
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectConfigurationChanged(s_hostProjectWithConfigurationChange); updater.ProjectChanged(s_hostProjectWithConfigurationChange, _projectWorkspaceStateWithTagHelpers);
}); });
// Assert // Assert
@ -686,7 +686,7 @@ public class ProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
// Act // Act
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectConfigurationChanged(s_hostProjectWithConfigurationChange); updater.ProjectChanged(s_hostProjectWithConfigurationChange, ProjectWorkspaceState.Default);
}); });
// Assert // Assert
@ -703,7 +703,7 @@ public class ProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
// Act // Act
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectConfigurationChanged(s_hostProject); updater.ProjectChanged(s_hostProject, ProjectWorkspaceState.Default);
}); });
// Assert // Assert
@ -745,7 +745,7 @@ public class ProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
// Act // Act
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectWorkspaceStateChanged(s_hostProject.Key, _projectWorkspaceStateWithTagHelpers); updater.ProjectChanged(s_hostProject, _projectWorkspaceStateWithTagHelpers);
}); });
// Assert // Assert
@ -767,7 +767,7 @@ public class ProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
// Act // Act
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectWorkspaceStateChanged(s_hostProject.Key, _projectWorkspaceStateWithTagHelpers); updater.ProjectChanged(s_hostProject, _projectWorkspaceStateWithTagHelpers);
}); });
// Assert // Assert
@ -791,7 +791,7 @@ public class ProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
// Act // Act
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectWorkspaceStateChanged(s_hostProject.Key, _projectWorkspaceStateWithTagHelpers); updater.ProjectChanged(s_hostProject, _projectWorkspaceStateWithTagHelpers);
}); });
// Assert // Assert
@ -806,7 +806,7 @@ public class ProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectAdded(s_hostProject); updater.ProjectAdded(s_hostProject);
updater.ProjectWorkspaceStateChanged(s_hostProject.Key, ProjectWorkspaceState.Default); updater.ProjectChanged(s_hostProject, ProjectWorkspaceState.Default);
}); });
using var listener = _projectManager.ListenToNotifications(); using var listener = _projectManager.ListenToNotifications();
@ -814,7 +814,7 @@ public class ProjectSnapshotManagerTest : VisualStudioWorkspaceTestBase
// Act // Act
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectWorkspaceStateChanged(s_hostProject.Key, _projectWorkspaceStateWithTagHelpers); updater.ProjectChanged(s_hostProject, _projectWorkspaceStateWithTagHelpers);
}); });
// Assert // Assert

Просмотреть файл

@ -120,7 +120,7 @@ public class ProjectWorkspaceStateGeneratorTest : VisualStudioWorkspaceTestBase
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectAdded(_projectSnapshot.HostProject); updater.ProjectAdded(_projectSnapshot.HostProject);
updater.ProjectWorkspaceStateChanged(_projectSnapshot.Key, _projectWorkspaceStateWithTagHelpers); updater.ProjectChanged(_projectSnapshot.HostProject, _projectWorkspaceStateWithTagHelpers);
}); });
// Act // Act

Просмотреть файл

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.AspNetCore.Razor.Test.Common;
using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem; using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem;
using Microsoft.AspNetCore.Razor.Test.Common.VisualStudio; using Microsoft.AspNetCore.Razor.Test.Common.VisualStudio;
@ -470,7 +471,7 @@ public class VisualStudioDocumentTrackerTest : VisualStudioWorkspaceTestBase
// Act // Act
await _projectManager.UpdateAsync(updater => await _projectManager.UpdateAsync(updater =>
{ {
updater.ProjectConfigurationChanged(_updatedHostProject); updater.ProjectChanged(_updatedHostProject, ProjectWorkspaceState.Default);
}); });
// Assert // Assert