From 1a98bfb69fd12e163eec44934a49fbd97213834f Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Fri, 12 Jan 2024 14:05:05 +0000 Subject: [PATCH 01/25] Update dependencies from https://github.com/dotnet/arcade build 20240110.4 Microsoft.DotNet.Arcade.Sdk From Version 8.0.0-beta.24059.4 -> To Version 8.0.0-beta.24060.4 --- eng/Version.Details.xml | 4 ++-- global.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index e43c0b19880..1d519a3a805 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -90,9 +90,9 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-runtime 3a25a7f1cc446b60678ed25c9d829420d6321eba - + https://github.com/dotnet/arcade - 61ae141d2bf3534619265c8f691fd55dc3e75147 + 888985fb9a9ae4cb30bca75f98af9126c839e660 diff --git a/global.json b/global.json index 548da1aa8b3..e0ee01f1c90 100644 --- a/global.json +++ b/global.json @@ -21,6 +21,6 @@ "rollForward": "latestPatch" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24059.4" + "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24060.4" } } From e5eb180c83f099f8c5cb311b10d6755a20429bc8 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Sat, 13 Jan 2024 14:07:44 +0000 Subject: [PATCH 02/25] Update dependencies from https://github.com/dotnet/arcade build 20240110.4 Microsoft.DotNet.Arcade.Sdk From Version 8.0.0-beta.24059.4 -> To Version 8.0.0-beta.24060.4 From 65b5674b05248f08fb10bc9fdfdcc98ec992f9dc Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Sun, 14 Jan 2024 13:59:20 +0000 Subject: [PATCH 03/25] Update dependencies from https://github.com/dotnet/arcade build 20240110.4 Microsoft.DotNet.Arcade.Sdk From Version 8.0.0-beta.24059.4 -> To Version 8.0.0-beta.24060.4 From 50fa3cb00431bf75cf94697705f9b5a4abdffe71 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Mon, 15 Jan 2024 13:49:28 +0000 Subject: [PATCH 04/25] Update dependencies from https://github.com/dotnet/arcade build 20240110.4 Microsoft.DotNet.Arcade.Sdk From Version 8.0.0-beta.24059.4 -> To Version 8.0.0-beta.24060.4 From 43c78b9820c6c398cbf6caf955bc5689b1a1c135 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Tue, 16 Jan 2024 14:08:02 +0000 Subject: [PATCH 05/25] Update dependencies from https://github.com/dotnet/arcade build 20240110.4 Microsoft.DotNet.Arcade.Sdk From Version 8.0.0-beta.24059.4 -> To Version 8.0.0-beta.24060.4 From 56c0bf2cd42fd989eba1fe504530f8736667d7b0 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Wed, 17 Jan 2024 14:04:48 +0000 Subject: [PATCH 06/25] Update dependencies from https://github.com/dotnet/arcade build 20240110.4 Microsoft.DotNet.Arcade.Sdk From Version 8.0.0-beta.24059.4 -> To Version 8.0.0-beta.24060.4 From cf9e72e4ea948488954e52d9d4603ff2ac37bde0 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Thu, 18 Jan 2024 21:16:24 +1100 Subject: [PATCH 07/25] Allow document snapshots to be forked to new snapshots with changed text --- .../Cohost/CohostDocumentSnapshot.cs | 8 ++++++++ .../ProjectSystem/DocumentSnapshot.cs | 5 +++++ .../ProjectSystem/IDocumentSnapshot.cs | 2 ++ .../ProjectSystem/ImportDocumentSnapshot.cs | 3 +++ 4 files changed, 18 insertions(+) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Cohost/CohostDocumentSnapshot.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Cohost/CohostDocumentSnapshot.cs index e653868f346..cc6f1d94a28 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Cohost/CohostDocumentSnapshot.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Cohost/CohostDocumentSnapshot.cs @@ -70,4 +70,12 @@ public bool TryGetGeneratedOutput([NotNullWhen(true)] out RazorCodeDocument? res result = _codeDocument; return result is not null; } + + public IDocumentSnapshot WithText(SourceText text) + { + var id = _textDocument.Id; + var newDocument = _textDocument.Project.Solution.WithAdditionalDocumentText(id, text).GetAdditionalDocument(id).AssumeNotNull(); + + return new CohostDocumentSnapshot(newDocument, _projectSnapshot); + } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DocumentSnapshot.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DocumentSnapshot.cs index 20e9d128c5c..760db0c5edd 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DocumentSnapshot.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DocumentSnapshot.cs @@ -61,4 +61,9 @@ public virtual bool TryGetGeneratedOutput([NotNullWhen(true)] out RazorCodeDocum result = null; return false; } + + public IDocumentSnapshot WithText(SourceText text) + { + return new DocumentSnapshot(ProjectInternal, State.WithText(text, VersionStamp.Create())); + } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/IDocumentSnapshot.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/IDocumentSnapshot.cs index a5919e69ccb..0e7e9f626fa 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/IDocumentSnapshot.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/IDocumentSnapshot.cs @@ -26,4 +26,6 @@ internal interface IDocumentSnapshot bool TryGetText([NotNullWhen(true)] out SourceText? result); bool TryGetTextVersion(out VersionStamp result); bool TryGetGeneratedOutput([NotNullWhen(true)] out RazorCodeDocument? result); + + IDocumentSnapshot WithText(SourceText text); } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ImportDocumentSnapshot.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ImportDocumentSnapshot.cs index ba9df04838f..f923e1140d8 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ImportDocumentSnapshot.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ImportDocumentSnapshot.cs @@ -76,4 +76,7 @@ public bool TryGetTextVersion(out VersionStamp result) public bool TryGetGeneratedOutput([NotNullWhen(true)] out RazorCodeDocument? result) => throw new NotSupportedException(); + + public IDocumentSnapshot WithText(SourceText text) + => throw new NotSupportedException(); } From 9ddd122bd1226fbb321119a291eb4855e0cab11a Mon Sep 17 00:00:00 2001 From: David Wengier Date: Thu, 18 Jan 2024 21:16:59 +1100 Subject: [PATCH 08/25] Modify the snapshot instead of using the project engine directly in formatting --- .../Formatting/FormattingContext.cs | 42 +------------------ .../FormattingDiagnosticValidationPassTest.cs | 27 ++---------- .../Formatting_NetFx/FormattingTestBase.cs | 22 ++++++++-- 3 files changed, 24 insertions(+), 67 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingContext.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingContext.cs index b6fd5db9750..01e284a5be2 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingContext.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingContext.cs @@ -10,7 +10,6 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.LanguageServer.Extensions; -using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Razor.Workspaces.Extensions; @@ -27,8 +26,6 @@ internal class FormattingContext : IDisposable private IReadOnlyList? _formattingSpans; private IReadOnlyDictionary? _indentations; - private RazorProjectEngine? _engine; - private ImmutableArray _importSources; private FormattingContext(AdhocWorkspaceFactory workspaceFactory, Uri uri, IDocumentSnapshot originalSnapshot, RazorCodeDocument codeDocument, FormattingOptions options, bool isFormatOnType, bool automaticallyAddUsings, int hostDocumentIndex, char triggerCharacter) @@ -44,14 +41,6 @@ private FormattingContext(AdhocWorkspaceFactory workspaceFactory, Uri uri, IDocu TriggerCharacter = triggerCharacter; } - private FormattingContext(RazorProjectEngine engine, ImmutableArray importSources, AdhocWorkspaceFactory workspaceFactory, Uri uri, IDocumentSnapshot originalSnapshot, RazorCodeDocument codeDocument, FormattingOptions options, - bool isFormatOnType, bool automaticallyAddUsings, int hostDocumentIndex, char triggerCharacter) - : this(workspaceFactory, uri, originalSnapshot, codeDocument, options, isFormatOnType, automaticallyAddUsings, hostDocumentIndex, triggerCharacter) - { - _engine = engine; - _importSources = importSources; - } - public static bool SkipValidateComponents { get; set; } public Uri Uri { get; } @@ -281,22 +270,13 @@ public async Task WithTextAsync(SourceText changedText) throw new ArgumentNullException(nameof(changedText)); } - if (_engine is null) - { - await InitializeProjectEngineAsync().ConfigureAwait(false); - } - - Assumes.NotNull(_engine); - - var changedSourceDocument = RazorSourceDocument.Create(changedText, RazorSourceDocumentProperties.Create(OriginalSnapshot.FilePath, OriginalSnapshot.TargetPath)); + var changedSnapshot = OriginalSnapshot.WithText(changedText); - var codeDocument = _engine.ProcessDesignTime(changedSourceDocument, OriginalSnapshot.FileKind, _importSources, OriginalSnapshot.Project.TagHelpers); + var codeDocument = await changedSnapshot.GetGeneratedOutputAsync().ConfigureAwait(false); DEBUG_ValidateComponents(CodeDocument, codeDocument); var newContext = new FormattingContext( - _engine, - _importSources!, _workspaceFactory, Uri, OriginalSnapshot, @@ -310,24 +290,6 @@ public async Task WithTextAsync(SourceText changedText) return newContext; } - private async Task InitializeProjectEngineAsync() - { - var engine = OriginalSnapshot.Project.GetProjectEngine(); - - var imports = OriginalSnapshot.GetImports(); - using var importSources = new PooledArrayBuilder(imports.Length); - - foreach (var import in imports) - { - var sourceText = await import.GetTextAsync().ConfigureAwait(false); - var source = RazorSourceDocument.Create(sourceText, RazorSourceDocumentProperties.Create(import.FilePath, import.TargetPath)); - importSources.Add(source); - } - - _engine = engine; - _importSources = importSources.DrainToImmutable(); - } - /// /// It can be difficult in the testing infrastructure to correct constructs input files that work consistently across /// context changes, so this method validates that the number of components isn't changing due to lost tag help info. diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingDiagnosticValidationPassTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingDiagnosticValidationPassTest.cs index 660d8f1db74..3288c810206 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingDiagnosticValidationPassTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingDiagnosticValidationPassTest.cs @@ -158,29 +158,8 @@ private static (RazorCodeDocument, IDocumentSnapshot) CreateCodeDocumentAndSnaps var projectEngine = RazorProjectEngine.Create(builder => builder.SetRootNamespace("Test")); var codeDocument = projectEngine.ProcessDesignTime(sourceDocument, fileKind, importSources: default, tagHelpers); - var documentSnapshot = new Mock(MockBehavior.Strict); - documentSnapshot - .Setup(d => d.GetImports()) - .Returns(ImmutableArray.Empty); - documentSnapshot - .Setup(d => d.GetGeneratedOutputAsync()) - .ReturnsAsync(codeDocument); - documentSnapshot - .Setup(d => d.Project.GetProjectEngine()) - .Returns(projectEngine); - documentSnapshot - .Setup(d => d.TargetPath) - .Returns(path); - documentSnapshot - .Setup(d => d.Project.TagHelpers) - .Returns(tagHelpers); - documentSnapshot - .Setup(d => d.FileKind) - .Returns(fileKind); - documentSnapshot - .Setup(d => d.FilePath) - .Returns(path); - - return (codeDocument, documentSnapshot.Object); + var documentSnapshot = FormattingTestBase.CreateDocumentSnapshot(path, tagHelpers, fileKind, ImmutableArray.Empty, ImmutableArray.Empty, projectEngine, codeDocument); + + return (codeDocument, documentSnapshot); } } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingTestBase.cs index b19e1354451..04e12f1f128 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingTestBase.cs @@ -267,13 +267,22 @@ @using Microsoft.AspNetCore.Components.Web Assert.False(codeDocument.GetCSharpDocument().Diagnostics.Any(), "Error creating document:" + Environment.NewLine + string.Join(Environment.NewLine, codeDocument.GetCSharpDocument().Diagnostics)); } + var imports = ImmutableArray.Create(importsSnapshot.Object); + var importsDocuments = ImmutableArray.Create(importsDocument); + var documentSnapshot = CreateDocumentSnapshot(path, tagHelpers, fileKind, importsDocuments, imports, projectEngine, codeDocument); + + return (codeDocument, documentSnapshot); + } + + internal static IDocumentSnapshot CreateDocumentSnapshot(string path, ImmutableArray tagHelpers, string? fileKind, ImmutableArray importsDocuments, ImmutableArray imports, RazorProjectEngine projectEngine, RazorCodeDocument codeDocument) + { var documentSnapshot = new Mock(MockBehavior.Strict); documentSnapshot .Setup(d => d.GetGeneratedOutputAsync()) .ReturnsAsync(codeDocument); documentSnapshot .Setup(d => d.GetImports()) - .Returns(ImmutableArray.Create(importsSnapshot.Object)); + .Returns(imports); documentSnapshot .Setup(d => d.Project.GetProjectEngine()) .Returns(projectEngine); @@ -292,7 +301,14 @@ @using Microsoft.AspNetCore.Components.Web documentSnapshot .Setup(d => d.FileKind) .Returns(fileKind); - - return (codeDocument, documentSnapshot.Object); + documentSnapshot + .Setup(d => d.WithText(It.IsAny())) + .Returns(text => + { + var sourceDocument = RazorSourceDocument.Create(text, RazorSourceDocumentProperties.Create(path, path)); + var codeDocument = projectEngine.ProcessDesignTime(sourceDocument, fileKind, importsDocuments, tagHelpers); + return CreateDocumentSnapshot(path, tagHelpers, fileKind, importsDocuments, imports, projectEngine, codeDocument); + }); + return documentSnapshot.Object; } } From fb46eed5cb129611d97a41959e559d0e095d3dd5 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Thu, 18 Jan 2024 21:20:31 +1100 Subject: [PATCH 09/25] Fix bad test data exposed from new code --- .../AutoInsert/OnAutoInsertEndpointTest.NetFx.cs | 2 +- .../CodeActions/CodeActionEndToEndTest.NetFx.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/AutoInsert/OnAutoInsertEndpointTest.NetFx.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/AutoInsert/OnAutoInsertEndpointTest.NetFx.cs index 458acada11a..81b406417c7 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/AutoInsert/OnAutoInsertEndpointTest.NetFx.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/AutoInsert/OnAutoInsertEndpointTest.NetFx.cs @@ -363,7 +363,7 @@ private async Task VerifyCSharpOnAutoInsertAsync(string input, string expected, TestFileMarkupParser.GetPosition(input, out input, out var cursorPosition); var codeDocument = CreateCodeDocument(input); - var razorFilePath = "file://path/test.razor"; + var razorFilePath = "C:/path/test.razor"; var languageServer = await CreateLanguageServerAsync(codeDocument, razorFilePath); var optionsMonitor = GetOptionsMonitor(); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndToEndTest.NetFx.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndToEndTest.NetFx.cs index 502ce7c7f3a..27ac6c5852c 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndToEndTest.NetFx.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/CodeActions/CodeActionEndToEndTest.NetFx.cs @@ -1026,7 +1026,7 @@ private async Task ValidateCodeActionAsync( { TestFileMarkupParser.GetSpan(input, out input, out var textSpan); - var razorFilePath = "file://C:/path/test.razor"; + var razorFilePath = "C:/path/test.razor"; var codeDocument = CreateCodeDocument(input, filePath: razorFilePath); var sourceText = codeDocument.GetSourceText(); var uri = new Uri(razorFilePath); From d6a4dfadbf3241899756d6d47bca229537de35bf Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Thu, 18 Jan 2024 14:00:51 +0000 Subject: [PATCH 10/25] Update dependencies from https://github.com/dotnet/arcade build 20240110.4 Microsoft.DotNet.Arcade.Sdk From Version 8.0.0-beta.24059.4 -> To Version 8.0.0-beta.24060.4 From dd2b34d24323b0340cb078a8cafe21caee6d1763 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jan 2024 13:02:07 -0800 Subject: [PATCH 11/25] Convert ProjectSnapshotProjectEngineFactory to an interface --- ...aticProjectSnapshotProjectEngineFactory.cs | 10 +-- ...moteProjectSnapshotProjectEngineFactory.cs | 10 +-- ...aultProjectSnapshotProjectEngineFactory.cs | 14 ++-- ...jectSnapshotProjectEngineFactoryFactory.cs | 2 +- .../IProjectSnapshotProjectEngineFactory.cs | 18 ++++ ...tSnapshotProjectEngineFactoryExtensions.cs | 72 ++++++++++++++++ .../ProjectSnapshotProjectEngineFactory.cs | 83 ------------------- .../DefaultProjectSnapshotManager.cs | 2 +- .../ProjectSystem/ProjectState.cs | 9 +- .../OOPTagHelperResolver.cs | 4 +- .../OOPTagHelperResolverFactory.cs | 2 +- .../DefaultVisualStudioRazorParser.cs | 6 +- .../DefaultVisualStudioRazorParserFactory.cs | 4 +- ...ltVisualStudioRazorParserFactoryFactory.cs | 2 +- .../EphemeralProjectSnapshot.cs | 2 +- ...TestProjectSnapshotProjectEngineFactory.cs | 8 +- ...TestProjectSnapshotProjectEngineFactory.cs | 8 +- .../Workspaces/WorkspaceTestBase.cs | 4 +- .../OOPTagHelperResolverTest.TestResolver.cs | 2 +- .../OOPTagHelperResolverTest.cs | 2 +- ...ProjectSnapshotProjectEngineFactoryTest.cs | 2 +- ...faultProjectWorkspaceStateGeneratorTest.cs | 2 +- ...tVisualStudioRazorParserIntegrationTest.cs | 2 +- .../DefaultVisualStudioRazorParserTest.cs | 4 +- ...UpdatesProjectSnapshotChangeTriggerTest.cs | 4 +- .../DefaultProjectSnapshotManagerProxyTest.cs | 2 +- 26 files changed, 141 insertions(+), 139 deletions(-) create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactory.cs create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactoryExtensions.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSnapshotProjectEngineFactory.cs diff --git a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs index 5f1375fa05f..9d97a6a0b66 100644 --- a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs +++ b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs @@ -11,18 +11,18 @@ namespace Microsoft.AspNetCore.Razor.Microbenchmarks; public abstract partial class ProjectSnapshotManagerBenchmarkBase { - private class StaticProjectSnapshotProjectEngineFactory : ProjectSnapshotProjectEngineFactory + private class StaticProjectSnapshotProjectEngineFactory : IProjectSnapshotProjectEngineFactory { - public override IProjectEngineFactory FindFactory(IProjectSnapshot project) + public IProjectEngineFactory? FindFactory(IProjectSnapshot project) => throw new NotImplementedException(); - public override IProjectEngineFactory FindSerializableFactory(IProjectSnapshot project) + public IProjectEngineFactory? FindSerializableFactory(IProjectSnapshot project) => throw new NotImplementedException(); - public override RazorProjectEngine Create( + public RazorProjectEngine Create( RazorConfiguration configuration, RazorProjectFileSystem fileSystem, - Action configure) + Action? configure) => RazorProjectEngine.Create(configuration, fileSystem, RazorExtensions.Register); } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RemoteProjectSnapshotProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RemoteProjectSnapshotProjectEngineFactory.cs index 2e6474867bb..08cb1f5e884 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RemoteProjectSnapshotProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RemoteProjectSnapshotProjectEngineFactory.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; -using System.Diagnostics; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.LanguageServer.Common; using Microsoft.CodeAnalysis.Razor; @@ -27,15 +26,14 @@ public RemoteProjectSnapshotProjectEngineFactory(IOptionsMonitor configure) + Action? configure) { if (fileSystem is not DefaultRazorProjectFileSystem defaultFileSystem) { - Debug.Fail("Unexpected file system."); - return null; + throw new InvalidOperationException("Unexpected file system."); } var remoteFileSystem = new RemoteRazorProjectFileSystem(defaultFileSystem.Root); @@ -43,7 +41,7 @@ public RemoteProjectSnapshotProjectEngineFactory(IOptionsMonitor configure) + public virtual RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure) { if (fileSystem is null) { @@ -62,9 +59,8 @@ public DefaultProjectSnapshotProjectEngineFactory( var factory = SelectFactory(configuration) ?? _fallback; return factory.Create(configuration, fileSystem, configure); } -#nullable disable - public override IProjectEngineFactory FindFactory(IProjectSnapshot project) + public IProjectEngineFactory? FindFactory(IProjectSnapshot project) { if (project is null) { @@ -74,7 +70,7 @@ public override IProjectEngineFactory FindFactory(IProjectSnapshot project) return SelectFactory(project.Configuration, requireSerializable: false); } - public override IProjectEngineFactory FindSerializableFactory(IProjectSnapshot project) + public IProjectEngineFactory? FindSerializableFactory(IProjectSnapshot project) { if (project is null) { @@ -84,7 +80,7 @@ public override IProjectEngineFactory FindSerializableFactory(IProjectSnapshot p return SelectFactory(project.Configuration, requireSerializable: true); } - private IProjectEngineFactory SelectFactory(RazorConfiguration configuration, bool requireSerializable = false) + private IProjectEngineFactory? SelectFactory(RazorConfiguration configuration, bool requireSerializable = false) { for (var i = 0; i < _factories.Length; i++) { diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactoryFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactoryFactory.cs index 60e38031ff1..47e793f24e4 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactoryFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactoryFactory.cs @@ -8,7 +8,7 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces; -[ExportWorkspaceServiceFactory(typeof(ProjectSnapshotProjectEngineFactory))] +[ExportWorkspaceServiceFactory(typeof(IProjectSnapshotProjectEngineFactory))] internal class DefaultProjectSnapshotProjectEngineFactoryFactory : IWorkspaceServiceFactory { private readonly IFallbackProjectEngineFactory _fallback; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactory.cs new file mode 100644 index 00000000000..8fad079af6b --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactory.cs @@ -0,0 +1,18 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using Microsoft.AspNetCore.Razor.Language; +using Microsoft.CodeAnalysis.Host; +using Microsoft.CodeAnalysis.Razor.ProjectSystem; + +namespace Microsoft.CodeAnalysis.Razor; + +internal interface IProjectSnapshotProjectEngineFactory : IWorkspaceService +{ + IProjectEngineFactory? FindFactory(IProjectSnapshot project); + + IProjectEngineFactory? FindSerializableFactory(IProjectSnapshot project); + + RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure); +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactoryExtensions.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactoryExtensions.cs new file mode 100644 index 00000000000..d608b22ae78 --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactoryExtensions.cs @@ -0,0 +1,72 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.IO; +using Microsoft.AspNetCore.Razor.Language; +using Microsoft.CodeAnalysis.Razor.ProjectSystem; + +namespace Microsoft.CodeAnalysis.Razor; + +internal static class IProjectSnapshotProjectEngineFactoryExtensions +{ + public static RazorProjectEngine Create(this IProjectSnapshotProjectEngineFactory factory, IProjectSnapshot project) + { + return factory.Create(project, RazorProjectFileSystem.Create(Path.GetDirectoryName(project.FilePath)), null); + } + + public static RazorProjectEngine Create(this IProjectSnapshotProjectEngineFactory factory, IProjectSnapshot project, RazorProjectFileSystem fileSystem) + { + if (project is null) + { + throw new ArgumentNullException(nameof(project)); + } + + if (fileSystem is null) + { + throw new ArgumentNullException(nameof(fileSystem)); + } + + return factory.Create(project, fileSystem, configure: null); + } + + public static RazorProjectEngine Create(this IProjectSnapshotProjectEngineFactory factory, IProjectSnapshot project, Action? configure) + { + if (project is null) + { + throw new ArgumentNullException(nameof(project)); + } + + return factory.Create(project, RazorProjectFileSystem.Create(Path.GetDirectoryName(project.FilePath)), configure); + } + + public static RazorProjectEngine Create(this IProjectSnapshotProjectEngineFactory factory, IProjectSnapshot project, RazorProjectFileSystem fileSystem, Action? configure) + { + if (project is null) + { + throw new ArgumentNullException(nameof(project)); + } + + if (fileSystem is null) + { + throw new ArgumentNullException(nameof(fileSystem)); + } + + return factory.Create(project.Configuration, fileSystem, configure); + } + + public static RazorProjectEngine Create(this IProjectSnapshotProjectEngineFactory factory, RazorConfiguration configuration, string directoryPath, Action? configure) + { + if (configuration is null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + if (directoryPath is null) + { + throw new ArgumentNullException(nameof(directoryPath)); + } + + return factory.Create(configuration, RazorProjectFileSystem.Create(directoryPath), configure); + } +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSnapshotProjectEngineFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSnapshotProjectEngineFactory.cs deleted file mode 100644 index 671fa61fbfe..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSnapshotProjectEngineFactory.cs +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -#nullable disable - -using System; -using System.IO; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Razor.ProjectSystem; - -namespace Microsoft.CodeAnalysis.Razor; - -internal abstract class ProjectSnapshotProjectEngineFactory : IWorkspaceService -{ - public abstract IProjectEngineFactory FindFactory(IProjectSnapshot project); - - public abstract IProjectEngineFactory FindSerializableFactory(IProjectSnapshot project); - - public RazorProjectEngine Create(IProjectSnapshot project) - { - return Create(project, RazorProjectFileSystem.Create(Path.GetDirectoryName(project.FilePath)), null); - } - - public RazorProjectEngine Create(IProjectSnapshot project, RazorProjectFileSystem fileSystem) - { - if (project is null) - { - throw new ArgumentNullException(nameof(project)); - } - - if (fileSystem is null) - { - throw new ArgumentNullException(nameof(fileSystem)); - } - - return Create(project, fileSystem, null); - } - - public RazorProjectEngine Create(IProjectSnapshot project, Action configure) - { - if (project is null) - { - throw new ArgumentNullException(nameof(project)); - } - - return Create(project, RazorProjectFileSystem.Create(Path.GetDirectoryName(project.FilePath)), configure); - } - - public RazorProjectEngine Create(IProjectSnapshot project, RazorProjectFileSystem fileSystem, Action configure) - { - if (project is null) - { - throw new ArgumentNullException(nameof(project)); - } - - if (fileSystem is null) - { - throw new ArgumentNullException(nameof(fileSystem)); - } - - return Create(project.Configuration, fileSystem, configure); - } - - public RazorProjectEngine Create(RazorConfiguration configuration, string directoryPath, Action configure) - { - if (configuration is null) - { - throw new ArgumentNullException(nameof(configuration)); - } - - if (directoryPath is null) - { - throw new ArgumentNullException(nameof(directoryPath)); - } - - return Create(configuration, RazorProjectFileSystem.Create(directoryPath), configure); - } - -#nullable enable - public abstract RazorProjectEngine? Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure); -#nullable disable -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DefaultProjectSnapshotManager.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DefaultProjectSnapshotManager.cs index 7103f2d57c4..2d212cebb9e 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DefaultProjectSnapshotManager.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DefaultProjectSnapshotManager.cs @@ -442,7 +442,7 @@ private bool TryChangeEntry_UsesLock( return false; } - var projectEngineFactory = Workspace.Services.GetRequiredService(); + var projectEngineFactory = Workspace.Services.GetRequiredService(); var state = ProjectState.Create( projectEngineFactory, diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ProjectState.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ProjectState.cs index 84c8916d39e..17670773206 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ProjectState.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ProjectState.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.ProjectSystem; using Microsoft.AspNetCore.Razor.Utilities; @@ -33,11 +34,11 @@ internal class ProjectState private static readonly ImmutableDictionary> s_emptyImportsToRelatedDocuments = ImmutableDictionary.Create>(FilePathNormalizer.Comparer); private readonly object _lock; - private readonly ProjectSnapshotProjectEngineFactory _projectEngineFactory; + private readonly IProjectSnapshotProjectEngineFactory _projectEngineFactory; private RazorProjectEngine? _projectEngine; public static ProjectState Create( - ProjectSnapshotProjectEngineFactory projectEngineFactory, + IProjectSnapshotProjectEngineFactory projectEngineFactory, HostProject hostProject, ProjectWorkspaceState projectWorkspaceState) { @@ -60,7 +61,7 @@ public static ProjectState Create( } private ProjectState( - ProjectSnapshotProjectEngineFactory projectEngineFactory, + IProjectSnapshotProjectEngineFactory projectEngineFactory, HostProject hostProject, ProjectWorkspaceState projectWorkspaceState) { @@ -202,7 +203,7 @@ RazorProjectEngine CreateProjectEngine() { return _projectEngineFactory.Create( HostProject.Configuration, - Path.GetDirectoryName(HostProject.FilePath), + Path.GetDirectoryName(HostProject.FilePath).AssumeNotNull(), configure: builder => { builder.SetRootNamespace(HostProject.RootNamespace); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs index ae4fb30a7c4..588f2a624ca 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs @@ -22,11 +22,11 @@ internal class OOPTagHelperResolver : ITagHelperResolver { private readonly TagHelperResultCache _resultCache; private readonly CompilationTagHelperResolver _innerResolver; - private readonly ProjectSnapshotProjectEngineFactory _factory; + private readonly IProjectSnapshotProjectEngineFactory _factory; private readonly IErrorReporter _errorReporter; private readonly Workspace _workspace; - public OOPTagHelperResolver(ProjectSnapshotProjectEngineFactory factory, IErrorReporter errorReporter, Workspace workspace, ITelemetryReporter telemetryReporter) + public OOPTagHelperResolver(IProjectSnapshotProjectEngineFactory factory, IErrorReporter errorReporter, Workspace workspace, ITelemetryReporter telemetryReporter) { _factory = factory ?? throw new ArgumentNullException(nameof(factory)); _errorReporter = errorReporter ?? throw new ArgumentNullException(nameof(errorReporter)); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolverFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolverFactory.cs index 72900676d25..fd0af047bef 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolverFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolverFactory.cs @@ -19,7 +19,7 @@ internal class OOPTagHelperResolverFactory( { public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) => new OOPTagHelperResolver( - workspaceServices.GetRequiredService(), + workspaceServices.GetRequiredService(), errorReporter, workspaceServices.Workspace, telemetryReporter); diff --git a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs index e5fb0ddabe4..ae58fa1558b 100644 --- a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs +++ b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs @@ -38,7 +38,7 @@ internal class DefaultVisualStudioRazorParser : VisualStudioRazorParser, IDispos private readonly VisualStudioCompletionBroker _completionBroker; private readonly VisualStudioDocumentTracker _documentTracker; private readonly JoinableTaskContext _joinableTaskContext; - private readonly ProjectSnapshotProjectEngineFactory _projectEngineFactory; + private readonly IProjectSnapshotProjectEngineFactory _projectEngineFactory; private readonly IErrorReporter _errorReporter; private readonly List _codeDocumentRequests; private readonly TaskScheduler _uiThreadScheduler; @@ -60,7 +60,7 @@ internal DefaultVisualStudioRazorParser(RazorCodeDocument codeDocument) public DefaultVisualStudioRazorParser( JoinableTaskContext joinableTaskContext, VisualStudioDocumentTracker documentTracker, - ProjectSnapshotProjectEngineFactory projectEngineFactory, + IProjectSnapshotProjectEngineFactory projectEngineFactory, IErrorReporter errorReporter, VisualStudioCompletionBroker completionBroker) { @@ -246,7 +246,7 @@ internal void StartParser() // Make sure any tests use the real thing or a good mock. These tests can cause failures // that are hard to understand when this throws. Debug.Assert(_documentTracker.IsSupportedProject); - Debug.Assert(_documentTracker.ProjectSnapshot is not null); + Assumes.NotNull(_documentTracker.ProjectSnapshot); _projectEngine = _projectEngineFactory.Create(_documentTracker.ProjectSnapshot, ConfigureProjectEngine); diff --git a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactory.cs b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactory.cs index 454a85dfbdb..721678c665d 100644 --- a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactory.cs +++ b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactory.cs @@ -10,7 +10,7 @@ namespace Microsoft.VisualStudio.Editor.Razor; internal class DefaultVisualStudioRazorParserFactory : VisualStudioRazorParserFactory { private readonly JoinableTaskContext _joinableTaskContext; - private readonly ProjectSnapshotProjectEngineFactory _projectEngineFactory; + private readonly IProjectSnapshotProjectEngineFactory _projectEngineFactory; private readonly VisualStudioCompletionBroker _completionBroker; private readonly IErrorReporter _errorReporter; @@ -18,7 +18,7 @@ public DefaultVisualStudioRazorParserFactory( JoinableTaskContext joinableTaskContext, IErrorReporter errorReporter, VisualStudioCompletionBroker completionBroker, - ProjectSnapshotProjectEngineFactory projectEngineFactory) + IProjectSnapshotProjectEngineFactory projectEngineFactory) { if (joinableTaskContext is null) { diff --git a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactoryFactory.cs b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactoryFactory.cs index 2fb676b2812..f169c4b535f 100644 --- a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactoryFactory.cs +++ b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactoryFactory.cs @@ -26,7 +26,7 @@ public ILanguageService CreateLanguageService(HostLanguageServices languageServi var workspaceServices = languageServices.WorkspaceServices; var completionBroker = languageServices.GetRequiredService(); - var projectEngineFactory = workspaceServices.GetRequiredService(); + var projectEngineFactory = workspaceServices.GetRequiredService(); return new DefaultVisualStudioRazorParserFactory( joinableTaskContext, diff --git a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/EphemeralProjectSnapshot.cs b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/EphemeralProjectSnapshot.cs index 3fd1ec69c55..849abd43c75 100644 --- a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/EphemeralProjectSnapshot.cs +++ b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/EphemeralProjectSnapshot.cs @@ -101,7 +101,7 @@ public RazorProjectEngine GetProjectEngine() private RazorProjectEngine CreateProjectEngine() { - var factory = _services.GetRequiredService(); + var factory = _services.GetRequiredService(); return factory.Create(this); } } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotProjectEngineFactory.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotProjectEngineFactory.cs index 534202a4c6b..b0c5dbf9366 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotProjectEngineFactory.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotProjectEngineFactory.cs @@ -8,13 +8,13 @@ namespace Microsoft.AspNetCore.Razor.Test.Common.LanguageServer; -internal class TestProjectSnapshotProjectEngineFactory : ProjectSnapshotProjectEngineFactory +internal class TestProjectSnapshotProjectEngineFactory : IProjectSnapshotProjectEngineFactory { public Action? Configure { get; set; } public RazorProjectEngine? Engine { get; set; } - public override RazorProjectEngine Create( + public RazorProjectEngine Create( RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure) @@ -22,12 +22,12 @@ public override RazorProjectEngine Create( return Engine ?? RazorProjectEngine.Create(configuration, fileSystem, configure ?? Configure); } - public override IProjectEngineFactory FindFactory(IProjectSnapshot project) + public IProjectEngineFactory? FindFactory(IProjectSnapshot project) { throw new NotImplementedException(); } - public override IProjectEngineFactory FindSerializableFactory(IProjectSnapshot project) + public IProjectEngineFactory? FindSerializableFactory(IProjectSnapshot project) { throw new NotImplementedException(); } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectSnapshotProjectEngineFactory.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectSnapshotProjectEngineFactory.cs index 8ec274d428f..0e1b79b90c8 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectSnapshotProjectEngineFactory.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectSnapshotProjectEngineFactory.cs @@ -8,13 +8,13 @@ namespace Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem; -internal class TestProjectSnapshotProjectEngineFactory : ProjectSnapshotProjectEngineFactory +internal class TestProjectSnapshotProjectEngineFactory : IProjectSnapshotProjectEngineFactory { public Action? Configure { get; set; } public RazorProjectEngine? Engine { get; set; } - public override RazorProjectEngine Create( + public RazorProjectEngine Create( RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure) @@ -26,12 +26,12 @@ public override RazorProjectEngine Create( }); } - public override IProjectEngineFactory FindFactory(IProjectSnapshot project) + public IProjectEngineFactory FindFactory(IProjectSnapshot project) { throw new NotImplementedException(); } - public override IProjectEngineFactory FindSerializableFactory(IProjectSnapshot project) + public IProjectEngineFactory FindSerializableFactory(IProjectSnapshot project) { throw new NotImplementedException(); } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/WorkspaceTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/WorkspaceTestBase.cs index febf5e4d810..18249d3e205 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/WorkspaceTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/WorkspaceTestBase.cs @@ -17,7 +17,7 @@ public abstract class WorkspaceTestBase : ToolingTestBase private bool _initialized; private HostServices? _hostServices; private Workspace? _workspace; - private ProjectSnapshotProjectEngineFactory? _projectEngineFactory; + private IProjectSnapshotProjectEngineFactory? _projectEngineFactory; protected WorkspaceTestBase(ITestOutputHelper testOutput) : base(testOutput) @@ -42,7 +42,7 @@ protected Workspace Workspace } } - private protected ProjectSnapshotProjectEngineFactory ProjectEngineFactory + private protected IProjectSnapshotProjectEngineFactory ProjectEngineFactory { get { diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestResolver.cs b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestResolver.cs index 771b5107cad..7e14936108f 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestResolver.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestResolver.cs @@ -18,7 +18,7 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; public partial class OOPTagHelperResolverTest { private class TestResolver( - ProjectSnapshotProjectEngineFactory factory, + IProjectSnapshotProjectEngineFactory factory, IErrorReporter errorReporter, Workspace workspace, ITelemetryReporter telemetryReporter) diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.cs b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.cs index caa2fd9459d..51bfc6d4aaa 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.cs @@ -23,7 +23,7 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; public partial class OOPTagHelperResolverTest : TagHelperDescriptorTestBase { - private readonly ProjectSnapshotProjectEngineFactory _engineFactory; + private readonly IProjectSnapshotProjectEngineFactory _engineFactory; private readonly Lazy[] _customFactories; private readonly HostProject _hostProject_For_2_0; private readonly HostProject _hostProject_For_NonSerializableConfiguration; diff --git a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectSnapshotProjectEngineFactoryTest.cs b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectSnapshotProjectEngineFactoryTest.cs index ec7da7d7865..af01525de94 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectSnapshotProjectEngineFactoryTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectSnapshotProjectEngineFactoryTest.cs @@ -52,7 +52,7 @@ public DefaultProjectSnapshotProjectEngineFactoryTest(ITestOutputHelper testOutp projectFilePath, intermediateOutputPath, new ProjectSystemRazorConfiguration(RazorLanguageVersion.Version_2_1, "Random-0.1", Array.Empty()), rootNamespace: null); - var projectEngineFactory = Mock.Of(MockBehavior.Strict); + var projectEngineFactory = Mock.Of(MockBehavior.Strict); _snapshot_For_1_0 = new ProjectSnapshot(ProjectState.Create(projectEngineFactory, hostProject_For_1_0, ProjectWorkspaceState.Default)); _snapshot_For_1_1 = new ProjectSnapshot(ProjectState.Create(projectEngineFactory, hostProject_For_1_1, ProjectWorkspaceState.Default)); diff --git a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectWorkspaceStateGeneratorTest.cs b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectWorkspaceStateGeneratorTest.cs index 30ebb3ffcee..85def827c74 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectWorkspaceStateGeneratorTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectWorkspaceStateGeneratorTest.cs @@ -35,7 +35,7 @@ public class DefaultProjectWorkspaceStateGeneratorTest : ProjectSnapshotManagerD public DefaultProjectWorkspaceStateGeneratorTest(ITestOutputHelper testOutput) : base(testOutput) { - var projectEngineFactory = Mock.Of(MockBehavior.Strict); + var projectEngineFactory = Mock.Of(MockBehavior.Strict); var tagHelperResolver = new TestTagHelperResolver() { diff --git a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserIntegrationTest.cs b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserIntegrationTest.cs index f1add388e48..0ec5f44c3e1 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserIntegrationTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserIntegrationTest.cs @@ -587,7 +587,7 @@ private TestParserManager CreateParserManager(ITextSnapshot originalSnapshot) return CreateParserManager(documentTracker); } - private static ProjectSnapshotProjectEngineFactory CreateProjectEngineFactory(IEnumerable tagHelpers = null) + private static IProjectSnapshotProjectEngineFactory CreateProjectEngineFactory(IEnumerable tagHelpers = null) { var fileSystem = new TestRazorProjectFileSystem(); var projectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem, builder => diff --git a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs index 76266fd0f74..8bf250de3a2 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs @@ -20,7 +20,7 @@ namespace Microsoft.VisualStudio.Editor.Razor; public class DefaultVisualStudioRazorParserTest : ProjectSnapshotManagerDispatcherTestBase { private readonly IProjectSnapshot _projectSnapshot; - private readonly ProjectSnapshotProjectEngineFactory _projectEngineFactory; + private readonly IProjectSnapshotProjectEngineFactory _projectEngineFactory; private readonly CodeAnalysis.Workspace _workspace; public DefaultVisualStudioRazorParserTest(ITestOutputHelper testOutput) @@ -32,7 +32,7 @@ public DefaultVisualStudioRazorParserTest(ITestOutputHelper testOutput) _projectSnapshot = new EphemeralProjectSnapshot(_workspace.Services, "c:\\SomeProject.csproj"); var engine = RazorProjectEngine.Create(RazorConfiguration.Default, RazorProjectFileSystem.Empty); - _projectEngineFactory = Mock.Of( + _projectEngineFactory = Mock.Of( f => f.Create( It.IsAny(), It.IsAny(), diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/VsSolutionUpdatesProjectSnapshotChangeTriggerTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/VsSolutionUpdatesProjectSnapshotChangeTriggerTest.cs index 45efd7ba2da..588541fa01e 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/VsSolutionUpdatesProjectSnapshotChangeTriggerTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/VsSolutionUpdatesProjectSnapshotChangeTriggerTest.cs @@ -40,7 +40,7 @@ public VsSolutionUpdatesProjectSnapshotChangeTriggerTest(ITestOutputHelper testO _someProject = new HostProject(TestProjectData.SomeProject.FilePath, TestProjectData.SomeProject.IntermediateOutputPath, FallbackRazorConfiguration.MVC_1_0, TestProjectData.SomeProject.RootNamespace); _someOtherProject = new HostProject(TestProjectData.AnotherProject.FilePath, TestProjectData.AnotherProject.IntermediateOutputPath, FallbackRazorConfiguration.MVC_2_0, TestProjectData.AnotherProject.RootNamespace); - var projectEngineFactory = Mock.Of(MockBehavior.Strict); + var projectEngineFactory = Mock.Of(MockBehavior.Strict); var testServices = TestServices.Create([projectEngineFactory], []); _workspace = TestWorkspace.Create(testServices, @@ -204,7 +204,7 @@ public async Task OnProjectBuiltAsync_WithoutWorkspaceProject_DoesNotEnqueueUpda .Setup(s => s.GetService(It.Is(f => f == typeof(SVsSolutionBuildManager)))) .Returns(buildManager.Object); - var projectEngineFactory = Mock.Of(MockBehavior.Strict); + var projectEngineFactory = Mock.Of(MockBehavior.Strict); var projectSnapshot = new ProjectSnapshot( ProjectState.Create( diff --git a/src/Razor/test/Microsoft.VisualStudio.LiveShare.Razor.Test/Host/DefaultProjectSnapshotManagerProxyTest.cs b/src/Razor/test/Microsoft.VisualStudio.LiveShare.Razor.Test/Host/DefaultProjectSnapshotManagerProxyTest.cs index b9ad63dcb60..8b56ce768e5 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LiveShare.Razor.Test/Host/DefaultProjectSnapshotManagerProxyTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LiveShare.Razor.Test/Host/DefaultProjectSnapshotManagerProxyTest.cs @@ -27,7 +27,7 @@ public class DefaultProjectSnapshotManagerProxyTest : ProjectSnapshotManagerDisp public DefaultProjectSnapshotManagerProxyTest(ITestOutputHelper testOutput) : base(testOutput) { - var projectEngineFactory = Mock.Of(MockBehavior.Strict); + var projectEngineFactory = Mock.Of(MockBehavior.Strict); var projectWorkspaceState1 = ProjectWorkspaceState.Create(ImmutableArray.Create( TagHelperDescriptorBuilder.Create("test1", "TestAssembly1").Build())); From 620748b70ad19fc3f32723c0a49e90544414fa61 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 17 Jan 2024 14:12:43 -0800 Subject: [PATCH 12/25] Refactor IProjectEngineFactory instances a bit --- .../RazorProjectInfoSerializer.cs | 5 +-- .../Cohost/CohostProjectSnapshot.cs | 3 +- .../Common/DefaultProjectEngineFactory.cs | 5 ++- .../Common/MEFProjectEngineFactories.cs | 4 +-- ...moteProjectSnapshotProjectEngineFactory.cs | 2 +- .../IProjectEngineFactory.cs | 7 ++-- .../DefaultProjectEngineFactory.cs | 19 ++++++---- .../EmptyProjectEngineFactory.cs | 7 ++-- .../ProjectEngineFactories.cs | 35 +++++++++++-------- .../ProjectEngineHost/ProjectEngineFactory.cs | 11 +++--- .../ProjectEngineFactory_1_0.cs | 9 ----- .../ProjectEngineFactory_1_1.cs | 9 ----- .../ProjectEngineFactory_2_0.cs | 9 ----- .../ProjectEngineFactory_2_1.cs | 9 ----- .../ProjectEngineFactory_3_0.cs | 9 ----- .../ProjectEngineFactory_Unsupported.cs | 5 ++- .../LegacyProjectEngineFactory_1_0.cs | 3 ++ .../LegacyProjectEngineFactory_1_1.cs | 3 ++ .../LegacyProjectEngineFactory_2_0.cs | 3 ++ .../LegacyProjectEngineFactory_2_1.cs | 4 +++ .../LegacyProjectEngineFactory_3_0.cs | 4 +++ .../TestProjectSnapshotManager.cs | 2 +- 22 files changed, 80 insertions(+), 87 deletions(-) delete mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_1_0.cs delete mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_1_1.cs delete mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_2_0.cs delete mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_2_1.cs delete mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_3_0.cs diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace/RazorProjectInfoSerializer.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace/RazorProjectInfoSerializer.cs index 4d793a35b68..6ce7cdf9bd0 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace/RazorProjectInfoSerializer.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace/RazorProjectInfoSerializer.cs @@ -22,7 +22,6 @@ internal static class RazorProjectInfoSerializer { private static readonly EmptyProjectEngineFactory s_fallbackProjectEngineFactory; private static readonly StringComparison s_stringComparison; - private static readonly (IProjectEngineFactory Value, ICustomProjectEngineFactoryMetadata)[] s_projectEngineFactories; static RazorProjectInfoSerializer() { @@ -30,8 +29,6 @@ static RazorProjectInfoSerializer() s_stringComparison = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase; - - s_projectEngineFactories = ProjectEngineFactories.Factories.Select(f => (f.Item1.Value, f.Item2)).ToArray(); } public static async Task SerializeAsync(Project project, string configurationFileName, CancellationToken cancellationToken) @@ -80,7 +77,7 @@ public static async Task SerializeAsync(Project project, string configurationFil fileSystem: fileSystem, configure: defaultConfigure, fallback: s_fallbackProjectEngineFactory, - factories: s_projectEngineFactories); + factories: ProjectEngineFactories.All); var resolver = new CompilationTagHelperResolver(NoOpTelemetryReporter.Instance); var tagHelpers = await resolver.GetTagHelpersAsync(project, engine, cancellationToken).ConfigureAwait(false); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Cohost/CohostProjectSnapshot.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Cohost/CohostProjectSnapshot.cs index d7cbd77f73b..4e14264bff6 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Cohost/CohostProjectSnapshot.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Cohost/CohostProjectSnapshot.cs @@ -24,7 +24,6 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Cohost; internal class CohostProjectSnapshot : IProjectSnapshot { private static readonly EmptyProjectEngineFactory s_fallbackProjectEngineFactory = new(); - private static readonly (IProjectEngineFactory Value, ICustomProjectEngineFactoryMetadata)[] s_projectEngineFactories = ProjectEngineFactories.Factories.Select(f => (f.Item1.Value, f.Item2)).ToArray(); private readonly Project _project; private readonly DocumentSnapshotFactory _documentSnapshotFactory; @@ -54,7 +53,7 @@ public CohostProjectSnapshot(Project project, DocumentSnapshotFactory documentSn builder.SetSupportLocalizedComponentNames(); }, fallback: s_fallbackProjectEngineFactory, - factories: s_projectEngineFactories)); + factories: ProjectEngineFactories.All)); _tagHelpersLazy = new AsyncLazy>(() => { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/DefaultProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/DefaultProjectEngineFactory.cs index 36cfbac1d2b..f72ceb5f564 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/DefaultProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/DefaultProjectEngineFactory.cs @@ -10,7 +10,10 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Common; [ExportCustomProjectEngineFactory("Default", SupportsSerialization = true)] internal class DefaultProjectEngineFactory : IProjectEngineFactory { - public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure) + public string ConfigurationName => "Default"; + public bool SupportsSerialization => true; + + public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure) { return RazorProjectEngine.Create(configuration, fileSystem, b => { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/MEFProjectEngineFactories.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/MEFProjectEngineFactories.cs index 69b6bdca152..7031c19fe8d 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/MEFProjectEngineFactories.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/MEFProjectEngineFactories.cs @@ -12,6 +12,6 @@ internal static class MefProjectEngineFactories { // The actual factories are defined in the ProjectEngineHost project, but we need to convert them // to Lazy<,> to be MEF compatible. - public static readonly Lazy[] Factories = - ProjectEngineFactories.Factories.Select(f => new Lazy(() => f.Item1.Value, f.Item2)).ToArray(); + public static readonly Lazy[] All = + ProjectEngineFactories.All.Select(f => new Lazy(() => f, new CustomProjectEngineFactoryMetadata(f.ConfigurationName) { SupportsSerialization = f.SupportsSerialization })).ToArray(); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RemoteProjectSnapshotProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RemoteProjectSnapshotProjectEngineFactory.cs index 08cb1f5e884..f884f135708 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RemoteProjectSnapshotProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RemoteProjectSnapshotProjectEngineFactory.cs @@ -16,7 +16,7 @@ internal class RemoteProjectSnapshotProjectEngineFactory : DefaultProjectSnapsho private readonly IOptionsMonitor _optionsMonitor; public RemoteProjectSnapshotProjectEngineFactory(IOptionsMonitor optionsMonitor) - : base(FallbackProjectEngineFactory, MefProjectEngineFactories.Factories) + : base(FallbackProjectEngineFactory, MefProjectEngineFactories.All) { if (optionsMonitor is null) { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/IProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/IProjectEngineFactory.cs index 096aff11cb7..45c3918a7b3 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/IProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/IProjectEngineFactory.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -#nullable disable - using System; using Microsoft.AspNetCore.Razor.Language; @@ -10,5 +8,8 @@ namespace Microsoft.CodeAnalysis.Razor; internal interface IProjectEngineFactory { - RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure); + string ConfigurationName { get; } + bool SupportsSerialization { get; } + + RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/DefaultProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/DefaultProjectEngineFactory.cs index dab7adaedbc..963ce37f622 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/DefaultProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/DefaultProjectEngineFactory.cs @@ -1,9 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -#nullable disable - using System; +using System.Collections.Immutable; using Microsoft.AspNetCore.Razor.Language; using Microsoft.CodeAnalysis.Razor; @@ -11,12 +10,20 @@ namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; internal class DefaultProjectEngineFactory : IProjectEngineFactory { - internal static RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure, IProjectEngineFactory fallback, (IProjectEngineFactory, ICustomProjectEngineFactoryMetadata)[] factories) + public string ConfigurationName => "Default"; + public bool SupportsSerialization => true; + + internal static RazorProjectEngine Create( + RazorConfiguration configuration, + RazorProjectFileSystem fileSystem, + Action? configure, + IProjectEngineFactory fallback, + ImmutableArray factories) { var factoryToUse = fallback; - foreach (var (factory, metadata) in factories) + foreach (var factory in factories) { - if (configuration.ConfigurationName == metadata.ConfigurationName) + if (configuration.ConfigurationName == factory.ConfigurationName) { factoryToUse = factory; } @@ -25,7 +32,7 @@ internal static RazorProjectEngine Create(RazorConfiguration configuration, Razo return factoryToUse.Create(configuration, fileSystem, configure); } - public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure) + public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure) { return RazorProjectEngine.Create(configuration, fileSystem, b => { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/EmptyProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/EmptyProjectEngineFactory.cs index 7ce027938aa..d242b2beac0 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/EmptyProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/EmptyProjectEngineFactory.cs @@ -1,8 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -#nullable disable - using System; using Microsoft.AspNetCore.Razor.Language; using Microsoft.CodeAnalysis.Razor; @@ -11,7 +9,10 @@ namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; internal class EmptyProjectEngineFactory : IProjectEngineFactory { - public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure) + public string ConfigurationName => "Empty"; + public bool SupportsSerialization => true; + + public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure) { if (configuration is null) { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactories.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactories.cs index e231d00c804..acdf946878c 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactories.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactories.cs @@ -1,24 +1,31 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System; +using System.Collections.Immutable; using Microsoft.CodeAnalysis.Razor; namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; internal static class ProjectEngineFactories { - public static readonly (Lazy, ICustomProjectEngineFactoryMetadata)[] Factories = - new (Lazy, ICustomProjectEngineFactoryMetadata)[] - { - // Razor based configurations - (new (() => new DefaultProjectEngineFactory()), new CustomProjectEngineFactoryMetadata("Default") { SupportsSerialization = true }), - (new (() => new ProjectEngineFactory_1_0()), new CustomProjectEngineFactoryMetadata("MVC-1.0") { SupportsSerialization = true }), - (new (() => new ProjectEngineFactory_1_1()), new CustomProjectEngineFactoryMetadata("MVC-1.1") { SupportsSerialization = true }), - (new (() => new ProjectEngineFactory_2_0()), new CustomProjectEngineFactoryMetadata("MVC-2.0") { SupportsSerialization = true }), - (new (() => new ProjectEngineFactory_2_1()), new CustomProjectEngineFactoryMetadata("MVC-2.1") { SupportsSerialization = true }), - (new (() => new ProjectEngineFactory_3_0()), new CustomProjectEngineFactoryMetadata("MVC-3.0") { SupportsSerialization = true }), - // Unsupported (Legacy/System.Web.Razor) - (new (() => new ProjectEngineFactory_Unsupported()), new CustomProjectEngineFactoryMetadata(UnsupportedRazorConfiguration.Instance.ConfigurationName) { SupportsSerialization = true }), - }; + public static IProjectEngineFactory Default { get; } = new DefaultProjectEngineFactory(); + + public static IProjectEngineFactory MVC_1_0 { get; } = new ProjectEngineFactory("MVC-1.0", "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version1_X"); + public static IProjectEngineFactory MVC_1_1 { get; } = new ProjectEngineFactory("MVC-1.1", "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version1_X"); + public static IProjectEngineFactory MVC_2_0 { get; } = new ProjectEngineFactory("MVC-2.0", "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version2_X"); + public static IProjectEngineFactory MVC_2_1 { get; } = new ProjectEngineFactory("MVC-2.1", "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version2_X"); + public static IProjectEngineFactory MVC_3_0 { get; } = new ProjectEngineFactory("MVC-3.0", "Microsoft.CodeAnalysis.Razor.Compiler.Mvc"); + + public static IProjectEngineFactory Unsupported { get; } = new ProjectEngineFactory_Unsupported(); + + public static ImmutableArray All { get; } = ImmutableArray.Create( + // Razor based configurations + Default, + MVC_1_0, + MVC_1_1, + MVC_2_0, + MVC_2_1, + MVC_3_0, + // Unsupported (Legacy/System.Web.Razor) + Unsupported); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory.cs index 08051ae6da8..5b32d32165e 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory.cs @@ -8,21 +8,24 @@ namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; -internal abstract class ProjectEngineFactory : IProjectEngineFactory +internal sealed class ProjectEngineFactory(string configurationName, string assemblyName) : IProjectEngineFactory { - protected abstract string AssemblyName { get; } + private readonly string _assemblyName = assemblyName; + + public string ConfigurationName => configurationName; + public bool SupportsSerialization => true; public RazorProjectEngine Create( RazorConfiguration configuration, RazorProjectFileSystem fileSystem, - Action configure) + Action? configure) { // Rewrite the assembly name into a full name just like this one, but with the name of the MVC design time assembly. var assemblyFullName = typeof(RazorProjectEngine).Assembly.FullName.AssumeNotNull(); var assemblyName = new AssemblyName(assemblyFullName) { - Name = AssemblyName + Name = _assemblyName }; var extension = new AssemblyExtension(configuration.ConfigurationName, Assembly.Load(assemblyName)); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_1_0.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_1_0.cs deleted file mode 100644 index ffa44723fdc..00000000000 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_1_0.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; - -internal class ProjectEngineFactory_1_0 : ProjectEngineFactory -{ - protected override string AssemblyName { get; } = "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version1_X"; -} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_1_1.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_1_1.cs deleted file mode 100644 index c3904e0e2a8..00000000000 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_1_1.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; - -internal class ProjectEngineFactory_1_1 : ProjectEngineFactory -{ - protected override string AssemblyName { get; } = "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version1_X"; -} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_2_0.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_2_0.cs deleted file mode 100644 index 4a5acfcfbeb..00000000000 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_2_0.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; - -internal class ProjectEngineFactory_2_0 : ProjectEngineFactory -{ - protected override string AssemblyName { get; } = "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version2_X"; -} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_2_1.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_2_1.cs deleted file mode 100644 index 759c9555405..00000000000 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_2_1.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; - -internal class ProjectEngineFactory_2_1 : ProjectEngineFactory -{ - protected override string AssemblyName { get; } = "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version2_X"; -} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_3_0.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_3_0.cs deleted file mode 100644 index 6012bf618fb..00000000000 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_3_0.cs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; - -internal class ProjectEngineFactory_3_0 : ProjectEngineFactory -{ - protected override string AssemblyName { get; } = "Microsoft.CodeAnalysis.Razor.Compiler.Mvc"; -} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_Unsupported.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_Unsupported.cs index 6b00cf85867..620d2c6fc31 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_Unsupported.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_Unsupported.cs @@ -10,7 +10,10 @@ namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; internal class ProjectEngineFactory_Unsupported : IProjectEngineFactory { - public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure) + public string ConfigurationName => UnsupportedRazorConfiguration.Instance.ConfigurationName; + public bool SupportsSerialization => true; + + public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure) { return RazorProjectEngine.Create(configuration, fileSystem, builder => { diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_0.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_0.cs index a22285b0590..e67f03bac81 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_0.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_0.cs @@ -12,6 +12,9 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces; [ExportCustomProjectEngineFactory("MVC-1.0", SupportsSerialization = true)] internal class LegacyProjectEngineFactory_1_0 : IProjectEngineFactory { + public string ConfigurationName => "MVC-1.0"; + public bool SupportsSerialization => true; + private const string AssemblyName = "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version1_X"; public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_1.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_1.cs index 5426c21c53a..85f9c042b2e 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_1.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_1.cs @@ -12,6 +12,9 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces; [ExportCustomProjectEngineFactory("MVC-1.1", SupportsSerialization = true)] internal class LegacyProjectEngineFactory_1_1 : IProjectEngineFactory { + public string ConfigurationName => "MVC-1.1"; + public bool SupportsSerialization => true; + private const string AssemblyName = "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version1_X"; public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_0.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_0.cs index ec96ff17c81..5816380db4b 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_0.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_0.cs @@ -12,6 +12,9 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces; [ExportCustomProjectEngineFactory("MVC-2.0", SupportsSerialization = true)] internal class LegacyProjectEngineFactory_2_0 : IProjectEngineFactory { + public string ConfigurationName => "MVC-2.0"; + public bool SupportsSerialization => true; + private const string AssemblyName = "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version2_X"; public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure) { diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_1.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_1.cs index 1c6e383f476..5b04bae4545 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_1.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_1.cs @@ -14,7 +14,11 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces; [ExportCustomProjectEngineFactory("MVC-2.1", SupportsSerialization = true)] internal class LegacyProjectEngineFactory_2_1 : IProjectEngineFactory { + public string ConfigurationName => "MVC-2.1"; + public bool SupportsSerialization => true; + private const string AssemblyName = "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version2_X"; + public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure) { // Rewrite the assembly name into a full name just like this one, but with the name of the MVC design time assembly. diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_3_0.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_3_0.cs index 3c8952df713..f0f0adf3e73 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_3_0.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_3_0.cs @@ -12,7 +12,11 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces; [ExportCustomProjectEngineFactory("MVC-3.0", SupportsSerialization = true)] internal class LegacyProjectEngineFactory_3_0 : IProjectEngineFactory { + public string ConfigurationName => "MVC-3.0"; + public bool SupportsSerialization => true; + private const string AssemblyName = "Microsoft.CodeAnalysis.Razor.Compiler.Mvc"; + public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure) { // Rewrite the assembly name into a full name just like this one, but with the name of the MVC design time assembly. diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotManager.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotManager.cs index c9e962a7246..0ff5fbca5ec 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotManager.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotManager.cs @@ -25,7 +25,7 @@ public static TestProjectSnapshotManager Create(IErrorReporter errorReporter, Pr var services = TestServices.Create( workspaceServices: new[] { - new DefaultProjectSnapshotProjectEngineFactory(new FallbackProjectEngineFactory(), MefProjectEngineFactories.Factories) + new DefaultProjectSnapshotProjectEngineFactory(new FallbackProjectEngineFactory(), MefProjectEngineFactories.All) }, razorLanguageServices: Enumerable.Empty()); var workspace = TestWorkspace.Create(services); From 8515b2d31e9fa0076b6e480208b288a11b9d6042 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Wed, 17 Jan 2024 14:26:13 -0800 Subject: [PATCH 13/25] Move related types to ProjectEngineHost namespace --- ...erBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs | 1 + .../Common/DefaultProjectEngineFactory.cs | 1 + .../Common/MEFProjectEngineFactories.cs | 1 - .../ProjectEngineHost/CustomProjectEngineFactoryMetadata.cs | 1 - .../ProjectEngineHost/EmptyProjectEngineFactory.cs | 1 - .../ICustomProjectEngineFactoryMetadata.cs | 2 +- .../{ => ProjectEngineHost}/IProjectEngineFactory.cs | 2 +- .../ProjectEngineHost/ProjectEngineFactories.cs | 1 - .../ProjectEngineHost/ProjectEngineFactory_Unsupported.cs | 1 - .../DefaultProjectSnapshotProjectEngineFactory.cs | 1 + .../DefaultProjectSnapshotProjectEngineFactoryFactory.cs | 1 + .../ExportCustomProjectEngineFactoryAttribute.cs | 1 + .../IFallbackProjectEngineFactory.cs | 2 ++ .../IProjectSnapshotProjectEngineFactory.cs | 1 + .../LegacyProjectEngineFactory_1_0.cs | 1 + .../LegacyProjectEngineFactory_1_1.cs | 1 + .../LegacyProjectEngineFactory_2_0.cs | 1 + .../LegacyProjectEngineFactory_2_1.cs | 1 + .../LegacyProjectEngineFactory_3_0.cs | 1 + .../Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs | 1 + .../RemoteTagHelperResolver.cs | 1 + .../LanguageServer/TestProjectSnapshotProjectEngineFactory.cs | 1 + .../ProjectSystem/TestProjectSnapshotProjectEngineFactory.cs | 1 + .../OOPTagHelperResolverTest.TestResolver.cs | 1 + .../OOPTagHelperResolverTest.cs | 1 + .../DefaultProjectSnapshotProjectEngineFactoryTest.cs | 1 + 26 files changed, 22 insertions(+), 7 deletions(-) rename src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/{ => ProjectEngineHost}/ICustomProjectEngineFactoryMetadata.cs (84%) rename src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/{ => ProjectEngineHost}/IProjectEngineFactory.cs (89%) diff --git a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs index 9d97a6a0b66..ffcb8a5a65b 100644 --- a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs +++ b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs @@ -4,6 +4,7 @@ using System; using Microsoft.AspNetCore.Mvc.Razor.Extensions; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.ProjectSystem; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/DefaultProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/DefaultProjectEngineFactory.cs index f72ceb5f564..b92f3801d66 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/DefaultProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/DefaultProjectEngineFactory.cs @@ -3,6 +3,7 @@ using System; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis.Razor; namespace Microsoft.AspNetCore.Razor.LanguageServer.Common; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/MEFProjectEngineFactories.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/MEFProjectEngineFactories.cs index 7031c19fe8d..40ebbf0e8f4 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/MEFProjectEngineFactories.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/MEFProjectEngineFactories.cs @@ -4,7 +4,6 @@ using System; using System.Linq; using Microsoft.AspNetCore.Razor.ProjectEngineHost; -using Microsoft.CodeAnalysis.Razor; namespace Microsoft.AspNetCore.Razor.LanguageServer.Common; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/CustomProjectEngineFactoryMetadata.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/CustomProjectEngineFactoryMetadata.cs index 48a81da5410..8ba90c1c88b 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/CustomProjectEngineFactoryMetadata.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/CustomProjectEngineFactoryMetadata.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; -using Microsoft.CodeAnalysis.Razor; namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/EmptyProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/EmptyProjectEngineFactory.cs index d242b2beac0..8719ef8ab76 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/EmptyProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/EmptyProjectEngineFactory.cs @@ -3,7 +3,6 @@ using System; using Microsoft.AspNetCore.Razor.Language; -using Microsoft.CodeAnalysis.Razor; namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ICustomProjectEngineFactoryMetadata.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ICustomProjectEngineFactoryMetadata.cs similarity index 84% rename from src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ICustomProjectEngineFactoryMetadata.cs rename to src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ICustomProjectEngineFactoryMetadata.cs index 15ef7fc16fd..943632d4d61 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ICustomProjectEngineFactoryMetadata.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ICustomProjectEngineFactoryMetadata.cs @@ -1,7 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -namespace Microsoft.CodeAnalysis.Razor; +namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; internal interface ICustomProjectEngineFactoryMetadata { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/IProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/IProjectEngineFactory.cs similarity index 89% rename from src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/IProjectEngineFactory.cs rename to src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/IProjectEngineFactory.cs index 45c3918a7b3..4dcdbe90179 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/IProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/IProjectEngineFactory.cs @@ -4,7 +4,7 @@ using System; using Microsoft.AspNetCore.Razor.Language; -namespace Microsoft.CodeAnalysis.Razor; +namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; internal interface IProjectEngineFactory { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactories.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactories.cs index acdf946878c..cac35d58d2d 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactories.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactories.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System.Collections.Immutable; -using Microsoft.CodeAnalysis.Razor; namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_Unsupported.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_Unsupported.cs index 620d2c6fc31..b0475e00ab8 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_Unsupported.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_Unsupported.cs @@ -4,7 +4,6 @@ using System; using System.Linq; using Microsoft.AspNetCore.Razor.Language; -using Microsoft.CodeAnalysis.Razor; namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactory.cs index a0aa679c645..c10324d3cd5 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactory.cs @@ -3,6 +3,7 @@ using System; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis.Razor.ProjectSystem; namespace Microsoft.CodeAnalysis.Razor; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactoryFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactoryFactory.cs index 47e793f24e4..8a756166dd5 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactoryFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactoryFactory.cs @@ -3,6 +3,7 @@ using System; using System.Composition; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ExportCustomProjectEngineFactoryAttribute.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ExportCustomProjectEngineFactoryAttribute.cs index 260c1065fd1..3d3a90e5979 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ExportCustomProjectEngineFactoryAttribute.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ExportCustomProjectEngineFactoryAttribute.cs @@ -3,6 +3,7 @@ using System; using System.Composition; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; namespace Microsoft.CodeAnalysis.Razor; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IFallbackProjectEngineFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IFallbackProjectEngineFactory.cs index ae02e94736e..f56b0479802 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IFallbackProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IFallbackProjectEngineFactory.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. +using Microsoft.AspNetCore.Razor.ProjectEngineHost; + namespace Microsoft.CodeAnalysis.Razor; // Used to create the 'fallback' project engine when we don't have a custom implementation. diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactory.cs index 8fad079af6b..ec8d72bbc3b 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactory.cs @@ -3,6 +3,7 @@ using System; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Razor.ProjectSystem; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_0.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_0.cs index e67f03bac81..88c19f93726 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_0.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_0.cs @@ -6,6 +6,7 @@ using System; using System.Reflection; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; namespace Microsoft.CodeAnalysis.Razor.Workspaces; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_1.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_1.cs index 85f9c042b2e..9497a953f4c 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_1.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_1.cs @@ -6,6 +6,7 @@ using System; using System.Reflection; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; namespace Microsoft.CodeAnalysis.Razor.Workspaces; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_0.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_0.cs index 5816380db4b..03459bc33d3 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_0.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_0.cs @@ -6,6 +6,7 @@ using System; using System.Reflection; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; namespace Microsoft.CodeAnalysis.Razor.Workspaces; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_1.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_1.cs index 5b04bae4545..c036419a222 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_1.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_1.cs @@ -6,6 +6,7 @@ using System; using System.Reflection; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; namespace Microsoft.CodeAnalysis.Razor.Workspaces; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_3_0.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_3_0.cs index f0f0adf3e73..731e2cec031 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_3_0.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_3_0.cs @@ -6,6 +6,7 @@ using System; using System.Reflection; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; namespace Microsoft.CodeAnalysis.Razor.Workspaces; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs index 588f2a624ca..b5fc3b63f7b 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.PooledObjects; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Serialization; using Microsoft.AspNetCore.Razor.Telemetry; using Microsoft.AspNetCore.Razor.Utilities; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteTagHelperResolver.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteTagHelperResolver.cs index c69f7749190..02c00cf664e 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteTagHelperResolver.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteTagHelperResolver.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Telemetry; using Microsoft.CodeAnalysis.Razor; diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotProjectEngineFactory.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotProjectEngineFactory.cs index b0c5dbf9366..cd8a0113aba 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotProjectEngineFactory.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotProjectEngineFactory.cs @@ -3,6 +3,7 @@ using System; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.ProjectSystem; diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectSnapshotProjectEngineFactory.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectSnapshotProjectEngineFactory.cs index 0e1b79b90c8..3bb5abc93f8 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectSnapshotProjectEngineFactory.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectSnapshotProjectEngineFactory.cs @@ -3,6 +3,7 @@ using System; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.ProjectSystem; diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestResolver.cs b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestResolver.cs index 7e14936108f..520dfeedf90 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestResolver.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestResolver.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Serialization; using Microsoft.AspNetCore.Razor.Telemetry; using Microsoft.AspNetCore.Razor.Utilities; diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.cs b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.cs index 51bfc6d4aaa..6ec3adb3f25 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Serialization; using Microsoft.AspNetCore.Razor.Telemetry; using Microsoft.AspNetCore.Razor.Test.Common.Workspaces; diff --git a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectSnapshotProjectEngineFactoryTest.cs b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectSnapshotProjectEngineFactoryTest.cs index af01525de94..49f0e911b3f 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectSnapshotProjectEngineFactoryTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectSnapshotProjectEngineFactoryTest.cs @@ -6,6 +6,7 @@ using System; using System.Reflection; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.ProjectSystem; using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.CodeAnalysis.Razor.ProjectSystem; From 3f6d4949b8b15c7269dce696e20550a987fdd915 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Thu, 18 Jan 2024 11:54:27 -0800 Subject: [PATCH 14/25] Remove IProjectSnapshotProjectEngineFactory This is a much larger commit because it removes a fundamental service that is used in a lot of places and replaces it with a simpler system. Razor has a system for defining custom IProjectEngineFactory instances whose jobs are to create RazorProjectEngines. This system was fairly complex and clearly designed with extensibility in mind so that anyone could export their own IProjectEngineFactory via MEF. However, this extensibility isn't actually possible, since the IProjectEngineFactory interface is internal. My guess is that this might have been a real extensibility point many years ago, but was lost in some transition to support a new platform (maybe ASP.NET Core? maybe LSP?). There is now a simpler service called IProjectEngineFactoryProvider. The job of this service is to locate the correct factory to use from a static list of choices. There is likely further work that can be done here, but this change removes much of the complexity. --- ...aticProjectSnapshotProjectEngineFactory.cs | 37 ++++--- .../ProjectSnapshotManagerBenchmarkBase.cs | 7 +- .../RazorProjectInfoSerializer.cs | 13 ++- .../Cohost/CohostProjectSnapshot.cs | 27 +++--- .../Common/DefaultProjectEngineFactory.cs | 26 ----- .../Common/MEFProjectEngineFactories.cs | 16 --- .../DefaultProjectSnapshotManagerAccessor.cs | 9 +- .../LspProjectEngineFactoryProvider.cs | 70 +++++++++++++ ...moteProjectSnapshotProjectEngineFactory.cs | 73 -------------- .../CustomProjectEngineFactoryMetadata.cs | 18 ---- .../DefaultProjectEngineFactory.cs | 20 ---- .../EmptyProjectEngineFactory.cs | 2 +- .../ICustomProjectEngineFactoryMetadata.cs | 11 --- .../IProjectEngineFactoryProvider.cs | 16 +++ .../ProjectEngineFactories.cs | 6 +- .../ProjectEngineFactory.InitializerKey.cs | 26 +++++ .../ProjectEngineHost/ProjectEngineFactory.cs | 36 +++++-- .../ProjectEngineFactoryProvider.cs | 29 ++++++ .../Properties/AssemblyInfo.cs | 1 + ...aultProjectSnapshotProjectEngineFactory.cs | 97 ------------------- ...jectSnapshotProjectEngineFactoryFactory.cs | 46 --------- ...portCustomProjectEngineFactoryAttribute.cs | 23 ----- .../ExportDefaultProjectEngineFactory.cs | 13 --- .../FallbackProjectEngineFactory.cs | 14 --- .../IFallbackProjectEngineFactory.cs | 11 --- .../IProjectSnapshotProjectEngineFactory.cs | 19 ---- ...tSnapshotProjectEngineFactoryExtensions.cs | 72 -------------- .../LegacyProjectEngineFactory_1_0.cs | 38 -------- .../LegacyProjectEngineFactory_1_1.cs | 38 -------- .../LegacyProjectEngineFactory_2_0.cs | 37 ------- .../LegacyProjectEngineFactory_2_1.cs | 40 -------- .../LegacyProjectEngineFactory_3_0.cs | 40 -------- .../IProjectEngineFactoryExtensions.cs | 45 +++++++++ .../DefaultProjectSnapshotManager.cs | 8 +- .../DefaultProjectSnapshotManagerFactory.cs | 3 + .../ProjectSystem/ProjectState.cs | 36 +++---- .../IRemoteTagHelperProviderService.cs | 2 - .../OOPTagHelperResolver.cs | 16 ++- .../OOPTagHelperResolverFactory.cs | 4 +- .../RemoteTagHelperProviderService.cs | 12 +-- .../RemoteTagHelperResolver.cs | 48 ++++----- .../DefaultVisualStudioDocumentTracker.cs | 35 ++++--- ...faultVisualStudioDocumentTrackerFactory.cs | 51 ++-------- ...sualStudioDocumentTrackerFactoryFactory.cs | 52 +++------- .../DefaultVisualStudioRazorParser.cs | 24 +++-- .../DefaultVisualStudioRazorParserFactory.cs | 52 +++------- ...ltVisualStudioRazorParserFactoryFactory.cs | 12 +-- .../EphemeralProjectSnapshot.cs | 21 +--- .../VisualStudioDocumentTracker.cs | 3 - ...isualStudioProjectEngineFactoryProvider.cs | 20 ++++ .../LanguageServer/TestProjectSnapshot.cs | 4 +- .../TestProjectSnapshotManager.cs | 22 ++--- ...TestProjectSnapshotProjectEngineFactory.cs | 35 ------- .../TestProjectEngineFactoryProvider.cs | 41 ++++++++ .../TestProjectSnapshotManager.cs | 7 +- ...TestProjectSnapshotProjectEngineFactory.cs | 39 -------- .../DocumentExcerptServiceTestBase.cs | 2 +- .../Workspaces/WorkspaceTestBase.cs | 19 ++-- .../DefaultDocumentSnapshotTest.cs | 2 +- .../DefaultProjectSnapshotTest.cs | 10 +- .../FallbackProjectManagerTest.cs | 2 +- .../GeneratedDocumentTextLoaderTest.cs | 2 +- .../ProjectStateGeneratedOutputTest.cs | 18 ++-- .../ProjectSystem/ProjectStateTest.cs | 68 ++++++------- .../RazorSpanMappingServiceTest.cs | 8 +- ...ResolverTest.TestProjectSnapshotManager.cs | 4 +- .../OOPTagHelperResolverTest.TestResolver.cs | 4 +- .../OOPTagHelperResolverTest.cs | 70 ++++++++----- ...ProjectSnapshotProjectEngineFactoryTest.cs | 68 ++++++------- ...faultProjectWorkspaceStateGeneratorTest.cs | 12 ++- .../DefaultRazorDocumentManagerTest.cs | 16 ++- .../DefaultVisualStudioDocumentTrackerTest.cs | 4 +- ...tVisualStudioRazorParserIntegrationTest.cs | 33 ++++--- .../DefaultVisualStudioRazorParserTest.cs | 61 ++++++------ .../RazorDocumentOptionsServiceTest.cs | 2 +- .../BackgroundDocumentGeneratorTest.cs | 14 +-- .../DefaultProjectSnapshotManagerTest.cs | 17 ++-- ...DefaultRazorDynamicFileInfoProviderTest.cs | 2 +- .../DefaultWindowsRazorProjectHostTest.cs | 19 ++-- .../FallbackWindowsRazorProjectHostTest.cs | 17 ++-- ...WorkspaceProjectStateChangeDetectorTest.cs | 42 ++++---- ...UpdatesProjectSnapshotChangeTriggerTest.cs | 12 +-- ...ojectSnapshotSynchronizationServiceTest.cs | 2 +- .../DefaultProjectSnapshotManagerProxyTest.cs | 8 +- 84 files changed, 771 insertions(+), 1290 deletions(-) delete mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/DefaultProjectEngineFactory.cs delete mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/MEFProjectEngineFactories.cs create mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspProjectEngineFactoryProvider.cs delete mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RemoteProjectSnapshotProjectEngineFactory.cs delete mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/CustomProjectEngineFactoryMetadata.cs delete mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ICustomProjectEngineFactoryMetadata.cs create mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/IProjectEngineFactoryProvider.cs create mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory.InitializerKey.cs create mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactoryProvider.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactoryFactory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ExportCustomProjectEngineFactoryAttribute.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ExportDefaultProjectEngineFactory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/FallbackProjectEngineFactory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IFallbackProjectEngineFactory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactory.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactoryExtensions.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_0.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_1.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_0.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_1.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_3_0.cs create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectEngineHost/IProjectEngineFactoryExtensions.cs create mode 100644 src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioProjectEngineFactoryProvider.cs delete mode 100644 src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotProjectEngineFactory.cs create mode 100644 src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectEngineFactoryProvider.cs delete mode 100644 src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectSnapshotProjectEngineFactory.cs diff --git a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs index ffcb8a5a65b..d2be110cb9e 100644 --- a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs +++ b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs @@ -2,28 +2,43 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; +using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Mvc.Razor.Extensions; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.ProjectEngineHost; -using Microsoft.CodeAnalysis.Razor; -using Microsoft.CodeAnalysis.Razor.ProjectSystem; namespace Microsoft.AspNetCore.Razor.Microbenchmarks; public abstract partial class ProjectSnapshotManagerBenchmarkBase { - private class StaticProjectSnapshotProjectEngineFactory : IProjectSnapshotProjectEngineFactory + private class StaticProjectEngineFactoryProvider : IProjectEngineFactoryProvider { - public IProjectEngineFactory? FindFactory(IProjectSnapshot project) - => throw new NotImplementedException(); + public static readonly StaticProjectEngineFactoryProvider Instance = new(); - public IProjectEngineFactory? FindSerializableFactory(IProjectSnapshot project) - => throw new NotImplementedException(); + private StaticProjectEngineFactoryProvider() + { + } - public RazorProjectEngine Create( + [return: NotNullIfNotNull(nameof(fallbackFactory))] + public IProjectEngineFactory? GetFactory( RazorConfiguration configuration, - RazorProjectFileSystem fileSystem, - Action? configure) - => RazorProjectEngine.Create(configuration, fileSystem, RazorExtensions.Register); + IProjectEngineFactory? fallbackFactory = null, + bool requireSerializationSupport = false) + => Factory.Instance; + + private sealed class Factory : IProjectEngineFactory + { + public static readonly Factory Instance = new(); + + private Factory() + { + } + + public string ConfigurationName => "Static"; + public bool SupportsSerialization => false; + + public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure) + => RazorProjectEngine.Create(configuration, fileSystem, RazorExtensions.Register); + } } } diff --git a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.cs b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.cs index ad1fc9cd30b..e9ca40232c2 100644 --- a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.cs +++ b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.cs @@ -67,11 +67,7 @@ protected ProjectSnapshotManagerBenchmarkBase(int documentCount = 100) internal DefaultProjectSnapshotManager CreateProjectSnapshotManager() { var services = TestServices.Create( - new IWorkspaceService[] - { - TagHelperResolver, - new StaticProjectSnapshotProjectEngineFactory(), - }, + [TagHelperResolver], Array.Empty()); return new DefaultProjectSnapshotManager( @@ -79,6 +75,7 @@ internal DefaultProjectSnapshotManager CreateProjectSnapshotManager() Array.Empty(), #pragma warning disable CA2000 // Dispose objects before losing scope new AdhocWorkspace(services), + StaticProjectEngineFactoryProvider.Instance, new TestProjectSnapshotManagerDispatcher()); #pragma warning restore CA2000 // Dispose objects before losing scope } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace/RazorProjectInfoSerializer.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace/RazorProjectInfoSerializer.cs index 6ce7cdf9bd0..0b10016bb18 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace/RazorProjectInfoSerializer.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace/RazorProjectInfoSerializer.cs @@ -20,12 +20,10 @@ namespace Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace; internal static class RazorProjectInfoSerializer { - private static readonly EmptyProjectEngineFactory s_fallbackProjectEngineFactory; private static readonly StringComparison s_stringComparison; static RazorProjectInfoSerializer() { - s_fallbackProjectEngineFactory = new EmptyProjectEngineFactory(); s_stringComparison = RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase; @@ -72,12 +70,13 @@ public static async Task SerializeAsync(Project project, string configurationFil builder.SetSupportLocalizedComponentNames(); // ProjectState in MS.CA.Razor.Workspaces does this, so I'm doing it too! }; - var engine = DefaultProjectEngineFactory.Create( + var engineFactory = ProjectEngineFactories.DefaultProvider.GetFactory( + configuration, ProjectEngineFactories.Empty); + + var engine = engineFactory.Create( configuration, - fileSystem: fileSystem, - configure: defaultConfigure, - fallback: s_fallbackProjectEngineFactory, - factories: ProjectEngineFactories.All); + fileSystem, + configure: defaultConfigure); var resolver = new CompilationTagHelperResolver(NoOpTelemetryReporter.Instance); var tagHelpers = await resolver.GetTagHelpersAsync(project, engine, cancellationToken).ConfigureAwait(false); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Cohost/CohostProjectSnapshot.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Cohost/CohostProjectSnapshot.cs index 4e14264bff6..aa72196c6c7 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Cohost/CohostProjectSnapshot.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Cohost/CohostProjectSnapshot.cs @@ -23,8 +23,6 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Cohost; internal class CohostProjectSnapshot : IProjectSnapshot { - private static readonly EmptyProjectEngineFactory s_fallbackProjectEngineFactory = new(); - private readonly Project _project; private readonly DocumentSnapshotFactory _documentSnapshotFactory; private readonly ITelemetryReporter _telemetryReporter; @@ -43,17 +41,20 @@ public CohostProjectSnapshot(Project project, DocumentSnapshotFactory documentSn _projectKey = ProjectKey.From(_project).AssumeNotNull(); _lazyConfiguration = new Lazy(CreateRazorConfiguration); - _lazyProjectEngine = new Lazy(() => DefaultProjectEngineFactory.Create( - Configuration, - fileSystem: RazorProjectFileSystem.Create(Path.GetDirectoryName(FilePath)), - configure: builder => - { - builder.SetRootNamespace(RootNamespace); - builder.SetCSharpLanguageVersion(CSharpLanguageVersion); - builder.SetSupportLocalizedComponentNames(); - }, - fallback: s_fallbackProjectEngineFactory, - factories: ProjectEngineFactories.All)); + _lazyProjectEngine = new Lazy(() => + { + var factory = ProjectEngineFactories.DefaultProvider.GetFactory(Configuration, ProjectEngineFactories.Empty); + + return factory.Create( + Configuration, + fileSystem: RazorProjectFileSystem.Create(Path.GetDirectoryName(FilePath)), + configure: builder => + { + builder.SetRootNamespace(RootNamespace); + builder.SetCSharpLanguageVersion(CSharpLanguageVersion); + builder.SetSupportLocalizedComponentNames(); + }); + }); _tagHelpersLazy = new AsyncLazy>(() => { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/DefaultProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/DefaultProjectEngineFactory.cs deleted file mode 100644 index b92f3801d66..00000000000 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/DefaultProjectEngineFactory.cs +++ /dev/null @@ -1,26 +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; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; -using Microsoft.CodeAnalysis.Razor; - -namespace Microsoft.AspNetCore.Razor.LanguageServer.Common; - -[ExportCustomProjectEngineFactory("Default", SupportsSerialization = true)] -internal class DefaultProjectEngineFactory : IProjectEngineFactory -{ - public string ConfigurationName => "Default"; - public bool SupportsSerialization => true; - - public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure) - { - return RazorProjectEngine.Create(configuration, fileSystem, b => - { - CompilerFeatures.Register(b); - - configure?.Invoke(b); - }); - } -} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/MEFProjectEngineFactories.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/MEFProjectEngineFactories.cs deleted file mode 100644 index 40ebbf0e8f4..00000000000 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/MEFProjectEngineFactories.cs +++ /dev/null @@ -1,16 +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; -using System.Linq; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; - -namespace Microsoft.AspNetCore.Razor.LanguageServer.Common; - -internal static class MefProjectEngineFactories -{ - // The actual factories are defined in the ProjectEngineHost project, but we need to convert them - // to Lazy<,> to be MEF compatible. - public static readonly Lazy[] All = - ProjectEngineFactories.All.Select(f => new Lazy(() => f, new CustomProjectEngineFactoryMetadata(f.ConfigurationName) { SupportsSerialization = f.SupportsSerialization })).ToArray(); -} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultProjectSnapshotManagerAccessor.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultProjectSnapshotManagerAccessor.cs index 84e1f95a1da..49b506912b5 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultProjectSnapshotManagerAccessor.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultProjectSnapshotManagerAccessor.cs @@ -31,15 +31,14 @@ public override ProjectSnapshotManagerBase Instance { if (_instance is null) { - var workspace = _workspaceFactory.Create( - workspaceServices: new[] - { - new RemoteProjectSnapshotProjectEngineFactory(_optionsMonitor) - }); + var projectEngineFactoryProvider = new LspProjectEngineFactoryProvider(_optionsMonitor); + var workspace = _workspaceFactory.Create(); + _instance = new DefaultProjectSnapshotManager( _errorReporter, _changeTriggers, workspace, + projectEngineFactoryProvider, _dispatcher); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspProjectEngineFactoryProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspProjectEngineFactoryProvider.cs new file mode 100644 index 00000000000..b9892a84e36 --- /dev/null +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspProjectEngineFactoryProvider.cs @@ -0,0 +1,70 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.Diagnostics.CodeAnalysis; +using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.Razor.LanguageServer; + +/// +/// In the language server, we provide an that wraps +/// and configure every +/// with the current code-gen options. +/// +internal sealed class LspProjectEngineFactoryProvider(IOptionsMonitor optionsMonitor) : IProjectEngineFactoryProvider +{ + [return: NotNullIfNotNull(nameof(fallbackFactory))] + public IProjectEngineFactory? GetFactory( + RazorConfiguration configuration, + IProjectEngineFactory? fallbackFactory = null, + bool requireSerializationSupport = false) + { + var factory = ProjectEngineFactories.DefaultProvider.GetFactory(configuration, ProjectEngineFactories.Empty); + + return new Factory(factory, optionsMonitor); + } + + private class Factory(IProjectEngineFactory innerFactory, IOptionsMonitor optionsMonitor) : IProjectEngineFactory + { + public string ConfigurationName => innerFactory.ConfigurationName; + public bool SupportsSerialization => false; + + public RazorProjectEngine Create( + RazorConfiguration configuration, + RazorProjectFileSystem fileSystem, + Action? configure) + { + if (fileSystem is not DefaultRazorProjectFileSystem defaultFileSystem) + { + throw new InvalidOperationException("Unexpected file system."); + } + + var remoteFileSystem = new RemoteRazorProjectFileSystem(defaultFileSystem.Root); + return innerFactory.Create(configuration, remoteFileSystem, Configure); + + void Configure(RazorProjectEngineBuilder builder) + { + configure?.Invoke(builder); + builder.Features.Add(new CodeGenFeature(optionsMonitor)); + } + } + + private class CodeGenFeature(IOptionsMonitor optionsMonitor) : RazorEngineFeatureBase, IConfigureRazorCodeGenerationOptionsFeature + { + public int Order { get; set; } + + public void Configure(RazorCodeGenerationOptionsBuilder options) + { + // We don't need to explicitly subscribe to options changing because this method will be run on every parse. + var currentOptions = optionsMonitor.CurrentValue; + + options.IndentSize = currentOptions.TabSize; + options.IndentWithTabs = !currentOptions.InsertSpaces; + options.RemapLinePragmaPathsOnWindows = true; + } + } + } +} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RemoteProjectSnapshotProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RemoteProjectSnapshotProjectEngineFactory.cs deleted file mode 100644 index f884f135708..00000000000 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RemoteProjectSnapshotProjectEngineFactory.cs +++ /dev/null @@ -1,73 +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; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.LanguageServer.Common; -using Microsoft.CodeAnalysis.Razor; -using Microsoft.Extensions.Options; - -namespace Microsoft.AspNetCore.Razor.LanguageServer; - -internal class RemoteProjectSnapshotProjectEngineFactory : DefaultProjectSnapshotProjectEngineFactory -{ - public static readonly IFallbackProjectEngineFactory FallbackProjectEngineFactory = new FallbackProjectEngineFactory(); - - private readonly IOptionsMonitor _optionsMonitor; - - public RemoteProjectSnapshotProjectEngineFactory(IOptionsMonitor optionsMonitor) - : base(FallbackProjectEngineFactory, MefProjectEngineFactories.All) - { - if (optionsMonitor is null) - { - throw new ArgumentNullException(nameof(optionsMonitor)); - } - - _optionsMonitor = optionsMonitor; - } - - public override RazorProjectEngine Create( - RazorConfiguration configuration, - RazorProjectFileSystem fileSystem, - Action? configure) - { - if (fileSystem is not DefaultRazorProjectFileSystem defaultFileSystem) - { - throw new InvalidOperationException("Unexpected file system."); - } - - var remoteFileSystem = new RemoteRazorProjectFileSystem(defaultFileSystem.Root); - return base.Create(configuration, remoteFileSystem, Configure); - - void Configure(RazorProjectEngineBuilder builder) - { - configure?.Invoke(builder); - builder.Features.Add(new RemoteCodeGenerationOptionsFeature(_optionsMonitor)); - } - } - - private class RemoteCodeGenerationOptionsFeature : RazorEngineFeatureBase, IConfigureRazorCodeGenerationOptionsFeature - { - private readonly IOptionsMonitor _optionsMonitor; - - public RemoteCodeGenerationOptionsFeature(IOptionsMonitor optionsMonitor) - { - if (optionsMonitor is null) - { - throw new ArgumentNullException(nameof(optionsMonitor)); - } - - _optionsMonitor = optionsMonitor; - } - - public int Order { get; set; } - - public void Configure(RazorCodeGenerationOptionsBuilder options) - { - // We don't need to explicitly subscribe to options changing because this method will be run on every parse. - options.IndentSize = _optionsMonitor.CurrentValue.TabSize; - options.IndentWithTabs = !_optionsMonitor.CurrentValue.InsertSpaces; - options.RemapLinePragmaPathsOnWindows = true; - } - } -} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/CustomProjectEngineFactoryMetadata.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/CustomProjectEngineFactoryMetadata.cs deleted file mode 100644 index 8ba90c1c88b..00000000000 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/CustomProjectEngineFactoryMetadata.cs +++ /dev/null @@ -1,18 +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.AspNetCore.Razor.ProjectEngineHost; - -internal class CustomProjectEngineFactoryMetadata : ICustomProjectEngineFactoryMetadata -{ - public CustomProjectEngineFactoryMetadata(string configurationName) - { - ConfigurationName = configurationName ?? throw new ArgumentNullException(nameof(configurationName)); - } - - public string ConfigurationName { get; } - - public bool SupportsSerialization { get; set; } -} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/DefaultProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/DefaultProjectEngineFactory.cs index 963ce37f622..098316dbfce 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/DefaultProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/DefaultProjectEngineFactory.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; -using System.Collections.Immutable; using Microsoft.AspNetCore.Razor.Language; using Microsoft.CodeAnalysis.Razor; @@ -13,25 +12,6 @@ internal class DefaultProjectEngineFactory : IProjectEngineFactory public string ConfigurationName => "Default"; public bool SupportsSerialization => true; - internal static RazorProjectEngine Create( - RazorConfiguration configuration, - RazorProjectFileSystem fileSystem, - Action? configure, - IProjectEngineFactory fallback, - ImmutableArray factories) - { - var factoryToUse = fallback; - foreach (var factory in factories) - { - if (configuration.ConfigurationName == factory.ConfigurationName) - { - factoryToUse = factory; - } - } - - return factoryToUse.Create(configuration, fileSystem, configure); - } - public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure) { return RazorProjectEngine.Create(configuration, fileSystem, b => diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/EmptyProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/EmptyProjectEngineFactory.cs index 8719ef8ab76..d1c0d7fd4b1 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/EmptyProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/EmptyProjectEngineFactory.cs @@ -6,7 +6,7 @@ namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; -internal class EmptyProjectEngineFactory : IProjectEngineFactory +internal sealed class EmptyProjectEngineFactory : IProjectEngineFactory { public string ConfigurationName => "Empty"; public bool SupportsSerialization => true; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ICustomProjectEngineFactoryMetadata.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ICustomProjectEngineFactoryMetadata.cs deleted file mode 100644 index 943632d4d61..00000000000 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ICustomProjectEngineFactoryMetadata.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; - -internal interface ICustomProjectEngineFactoryMetadata -{ - string ConfigurationName { get; } - - bool SupportsSerialization { get; } -} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/IProjectEngineFactoryProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/IProjectEngineFactoryProvider.cs new file mode 100644 index 00000000000..4eebe20b1b5 --- /dev/null +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/IProjectEngineFactoryProvider.cs @@ -0,0 +1,16 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Diagnostics.CodeAnalysis; +using Microsoft.AspNetCore.Razor.Language; + +namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; + +internal interface IProjectEngineFactoryProvider +{ + [return: NotNullIfNotNull(nameof(fallbackFactory))] + IProjectEngineFactory? GetFactory( + RazorConfiguration configuration, + IProjectEngineFactory? fallbackFactory = null, + bool requireSerializationSupport = false); +} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactories.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactories.cs index cac35d58d2d..7e13f441924 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactories.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactories.cs @@ -5,8 +5,10 @@ namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; -internal static class ProjectEngineFactories +internal static partial class ProjectEngineFactories { + public static IProjectEngineFactory Empty { get; } = new EmptyProjectEngineFactory(); + public static IProjectEngineFactory Default { get; } = new DefaultProjectEngineFactory(); public static IProjectEngineFactory MVC_1_0 { get; } = new ProjectEngineFactory("MVC-1.0", "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version1_X"); @@ -27,4 +29,6 @@ internal static class ProjectEngineFactories MVC_3_0, // Unsupported (Legacy/System.Web.Razor) Unsupported); + + public static IProjectEngineFactoryProvider DefaultProvider { get; } = new ProjectEngineFactoryProvider(All); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory.InitializerKey.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory.InitializerKey.cs new file mode 100644 index 00000000000..569d82e64d4 --- /dev/null +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory.InitializerKey.cs @@ -0,0 +1,26 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using Microsoft.Extensions.Internal; + +namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; + +internal sealed partial class ProjectEngineFactory +{ + private readonly record struct InitializerKey(string ConfigurationName, string AssemblyName) + { + public bool Equals(InitializerKey other) + => ConfigurationName == other.ConfigurationName && + AssemblyName == other.AssemblyName; + + public override int GetHashCode() + { + var hash = HashCodeCombiner.Start(); + hash.Add(ConfigurationName, StringComparer.Ordinal); + hash.Add(AssemblyName, StringComparer.Ordinal); + + return hash.CombinedHash; + } + } +} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory.cs index 5b32d32165e..697ceac6149 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory.cs @@ -2,14 +2,17 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Reflection; using Microsoft.AspNetCore.Razor.Language; using Microsoft.CodeAnalysis.Razor; namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; -internal sealed class ProjectEngineFactory(string configurationName, string assemblyName) : IProjectEngineFactory +internal sealed partial class ProjectEngineFactory(string configurationName, string assemblyName) : IProjectEngineFactory { + private static readonly Dictionary s_initializerMap = []; + private readonly string _assemblyName = assemblyName; public string ConfigurationName => configurationName; @@ -20,16 +23,18 @@ public RazorProjectEngine Create( RazorProjectFileSystem fileSystem, Action? configure) { - // Rewrite the assembly name into a full name just like this one, but with the name of the MVC design time assembly. - var assemblyFullName = typeof(RazorProjectEngine).Assembly.FullName.AssumeNotNull(); + RazorExtensionInitializer? initializer; - var assemblyName = new AssemblyName(assemblyFullName) + lock (s_initializerMap) { - Name = _assemblyName - }; + var key = new InitializerKey(configuration.ConfigurationName, _assemblyName); + if (!s_initializerMap.TryGetValue(key, out initializer)) + { + initializer = CreateInitializer(key); - var extension = new AssemblyExtension(configuration.ConfigurationName, Assembly.Load(assemblyName)); - var initializer = extension.CreateInitializer(); + s_initializerMap.Add(key, initializer); + } + } return RazorProjectEngine.Create(configuration, fileSystem, builder => { @@ -37,5 +42,20 @@ public RazorProjectEngine Create( initializer.Initialize(builder); configure?.Invoke(builder); }); + + static RazorExtensionInitializer CreateInitializer(InitializerKey key) + { + // Rewrite the assembly name into a full name just like this one, but with the name of the MVC design time assembly. + var assemblyFullName = typeof(RazorProjectEngine).Assembly.FullName.AssumeNotNull(); + + var extensionAssemblyName = new AssemblyName(assemblyFullName) + { + Name = key.AssemblyName + }; + + var extension = new AssemblyExtension(key.ConfigurationName, Assembly.Load(extensionAssemblyName)); + + return extension.CreateInitializer(); + } } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactoryProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactoryProvider.cs new file mode 100644 index 00000000000..95d3b40a84b --- /dev/null +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactoryProvider.cs @@ -0,0 +1,29 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using Microsoft.AspNetCore.Razor.Language; + +namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; + +internal class ProjectEngineFactoryProvider(ImmutableArray factories) : IProjectEngineFactoryProvider +{ + [return: NotNullIfNotNull(nameof(fallbackFactory))] + public IProjectEngineFactory? GetFactory( + RazorConfiguration configuration, + IProjectEngineFactory? fallbackFactory = null, + bool requireSerializationSupport = false) + { + foreach (var factory in factories) + { + if (factory.ConfigurationName == configuration.ConfigurationName && + (!requireSerializationSupport || factory.SupportsSerialization)) + { + return factory; + } + } + + return fallbackFactory; + } +} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Properties/AssemblyInfo.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Properties/AssemblyInfo.cs index f16be2d8ef9..ffdaf0c231f 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Properties/AssemblyInfo.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/Properties/AssemblyInfo.cs @@ -19,6 +19,7 @@ [assembly: InternalsVisibleTo("Microsoft.VisualStudio.Editor.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.VisualStudio.LanguageServerClient.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.VisualStudio.LanguageServerClient.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.LanguageServices.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.VisualStudio.LanguageServices.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.VisualStudio.LiveShare.Razor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] [assembly: InternalsVisibleTo("Microsoft.VisualStudio.LiveShare.Razor.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")] diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactory.cs deleted file mode 100644 index c10324d3cd5..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactory.cs +++ /dev/null @@ -1,97 +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; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; -using Microsoft.CodeAnalysis.Razor.ProjectSystem; - -namespace Microsoft.CodeAnalysis.Razor; - -internal class DefaultProjectSnapshotProjectEngineFactory : IProjectSnapshotProjectEngineFactory -{ - private readonly static RazorConfiguration s_defaultConfiguration = FallbackRazorConfiguration.Latest; - - private readonly IFallbackProjectEngineFactory _fallback; - private readonly Lazy[] _factories; - - public DefaultProjectSnapshotProjectEngineFactory( - IFallbackProjectEngineFactory fallback, - Lazy[] factories) - { - if (fallback is null) - { - throw new ArgumentNullException(nameof(fallback)); - } - - if (factories is null) - { - throw new ArgumentNullException(nameof(factories)); - } - - _fallback = fallback; - _factories = factories; - } - - public virtual RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure) - { - if (fileSystem is null) - { - throw new ArgumentNullException(nameof(fileSystem)); - } - - // When we're running in the editor, the editor provides a configure delegate that will include - // the editor settings and tag helpers. - // - // This service is only used in process in Visual Studio, and any other callers should provide these - // things also. - configure ??= ((b) => { }); - - // The default configuration currently matches the newest MVC configuration. - // - // We typically want this because the language adds features over time - we don't want to a bunch of errors - // to show up when a document is first opened, and then go away when the configuration loads, we'd prefer the opposite. - configuration ??= s_defaultConfiguration; - - // If there's no factory to handle the configuration then fall back to a very basic configuration. - // - // This will stop a crash from happening in this case (misconfigured project), but will still make - // it obvious to the user that something is wrong. - var factory = SelectFactory(configuration) ?? _fallback; - return factory.Create(configuration, fileSystem, configure); - } - - public IProjectEngineFactory? FindFactory(IProjectSnapshot project) - { - if (project is null) - { - throw new ArgumentNullException(nameof(project)); - } - - return SelectFactory(project.Configuration, requireSerializable: false); - } - - public IProjectEngineFactory? FindSerializableFactory(IProjectSnapshot project) - { - if (project is null) - { - throw new ArgumentNullException(nameof(project)); - } - - return SelectFactory(project.Configuration, requireSerializable: true); - } - - private IProjectEngineFactory? SelectFactory(RazorConfiguration configuration, bool requireSerializable = false) - { - for (var i = 0; i < _factories.Length; i++) - { - var factory = _factories[i]; - if (string.Equals(configuration.ConfigurationName, factory.Metadata.ConfigurationName, StringComparison.Ordinal)) - { - return requireSerializable && !factory.Metadata.SupportsSerialization ? null : factory.Value; - } - } - - return null; - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactoryFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactoryFactory.cs deleted file mode 100644 index 8a756166dd5..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectSnapshotProjectEngineFactoryFactory.cs +++ /dev/null @@ -1,46 +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; -using System.Composition; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Host.Mef; - -namespace Microsoft.CodeAnalysis.Razor.Workspaces; - -[ExportWorkspaceServiceFactory(typeof(IProjectSnapshotProjectEngineFactory))] -internal class DefaultProjectSnapshotProjectEngineFactoryFactory : IWorkspaceServiceFactory -{ - private readonly IFallbackProjectEngineFactory _fallback; - private readonly Lazy[] _factories; - - [ImportingConstructor] - public DefaultProjectSnapshotProjectEngineFactoryFactory( - IFallbackProjectEngineFactory fallback, - [ImportMany] Lazy[] factories) - { - if (fallback is null) - { - throw new ArgumentNullException(nameof(fallback)); - } - - if (factories is null) - { - throw new ArgumentNullException(nameof(factories)); - } - - _fallback = fallback; - _factories = factories; - } - - public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) - { - if (workspaceServices is null) - { - throw new ArgumentNullException(nameof(workspaceServices)); - } - - return new DefaultProjectSnapshotProjectEngineFactory(_fallback, _factories); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ExportCustomProjectEngineFactoryAttribute.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ExportCustomProjectEngineFactoryAttribute.cs deleted file mode 100644 index 3d3a90e5979..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ExportCustomProjectEngineFactoryAttribute.cs +++ /dev/null @@ -1,23 +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; -using System.Composition; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; - -namespace Microsoft.CodeAnalysis.Razor; - -[MetadataAttribute] -[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] -internal sealed class ExportCustomProjectEngineFactoryAttribute : ExportAttribute, ICustomProjectEngineFactoryMetadata -{ - public ExportCustomProjectEngineFactoryAttribute(string configurationName) - : base(typeof(IProjectEngineFactory)) - { - ConfigurationName = configurationName ?? throw new ArgumentNullException(nameof(configurationName)); - } - - public string ConfigurationName { get; } - - public bool SupportsSerialization { get; set; } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ExportDefaultProjectEngineFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ExportDefaultProjectEngineFactory.cs deleted file mode 100644 index 7315b91c53a..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ExportDefaultProjectEngineFactory.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -#nullable disable - -using Microsoft.AspNetCore.Razor.ProjectEngineHost; - -namespace Microsoft.CodeAnalysis.Razor.Workspaces; - -[ExportCustomProjectEngineFactory("Default", SupportsSerialization = true)] -internal class ExportDefaultProjectEngineFactory : DefaultProjectEngineFactory -{ -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/FallbackProjectEngineFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/FallbackProjectEngineFactory.cs deleted file mode 100644 index 3a7bbb49c3d..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/FallbackProjectEngineFactory.cs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -#nullable disable - -using System.Composition; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; - -namespace Microsoft.CodeAnalysis.Razor; - -[Export(typeof(IFallbackProjectEngineFactory))] -internal class FallbackProjectEngineFactory : EmptyProjectEngineFactory, IFallbackProjectEngineFactory -{ -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IFallbackProjectEngineFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IFallbackProjectEngineFactory.cs deleted file mode 100644 index f56b0479802..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IFallbackProjectEngineFactory.cs +++ /dev/null @@ -1,11 +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 Microsoft.AspNetCore.Razor.ProjectEngineHost; - -namespace Microsoft.CodeAnalysis.Razor; - -// Used to create the 'fallback' project engine when we don't have a custom implementation. -internal interface IFallbackProjectEngineFactory : IProjectEngineFactory -{ -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactory.cs deleted file mode 100644 index ec8d72bbc3b..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactory.cs +++ /dev/null @@ -1,19 +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; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Razor.ProjectSystem; - -namespace Microsoft.CodeAnalysis.Razor; - -internal interface IProjectSnapshotProjectEngineFactory : IWorkspaceService -{ - IProjectEngineFactory? FindFactory(IProjectSnapshot project); - - IProjectEngineFactory? FindSerializableFactory(IProjectSnapshot project); - - RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure); -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactoryExtensions.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactoryExtensions.cs deleted file mode 100644 index d608b22ae78..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotProjectEngineFactoryExtensions.cs +++ /dev/null @@ -1,72 +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; -using System.IO; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.CodeAnalysis.Razor.ProjectSystem; - -namespace Microsoft.CodeAnalysis.Razor; - -internal static class IProjectSnapshotProjectEngineFactoryExtensions -{ - public static RazorProjectEngine Create(this IProjectSnapshotProjectEngineFactory factory, IProjectSnapshot project) - { - return factory.Create(project, RazorProjectFileSystem.Create(Path.GetDirectoryName(project.FilePath)), null); - } - - public static RazorProjectEngine Create(this IProjectSnapshotProjectEngineFactory factory, IProjectSnapshot project, RazorProjectFileSystem fileSystem) - { - if (project is null) - { - throw new ArgumentNullException(nameof(project)); - } - - if (fileSystem is null) - { - throw new ArgumentNullException(nameof(fileSystem)); - } - - return factory.Create(project, fileSystem, configure: null); - } - - public static RazorProjectEngine Create(this IProjectSnapshotProjectEngineFactory factory, IProjectSnapshot project, Action? configure) - { - if (project is null) - { - throw new ArgumentNullException(nameof(project)); - } - - return factory.Create(project, RazorProjectFileSystem.Create(Path.GetDirectoryName(project.FilePath)), configure); - } - - public static RazorProjectEngine Create(this IProjectSnapshotProjectEngineFactory factory, IProjectSnapshot project, RazorProjectFileSystem fileSystem, Action? configure) - { - if (project is null) - { - throw new ArgumentNullException(nameof(project)); - } - - if (fileSystem is null) - { - throw new ArgumentNullException(nameof(fileSystem)); - } - - return factory.Create(project.Configuration, fileSystem, configure); - } - - public static RazorProjectEngine Create(this IProjectSnapshotProjectEngineFactory factory, RazorConfiguration configuration, string directoryPath, Action? configure) - { - if (configuration is null) - { - throw new ArgumentNullException(nameof(configuration)); - } - - if (directoryPath is null) - { - throw new ArgumentNullException(nameof(directoryPath)); - } - - return factory.Create(configuration, RazorProjectFileSystem.Create(directoryPath), configure); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_0.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_0.cs deleted file mode 100644 index 88c19f93726..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_0.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -#nullable disable - -using System; -using System.Reflection; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; - -namespace Microsoft.CodeAnalysis.Razor.Workspaces; - -[ExportCustomProjectEngineFactory("MVC-1.0", SupportsSerialization = true)] -internal class LegacyProjectEngineFactory_1_0 : IProjectEngineFactory -{ - public string ConfigurationName => "MVC-1.0"; - public bool SupportsSerialization => true; - - private const string AssemblyName = "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version1_X"; - - public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure) - { - // Rewrite the assembly name into a full name just like this one, but with the name of the MVC design time assembly. - var assemblyName = new AssemblyName(typeof(RazorProjectEngine).Assembly.FullName) - { - Name = AssemblyName - }; - - var extension = new AssemblyExtension(configuration.ConfigurationName, Assembly.Load(assemblyName)); - var initializer = extension.CreateInitializer(); - - return RazorProjectEngine.Create(configuration, fileSystem, b => - { - initializer.Initialize(b); - configure?.Invoke(b); - }); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_1.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_1.cs deleted file mode 100644 index 9497a953f4c..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_1_1.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -#nullable disable - -using System; -using System.Reflection; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; - -namespace Microsoft.CodeAnalysis.Razor.Workspaces; - -[ExportCustomProjectEngineFactory("MVC-1.1", SupportsSerialization = true)] -internal class LegacyProjectEngineFactory_1_1 : IProjectEngineFactory -{ - public string ConfigurationName => "MVC-1.1"; - public bool SupportsSerialization => true; - - private const string AssemblyName = "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version1_X"; - - public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure) - { - // Rewrite the assembly name into a full name just like this one, but with the name of the MVC design time assembly. - var assemblyName = new AssemblyName(typeof(RazorProjectEngine).Assembly.FullName) - { - Name = AssemblyName - }; - - var extension = new AssemblyExtension(configuration.ConfigurationName, Assembly.Load(assemblyName)); - var initializer = extension.CreateInitializer(); - - return RazorProjectEngine.Create(configuration, fileSystem, b => - { - initializer.Initialize(b); - configure?.Invoke(b); - }); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_0.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_0.cs deleted file mode 100644 index 03459bc33d3..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_0.cs +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -#nullable disable - -using System; -using System.Reflection; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; - -namespace Microsoft.CodeAnalysis.Razor.Workspaces; - -[ExportCustomProjectEngineFactory("MVC-2.0", SupportsSerialization = true)] -internal class LegacyProjectEngineFactory_2_0 : IProjectEngineFactory -{ - public string ConfigurationName => "MVC-2.0"; - public bool SupportsSerialization => true; - - private const string AssemblyName = "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version2_X"; - public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure) - { - // Rewrite the assembly name into a full name just like this one, but with the name of the MVC design time assembly. - var assemblyName = new AssemblyName(typeof(RazorProjectEngine).Assembly.FullName) - { - Name = AssemblyName - }; - - var extension = new AssemblyExtension(configuration.ConfigurationName, Assembly.Load(assemblyName)); - var initializer = extension.CreateInitializer(); - - return RazorProjectEngine.Create(configuration, fileSystem, b => - { - initializer.Initialize(b); - configure?.Invoke(b); - }); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_1.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_1.cs deleted file mode 100644 index c036419a222..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_2_1.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -#nullable disable - -using System; -using System.Reflection; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; - -namespace Microsoft.CodeAnalysis.Razor.Workspaces; - -// Currently we provide a fixed configuration for 2.1, but this is a point-in-time issue. We plan -// to make the 2.1 configuration more flexible and less hardcoded. -[ExportCustomProjectEngineFactory("MVC-2.1", SupportsSerialization = true)] -internal class LegacyProjectEngineFactory_2_1 : IProjectEngineFactory -{ - public string ConfigurationName => "MVC-2.1"; - public bool SupportsSerialization => true; - - private const string AssemblyName = "Microsoft.CodeAnalysis.Razor.Compiler.Mvc.Version2_X"; - - public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure) - { - // Rewrite the assembly name into a full name just like this one, but with the name of the MVC design time assembly. - var assemblyName = new AssemblyName(typeof(RazorProjectEngine).Assembly.FullName) - { - Name = AssemblyName - }; - - var extension = new AssemblyExtension(configuration.ConfigurationName, Assembly.Load(assemblyName)); - var initializer = extension.CreateInitializer(); - - return RazorProjectEngine.Create(configuration, fileSystem, b => - { - initializer.Initialize(b); - configure?.Invoke(b); - }); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_3_0.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_3_0.cs deleted file mode 100644 index 731e2cec031..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/LegacyProjectEngineFactory_3_0.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT license. See License.txt in the project root for license information. - -#nullable disable - -using System; -using System.Reflection; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; - -namespace Microsoft.CodeAnalysis.Razor.Workspaces; - -[ExportCustomProjectEngineFactory("MVC-3.0", SupportsSerialization = true)] -internal class LegacyProjectEngineFactory_3_0 : IProjectEngineFactory -{ - public string ConfigurationName => "MVC-3.0"; - public bool SupportsSerialization => true; - - private const string AssemblyName = "Microsoft.CodeAnalysis.Razor.Compiler.Mvc"; - - public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action configure) - { - // Rewrite the assembly name into a full name just like this one, but with the name of the MVC design time assembly. - var assemblyName = new AssemblyName(typeof(RazorProjectEngine).Assembly.FullName) - { - Name = AssemblyName - }; - - var extension = new AssemblyExtension(configuration.ConfigurationName, Assembly.Load(assemblyName)); - var initializer = extension.CreateInitializer(); - - return RazorProjectEngine.Create(configuration, fileSystem, b => - { - CompilerFeatures.Register(b); - - initializer.Initialize(b); - configure?.Invoke(b); - }); - } -} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectEngineHost/IProjectEngineFactoryExtensions.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectEngineHost/IProjectEngineFactoryExtensions.cs new file mode 100644 index 00000000000..7d80a113aed --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectEngineHost/IProjectEngineFactoryExtensions.cs @@ -0,0 +1,45 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using Microsoft.AspNetCore.Razor.Language; +using Microsoft.CodeAnalysis.Razor.ProjectSystem; + +namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; + +internal static class IProjectEngineFactoryExtensions +{ + public static RazorProjectEngine Create( + this IProjectEngineFactory factory, + IProjectSnapshot projectSnapshot, + Action? configure = null) + => factory.Create( + projectSnapshot.Configuration, + RazorProjectFileSystem.Create(Path.GetDirectoryName(projectSnapshot.FilePath)), + configure); + + [return: NotNullIfNotNull(nameof(fallbackFactory))] + public static RazorProjectEngine? Create( + this IProjectEngineFactoryProvider factoryProvider, + IProjectSnapshot projectSnapshot, + IProjectEngineFactory? fallbackFactory = null, + Action? configure = null) + => factoryProvider.Create( + projectSnapshot.Configuration, + rootDirectoryPath: Path.GetDirectoryName(projectSnapshot.FilePath).AssumeNotNull(), + fallbackFactory, + configure); + + [return: NotNullIfNotNull(nameof(fallbackFactory))] + public static RazorProjectEngine? Create( + this IProjectEngineFactoryProvider factoryProvider, + RazorConfiguration configuration, + string rootDirectoryPath, + IProjectEngineFactory? fallbackFactory = null, + Action? configure = null) + => factoryProvider.GetFactory(configuration, fallbackFactory) is IProjectEngineFactory factory + ? factory.Create(configuration, RazorProjectFileSystem.Create(rootDirectoryPath), configure) + : null; +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DefaultProjectSnapshotManager.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DefaultProjectSnapshotManager.cs index 2d212cebb9e..b95331fe97e 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DefaultProjectSnapshotManager.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DefaultProjectSnapshotManager.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.PooledObjects; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Razor.Workspaces.ProjectSystem; using Microsoft.CodeAnalysis.Text; @@ -35,16 +36,19 @@ internal class DefaultProjectSnapshotManager : ProjectSnapshotManagerBase // We have a queue for changes because if one change results in another change aka, add -> open we want to make sure the "add" finishes running first before "open" is notified. private readonly Queue _notificationWork = new(); + private readonly IProjectEngineFactoryProvider _projectEngineFactoryProvider; private readonly ProjectSnapshotManagerDispatcher _dispatcher; public DefaultProjectSnapshotManager( IErrorReporter errorReporter, IEnumerable triggers, Workspace workspace, + IProjectEngineFactoryProvider projectEngineFactoryProvider, ProjectSnapshotManagerDispatcher dispatcher) { ErrorReporter = errorReporter ?? throw new ArgumentNullException(nameof(errorReporter)); Workspace = workspace ?? throw new ArgumentNullException(nameof(workspace)); + _projectEngineFactoryProvider = projectEngineFactoryProvider ?? throw new ArgumentNullException(nameof(projectEngineFactoryProvider)); _dispatcher = dispatcher ?? throw new ArgumentException(nameof(dispatcher)); using (_rwLocker.EnterReadLock()) @@ -442,10 +446,8 @@ private bool TryChangeEntry_UsesLock( return false; } - var projectEngineFactory = Workspace.Services.GetRequiredService(); - var state = ProjectState.Create( - projectEngineFactory, + _projectEngineFactoryProvider, projectAddedAction.HostProject, ProjectWorkspaceState.Default); var newEntry = new Entry(state); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DefaultProjectSnapshotManagerFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DefaultProjectSnapshotManagerFactory.cs index b0576fc073c..c15c79aa734 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DefaultProjectSnapshotManagerFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/DefaultProjectSnapshotManagerFactory.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Composition; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; @@ -13,6 +14,7 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem; [method: ImportingConstructor] internal class DefaultProjectSnapshotManagerFactory( [ImportMany] IEnumerable triggers, + IProjectEngineFactoryProvider projectEngineFactoryProvider, ProjectSnapshotManagerDispatcher dispatcher, IErrorReporter errorReporter) : ILanguageServiceFactory { @@ -21,5 +23,6 @@ public ILanguageService CreateLanguageService(HostLanguageServices languageServi errorReporter, triggers, languageServices.WorkspaceServices.Workspace, + projectEngineFactoryProvider, dispatcher); } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ProjectState.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ProjectState.cs index 17670773206..c030a138868 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ProjectState.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ProjectState.cs @@ -9,6 +9,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.ProjectSystem; using Microsoft.AspNetCore.Razor.Utilities; using Microsoft.CodeAnalysis.CSharp; @@ -34,17 +35,17 @@ internal class ProjectState private static readonly ImmutableDictionary> s_emptyImportsToRelatedDocuments = ImmutableDictionary.Create>(FilePathNormalizer.Comparer); private readonly object _lock; - private readonly IProjectSnapshotProjectEngineFactory _projectEngineFactory; + private readonly IProjectEngineFactoryProvider _projectEngineFactoryProvider; private RazorProjectEngine? _projectEngine; public static ProjectState Create( - IProjectSnapshotProjectEngineFactory projectEngineFactory, + IProjectEngineFactoryProvider projectEngineFactoryProvider, HostProject hostProject, ProjectWorkspaceState projectWorkspaceState) { - if (projectEngineFactory is null) + if (projectEngineFactoryProvider is null) { - throw new ArgumentNullException(nameof(projectEngineFactory)); + throw new ArgumentNullException(nameof(projectEngineFactoryProvider)); } if (hostProject is null) @@ -57,15 +58,15 @@ public static ProjectState Create( throw new ArgumentNullException(nameof(projectWorkspaceState)); } - return new ProjectState(projectEngineFactory, hostProject, projectWorkspaceState); + return new ProjectState(projectEngineFactoryProvider, hostProject, projectWorkspaceState); } private ProjectState( - IProjectSnapshotProjectEngineFactory projectEngineFactory, + IProjectEngineFactoryProvider projectEngineFactoryProvider, HostProject hostProject, ProjectWorkspaceState projectWorkspaceState) { - _projectEngineFactory = projectEngineFactory; + _projectEngineFactoryProvider = projectEngineFactoryProvider; HostProject = hostProject; ProjectWorkspaceState = projectWorkspaceState; Documents = s_emptyDocuments; @@ -110,7 +111,7 @@ private ProjectState( throw new ArgumentNullException(nameof(projectWorkspaceState)); } - _projectEngineFactory = older._projectEngineFactory; + _projectEngineFactoryProvider = older._projectEngineFactoryProvider; Version = older.Version.GetNewerVersion(); HostProject = hostProject; @@ -201,15 +202,16 @@ public RazorProjectEngine ProjectEngine RazorProjectEngine CreateProjectEngine() { - return _projectEngineFactory.Create( - HostProject.Configuration, - Path.GetDirectoryName(HostProject.FilePath).AssumeNotNull(), - configure: builder => - { - builder.SetRootNamespace(HostProject.RootNamespace); - builder.SetCSharpLanguageVersion(CSharpLanguageVersion); - builder.SetSupportLocalizedComponentNames(); - }); + var configuration = HostProject.Configuration; + var rootDirectoryPath = Path.GetDirectoryName(HostProject.FilePath).AssumeNotNull(); + var fallbackFactory = ProjectEngineFactories.Empty; + + return _projectEngineFactoryProvider.Create(configuration, rootDirectoryPath, fallbackFactory, builder => + { + builder.SetRootNamespace(HostProject.RootNamespace); + builder.SetCSharpLanguageVersion(CSharpLanguageVersion); + builder.SetSupportLocalizedComponentNames(); + }); } } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IRemoteTagHelperProviderService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IRemoteTagHelperProviderService.cs index 071891f9ba6..ba79a0a70a7 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IRemoteTagHelperProviderService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/IRemoteTagHelperProviderService.cs @@ -15,14 +15,12 @@ internal interface IRemoteTagHelperProviderService ValueTask GetTagHelpersDeltaAsync( RazorPinnedSolutionInfoWrapper solutionInfo, ProjectSnapshotHandle projectHandle, - string factoryTypeName, int lastResultId, CancellationToken cancellationToken); ValueTask FetchTagHelpersAsync( RazorPinnedSolutionInfoWrapper solutionInfo, ProjectSnapshotHandle projectHandle, - string factoryTypeName, ImmutableArray checksums, CancellationToken cancellationToken); } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs index b5fc3b63f7b..763bc4e36ff 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs @@ -23,13 +23,13 @@ internal class OOPTagHelperResolver : ITagHelperResolver { private readonly TagHelperResultCache _resultCache; private readonly CompilationTagHelperResolver _innerResolver; - private readonly IProjectSnapshotProjectEngineFactory _factory; + private readonly IProjectEngineFactoryProvider _projectEngineFactoryProvider; private readonly IErrorReporter _errorReporter; private readonly Workspace _workspace; - public OOPTagHelperResolver(IProjectSnapshotProjectEngineFactory factory, IErrorReporter errorReporter, Workspace workspace, ITelemetryReporter telemetryReporter) + public OOPTagHelperResolver(IProjectEngineFactoryProvider projectEngineFactoryProvider, IErrorReporter errorReporter, Workspace workspace, ITelemetryReporter telemetryReporter) { - _factory = factory ?? throw new ArgumentNullException(nameof(factory)); + _projectEngineFactoryProvider = projectEngineFactoryProvider ?? throw new ArgumentNullException(nameof(projectEngineFactoryProvider)); _errorReporter = errorReporter ?? throw new ArgumentNullException(nameof(errorReporter)); _workspace = workspace ?? throw new ArgumentNullException(nameof(workspace)); @@ -47,9 +47,8 @@ public async ValueTask> GetTagHelpersAsync( // 1. Use custom factory out of process // 2. Use custom factory in process // 3. Use fallback factory in process - // - // Calling into RazorTemplateEngineFactoryService.Create will accomplish #2 and #3 in one step. - var factory = _factory.FindSerializableFactory(projectSnapshot); + + var factory = _projectEngineFactoryProvider.GetFactory(projectSnapshot.Configuration, requireSerializationSupport: true); ImmutableArray result = default; @@ -109,12 +108,11 @@ protected virtual async ValueTask> ResolveTa } var projectHandle = new ProjectSnapshotHandle(workspaceProject.Id, projectSnapshot.Configuration, projectSnapshot.RootNamespace); - var factoryTypeName = factory.GetType().AssemblyQualifiedName; var deltaResult = await remoteClient.TryInvokeAsync( workspaceProject.Solution, (service, solutionInfo, innerCancellationToken) => - service.GetTagHelpersDeltaAsync(solutionInfo, projectHandle, factoryTypeName, lastResultId, innerCancellationToken), + service.GetTagHelpersDeltaAsync(solutionInfo, projectHandle, lastResultId, innerCancellationToken), cancellationToken); if (!deltaResult.HasValue) @@ -149,7 +147,7 @@ protected virtual async ValueTask> ResolveTa var fetchResult = await remoteClient.TryInvokeAsync( workspaceProject.Solution, (service, solutionInfo, innerCancellationToken) => - service.FetchTagHelpersAsync(solutionInfo, projectHandle, factoryTypeName, checksumsToFetch.DrainToImmutable(), innerCancellationToken), + service.FetchTagHelpersAsync(solutionInfo, projectHandle, checksumsToFetch.DrainToImmutable(), innerCancellationToken), cancellationToken); if (!fetchResult.HasValue) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolverFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolverFactory.cs index fd0af047bef..ba953cd7c0c 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolverFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolverFactory.cs @@ -2,6 +2,7 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System.Composition; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Telemetry; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; @@ -14,12 +15,13 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; [ExportWorkspaceServiceFactory(typeof(ITagHelperResolver), ServiceLayer.Host)] [method: ImportingConstructor] internal class OOPTagHelperResolverFactory( + IProjectEngineFactoryProvider projectEngineFactoryProvider, IErrorReporter errorReporter, ITelemetryReporter telemetryReporter) : IWorkspaceServiceFactory { public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) => new OOPTagHelperResolver( - workspaceServices.GetRequiredService(), + projectEngineFactoryProvider, errorReporter, workspaceServices.Workspace, telemetryReporter); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteTagHelperProviderService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteTagHelperProviderService.cs index 49bafb38a4d..6cceaff9096 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteTagHelperProviderService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteTagHelperProviderService.cs @@ -30,19 +30,17 @@ internal RemoteTagHelperProviderService(IServiceBroker serviceBroker, ITelemetry public ValueTask FetchTagHelpersAsync( RazorPinnedSolutionInfoWrapper solutionInfo, ProjectSnapshotHandle projectHandle, - string factoryTypeName, ImmutableArray checksums, CancellationToken cancellationToken) => RazorBrokeredServiceImplementation.RunServiceAsync( solutionInfo, ServiceBrokerClient, - solution => FetchTagHelpersCoreAsync(solution, projectHandle, factoryTypeName, checksums, cancellationToken), + solution => FetchTagHelpersCoreAsync(solution, projectHandle, checksums, cancellationToken), cancellationToken); private async ValueTask FetchTagHelpersCoreAsync( Solution solution, ProjectSnapshotHandle projectHandle, - string factoryTypeName, ImmutableArray checksums, CancellationToken cancellationToken) { @@ -61,7 +59,7 @@ private async ValueTask FetchTagHelpersCoreAsync( // Compute the latest tag helpers and add them all to the cache. var latestTagHelpers = await _tagHelperResolver - .GetTagHelpersAsync(workspaceProject, projectHandle.Configuration, factoryTypeName, cancellationToken) + .GetTagHelpersAsync(workspaceProject, projectHandle.Configuration, cancellationToken) .ConfigureAwait(false); var cache = TagHelperCache.Default; @@ -105,19 +103,17 @@ static bool TryGetCachedTagHelpers(ImmutableArray checksums, out Immut public ValueTask GetTagHelpersDeltaAsync( RazorPinnedSolutionInfoWrapper solutionInfo, ProjectSnapshotHandle projectHandle, - string factoryTypeName, int lastResultId, CancellationToken cancellationToken) => RazorBrokeredServiceImplementation.RunServiceAsync( solutionInfo, ServiceBrokerClient, - solution => GetTagHelpersDeltaCoreAsync(solution, projectHandle, factoryTypeName, lastResultId, cancellationToken), + solution => GetTagHelpersDeltaCoreAsync(solution, projectHandle, lastResultId, cancellationToken), cancellationToken); private async ValueTask GetTagHelpersDeltaCoreAsync( Solution solution, ProjectSnapshotHandle projectHandle, - string factoryTypeName, int lastResultId, CancellationToken cancellationToken) { @@ -130,7 +126,7 @@ private async ValueTask GetTagHelpersDeltaCoreAsync( else { var tagHelpers = await _tagHelperResolver - .GetTagHelpersAsync(workspaceProject, projectHandle.Configuration, factoryTypeName, cancellationToken) + .GetTagHelpersAsync(workspaceProject, projectHandle.Configuration, cancellationToken) .ConfigureAwait(false); checksums = GetChecksums(tagHelpers); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteTagHelperResolver.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteTagHelperResolver.cs index 02c00cf664e..1151149a062 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteTagHelperResolver.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/RemoteTagHelperResolver.cs @@ -10,20 +10,33 @@ using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Telemetry; -using Microsoft.CodeAnalysis.Razor; namespace Microsoft.CodeAnalysis.Remote.Razor; internal class RemoteTagHelperResolver(ITelemetryReporter telemetryReporter) { - private readonly IFallbackProjectEngineFactory _fallbackFactory = new FallbackProjectEngineFactory(); - private readonly Dictionary _typeNameToFactoryMap = new(StringComparer.Ordinal); + /// + /// A map of configuration names to instances. + /// + private static readonly Dictionary s_configurationNameToFactoryMap = CreateConfigurationNameToFactoryMap(); + private readonly CompilationTagHelperResolver _compilationTagHelperResolver = new(telemetryReporter); + private static Dictionary CreateConfigurationNameToFactoryMap() + { + var map = new Dictionary(StringComparer.Ordinal); + + foreach (var factory in ProjectEngineFactories.All) + { + map.Add(factory.ConfigurationName, factory); + } + + return map; + } + public ValueTask> GetTagHelpersAsync( Project workspaceProject, RazorConfiguration? configuration, - string factoryTypeName, CancellationToken cancellationToken) { if (configuration is null) @@ -33,11 +46,11 @@ public ValueTask> GetTagHelpersAsync( return _compilationTagHelperResolver.GetTagHelpersAsync( workspaceProject, - CreateProjectEngine(configuration, factoryTypeName), + CreateProjectEngine(configuration), cancellationToken); } - private RazorProjectEngine CreateProjectEngine(RazorConfiguration configuration, string factoryTypeName) + private RazorProjectEngine CreateProjectEngine(RazorConfiguration configuration) { // If there's no factory to handle the configuration then fall back to a very basic configuration. // @@ -46,28 +59,15 @@ private RazorProjectEngine CreateProjectEngine(RazorConfiguration configuration, IProjectEngineFactory factory; - lock (_typeNameToFactoryMap) + lock (s_configurationNameToFactoryMap) { - if (!_typeNameToFactoryMap.TryGetValue(factoryTypeName, out factory)) + if (!s_configurationNameToFactoryMap.TryGetValue(configuration.ConfigurationName, out factory)) { - factory = CreateFactory(factoryTypeName) ?? _fallbackFactory; - _typeNameToFactoryMap.Add(factoryTypeName, factory); + factory = ProjectEngineFactories.Empty; + s_configurationNameToFactoryMap.Add(configuration.ConfigurationName, factory); } } - return factory.Create(configuration, RazorProjectFileSystem.Empty, static _ => { }); - - static IProjectEngineFactory? CreateFactory(string factoryTypeName) - { - try - { - var factoryType = Type.GetType(factoryTypeName, throwOnError: true); - return (IProjectEngineFactory)Activator.CreateInstance(factoryType); - } - catch - { - return null; - } - } + return factory.Create(configuration, RazorProjectFileSystem.Empty, configure: null); } } diff --git a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioDocumentTracker.cs b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioDocumentTracker.cs index 865107a4f54..b37a0eaaca6 100644 --- a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioDocumentTracker.cs +++ b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioDocumentTracker.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.Editor; @@ -19,7 +20,7 @@ namespace Microsoft.VisualStudio.Editor.Razor; internal class DefaultVisualStudioDocumentTracker : VisualStudioDocumentTracker { - private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher; + private readonly ProjectSnapshotManagerDispatcher _dispatcher; private readonly JoinableTaskContext _joinableTaskContext; private readonly string _filePath; private readonly string _projectPath; @@ -28,7 +29,7 @@ internal class DefaultVisualStudioDocumentTracker : VisualStudioDocumentTracker private readonly ITextBuffer _textBuffer; private readonly ImportDocumentManager _importDocumentManager; private readonly List _textViews; - private readonly Workspace _workspace; + private readonly IProjectEngineFactoryProvider _projectEngineFactoryProvider; private bool _isSupportedProject; private IProjectSnapshot? _projectSnapshot; private int _subscribeCount; @@ -36,19 +37,19 @@ internal class DefaultVisualStudioDocumentTracker : VisualStudioDocumentTracker public override event EventHandler? ContextChanged; public DefaultVisualStudioDocumentTracker( - ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher, + ProjectSnapshotManagerDispatcher dispatcher, JoinableTaskContext joinableTaskContext, string filePath, string projectPath, ProjectSnapshotManager projectManager, WorkspaceEditorSettings workspaceEditorSettings, - Workspace workspace, + IProjectEngineFactoryProvider projectEngineFactoryProvider, ITextBuffer textBuffer, ImportDocumentManager importDocumentManager) { - if (projectSnapshotManagerDispatcher is null) + if (dispatcher is null) { - throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher)); + throw new ArgumentNullException(nameof(dispatcher)); } if (joinableTaskContext is null) @@ -76,9 +77,9 @@ public DefaultVisualStudioDocumentTracker( throw new ArgumentNullException(nameof(workspaceEditorSettings)); } - if (workspace is null) + if (projectEngineFactoryProvider is null) { - throw new ArgumentNullException(nameof(workspace)); + throw new ArgumentNullException(nameof(projectEngineFactoryProvider)); } if (textBuffer is null) @@ -91,7 +92,7 @@ public DefaultVisualStudioDocumentTracker( throw new ArgumentNullException(nameof(importDocumentManager)); } - _projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher; + _dispatcher = dispatcher; _joinableTaskContext = joinableTaskContext; _filePath = filePath; _projectPath = projectPath; @@ -99,7 +100,7 @@ public DefaultVisualStudioDocumentTracker( _workspaceEditorSettings = workspaceEditorSettings; _textBuffer = textBuffer; _importDocumentManager = importDocumentManager; - _workspace = workspace; // For now we assume that the workspace is the always default VS workspace. + _projectEngineFactoryProvider = projectEngineFactoryProvider; _textViews = new List(); } @@ -118,8 +119,6 @@ public DefaultVisualStudioDocumentTracker( public override IReadOnlyList TextViews => _textViews; - public override Workspace Workspace => _workspace; - public override string FilePath => _filePath; public override string ProjectPath => _projectPath; @@ -171,7 +170,7 @@ internal void RemoveTextView(ITextView textView) public void Subscribe() { - _projectSnapshotManagerDispatcher.AssertDispatcherThread(); + _dispatcher.AssertDispatcherThread(); if (_subscribeCount++ > 0) { @@ -192,13 +191,13 @@ public void Subscribe() private IProjectSnapshot? GetOrCreateProject(string projectPath) { - _projectSnapshotManagerDispatcher.AssertDispatcherThread(); + _dispatcher.AssertDispatcherThread(); var projectKey = _projectManager.GetAllProjectKeys(projectPath).FirstOrDefault(); if (_projectManager.GetLoadedProject(projectKey) is not { } project) { - return new EphemeralProjectSnapshot(Workspace.Services, projectPath); + return new EphemeralProjectSnapshot(_projectEngineFactoryProvider, projectPath); } return project; @@ -206,7 +205,7 @@ public void Subscribe() public void Unsubscribe() { - _projectSnapshotManagerDispatcher.AssertDispatcherThread(); + _dispatcher.AssertDispatcherThread(); if (_subscribeCount == 0 || _subscribeCount-- > 1) { @@ -241,7 +240,7 @@ internal void ProjectManager_Changed(object sender, ProjectChangeEventArgs e) return; } - _projectSnapshotManagerDispatcher.AssertDispatcherThread(); + _dispatcher.AssertDispatcherThread(); if (_projectPath is not null && string.Equals(_projectPath, e.ProjectFilePath, StringComparison.OrdinalIgnoreCase)) @@ -292,7 +291,7 @@ internal void EditorSettingsManager_Changed(object sender, ClientSettingsChanged // Internal for testing internal void Import_Changed(object sender, ImportChangedEventArgs args) { - _projectSnapshotManagerDispatcher.AssertDispatcherThread(); + _dispatcher.AssertDispatcherThread(); foreach (var path in args.AssociatedDocuments) { diff --git a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioDocumentTrackerFactory.cs b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioDocumentTrackerFactory.cs index 89d825192f9..c23fb142b2a 100644 --- a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioDocumentTrackerFactory.cs +++ b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioDocumentTrackerFactory.cs @@ -3,7 +3,7 @@ using System; using System.Diagnostics; -using Microsoft.CodeAnalysis; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.Editor; using Microsoft.CodeAnalysis.Razor.ProjectSystem; @@ -14,68 +14,33 @@ namespace Microsoft.VisualStudio.Editor.Razor; internal class DefaultVisualStudioDocumentTrackerFactory : VisualStudioDocumentTrackerFactory { - private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher; + private readonly ProjectSnapshotManagerDispatcher _dispatcher; private readonly JoinableTaskContext _joinableTaskContext; private readonly ITextDocumentFactoryService _textDocumentFactory; private readonly ProjectPathProvider _projectPathProvider; - private readonly Workspace _workspace; private readonly ImportDocumentManager _importDocumentManager; private readonly ProjectSnapshotManager _projectManager; private readonly WorkspaceEditorSettings _workspaceEditorSettings; + private readonly IProjectEngineFactoryProvider _projectEngineFactoryProvider; public DefaultVisualStudioDocumentTrackerFactory( - ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher, + ProjectSnapshotManagerDispatcher dispatcher, JoinableTaskContext joinableTaskContext, ProjectSnapshotManager projectManager, WorkspaceEditorSettings workspaceEditorSettings, ProjectPathProvider projectPathProvider, ITextDocumentFactoryService textDocumentFactory, ImportDocumentManager importDocumentManager, - Workspace workspace) + IProjectEngineFactoryProvider projectEngineFactoryProvider) { - if (projectSnapshotManagerDispatcher is null) - { - throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher)); - } - - if (projectManager is null) - { - throw new ArgumentNullException(nameof(projectManager)); - } - - if (workspaceEditorSettings is null) - { - throw new ArgumentNullException(nameof(workspaceEditorSettings)); - } - - if (projectPathProvider is null) - { - throw new ArgumentNullException(nameof(projectPathProvider)); - } - - if (textDocumentFactory is null) - { - throw new ArgumentNullException(nameof(textDocumentFactory)); - } - - if (importDocumentManager is null) - { - throw new ArgumentNullException(nameof(importDocumentManager)); - } - - if (workspace is null) - { - throw new ArgumentNullException(nameof(workspace)); - } - - _projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher; + _dispatcher = dispatcher; _joinableTaskContext = joinableTaskContext; _projectManager = projectManager; _workspaceEditorSettings = workspaceEditorSettings; _projectPathProvider = projectPathProvider; _textDocumentFactory = textDocumentFactory; _importDocumentManager = importDocumentManager; - _workspace = workspace; + _projectEngineFactoryProvider = projectEngineFactoryProvider; } public override VisualStudioDocumentTracker? Create(ITextBuffer textBuffer) @@ -98,7 +63,7 @@ public DefaultVisualStudioDocumentTrackerFactory( var filePath = textDocument.FilePath; var tracker = new DefaultVisualStudioDocumentTracker( - _projectSnapshotManagerDispatcher, _joinableTaskContext, filePath, projectPath, _projectManager, _workspaceEditorSettings, _workspace, textBuffer, _importDocumentManager); + _dispatcher, _joinableTaskContext, filePath, projectPath, _projectManager, _workspaceEditorSettings, _projectEngineFactoryProvider, textBuffer, _importDocumentManager); return tracker; } diff --git a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioDocumentTrackerFactoryFactory.cs b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioDocumentTrackerFactoryFactory.cs index 37573de1475..fb07e9a8bda 100644 --- a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioDocumentTrackerFactoryFactory.cs +++ b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioDocumentTrackerFactoryFactory.cs @@ -1,8 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System; using System.Composition; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Razor; @@ -15,45 +15,15 @@ namespace Microsoft.VisualStudio.Editor.Razor; [Shared] [ExportLanguageServiceFactory(typeof(VisualStudioDocumentTrackerFactory), RazorLanguage.Name, ServiceLayer.Default)] -internal class DefaultVisualStudioDocumentTrackerFactoryFactory : ILanguageServiceFactory +[method: ImportingConstructor] +internal class DefaultVisualStudioDocumentTrackerFactoryFactory( + ProjectSnapshotManagerDispatcher dispatcher, + JoinableTaskContext joinableTaskContext, + ITextDocumentFactoryService textDocumentFactory, + IProjectEngineFactoryProvider projectEngineFactoryProvider) : ILanguageServiceFactory { - private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher; - private readonly JoinableTaskContext _joinableTaskContext; - private readonly ITextDocumentFactoryService _textDocumentFactory; - - [ImportingConstructor] - public DefaultVisualStudioDocumentTrackerFactoryFactory( - ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher, - JoinableTaskContext joinableTaskContext, - ITextDocumentFactoryService textDocumentFactory) - { - if (projectSnapshotManagerDispatcher is null) - { - throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher)); - } - - if (joinableTaskContext is null) - { - throw new ArgumentNullException(nameof(joinableTaskContext)); - } - - if (textDocumentFactory is null) - { - throw new ArgumentNullException(nameof(textDocumentFactory)); - } - - _projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher; - _joinableTaskContext = joinableTaskContext; - _textDocumentFactory = textDocumentFactory; - } - public ILanguageService CreateLanguageService(HostLanguageServices languageServices) { - if (languageServices is null) - { - throw new ArgumentNullException(nameof(languageServices)); - } - var projectManager = languageServices.GetRequiredService(); var workspaceEditorSettings = languageServices.GetRequiredService(); var importDocumentManager = languageServices.GetRequiredService(); @@ -61,13 +31,13 @@ public ILanguageService CreateLanguageService(HostLanguageServices languageServi var projectPathProvider = languageServices.WorkspaceServices.GetRequiredService(); return new DefaultVisualStudioDocumentTrackerFactory( - _projectSnapshotManagerDispatcher, - _joinableTaskContext, + dispatcher, + joinableTaskContext, projectManager, workspaceEditorSettings, projectPathProvider, - _textDocumentFactory, + textDocumentFactory, importDocumentManager, - languageServices.WorkspaceServices.Workspace); + projectEngineFactoryProvider); } } diff --git a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs index ae58fa1558b..d750070da95 100644 --- a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs +++ b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs @@ -11,6 +11,7 @@ using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Legacy; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.Editor; using Microsoft.Extensions.Internal; @@ -38,7 +39,7 @@ internal class DefaultVisualStudioRazorParser : VisualStudioRazorParser, IDispos private readonly VisualStudioCompletionBroker _completionBroker; private readonly VisualStudioDocumentTracker _documentTracker; private readonly JoinableTaskContext _joinableTaskContext; - private readonly IProjectSnapshotProjectEngineFactory _projectEngineFactory; + private readonly IProjectEngineFactoryProvider _projectEngineFactoryProvider; private readonly IErrorReporter _errorReporter; private readonly List _codeDocumentRequests; private readonly TaskScheduler _uiThreadScheduler; @@ -60,7 +61,7 @@ internal DefaultVisualStudioRazorParser(RazorCodeDocument codeDocument) public DefaultVisualStudioRazorParser( JoinableTaskContext joinableTaskContext, VisualStudioDocumentTracker documentTracker, - IProjectSnapshotProjectEngineFactory projectEngineFactory, + IProjectEngineFactoryProvider projectEngineFactoryProvider, IErrorReporter errorReporter, VisualStudioCompletionBroker completionBroker) { @@ -74,9 +75,9 @@ public DefaultVisualStudioRazorParser( throw new ArgumentNullException(nameof(documentTracker)); } - if (projectEngineFactory is null) + if (projectEngineFactoryProvider is null) { - throw new ArgumentNullException(nameof(projectEngineFactory)); + throw new ArgumentNullException(nameof(projectEngineFactoryProvider)); } if (errorReporter is null) @@ -90,7 +91,7 @@ public DefaultVisualStudioRazorParser( } _joinableTaskContext = joinableTaskContext; - _projectEngineFactory = projectEngineFactory; + _projectEngineFactoryProvider = projectEngineFactoryProvider; _errorReporter = errorReporter; _completionBroker = completionBroker; _documentTracker = documentTracker; @@ -246,17 +247,20 @@ internal void StartParser() // Make sure any tests use the real thing or a good mock. These tests can cause failures // that are hard to understand when this throws. Debug.Assert(_documentTracker.IsSupportedProject); - Assumes.NotNull(_documentTracker.ProjectSnapshot); - _projectEngine = _projectEngineFactory.Create(_documentTracker.ProjectSnapshot, ConfigureProjectEngine); + var projectSnapshot = _documentTracker.ProjectSnapshot.AssumeNotNull(); - Debug.Assert(_projectEngine is not null); - Debug.Assert(_projectEngine!.Engine is not null); + _projectEngine = _projectEngineFactoryProvider.Create( + projectSnapshot, + fallbackFactory: ProjectEngineFactories.Empty, + ConfigureProjectEngine).AssumeNotNull(); + + Debug.Assert(_projectEngine.Engine is not null); Debug.Assert(_projectEngine.FileSystem is not null); // We might not have a document snapshot in the case of an ephemeral project. // If we don't have a document then infer the FileKind from the FilePath. - var fileKind = _documentTracker.ProjectSnapshot?.GetDocument(_documentTracker.FilePath)?.FileKind ?? FileKinds.GetFileKindFromFilePath(_documentTracker.FilePath); + var fileKind = projectSnapshot.GetDocument(_documentTracker.FilePath)?.FileKind ?? FileKinds.GetFileKindFromFilePath(_documentTracker.FilePath); var projectDirectory = Path.GetDirectoryName(_documentTracker.ProjectPath); _parser = new BackgroundParser(_projectEngine, FilePath, projectDirectory, fileKind); diff --git a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactory.cs b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactory.cs index 721678c665d..b4d6136d0d7 100644 --- a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactory.cs +++ b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactory.cs @@ -2,49 +2,22 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis.Razor; using Microsoft.VisualStudio.Threading; namespace Microsoft.VisualStudio.Editor.Razor; -internal class DefaultVisualStudioRazorParserFactory : VisualStudioRazorParserFactory +internal class DefaultVisualStudioRazorParserFactory( + JoinableTaskContext joinableTaskContext, + IErrorReporter errorReporter, + VisualStudioCompletionBroker completionBroker, + IProjectEngineFactoryProvider projectEngineFactoryProvider) : VisualStudioRazorParserFactory { - private readonly JoinableTaskContext _joinableTaskContext; - private readonly IProjectSnapshotProjectEngineFactory _projectEngineFactory; - private readonly VisualStudioCompletionBroker _completionBroker; - private readonly IErrorReporter _errorReporter; - - public DefaultVisualStudioRazorParserFactory( - JoinableTaskContext joinableTaskContext, - IErrorReporter errorReporter, - VisualStudioCompletionBroker completionBroker, - IProjectSnapshotProjectEngineFactory projectEngineFactory) - { - if (joinableTaskContext is null) - { - throw new ArgumentNullException(nameof(joinableTaskContext)); - } - - if (errorReporter is null) - { - throw new ArgumentNullException(nameof(errorReporter)); - } - - if (completionBroker is null) - { - throw new ArgumentNullException(nameof(completionBroker)); - } - - if (projectEngineFactory is null) - { - throw new ArgumentNullException(nameof(projectEngineFactory)); - } - - _joinableTaskContext = joinableTaskContext; - _errorReporter = errorReporter; - _completionBroker = completionBroker; - _projectEngineFactory = projectEngineFactory; - } + private readonly JoinableTaskContext _joinableTaskContext = joinableTaskContext; + private readonly IProjectEngineFactoryProvider _projectEngineFactoryProvider = projectEngineFactoryProvider; + private readonly VisualStudioCompletionBroker _completionBroker = completionBroker; + private readonly IErrorReporter _errorReporter = errorReporter; public override VisualStudioRazorParser Create(VisualStudioDocumentTracker documentTracker) { @@ -55,12 +28,11 @@ public override VisualStudioRazorParser Create(VisualStudioDocumentTracker docum _joinableTaskContext.AssertUIThread(); - var parser = new DefaultVisualStudioRazorParser( + return new DefaultVisualStudioRazorParser( _joinableTaskContext, documentTracker, - _projectEngineFactory, + _projectEngineFactoryProvider, _errorReporter, _completionBroker); - return parser; } } diff --git a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactoryFactory.cs b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactoryFactory.cs index f169c4b535f..9868acb6986 100644 --- a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactoryFactory.cs +++ b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParserFactoryFactory.cs @@ -1,8 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System; using System.Composition; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Razor; @@ -15,23 +15,17 @@ namespace Microsoft.VisualStudio.Editor.Razor; [method: ImportingConstructor] internal class DefaultVisualStudioRazorParserFactoryFactory( JoinableTaskContext joinableTaskContext, + IProjectEngineFactoryProvider projectEngineFactoryProvider, IErrorReporter errorReporter) : ILanguageServiceFactory { public ILanguageService CreateLanguageService(HostLanguageServices languageServices) { - if (languageServices is null) - { - throw new ArgumentNullException(nameof(languageServices)); - } - - var workspaceServices = languageServices.WorkspaceServices; var completionBroker = languageServices.GetRequiredService(); - var projectEngineFactory = workspaceServices.GetRequiredService(); return new DefaultVisualStudioRazorParserFactory( joinableTaskContext, errorReporter, completionBroker, - projectEngineFactory); + projectEngineFactoryProvider); } } diff --git a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/EphemeralProjectSnapshot.cs b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/EphemeralProjectSnapshot.cs index 849abd43c75..8814a5faaa7 100644 --- a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/EphemeralProjectSnapshot.cs +++ b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/EphemeralProjectSnapshot.cs @@ -6,33 +6,22 @@ using System.Collections.Immutable; using System.IO; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.ProjectSystem; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.ProjectSystem; namespace Microsoft.VisualStudio.Editor.Razor; internal class EphemeralProjectSnapshot : IProjectSnapshot { - private readonly HostWorkspaceServices _services; + private readonly IProjectEngineFactoryProvider _projectEngineFactoryProvider; private readonly Lazy _projectEngine; - public EphemeralProjectSnapshot(HostWorkspaceServices services, string projectPath) + public EphemeralProjectSnapshot(IProjectEngineFactoryProvider projectEngineFactoryProvider, string projectPath) { - if (services is null) - { - throw new ArgumentNullException(nameof(services)); - } - - if (projectPath is null) - { - throw new ArgumentNullException(nameof(projectPath)); - } - - _services = services; + _projectEngineFactoryProvider = projectEngineFactoryProvider; FilePath = projectPath; IntermediateOutputPath = Path.Combine(Path.GetDirectoryName(FilePath) ?? FilePath, "obj"); DisplayName = Path.GetFileNameWithoutExtension(projectPath); @@ -101,7 +90,7 @@ public RazorProjectEngine GetProjectEngine() private RazorProjectEngine CreateProjectEngine() { - var factory = _services.GetRequiredService(); + var factory = _projectEngineFactoryProvider.GetFactory(Configuration, ProjectEngineFactories.Empty); return factory.Create(this); } } diff --git a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/VisualStudioDocumentTracker.cs b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/VisualStudioDocumentTracker.cs index fa0bfbc0dfe..3dbbfe96121 100644 --- a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/VisualStudioDocumentTracker.cs +++ b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/VisualStudioDocumentTracker.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using Microsoft.AspNetCore.Razor.Language; -using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Razor.Editor; using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Microsoft.VisualStudio.Text; @@ -31,8 +30,6 @@ internal abstract class VisualStudioDocumentTracker internal abstract IProjectSnapshot? ProjectSnapshot { get; } - public abstract Workspace Workspace { get; } - public abstract ITextBuffer TextBuffer { get; } public abstract IReadOnlyList TextViews { get; } diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioProjectEngineFactoryProvider.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioProjectEngineFactoryProvider.cs new file mode 100644 index 00000000000..4521eb8ccc7 --- /dev/null +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioProjectEngineFactoryProvider.cs @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.ComponentModel.Composition; +using System.Diagnostics.CodeAnalysis; +using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; + +namespace Microsoft.VisualStudio.LanguageServices.Razor; + +[Export(typeof(IProjectEngineFactoryProvider))] +internal sealed class VisualStudioProjectEngineFactoryProvider : IProjectEngineFactoryProvider +{ + [return: NotNullIfNotNull(nameof(fallbackFactory))] + public IProjectEngineFactory? GetFactory( + RazorConfiguration configuration, + IProjectEngineFactory? fallbackFactory = null, + bool requireSerializationSupport = false) + => ProjectEngineFactories.DefaultProvider.GetFactory(configuration, fallbackFactory, requireSerializationSupport); +} diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshot.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshot.cs index f5a6932eb4a..5d1275a216e 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshot.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshot.cs @@ -5,6 +5,7 @@ using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.ProjectSystem; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Razor.ProjectSystem; @@ -28,9 +29,8 @@ public static TestProjectSnapshot Create( ProjectWorkspaceState? projectWorkspaceState = null, string? displayName = null) { - var projectEngineFactory = new TestProjectSnapshotProjectEngineFactory(); var hostProject = new HostProject(filePath, intermediateOutputPath, configuration, "TestRootNamespace", displayName); - var state = ProjectState.Create(projectEngineFactory, hostProject, projectWorkspaceState ?? ProjectWorkspaceState.Default); + var state = ProjectState.Create(ProjectEngineFactories.DefaultProvider, hostProject, projectWorkspaceState ?? ProjectWorkspaceState.Default); foreach (var documentFilePath in documentFilePaths) { diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotManager.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotManager.cs index 0ff5fbca5ec..9539ff706d0 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotManager.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotManager.cs @@ -1,13 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System; -using System.Linq; using Microsoft.AspNetCore.Razor.LanguageServer; -using Microsoft.AspNetCore.Razor.LanguageServer.Common; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Test.Common.Workspaces; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.ProjectSystem; @@ -15,21 +12,20 @@ namespace Microsoft.AspNetCore.Razor.Test.Common.LanguageServer; internal class TestProjectSnapshotManager : DefaultProjectSnapshotManager { - private TestProjectSnapshotManager(IErrorReporter errorReporter, Workspace workspace, ProjectSnapshotManagerDispatcher dispatcher) - : base(errorReporter, Array.Empty(), workspace, dispatcher) + private TestProjectSnapshotManager( + IErrorReporter errorReporter, + Workspace workspace, + IProjectEngineFactoryProvider projectEngineFactoryProvider, + ProjectSnapshotManagerDispatcher dispatcher) + : base(errorReporter, triggers: [], workspace, projectEngineFactoryProvider, dispatcher) { } public static TestProjectSnapshotManager Create(IErrorReporter errorReporter, ProjectSnapshotManagerDispatcher dispatcher) { - var services = TestServices.Create( - workspaceServices: new[] - { - new DefaultProjectSnapshotProjectEngineFactory(new FallbackProjectEngineFactory(), MefProjectEngineFactories.All) - }, - razorLanguageServices: Enumerable.Empty()); + var services = TestServices.Create(workspaceServices: [], razorLanguageServices: []); var workspace = TestWorkspace.Create(services); - var testProjectManager = new TestProjectSnapshotManager(errorReporter, workspace, dispatcher); + var testProjectManager = new TestProjectSnapshotManager(errorReporter, workspace, ProjectEngineFactories.DefaultProvider, dispatcher); return testProjectManager; } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotProjectEngineFactory.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotProjectEngineFactory.cs deleted file mode 100644 index cd8a0113aba..00000000000 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/TestProjectSnapshotProjectEngineFactory.cs +++ /dev/null @@ -1,35 +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; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; -using Microsoft.CodeAnalysis.Razor; -using Microsoft.CodeAnalysis.Razor.ProjectSystem; - -namespace Microsoft.AspNetCore.Razor.Test.Common.LanguageServer; - -internal class TestProjectSnapshotProjectEngineFactory : IProjectSnapshotProjectEngineFactory -{ - public Action? Configure { get; set; } - - public RazorProjectEngine? Engine { get; set; } - - public RazorProjectEngine Create( - RazorConfiguration configuration, - RazorProjectFileSystem fileSystem, - Action? configure) - { - return Engine ?? RazorProjectEngine.Create(configuration, fileSystem, configure ?? Configure); - } - - public IProjectEngineFactory? FindFactory(IProjectSnapshot project) - { - throw new NotImplementedException(); - } - - public IProjectEngineFactory? FindSerializableFactory(IProjectSnapshot project) - { - throw new NotImplementedException(); - } -} diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectEngineFactoryProvider.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectEngineFactoryProvider.cs new file mode 100644 index 00000000000..18991be1d46 --- /dev/null +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectEngineFactoryProvider.cs @@ -0,0 +1,41 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System; +using System.Diagnostics.CodeAnalysis; +using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; + +namespace Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem; + +internal class TestProjectEngineFactoryProvider : IProjectEngineFactoryProvider +{ + public Action? Configure { get; set; } + + [return: NotNullIfNotNull(nameof(fallbackFactory))] + public IProjectEngineFactory? GetFactory( + RazorConfiguration configuration, + IProjectEngineFactory? fallbackFactory = null, + bool requireSerializationSupport = false) + { + return new Factory(Configure); + } + + private sealed class Factory(Action? outerConfigure) : IProjectEngineFactory + { + public string ConfigurationName => "Test"; + public bool SupportsSerialization => false; + + public RazorProjectEngine Create( + RazorConfiguration configuration, + RazorProjectFileSystem fileSystem, + Action? innerConfigure) + { + return RazorProjectEngine.Create(configuration, fileSystem, b => + { + innerConfigure?.Invoke(b); + outerConfigure?.Invoke(b); + }); + } + } +} diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectSnapshotManager.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectSnapshotManager.cs index 6bda7eb7684..2e4a3a8a0da 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectSnapshotManager.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectSnapshotManager.cs @@ -3,6 +3,7 @@ using System; using System.Linq; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.ProjectSystem; @@ -10,11 +11,15 @@ namespace Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem; -internal class TestProjectSnapshotManager(Workspace workspace, ProjectSnapshotManagerDispatcher dispatcher) +internal class TestProjectSnapshotManager( + Workspace workspace, + IProjectEngineFactoryProvider projectEngineFactoryProvider, + ProjectSnapshotManagerDispatcher dispatcher) : DefaultProjectSnapshotManager( Mock.Of(MockBehavior.Strict), Array.Empty(), workspace, + projectEngineFactoryProvider, dispatcher) { public bool AllowNotifyListeners { get; set; } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectSnapshotProjectEngineFactory.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectSnapshotProjectEngineFactory.cs deleted file mode 100644 index 3bb5abc93f8..00000000000 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectSnapshotProjectEngineFactory.cs +++ /dev/null @@ -1,39 +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; -using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; -using Microsoft.CodeAnalysis.Razor; -using Microsoft.CodeAnalysis.Razor.ProjectSystem; - -namespace Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem; - -internal class TestProjectSnapshotProjectEngineFactory : IProjectSnapshotProjectEngineFactory -{ - public Action? Configure { get; set; } - - public RazorProjectEngine? Engine { get; set; } - - public RazorProjectEngine Create( - RazorConfiguration configuration, - RazorProjectFileSystem fileSystem, - Action? configure) - { - return Engine ?? RazorProjectEngine.Create(configuration, fileSystem, b => - { - configure?.Invoke(b); - Configure?.Invoke(b); - }); - } - - public IProjectEngineFactory FindFactory(IProjectSnapshot project) - { - throw new NotImplementedException(); - } - - public IProjectEngineFactory FindSerializableFactory(IProjectSnapshot project) - { - throw new NotImplementedException(); - } -} diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/DocumentExcerptServiceTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/DocumentExcerptServiceTestBase.cs index 4711ae69127..d6370f7eb2a 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/DocumentExcerptServiceTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/DocumentExcerptServiceTestBase.cs @@ -41,7 +41,7 @@ public static (SourceText sourceText, TextSpan span) CreateText(string text) private (IDocumentSnapshot primary, Document secondary) InitializeDocument(SourceText sourceText) { var project = new ProjectSnapshot( - ProjectState.Create(ProjectEngineFactory, _hostProject, ProjectWorkspaceState.Default) + ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, ProjectWorkspaceState.Default) .WithAddedHostDocument(_hostDocument, () => Task.FromResult(TextAndVersion.Create(sourceText, VersionStamp.Create())))); var primary = project.GetDocument(_hostDocument.FilePath).AssumeNotNull(); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/WorkspaceTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/WorkspaceTestBase.cs index 18249d3e205..0bd5637bca3 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/WorkspaceTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/Workspaces/WorkspaceTestBase.cs @@ -4,10 +4,10 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Host; -using Microsoft.CodeAnalysis.Razor; using Xunit.Abstractions; namespace Microsoft.AspNetCore.Razor.Test.Common.Workspaces; @@ -17,7 +17,7 @@ public abstract class WorkspaceTestBase : ToolingTestBase private bool _initialized; private HostServices? _hostServices; private Workspace? _workspace; - private IProjectSnapshotProjectEngineFactory? _projectEngineFactory; + private IProjectEngineFactoryProvider? _projectEngineFactoryProvider; protected WorkspaceTestBase(ITestOutputHelper testOutput) : base(testOutput) @@ -42,12 +42,12 @@ protected Workspace Workspace } } - private protected IProjectSnapshotProjectEngineFactory ProjectEngineFactory + private protected IProjectEngineFactoryProvider ProjectEngineFactoryProvider { get { EnsureInitialized(); - return _projectEngineFactory; + return _projectEngineFactoryProvider; } } @@ -67,26 +67,23 @@ protected virtual void ConfigureProjectEngine(RazorProjectEngineBuilder builder) { } - [MemberNotNull(nameof(_hostServices), nameof(_workspace), nameof(_projectEngineFactory))] + [MemberNotNull(nameof(_hostServices), nameof(_workspace), nameof(_projectEngineFactoryProvider))] private void EnsureInitialized() { if (_initialized) { _hostServices.AssumeNotNull(); _workspace.AssumeNotNull(); - _projectEngineFactory.AssumeNotNull(); + _projectEngineFactoryProvider.AssumeNotNull(); return; } - _projectEngineFactory = new TestProjectSnapshotProjectEngineFactory() + _projectEngineFactoryProvider = new TestProjectEngineFactoryProvider() { Configure = ConfigureProjectEngine, }; - var workspaceServices = new List() - { - _projectEngineFactory, - }; + var workspaceServices = new List(); ConfigureWorkspaceServices(workspaceServices); var languageServices = new List(); diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/DefaultDocumentSnapshotTest.cs b/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/DefaultDocumentSnapshotTest.cs index aa943d27f40..f34d8790b23 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/DefaultDocumentSnapshotTest.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/DefaultDocumentSnapshotTest.cs @@ -42,7 +42,7 @@ public DefaultDocumentSnapshotTest(ITestOutputHelper testOutput) _legacyHostDocument = new HostDocument(TestProjectData.SomeProjectFile1); _nestedComponentHostDocument = new HostDocument(TestProjectData.SomeProjectNestedComponentFile3); - var projectState = ProjectState.Create(ProjectEngineFactory, TestProjectData.SomeProject, ProjectWorkspaceState.Default); + var projectState = ProjectState.Create(ProjectEngineFactoryProvider, TestProjectData.SomeProject, ProjectWorkspaceState.Default); var project = new ProjectSnapshot(projectState); var textAndVersion = TextAndVersion.Create(_sourceText, _version); diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/DefaultProjectSnapshotTest.cs b/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/DefaultProjectSnapshotTest.cs index 0c3f632206a..701c3bd6af1 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/DefaultProjectSnapshotTest.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/DefaultProjectSnapshotTest.cs @@ -56,7 +56,7 @@ protected override void ConfigureProjectEngine(RazorProjectEngineBuilder builder public void ProjectSnapshot_CachesDocumentSnapshots() { // Arrange - var state = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var state = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[0], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader); @@ -77,7 +77,7 @@ public void ProjectSnapshot_CachesDocumentSnapshots() public void IsImportDocument_NonImportDocument_ReturnsFalse() { // Arrange - var state = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var state = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[0], DocumentState.EmptyLoader); var snapshot = new ProjectSnapshot(state); @@ -94,7 +94,7 @@ public void IsImportDocument_NonImportDocument_ReturnsFalse() public void IsImportDocument_ImportDocument_ReturnsTrue() { // Arrange - var state = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var state = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[0], DocumentState.EmptyLoader) .WithAddedHostDocument(TestProjectData.SomeProjectImportFile, DocumentState.EmptyLoader); var snapshot = new ProjectSnapshot(state); @@ -112,7 +112,7 @@ public void IsImportDocument_ImportDocument_ReturnsTrue() public void GetRelatedDocuments_NonImportDocument_ReturnsEmpty() { // Arrange - var state = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var state = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[0], DocumentState.EmptyLoader); var snapshot = new ProjectSnapshot(state); @@ -129,7 +129,7 @@ public void GetRelatedDocuments_NonImportDocument_ReturnsEmpty() public void GetRelatedDocuments_ImportDocument_ReturnsRelated() { // Arrange - var state = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var state = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[0], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader) .WithAddedHostDocument(TestProjectData.SomeProjectImportFile, DocumentState.EmptyLoader); diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/FallbackProjectManagerTest.cs b/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/FallbackProjectManagerTest.cs index d960a6161b7..5900f32d971 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/FallbackProjectManagerTest.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/FallbackProjectManagerTest.cs @@ -29,7 +29,7 @@ public FallbackProjectManagerTest(ITestOutputHelper testOutputHelper) _projectConfigurationFilePathStore = new TestProjectConfigurationFilePathStore(); var dispatcher = Mock.Of(MockBehavior.Strict); - _projectSnapshotManager = new TestProjectSnapshotManager(Workspace, dispatcher); + _projectSnapshotManager = new TestProjectSnapshotManager(Workspace, ProjectEngineFactoryProvider, dispatcher); var projectSnapshotManagerAccessor = Mock.Of(a => a.Instance == _projectSnapshotManager, MockBehavior.Strict); diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/GeneratedDocumentTextLoaderTest.cs b/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/GeneratedDocumentTextLoaderTest.cs index 3d9ed06a0de..ee1ca19e87f 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/GeneratedDocumentTextLoaderTest.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/GeneratedDocumentTextLoaderTest.cs @@ -31,7 +31,7 @@ public async Task LoadAsync_SpecifiesEncoding() { // Arrange var project = new ProjectSnapshot( - ProjectState.Create(ProjectEngineFactory, _hostProject, ProjectWorkspaceState.Default) + ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, ProjectWorkspaceState.Default) .WithAddedHostDocument(_hostDocument, () => Task.FromResult(TextAndVersion.Create(SourceText.From(""), VersionStamp.Create())))); var document = project.GetDocument(_hostDocument.FilePath); diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/ProjectStateGeneratedOutputTest.cs b/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/ProjectStateGeneratedOutputTest.cs index bff0afc112c..71e4b3e9d7a 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/ProjectStateGeneratedOutputTest.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/ProjectStateGeneratedOutputTest.cs @@ -58,7 +58,7 @@ public async Task HostDocumentAdded_CachesOutput() { // Arrange var original = - ProjectState.Create(ProjectEngineFactory, _hostProject, ProjectWorkspaceState.Default) + ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, ProjectWorkspaceState.Default) .WithAddedHostDocument(_hostDocument, DocumentState.EmptyLoader); var (originalOutput, originalInputVersion) = await GetOutputAsync(original, _hostDocument); @@ -77,7 +77,7 @@ public async Task HostDocumentAdded_Import_DoesNotCacheOutput() { // Arrange var original = - ProjectState.Create(ProjectEngineFactory, _hostProject, ProjectWorkspaceState.Default) + ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, ProjectWorkspaceState.Default) .WithAddedHostDocument(_hostDocument, DocumentState.EmptyLoader); var (originalOutput, originalInputVersion) = await GetOutputAsync(original, _hostDocument); @@ -97,7 +97,7 @@ public async Task HostDocumentChanged_DoesNotCacheOutput() { // Arrange var original = - ProjectState.Create(ProjectEngineFactory, _hostProject, ProjectWorkspaceState.Default) + ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, ProjectWorkspaceState.Default) .WithAddedHostDocument(_hostDocument, DocumentState.EmptyLoader) .WithAddedHostDocument(TestProjectData.SomeProjectImportFile, DocumentState.EmptyLoader); @@ -119,7 +119,7 @@ public async Task HostDocumentChanged_Import_DoesNotCacheOutput() { // Arrange var original = - ProjectState.Create(ProjectEngineFactory, _hostProject, ProjectWorkspaceState.Default) + ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, ProjectWorkspaceState.Default) .WithAddedHostDocument(_hostDocument, DocumentState.EmptyLoader) .WithAddedHostDocument(TestProjectData.SomeProjectImportFile, DocumentState.EmptyLoader); @@ -141,7 +141,7 @@ public async Task HostDocumentRemoved_Import_DoesNotCacheOutput() { // Arrange var original = - ProjectState.Create(ProjectEngineFactory, _hostProject, ProjectWorkspaceState.Default) + ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, ProjectWorkspaceState.Default) .WithAddedHostDocument(_hostDocument, DocumentState.EmptyLoader) .WithAddedHostDocument(TestProjectData.SomeProjectImportFile, DocumentState.EmptyLoader); @@ -162,7 +162,7 @@ public async Task ProjectWorkspaceStateChange_CachesOutput_EvenWhenNewerProjectW { // Arrange var original = - ProjectState.Create(ProjectEngineFactory, _hostProject, ProjectWorkspaceState.Default) + ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, ProjectWorkspaceState.Default) .WithAddedHostDocument(_hostDocument, DocumentState.EmptyLoader); var (originalOutput, originalInputVersion) = await GetOutputAsync(original, _hostDocument); @@ -183,7 +183,7 @@ public async Task ProjectWorkspaceStateChange_WithTagHelperChange_DoesNotCacheOu { // Arrange var original = - ProjectState.Create(ProjectEngineFactory, _hostProject, ProjectWorkspaceState.Default) + ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, ProjectWorkspaceState.Default) .WithAddedHostDocument(_hostDocument, DocumentState.EmptyLoader); var (originalOutput, originalInputVersion) = await GetOutputAsync(original, _hostDocument); @@ -207,7 +207,7 @@ public async Task ProjectWorkspaceStateChange_WithProjectWorkspaceState_CSharpLa var hostProject = new HostProject(TestProjectData.SomeProject.FilePath, TestProjectData.SomeProject.IntermediateOutputPath, csharp8ValidConfiguration, TestProjectData.SomeProject.RootNamespace); var originalWorkspaceState = ProjectWorkspaceState.Create(_someTagHelpers, LanguageVersion.CSharp7); var original = - ProjectState.Create(ProjectEngineFactory, hostProject, originalWorkspaceState) + ProjectState.Create(ProjectEngineFactoryProvider, hostProject, originalWorkspaceState) .WithAddedHostDocument(_hostDocument, () => Task.FromResult(TextAndVersion.Create(SourceText.From("@DateTime.Now"), VersionStamp.Default))); var changedWorkspaceState = ProjectWorkspaceState.Create(_someTagHelpers, LanguageVersion.CSharp8); @@ -228,7 +228,7 @@ public async Task ConfigurationChange_DoesNotCacheOutput() { // Arrange var original = - ProjectState.Create(ProjectEngineFactory, _hostProject, ProjectWorkspaceState.Default) + ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, ProjectWorkspaceState.Default) .WithAddedHostDocument(_hostDocument, DocumentState.EmptyLoader); var (originalOutput, originalInputVersion) = await GetOutputAsync(original, _hostDocument); diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/ProjectStateTest.cs b/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/ProjectStateTest.cs index 510c6830443..d60c998b004 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/ProjectStateTest.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/ProjectStateTest.cs @@ -72,7 +72,7 @@ protected override void ConfigureProjectEngine(RazorProjectEngineBuilder builder public void GetImportDocumentTargetPaths_DoesNotIncludeCurrentImport() { // Arrange - var state = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState); + var state = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState); // Act var paths = state.GetImportDocumentTargetPaths(TestProjectData.SomeProjectComponentImportFile1); @@ -87,7 +87,7 @@ public void ProjectState_ConstructedNew() // Arrange // Act - var state = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState); + var state = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState); // Assert Assert.Empty(state.Documents); @@ -98,7 +98,7 @@ public void ProjectState_ConstructedNew() public void ProjectState_AddHostDocument_ToEmpty() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState); + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState); // Act var state = original.WithAddedHostDocument(_documents[0], DocumentState.EmptyLoader); @@ -116,7 +116,7 @@ public void ProjectState_AddHostDocument_ToEmpty() public async Task ProjectState_AddHostDocument_DocumentIsEmpty() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState); + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState); // Act var state = original.WithAddedHostDocument(_documents[0], DocumentState.EmptyLoader); @@ -130,7 +130,7 @@ public async Task ProjectState_AddHostDocument_DocumentIsEmpty() public void ProjectState_AddHostDocument_ToProjectWithDocuments() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -154,7 +154,7 @@ public void ProjectState_AddHostDocument_TracksImports() // Arrange // Act - var state = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var state = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(TestProjectData.SomeProjectFile1, DocumentState.EmptyLoader) .WithAddedHostDocument(TestProjectData.SomeProjectFile2, DocumentState.EmptyLoader) .WithAddedHostDocument(TestProjectData.SomeProjectNestedFile3, DocumentState.EmptyLoader) @@ -193,7 +193,7 @@ public void ProjectState_AddHostDocument_TracksImports() public void ProjectState_AddHostDocument_TracksImports_AddImportFile() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(TestProjectData.SomeProjectFile1, DocumentState.EmptyLoader) .WithAddedHostDocument(TestProjectData.SomeProjectFile2, DocumentState.EmptyLoader) .WithAddedHostDocument(TestProjectData.SomeProjectNestedFile3, DocumentState.EmptyLoader) @@ -236,7 +236,7 @@ public void ProjectState_AddHostDocument_TracksImports_AddImportFile() public void ProjectState_AddHostDocument_RetainsComputedState() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -269,7 +269,7 @@ public void ProjectState_AddHostDocument_RetainsComputedState() public void ProjectState_AddHostDocument_DuplicateNoops() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -284,7 +284,7 @@ public void ProjectState_AddHostDocument_DuplicateNoops() public async Task ProjectState_WithChangedHostDocument_Loader() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -304,7 +304,7 @@ public async Task ProjectState_WithChangedHostDocument_Loader() public async Task ProjectState_WithChangedHostDocument_Snapshot() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -324,7 +324,7 @@ public async Task ProjectState_WithChangedHostDocument_Snapshot() public void ProjectState_WithChangedHostDocument_Loader_RetainsComputedState() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -356,7 +356,7 @@ public void ProjectState_WithChangedHostDocument_Loader_RetainsComputedState() public void ProjectState_WithChangedHostDocument_Snapshot_RetainsComputedState() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -388,7 +388,7 @@ public void ProjectState_WithChangedHostDocument_Snapshot_RetainsComputedState() public void ProjectState_WithChangedHostDocument_Loader_NotFoundNoops() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -403,7 +403,7 @@ public void ProjectState_WithChangedHostDocument_Loader_NotFoundNoops() public void ProjectState_WithChangedHostDocument_Snapshot_NotFoundNoops() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -418,7 +418,7 @@ public void ProjectState_WithChangedHostDocument_Snapshot_NotFoundNoops() public void ProjectState_RemoveHostDocument_FromProjectWithDocuments() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -439,7 +439,7 @@ public void ProjectState_RemoveHostDocument_FromProjectWithDocuments() public void ProjectState_RemoveHostDocument_TracksImports() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(TestProjectData.SomeProjectFile1, DocumentState.EmptyLoader) .WithAddedHostDocument(TestProjectData.SomeProjectFile2, DocumentState.EmptyLoader) .WithAddedHostDocument(TestProjectData.SomeProjectNestedFile3, DocumentState.EmptyLoader) @@ -479,7 +479,7 @@ public void ProjectState_RemoveHostDocument_TracksImports() public void ProjectState_RemoveHostDocument_TracksImports_RemoveAllDocuments() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(TestProjectData.SomeProjectFile1, DocumentState.EmptyLoader) .WithAddedHostDocument(TestProjectData.SomeProjectFile2, DocumentState.EmptyLoader) .WithAddedHostDocument(TestProjectData.SomeProjectNestedFile3, DocumentState.EmptyLoader) @@ -501,7 +501,7 @@ public void ProjectState_RemoveHostDocument_TracksImports_RemoveAllDocuments() public void ProjectState_RemoveHostDocument_RetainsComputedState() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -533,7 +533,7 @@ public void ProjectState_RemoveHostDocument_RetainsComputedState() public void ProjectState_RemoveHostDocument_NotFoundNoops() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -548,7 +548,7 @@ public void ProjectState_RemoveHostDocument_NotFoundNoops() public void ProjectState_WithHostProject_ConfigurationChange_UpdatesConfigurationState() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -588,7 +588,7 @@ public void ProjectState_WithHostProject_ConfigurationChange_UpdatesConfiguratio public void ProjectState_WithHostProject_RootNamespaceChange_UpdatesConfigurationState() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); var hostProjectWithRootNamespaceChange = new HostProject( @@ -614,7 +614,7 @@ public void ProjectState_WithHostProject_RootNamespaceChange_UpdatesConfiguratio public void ProjectState_WithHostProject_NoConfigurationChange_Noops() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -638,7 +638,7 @@ public void ProjectState_WithHostProject_CallsConfigurationChangeOnDocumentState documents[_documents[1].FilePath] = TestDocumentState.Create(_documents[1], onConfigurationChange: () => callCount++); documents[_documents[2].FilePath] = TestDocumentState.Create(_documents[2], onConfigurationChange: () => callCount++); - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState); + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState); original.Documents = documents.ToImmutable(); // Act @@ -654,7 +654,7 @@ public void ProjectState_WithHostProject_CallsConfigurationChangeOnDocumentState public void ProjectState_WithHostProject_ResetsImportedDocuments() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState); + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState); original = original.WithAddedHostDocument(TestProjectData.SomeProjectFile1, DocumentState.EmptyLoader); // Act @@ -670,7 +670,7 @@ public void ProjectState_WithHostProject_ResetsImportedDocuments() public void ProjectState_WithProjectWorkspaceState_Changed() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -709,7 +709,7 @@ public void ProjectState_WithProjectWorkspaceState_Changed() public void ProjectState_WithProjectWorkspaceState_Changed_TagHelpersChanged() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -746,7 +746,7 @@ public void ProjectState_WithProjectWorkspaceState_Changed_TagHelpersChanged() public void ProjectState_WithProjectWorkspaceState_IdenticalState_Caches() { // Arrange - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState) + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState) .WithAddedHostDocument(_documents[2], DocumentState.EmptyLoader) .WithAddedHostDocument(_documents[1], DocumentState.EmptyLoader); @@ -776,7 +776,7 @@ public void ProjectState_WithProjectWorkspaceState_CallsWorkspaceProjectChangeOn documents[_documents[1].FilePath] = TestDocumentState.Create(_documents[1], onProjectWorkspaceStateChange: () => callCount++); documents[_documents[2].FilePath] = TestDocumentState.Create(_documents[2], onProjectWorkspaceStateChange: () => callCount++); - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState); + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState); original.Documents = documents.ToImmutable(); var changed = ProjectWorkspaceState.Default; @@ -820,7 +820,7 @@ public void ProjectState_WhenImportDocumentAdded_CallsImportsChanged() TestProjectData.SomeProjectNestedFile3.FilePath, TestProjectData.AnotherProjectNestedFile4.FilePath)); - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState); + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState); original.Documents = documents.ToImmutable(); original.ImportsToRelatedDocuments = importsToRelatedDocuments.ToImmutable(); @@ -863,7 +863,7 @@ public void ProjectState_WhenImportDocumentAdded_CallsImportsChanged_Nested() TestProjectData.SomeProjectNestedFile3.FilePath, TestProjectData.AnotherProjectNestedFile4.FilePath)); - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState); + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState); original.Documents = documents.ToImmutable(); original.ImportsToRelatedDocuments = importsToRelatedDocuments.ToImmutable(); @@ -909,7 +909,7 @@ public void ProjectState_WhenImportDocumentChangedTextLoader_CallsImportsChanged TestProjectData.SomeProjectNestedFile3.FilePath, TestProjectData.AnotherProjectNestedFile4.FilePath)); - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState); + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState); original.Documents = documents.ToImmutable(); original.ImportsToRelatedDocuments = importsToRelatedDocuments.ToImmutable(); @@ -955,7 +955,7 @@ public void ProjectState_WhenImportDocumentChangedSnapshot_CallsImportsChanged() TestProjectData.SomeProjectNestedFile3.FilePath, TestProjectData.AnotherProjectNestedFile4.FilePath)); - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState); + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState); original.Documents = documents.ToImmutable(); original.ImportsToRelatedDocuments = importsToRelatedDocuments.ToImmutable(); @@ -1001,7 +1001,7 @@ public void ProjectState_WhenImportDocumentRemoved_CallsImportsChanged() TestProjectData.SomeProjectNestedFile3.FilePath, TestProjectData.AnotherProjectNestedFile4.FilePath)); - var original = ProjectState.Create(ProjectEngineFactory, _hostProject, _projectWorkspaceState); + var original = ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, _projectWorkspaceState); original.Documents = documents.ToImmutable(); original.ImportsToRelatedDocuments = importsToRelatedDocuments.ToImmutable(); diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/RazorSpanMappingServiceTest.cs b/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/RazorSpanMappingServiceTest.cs index d31c67776e0..3437a6237c9 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/RazorSpanMappingServiceTest.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/RazorSpanMappingServiceTest.cs @@ -37,7 +37,7 @@ public async Task TryGetMappedSpans_SpanMatchesSourceMapping_ReturnsTrue() "); var project = new ProjectSnapshot( - ProjectState.Create(ProjectEngineFactory, _hostProject, ProjectWorkspaceState.Default) + ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, ProjectWorkspaceState.Default) .WithAddedHostDocument(_hostDocument, () => Task.FromResult(TextAndVersion.Create(sourceText, VersionStamp.Create())))); var document = project.GetDocument(_hostDocument.FilePath); @@ -69,7 +69,7 @@ public async Task TryGetMappedSpans_SpanMatchesSourceMappingAndPosition_ReturnsT "); var project = new ProjectSnapshot( - ProjectState.Create(ProjectEngineFactory, _hostProject, ProjectWorkspaceState.Default) + ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, ProjectWorkspaceState.Default) .WithAddedHostDocument(_hostDocument, () => Task.FromResult(TextAndVersion.Create(sourceText, VersionStamp.Create())))); var document = project.GetDocument(_hostDocument.FilePath); @@ -102,7 +102,7 @@ public async Task TryGetMappedSpans_SpanWithinSourceMapping_ReturnsTrue() "); var project = new ProjectSnapshot( - ProjectState.Create(ProjectEngineFactory, _hostProject, ProjectWorkspaceState.Default) + ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, ProjectWorkspaceState.Default) .WithAddedHostDocument(_hostDocument, () => Task.FromResult(TextAndVersion.Create(sourceText, VersionStamp.Create())))); var document = project.GetDocument(_hostDocument.FilePath); @@ -134,7 +134,7 @@ public async Task TryGetMappedSpans_SpanOutsideSourceMapping_ReturnsFalse() "); var project = new ProjectSnapshot( - ProjectState.Create(ProjectEngineFactory, _hostProject, ProjectWorkspaceState.Default) + ProjectState.Create(ProjectEngineFactoryProvider, _hostProject, ProjectWorkspaceState.Default) .WithAddedHostDocument(_hostDocument, () => Task.FromResult(TextAndVersion.Create(sourceText, VersionStamp.Create())))); var document = project.GetDocument(_hostDocument.FilePath); diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestProjectSnapshotManager.cs b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestProjectSnapshotManager.cs index 1fcf804a2d6..95ce8ddcad6 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestProjectSnapshotManager.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestProjectSnapshotManager.cs @@ -5,6 +5,7 @@ using System; using System.Linq; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Moq; @@ -20,10 +21,11 @@ public partial class OOPTagHelperResolverTest return dispatcher.Object; }); - private class TestProjectSnapshotManager(Workspace workspace) : DefaultProjectSnapshotManager( + private class TestProjectSnapshotManager(Workspace workspace, IProjectEngineFactoryProvider projectEngineFactoryProvider) : DefaultProjectSnapshotManager( Mock.Of(MockBehavior.Strict), Enumerable.Empty(), workspace, + projectEngineFactoryProvider, s_projectSnapshotManagerDispatcher.Value) { } diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestResolver.cs b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestResolver.cs index 520dfeedf90..524cb98b3dd 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestResolver.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestResolver.cs @@ -19,11 +19,11 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; public partial class OOPTagHelperResolverTest { private class TestResolver( - IProjectSnapshotProjectEngineFactory factory, + IProjectEngineFactoryProvider projectEngineFactoryProvider, IErrorReporter errorReporter, Workspace workspace, ITelemetryReporter telemetryReporter) - : OOPTagHelperResolver(factory, errorReporter, workspace, telemetryReporter) + : OOPTagHelperResolver(projectEngineFactoryProvider, errorReporter, workspace, telemetryReporter) { public Func>>? OnResolveOutOfProcess { get; init; } diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.cs b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.cs index 6ec3adb3f25..1e1a73aaefc 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.cs @@ -13,7 +13,6 @@ using Microsoft.AspNetCore.Razor.Telemetry; using Microsoft.AspNetCore.Razor.Test.Common.Workspaces; using Microsoft.AspNetCore.Razor.Utilities; -using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Remote.Razor.Test; using Moq; @@ -24,8 +23,8 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; public partial class OOPTagHelperResolverTest : TagHelperDescriptorTestBase { - private readonly IProjectSnapshotProjectEngineFactory _engineFactory; - private readonly Lazy[] _customFactories; + private readonly IProjectEngineFactoryProvider _projectEngineFactoryProvider; + private readonly ImmutableArray _customFactories; private readonly HostProject _hostProject_For_2_0; private readonly HostProject _hostProject_For_NonSerializableConfiguration; private readonly ProjectSnapshotManagerBase _projectManager; @@ -40,22 +39,15 @@ public OOPTagHelperResolverTest(ITestOutputHelper testOutput) "Test.csproj", "/obj", new ProjectSystemRazorConfiguration(RazorLanguageVersion.Version_2_1, "Random-0.1", []), rootNamespace: null); - _customFactories = - [ - new Lazy( - () => Mock.Of(MockBehavior.Strict), - new ExportCustomProjectEngineFactoryAttribute("MVC-2.0") { SupportsSerialization = true, }), + _customFactories = ImmutableArray.Create( + CreateFactory("MVC-2.0"), // We don't really use this factory, we just use it to ensure that the call is going to go out of process. - new Lazy( - () => Mock.Of(MockBehavior.Strict), - new ExportCustomProjectEngineFactoryAttribute("Test-2") { SupportsSerialization = false, }), - ]; + CreateFactory("Test-2")); - var fallbackFactory = new FallbackProjectEngineFactory(); + _projectEngineFactoryProvider = new ProjectEngineFactoryProvider(_customFactories); - _engineFactory = new DefaultProjectSnapshotProjectEngineFactory(fallbackFactory, _customFactories); - var testServices = TestServices.Create([_engineFactory], []); + var testServices = TestServices.Create([], []); _workspace = new AdhocWorkspace(testServices); AddDisposable(_workspace); @@ -63,7 +55,19 @@ public OOPTagHelperResolverTest(ITestOutputHelper testOutput) var info = ProjectInfo.Create(ProjectId.CreateNewId("Test"), VersionStamp.Default, "Test", "Test", LanguageNames.CSharp, filePath: "Test.csproj"); _workspaceProject = _workspace.CurrentSolution.AddProject(info).GetProject(info.Id).AssumeNotNull(); - _projectManager = new TestProjectSnapshotManager(_workspace); + _projectManager = new TestProjectSnapshotManager(_workspace, _projectEngineFactoryProvider); + + static IProjectEngineFactory CreateFactory(string configurationName) + { + var mock = new Mock(MockBehavior.Strict); + + mock.SetupGet(x => x.ConfigurationName) + .Returns(configurationName); + mock.SetupGet(x => x.SupportsSerialization) + .Returns(true); + + return mock.Object; + } } [Fact] @@ -74,11 +78,15 @@ public async Task GetTagHelpersAsync_WithSerializableCustomFactory_GoesOutOfProc var projectSnapshot = _projectManager.GetLoadedProject(_hostProject_For_2_0.Key).AssumeNotNull(); - var resolver = new TestResolver(_engineFactory, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance) + var calledOutOfProcess = false; + + var resolver = new TestResolver(_projectEngineFactoryProvider, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance) { OnResolveOutOfProcess = (f, p) => { - Assert.Same(_customFactories[0].Value, f); + calledOutOfProcess = true; + + Assert.Same(_customFactories[0], f); Assert.Same(projectSnapshot, p); return new(ImmutableArray.Empty); @@ -88,6 +96,7 @@ public async Task GetTagHelpersAsync_WithSerializableCustomFactory_GoesOutOfProc var result = await resolver.GetTagHelpersAsync(_workspaceProject, projectSnapshot, DisposalToken); // Assert + Assert.True(calledOutOfProcess); Assert.Empty(result); } @@ -99,10 +108,14 @@ public async Task GetTagHelpersAsync_WithNonSerializableCustomFactory_StaysInPro var projectSnapshot = _projectManager.GetLoadedProject(_hostProject_For_2_0.Key).AssumeNotNull(); - var resolver = new TestResolver(_engineFactory, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance) + var calledInProcess = false; + + var resolver = new TestResolver(_projectEngineFactoryProvider, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance) { OnResolveInProcess = (p) => { + calledInProcess = true; + Assert.Same(projectSnapshot, p); return new(ImmutableArray.Empty); @@ -112,6 +125,7 @@ public async Task GetTagHelpersAsync_WithNonSerializableCustomFactory_StaysInPro var result = await resolver.GetTagHelpersAsync(_workspaceProject, projectSnapshot, DisposalToken); // Assert + Assert.True(calledInProcess); Assert.Empty(result); } @@ -123,17 +137,22 @@ public async Task GetTagHelpersAsync_OperationCanceledException_DoesNotGetWrappe var projectSnapshot = _projectManager.GetLoadedProject(_hostProject_For_2_0.Key).AssumeNotNull(); + var calledOutOfProcess = false; + var calledInProcess = false; + var cancellationToken = new CancellationToken(canceled: true); - var resolver = new TestResolver(_engineFactory, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance) + var resolver = new TestResolver(_projectEngineFactoryProvider, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance) { OnResolveInProcess = (p) => { + calledInProcess = true; Assert.Same(projectSnapshot, p); return new(ImmutableArray.Empty); }, OnResolveOutOfProcess = (f, p) => { + calledOutOfProcess = true; Assert.Same(projectSnapshot, p); throw new OperationCanceledException(); @@ -141,13 +160,16 @@ public async Task GetTagHelpersAsync_OperationCanceledException_DoesNotGetWrappe }; await Assert.ThrowsAsync(async () => await resolver.GetTagHelpersAsync(_workspaceProject, projectSnapshot, cancellationToken)); + + Assert.False(calledInProcess); + Assert.True(calledOutOfProcess); } [Fact] public void CalculateTagHelpersFromDelta_NewProject() { // Arrange - var resolver = new TestResolver(_engineFactory, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance); + var resolver = new TestResolver(_projectEngineFactoryProvider, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance); var initialDelta = new TagHelperDeltaResult(IsDelta: false, ResultId: 1, Project1TagHelperChecksums, ImmutableArray.Empty); // Act @@ -161,7 +183,7 @@ public void CalculateTagHelpersFromDelta_NewProject() public void CalculateTagHelpersFromDelta_DeltaFailedToApplyToKnownProject() { // Arrange - var resolver = new TestResolver(_engineFactory, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance); + var resolver = new TestResolver(_projectEngineFactoryProvider, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance); var initialDelta = new TagHelperDeltaResult(IsDelta: false, ResultId: 1, Project1TagHelperChecksums, ImmutableArray.Empty); resolver.PublicProduceChecksumsFromDelta(Project1Id, lastResultId: -1, initialDelta); var newTagHelperSet = ImmutableArray.Create(TagHelper1_Project1.Checksum); @@ -178,7 +200,7 @@ public void CalculateTagHelpersFromDelta_DeltaFailedToApplyToKnownProject() public void CalculateTagHelpersFromDelta_NoopResult() { // Arrange - var resolver = new TestResolver(_engineFactory, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance); + var resolver = new TestResolver(_projectEngineFactoryProvider, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance); var initialDelta = new TagHelperDeltaResult(IsDelta: false, ResultId: 1, Project1TagHelperChecksums, ImmutableArray.Empty); resolver.PublicProduceChecksumsFromDelta(Project1Id, lastResultId: -1, initialDelta); var noopDelta = new TagHelperDeltaResult(IsDelta: true, initialDelta.ResultId, ImmutableArray.Empty, ImmutableArray.Empty); @@ -194,7 +216,7 @@ public void CalculateTagHelpersFromDelta_NoopResult() public void CalculateTagHelpersFromDelta_ReplacedTagHelpers() { // Arrange - var resolver = new TestResolver(_engineFactory, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance); + var resolver = new TestResolver(_projectEngineFactoryProvider, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance); var initialDelta = new TagHelperDeltaResult(IsDelta: false, ResultId: 1, Project1TagHelperChecksums, ImmutableArray.Empty); resolver.PublicProduceChecksumsFromDelta(Project1Id, lastResultId: -1, initialDelta); var changedDelta = new TagHelperDeltaResult(IsDelta: true, initialDelta.ResultId + 1, ImmutableArray.Create(TagHelper2_Project2.Checksum), ImmutableArray.Create(TagHelper2_Project1.Checksum)); diff --git a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectSnapshotProjectEngineFactoryTest.cs b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectSnapshotProjectEngineFactoryTest.cs index 49f0e911b3f..f8bedee32ee 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectSnapshotProjectEngineFactoryTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectSnapshotProjectEngineFactoryTest.cs @@ -4,13 +4,12 @@ #nullable disable using System; -using System.Reflection; +using System.Collections.Immutable; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.ProjectSystem; using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.CodeAnalysis.Razor.ProjectSystem; -using Microsoft.CodeAnalysis.Razor.Workspaces; using Moq; using Xunit; using Xunit.Abstractions; @@ -23,8 +22,7 @@ namespace Microsoft.CodeAnalysis.Razor; // Testing this here because we need references to the MVC factories. public class DefaultProjectSnapshotProjectEngineFactoryTest : ToolingTestBase { - private readonly Lazy[] _customFactories; - private readonly IFallbackProjectEngineFactory _fallbackFactory; + private readonly ImmutableArray _customFactories; private readonly IProjectSnapshot _snapshot_For_1_0; private readonly IProjectSnapshot _snapshot_For_1_1; private readonly IProjectSnapshot _snapshot_For_2_0; @@ -53,35 +51,21 @@ public DefaultProjectSnapshotProjectEngineFactoryTest(ITestOutputHelper testOutp projectFilePath, intermediateOutputPath, new ProjectSystemRazorConfiguration(RazorLanguageVersion.Version_2_1, "Random-0.1", Array.Empty()), rootNamespace: null); - var projectEngineFactory = Mock.Of(MockBehavior.Strict); - - _snapshot_For_1_0 = new ProjectSnapshot(ProjectState.Create(projectEngineFactory, hostProject_For_1_0, ProjectWorkspaceState.Default)); - _snapshot_For_1_1 = new ProjectSnapshot(ProjectState.Create(projectEngineFactory, hostProject_For_1_1, ProjectWorkspaceState.Default)); - _snapshot_For_2_0 = new ProjectSnapshot(ProjectState.Create(projectEngineFactory, hostProject_For_2_0, ProjectWorkspaceState.Default)); - _snapshot_For_2_1 = new ProjectSnapshot(ProjectState.Create(projectEngineFactory, hostProject_For_2_1, ProjectWorkspaceState.Default)); - _snapshot_For_3_0 = new ProjectSnapshot(ProjectState.Create(projectEngineFactory, hostProject_For_3_0, ProjectWorkspaceState.Default)); - _snapshot_For_UnknownConfiguration = new ProjectSnapshot(ProjectState.Create(projectEngineFactory, hostProject_For_UnknownConfiguration, ProjectWorkspaceState.Default)); - - _customFactories = - [ - new Lazy( - () => new LegacyProjectEngineFactory_1_0(), - typeof(LegacyProjectEngineFactory_1_0).GetCustomAttribute()), - new Lazy( - () => new LegacyProjectEngineFactory_1_1(), - typeof(LegacyProjectEngineFactory_1_1).GetCustomAttribute()), - new Lazy( - () => new LegacyProjectEngineFactory_2_0(), - typeof(LegacyProjectEngineFactory_2_0).GetCustomAttribute()), - new Lazy( - () => new LegacyProjectEngineFactory_2_1(), - typeof(LegacyProjectEngineFactory_2_1).GetCustomAttribute()), - new Lazy( - () => new LegacyProjectEngineFactory_3_0(), - typeof(LegacyProjectEngineFactory_3_0).GetCustomAttribute()), - ]; - - _fallbackFactory = new FallbackProjectEngineFactory(); + var projectEngineFactoryProvider = Mock.Of(MockBehavior.Strict); + + _snapshot_For_1_0 = new ProjectSnapshot(ProjectState.Create(projectEngineFactoryProvider, hostProject_For_1_0, ProjectWorkspaceState.Default)); + _snapshot_For_1_1 = new ProjectSnapshot(ProjectState.Create(projectEngineFactoryProvider, hostProject_For_1_1, ProjectWorkspaceState.Default)); + _snapshot_For_2_0 = new ProjectSnapshot(ProjectState.Create(projectEngineFactoryProvider, hostProject_For_2_0, ProjectWorkspaceState.Default)); + _snapshot_For_2_1 = new ProjectSnapshot(ProjectState.Create(projectEngineFactoryProvider, hostProject_For_2_1, ProjectWorkspaceState.Default)); + _snapshot_For_3_0 = new ProjectSnapshot(ProjectState.Create(projectEngineFactoryProvider, hostProject_For_3_0, ProjectWorkspaceState.Default)); + _snapshot_For_UnknownConfiguration = new ProjectSnapshot(ProjectState.Create(projectEngineFactoryProvider, hostProject_For_UnknownConfiguration, ProjectWorkspaceState.Default)); + + _customFactories = ImmutableArray.Create( + ProjectEngineFactories.MVC_1_0, + ProjectEngineFactories.MVC_1_1, + ProjectEngineFactories.MVC_2_0, + ProjectEngineFactories.MVC_2_1, + ProjectEngineFactories.MVC_3_0); } [Fact] @@ -90,9 +74,10 @@ public void Create_CreatesDesignTimeTemplateEngine_ForVersion3_0() // Arrange var snapshot = _snapshot_For_3_0; - var factory = new DefaultProjectSnapshotProjectEngineFactory(_fallbackFactory, _customFactories); + var provider = new ProjectEngineFactoryProvider(_customFactories); // Act + var factory = provider.GetFactory(snapshot.Configuration, ProjectEngineFactories.Empty); var engine = factory.Create(snapshot, b => b.Features.Add(new MyCoolNewFeature())); // Assert @@ -108,9 +93,10 @@ public void Create_CreatesDesignTimeTemplateEngine_ForVersion2_1() // Arrange var snapshot = _snapshot_For_2_1; - var factory = new DefaultProjectSnapshotProjectEngineFactory(_fallbackFactory, _customFactories); + var provider = new ProjectEngineFactoryProvider(_customFactories); // Act + var factory = provider.GetFactory(snapshot.Configuration, ProjectEngineFactories.Empty); var engine = factory.Create(snapshot, b => b.Features.Add(new MyCoolNewFeature())); // Assert @@ -128,9 +114,10 @@ public void Create_CreatesDesignTimeTemplateEngine_ForVersion2_0() // Arrange var snapshot = _snapshot_For_2_0; - var factory = new DefaultProjectSnapshotProjectEngineFactory(_fallbackFactory, _customFactories); + var provider = new ProjectEngineFactoryProvider(_customFactories); // Act + var factory = provider.GetFactory(snapshot.Configuration, ProjectEngineFactories.Empty); var engine = factory.Create(snapshot, b => b.Features.Add(new MyCoolNewFeature())); // Assert @@ -146,9 +133,10 @@ public void Create_CreatesTemplateEngine_ForVersion1_1() // Arrange var snapshot = _snapshot_For_1_1; - var factory = new DefaultProjectSnapshotProjectEngineFactory(_fallbackFactory, _customFactories); + var provider = new ProjectEngineFactoryProvider(_customFactories); // Act + var factory = provider.GetFactory(snapshot.Configuration, ProjectEngineFactories.Empty); var engine = factory.Create(snapshot, b => b.Features.Add(new MyCoolNewFeature())); // Assert @@ -164,9 +152,10 @@ public void Create_DoesNotSupportViewComponentTagHelpers_ForVersion1_0() // Arrange var snapshot = _snapshot_For_1_0; - var factory = new DefaultProjectSnapshotProjectEngineFactory(_fallbackFactory, _customFactories); + var provider = new ProjectEngineFactoryProvider(_customFactories); // Act + var factory = provider.GetFactory(snapshot.Configuration, ProjectEngineFactories.Empty); var engine = factory.Create(snapshot, b => b.Features.Add(new MyCoolNewFeature())); // Assert @@ -190,9 +179,10 @@ public void Create_ForUnknownConfiguration_UsesFallbackFactory() { var snapshot = _snapshot_For_UnknownConfiguration; - var factory = new DefaultProjectSnapshotProjectEngineFactory(_fallbackFactory, _customFactories); + var provider = new ProjectEngineFactoryProvider(_customFactories); // Act + var factory = provider.GetFactory(snapshot.Configuration, ProjectEngineFactories.Empty); var engine = factory.Create(snapshot, b => b.Features.Add(new MyCoolNewFeature())); // Assert diff --git a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectWorkspaceStateGeneratorTest.cs b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectWorkspaceStateGeneratorTest.cs index 85def827c74..5aa5dac88a0 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectWorkspaceStateGeneratorTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectWorkspaceStateGeneratorTest.cs @@ -10,6 +10,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.ProjectSystem; using Microsoft.AspNetCore.Razor.Telemetry; using Microsoft.AspNetCore.Razor.Test.Common; @@ -26,6 +27,7 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces; public class DefaultProjectWorkspaceStateGeneratorTest : ProjectSnapshotManagerDispatcherTestBase { + private readonly IProjectEngineFactoryProvider _projectEngineFactoryProvider; private readonly ImmutableArray _resolvableTagHelpers; private readonly Workspace _workspace; private readonly Project _workspaceProject; @@ -35,7 +37,7 @@ public class DefaultProjectWorkspaceStateGeneratorTest : ProjectSnapshotManagerD public DefaultProjectWorkspaceStateGeneratorTest(ITestOutputHelper testOutput) : base(testOutput) { - var projectEngineFactory = Mock.Of(MockBehavior.Strict); + _projectEngineFactoryProvider = Mock.Of(MockBehavior.Strict); var tagHelperResolver = new TestTagHelperResolver() { @@ -43,7 +45,7 @@ public DefaultProjectWorkspaceStateGeneratorTest(ITestOutputHelper testOutput) }; _resolvableTagHelpers = tagHelperResolver.TagHelpers; - var workspaceServices = new List() { tagHelperResolver, projectEngineFactory }; + var workspaceServices = new List() { tagHelperResolver }; var testServices = TestServices.Create(workspaceServices, Enumerable.Empty()); _workspace = TestWorkspace.Create(testServices); AddDisposable(_workspace); @@ -57,7 +59,7 @@ public DefaultProjectWorkspaceStateGeneratorTest(ITestOutputHelper testOutput) TestProjectData.SomeProject.FilePath)); _workspaceProject = solution.GetProject(projectId); _projectSnapshot = new ProjectSnapshot( - ProjectState.Create(projectEngineFactory, TestProjectData.SomeProject, ProjectWorkspaceState.Default)); + ProjectState.Create(_projectEngineFactoryProvider, TestProjectData.SomeProject, ProjectWorkspaceState.Default)); _projectWorkspaceStateWithTagHelpers = ProjectWorkspaceState.Create(ImmutableArray.Create( TagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly").Build())); } @@ -121,7 +123,7 @@ public async Task Update_NullWorkspaceProject_ClearsProjectWorkspaceState() using (var stateGenerator = new DefaultProjectWorkspaceStateGenerator(Dispatcher, NoOpTelemetryReporter.Instance)) { stateGenerator.NotifyBackgroundWorkCompleted = new ManualResetEventSlim(initialState: false); - var projectManager = new TestProjectSnapshotManager(_workspace, Dispatcher); + var projectManager = new TestProjectSnapshotManager(_workspace, _projectEngineFactoryProvider, Dispatcher); stateGenerator.Initialize(projectManager); projectManager.ProjectAdded(_projectSnapshot.HostProject); projectManager.ProjectWorkspaceStateChanged(_projectSnapshot.Key, _projectWorkspaceStateWithTagHelpers); @@ -145,7 +147,7 @@ public async Task Update_ResolvesTagHelpersAndUpdatesWorkspaceState() using (var stateGenerator = new DefaultProjectWorkspaceStateGenerator(Dispatcher, NoOpTelemetryReporter.Instance)) { stateGenerator.NotifyBackgroundWorkCompleted = new ManualResetEventSlim(initialState: false); - var projectManager = new TestProjectSnapshotManager(_workspace, Dispatcher); + var projectManager = new TestProjectSnapshotManager(_workspace, _projectEngineFactoryProvider, Dispatcher); stateGenerator.Initialize(projectManager); projectManager.ProjectAdded(_projectSnapshot.HostProject); diff --git a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultRazorDocumentManagerTest.cs b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultRazorDocumentManagerTest.cs index a1f521de2dc..7a5d4cfcf08 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultRazorDocumentManagerTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultRazorDocumentManagerTest.cs @@ -6,8 +6,8 @@ using System.Collections.Immutable; using System.Collections.ObjectModel; using System.Threading.Tasks; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Test.Common.Editor; -using Microsoft.AspNetCore.Razor.Test.Common.Workspaces; using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.Editor; using Microsoft.CodeAnalysis.Razor.ProjectSystem; @@ -32,8 +32,6 @@ public class DefaultRazorDocumentManagerTest : ProjectSnapshotManagerDispatcherT private readonly WorkspaceEditorSettings _workspaceEditorSettings; private readonly ImportDocumentManager _importDocumentManager; - private readonly CodeAnalysis.Workspace _workspace; - public DefaultRazorDocumentManagerTest(ITestOutputHelper testOutput) : base(testOutput) { @@ -59,8 +57,6 @@ public DefaultRazorDocumentManagerTest(ITestOutputHelper testOutput) importDocumentManager.Setup(m => m.OnUnsubscribed(It.IsAny())).Verifiable(); _importDocumentManager = importDocumentManager.Object; - _workspace = TestWorkspace.Create(); - AddDisposable(_workspace); } [UIFact] @@ -90,7 +86,7 @@ public async Task OnTextViewOpened_ForRazorTextBuffer_AddsTextViewToTracker() }; var documentTracker = new DefaultVisualStudioDocumentTracker( Dispatcher, JoinableTaskContext, FilePath, ProjectPath, _projectManager, _workspaceEditorSettings, - _workspace, buffers[0], _importDocumentManager) as VisualStudioDocumentTracker; + ProjectEngineFactories.DefaultProvider, buffers[0], _importDocumentManager) as VisualStudioDocumentTracker; var editorFactoryService = Mock.Of( factoryService => factoryService.TryGetDocumentTracker( It.IsAny(), out documentTracker) == true, MockBehavior.Strict); @@ -114,7 +110,7 @@ public async Task OnTextViewOpened_SubscribesAfterFirstTextViewOpened() Mock.Of(b => b.ContentType == _nonRazorCoreContentType && b.Properties == new PropertyCollection(), MockBehavior.Strict), }; var documentTracker = new DefaultVisualStudioDocumentTracker( - Dispatcher, JoinableTaskContext, FilePath, ProjectPath, _projectManager, _workspaceEditorSettings, _workspace, buffers[0], _importDocumentManager) as VisualStudioDocumentTracker; + Dispatcher, JoinableTaskContext, FilePath, ProjectPath, _projectManager, _workspaceEditorSettings, ProjectEngineFactories.DefaultProvider, buffers[0], _importDocumentManager) as VisualStudioDocumentTracker; var editorFactoryService = Mock.Of(f => f.TryGetDocumentTracker(It.IsAny(), out documentTracker) == true, MockBehavior.Strict); var documentManager = new DefaultRazorDocumentManager(Dispatcher, JoinableTaskContext, editorFactoryService); @@ -161,14 +157,14 @@ public async Task OnTextViewClosed_ForAnyTextBufferWithTracker_RemovesTextView() // Preload the buffer's properties with a tracker, so it's like we've already tracked this one. var documentTracker = new DefaultVisualStudioDocumentTracker( Dispatcher, JoinableTaskContext, FilePath, ProjectPath, _projectManager, _workspaceEditorSettings, - _workspace, buffers[0], _importDocumentManager); + ProjectEngineFactories.DefaultProvider, buffers[0], _importDocumentManager); documentTracker.AddTextView(textView1); documentTracker.AddTextView(textView2); buffers[0].Properties.AddProperty(typeof(VisualStudioDocumentTracker), documentTracker); documentTracker = new DefaultVisualStudioDocumentTracker( Dispatcher, JoinableTaskContext, FilePath, ProjectPath, _projectManager, _workspaceEditorSettings, - _workspace, buffers[1], _importDocumentManager); + ProjectEngineFactories.DefaultProvider, buffers[1], _importDocumentManager); documentTracker.AddTextView(textView1); documentTracker.AddTextView(textView2); buffers[1].Properties.AddProperty(typeof(VisualStudioDocumentTracker), documentTracker); @@ -200,7 +196,7 @@ public async Task OnTextViewClosed_UnsubscribesAfterLastTextViewClosed() }; var documentTracker = new DefaultVisualStudioDocumentTracker( Dispatcher, JoinableTaskContext, FilePath, ProjectPath, _projectManager, _workspaceEditorSettings, - _workspace, buffers[0], _importDocumentManager); + ProjectEngineFactories.DefaultProvider, buffers[0], _importDocumentManager); buffers[0].Properties.AddProperty(typeof(VisualStudioDocumentTracker), documentTracker); var editorFactoryService = Mock.Of(MockBehavior.Strict); var documentManager = new DefaultRazorDocumentManager(Dispatcher, JoinableTaskContext, editorFactoryService); diff --git a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioDocumentTrackerTest.cs b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioDocumentTrackerTest.cs index 724b765a243..b7c991fb0d2 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioDocumentTrackerTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioDocumentTrackerTest.cs @@ -63,7 +63,7 @@ public DefaultVisualStudioDocumentTrackerTest(ITestOutputHelper testOutput) TagHelperDescriptorBuilder.Create("test", "test").Build(), }; - _projectManager = new TestProjectSnapshotManager(Workspace, Dispatcher) { AllowNotifyListeners = true }; + _projectManager = new TestProjectSnapshotManager(Workspace, ProjectEngineFactoryProvider, Dispatcher) { AllowNotifyListeners = true }; _hostProject = new HostProject(_projectPath, TestProjectData.SomeProject.IntermediateOutputPath, FallbackRazorConfiguration.MVC_2_1, _rootNamespace); _updatedHostProject = new HostProject(_projectPath, TestProjectData.SomeProject.IntermediateOutputPath, FallbackRazorConfiguration.MVC_2_0, _rootNamespace); @@ -76,7 +76,7 @@ public DefaultVisualStudioDocumentTrackerTest(ITestOutputHelper testOutput) _projectPath, _projectManager, _workspaceEditorSettings, - Workspace, + ProjectEngineFactoryProvider, _textBuffer, _importDocumentManager); } diff --git a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserIntegrationTest.cs b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserIntegrationTest.cs index 0ec5f44c3e1..556b899d83f 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserIntegrationTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserIntegrationTest.cs @@ -4,17 +4,15 @@ #nullable disable using System; -using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc.Razor.Extensions; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Syntax; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Test.Common.Editor; -using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem; using Microsoft.AspNetCore.Razor.Test.Common.Workspaces; -using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Microsoft.VisualStudio.Text; using Microsoft.VisualStudio.Text.Editor; @@ -30,6 +28,7 @@ public class DefaultVisualStudioRazorParserIntegrationTest : ProjectSnapshotMana private const string TestLinePragmaFileName = @"C:\This\Path\Is\Just\For\Line\Pragmas.cshtml"; private const string TestProjectPath = @"C:\This\Path\Is\Just\For\Project.csproj"; + private readonly IProjectEngineFactoryProvider _projectEngineFactoryProvider; private readonly IProjectSnapshot _projectSnapshot; private readonly CodeAnalysis.Workspace _workspace; @@ -39,7 +38,8 @@ public DefaultVisualStudioRazorParserIntegrationTest(ITestOutputHelper testOutpu _workspace = TestWorkspace.Create(); AddDisposable(_workspace); - _projectSnapshot = new EphemeralProjectSnapshot(_workspace.Services, TestProjectPath); + _projectEngineFactoryProvider = CreateProjectEngineFactoryProvider(); + _projectSnapshot = new EphemeralProjectSnapshot(_projectEngineFactoryProvider, TestProjectPath); } [UIFact] @@ -560,11 +560,10 @@ private void VerifyCurrentSyntaxTree(TestParserManager manager) private TestParserManager CreateParserManager(VisualStudioDocumentTracker documentTracker) { - var templateEngineFactory = CreateProjectEngineFactory(); var parser = new DefaultVisualStudioRazorParser( JoinableTaskFactory.Context, documentTracker, - templateEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, new TestCompletionBroker()) { @@ -587,7 +586,7 @@ private TestParserManager CreateParserManager(ITextSnapshot originalSnapshot) return CreateParserManager(documentTracker); } - private static IProjectSnapshotProjectEngineFactory CreateProjectEngineFactory(IEnumerable tagHelpers = null) + private static IProjectEngineFactoryProvider CreateProjectEngineFactoryProvider() { var fileSystem = new TestRazorProjectFileSystem(); var projectEngine = RazorProjectEngine.Create(RazorConfiguration.Default, fileSystem, builder => @@ -596,18 +595,20 @@ private static IProjectSnapshotProjectEngineFactory CreateProjectEngineFactory(I builder.AddDefaultImports("@addTagHelper *, Test"); - if (tagHelpers != null) - { - builder.AddTagHelpers(tagHelpers); - } - builder.Features.Add(new DefaultVisualStudioRazorParser.VisualStudioEnableTagHelpersFeature()); }); - return new TestProjectSnapshotProjectEngineFactory() - { - Engine = projectEngine, - }; + var factoryMock = new Mock(MockBehavior.Strict); + factoryMock + .Setup(x => x.Create(It.IsAny(), It.IsAny(), It.IsAny>())) + .Returns(projectEngine); + + var providerMock = new Mock(MockBehavior.Strict); + providerMock + .Setup(x => x.GetFactory(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns(factoryMock.Object); + + return providerMock.Object; } private async Task RunTypeKeywordTestAsync(string keyword) diff --git a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs index 8bf250de3a2..8c6f897c8c5 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs @@ -7,9 +7,9 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Test.Common.Editor; using Microsoft.AspNetCore.Razor.Test.Common.Workspaces; -using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Moq; using Xunit; @@ -20,7 +20,7 @@ namespace Microsoft.VisualStudio.Editor.Razor; public class DefaultVisualStudioRazorParserTest : ProjectSnapshotManagerDispatcherTestBase { private readonly IProjectSnapshot _projectSnapshot; - private readonly IProjectSnapshotProjectEngineFactory _projectEngineFactory; + private readonly IProjectEngineFactoryProvider _projectEngineFactoryProvider; private readonly CodeAnalysis.Workspace _workspace; public DefaultVisualStudioRazorParserTest(ITestOutputHelper testOutput) @@ -29,14 +29,21 @@ public DefaultVisualStudioRazorParserTest(ITestOutputHelper testOutput) _workspace = TestWorkspace.Create(); AddDisposable(_workspace); - _projectSnapshot = new EphemeralProjectSnapshot(_workspace.Services, "c:\\SomeProject.csproj"); - var engine = RazorProjectEngine.Create(RazorConfiguration.Default, RazorProjectFileSystem.Empty); - _projectEngineFactory = Mock.Of( - f => f.Create( - It.IsAny(), - It.IsAny(), - It.IsAny>()) == engine, MockBehavior.Strict); + + var factoryMock = new Mock(MockBehavior.Strict); + factoryMock + .Setup(x => x.Create(It.IsAny(), It.IsAny(), It.IsAny>())) + .Returns(engine); + + var factoryProviderMock = new Mock(MockBehavior.Strict); + factoryProviderMock + .Setup(x => x.GetFactory(It.IsAny(), It.IsAny(), It.IsAny())) + .Returns(factoryMock.Object); + + _projectEngineFactoryProvider = factoryProviderMock.Object; + + _projectSnapshot = new EphemeralProjectSnapshot(_projectEngineFactoryProvider, "c:\\SomeProject.csproj"); } private VisualStudioDocumentTracker CreateDocumentTracker(bool isSupportedProject = true, int versionNumber = 0) @@ -59,7 +66,7 @@ public async Task GetLatestCodeDocumentAsync_WaitsForParse() using (var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, documentTracker, - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict))) { @@ -101,7 +108,7 @@ public async Task GetLatestCodeDocumentAsync_NoPendingChangesReturnsImmediately( using (var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, documentTracker, - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict))) { @@ -140,7 +147,7 @@ public void GetLatestCodeDocumentAsync_MultipleCallsSameSnapshotMemoizesReturned using (var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, documentTracker, - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict))) { @@ -166,7 +173,7 @@ public void GetLatestCodeDocumentAsync_MultipleCallsDifferentSnapshotsReturnDiff using (var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, documentTracker, - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict))) { @@ -194,7 +201,7 @@ public async Task GetLatestCodeDocumentAsync_LatestChangeIsNewerThenRequested_Re using (var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, documentTracker, - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict))) { @@ -237,7 +244,7 @@ public async Task GetLatestCodeDocumentAsync_ParserDisposed_ReturnsImmediately() using (parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, documentTracker, - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict))) { @@ -379,7 +386,7 @@ public void ReparseOnUIThread_NoopsIfDisposed() var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, CreateDocumentTracker(), - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict)); parser.Dispose(); @@ -395,7 +402,7 @@ public void OnIdle_NoopsIfDisposed() var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, CreateDocumentTracker(), - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict)); parser.Dispose(); @@ -411,7 +418,7 @@ public void OnDocumentStructureChanged_NoopsIfDisposed() var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, CreateDocumentTracker(), - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict)); parser.Dispose(); @@ -427,7 +434,7 @@ public void OnDocumentStructureChanged_IgnoresEditsThatAreOld() using (var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, CreateDocumentTracker(), - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict))) { @@ -454,7 +461,7 @@ public void OnDocumentStructureChanged_FiresForLatestTextBufferEdit() using (var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, documentTracker, - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict))) { @@ -485,7 +492,7 @@ public void OnDocumentStructureChanged_FiresForOnlyLatestTextBufferReparseEdit() using (var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, documentTracker, - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict))) { @@ -524,7 +531,7 @@ public void StartIdleTimer_DoesNotRestartTimerWhenAlreadyRunning() using (var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, CreateDocumentTracker(), - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict)) { @@ -554,7 +561,7 @@ public void StopIdleTimer_StopsTimer() using (var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, CreateDocumentTracker(), - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict)) { @@ -583,7 +590,7 @@ public void StopParser_DetachesFromTextBufferChangeLoop() using (var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, CreateDocumentTracker(), - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict))) { @@ -607,7 +614,7 @@ public void StartParser_AttachesToTextBufferChangeLoop() using (var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, documentTracker, - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict))) { @@ -627,7 +634,7 @@ public void TryReinitializeParser_ReturnsTrue_IfProjectIsSupported() using (var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, CreateDocumentTracker(isSupportedProject: true), - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict))) { @@ -646,7 +653,7 @@ public void TryReinitializeParser_ReturnsFalse_IfProjectIsNotSupported() using (var parser = new DefaultVisualStudioRazorParser( JoinableTaskContext, CreateDocumentTracker(isSupportedProject: false), - _projectEngineFactory, + _projectEngineFactoryProvider, ErrorReporter, Mock.Of(MockBehavior.Strict))) { diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServerClient.Razor.Test/RazorDocumentOptionsServiceTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServerClient.Razor.Test/RazorDocumentOptionsServiceTest.cs index 041cd69492b..e439bffc506 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServerClient.Razor.Test/RazorDocumentOptionsServiceTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServerClient.Razor.Test/RazorDocumentOptionsServiceTest.cs @@ -104,7 +104,7 @@ private Document InitializeDocument(SourceText sourceText) Path.Combine(baseDirectory, "SomeProject", "File1.cshtml"), "File1.cshtml", FileKinds.Legacy); var project = new ProjectSnapshot( - ProjectState.Create(ProjectEngineFactory, hostProject, ProjectWorkspaceState.Default) + ProjectState.Create(ProjectEngineFactoryProvider, hostProject, ProjectWorkspaceState.Default) .WithAddedHostDocument(hostDocument, () => Task.FromResult(TextAndVersion.Create(sourceText, VersionStamp.Create())))); var documentSnapshot = project.GetDocument(hostDocument.FilePath); diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/DocumentGenerator/BackgroundDocumentGeneratorTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/DocumentGenerator/BackgroundDocumentGeneratorTest.cs index 199ccf1c5cb..350e5eb392f 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/DocumentGenerator/BackgroundDocumentGeneratorTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/DocumentGenerator/BackgroundDocumentGeneratorTest.cs @@ -53,7 +53,7 @@ protected override void ConfigureProjectEngine(RazorProjectEngineBuilder builder public async Task ProcessDocument_LongDocumentParse_DoesNotUpdateAfterSuppress() { // Arrange - var projectManager = new TestProjectSnapshotManager(Workspace, Dispatcher); + var projectManager = new TestProjectSnapshotManager(Workspace, ProjectEngineFactoryProvider, Dispatcher); projectManager.ProjectAdded(_hostProject1); // We utilize a task completion source here so we can "fake" a document parse taking a significant amount of time @@ -99,7 +99,7 @@ public async Task ProcessDocument_LongDocumentParse_DoesNotUpdateAfterSuppress() public async Task ProcessDocument_SwallowsIOExceptions() { // Arrange - var projectManager = new TestProjectSnapshotManager(Workspace, Dispatcher); + var projectManager = new TestProjectSnapshotManager(Workspace, ProjectEngineFactoryProvider, Dispatcher); projectManager.ProjectAdded(_hostProject1); var textLoader = new Mock(MockBehavior.Strict); @@ -130,7 +130,7 @@ public async Task ProcessDocument_SwallowsIOExceptions() public async Task ProcessDocument_SwallowsUnauthorizedAccessExceptions() { // Arrange - var projectManager = new TestProjectSnapshotManager(Workspace, Dispatcher); + var projectManager = new TestProjectSnapshotManager(Workspace, ProjectEngineFactoryProvider, Dispatcher); projectManager.ProjectAdded(_hostProject1); var textLoader = new Mock(MockBehavior.Strict); @@ -161,7 +161,7 @@ public async Task ProcessDocument_SwallowsUnauthorizedAccessExceptions() public async Task Queue_ProcessesNotifications_AndGoesBackToSleep() { // Arrange - var projectManager = new TestProjectSnapshotManager(Workspace, Dispatcher); + var projectManager = new TestProjectSnapshotManager(Workspace, ProjectEngineFactoryProvider, Dispatcher); projectManager.ProjectAdded(_hostProject1); projectManager.ProjectAdded(_hostProject2); projectManager.DocumentAdded(_hostProject1.Key, _documents[0], null); @@ -200,7 +200,7 @@ public async Task Queue_ProcessesNotifications_AndGoesBackToSleep() public async Task Queue_ProcessesNotifications_AndRestarts() { // Arrange - var projectManager = new TestProjectSnapshotManager(Workspace, Dispatcher); + var projectManager = new TestProjectSnapshotManager(Workspace, ProjectEngineFactoryProvider, Dispatcher); projectManager.ProjectAdded(_hostProject1); projectManager.ProjectAdded(_hostProject2); projectManager.DocumentAdded(_hostProject1.Key, _documents[0], null); @@ -263,7 +263,7 @@ public async Task Queue_ProcessesNotifications_AndRestarts() public async Task DocumentChanged_ReparsesRelatedFiles() { // Arrange - var projectManager = new TestProjectSnapshotManager(Workspace, Dispatcher) + var projectManager = new TestProjectSnapshotManager(Workspace, ProjectEngineFactoryProvider, Dispatcher) { AllowNotifyListeners = true, }; @@ -326,7 +326,7 @@ public async Task DocumentChanged_ReparsesRelatedFiles() public async Task DocumentRemoved_ReparsesRelatedFiles() { // Arrange - var projectManager = new TestProjectSnapshotManager(Workspace, Dispatcher) + var projectManager = new TestProjectSnapshotManager(Workspace, ProjectEngineFactoryProvider, Dispatcher) { AllowNotifyListeners = true, }; diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/DefaultProjectSnapshotManagerTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/DefaultProjectSnapshotManagerTest.cs index 57635b7804b..a618de1ec33 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/DefaultProjectSnapshotManagerTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/DefaultProjectSnapshotManagerTest.cs @@ -10,6 +10,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.ProjectSystem; using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.AspNetCore.Razor.Test.Common.Editor; @@ -59,7 +60,7 @@ public DefaultProjectSnapshotManagerTest(ITestOutputHelper testOutput) _hostProject2 = new HostProject(TestProjectData.AnotherProject.FilePath, TestProjectData.AnotherProject.IntermediateOutputPath, FallbackRazorConfiguration.MVC_2_1, TestProjectData.AnotherProject.RootNamespace); _hostProjectWithConfigurationChange = new HostProject(TestProjectData.SomeProject.FilePath, TestProjectData.SomeProject.IntermediateOutputPath, FallbackRazorConfiguration.MVC_1_0, TestProjectData.SomeProject.RootNamespace); - _projectManager = new TestProjectSnapshotManager(Enumerable.Empty(), Workspace, Dispatcher); + _projectManager = new TestProjectSnapshotManager(triggers: [], Workspace, ProjectEngineFactoryProvider, Dispatcher); _projectWorkspaceStateWithTagHelpers = ProjectWorkspaceState.Create(_tagHelperResolver.TagHelpers); @@ -88,7 +89,7 @@ public void Initialize_DoneInCorrectOrderBasedOnInitializePriorityPriority() var triggers = new[] { defaultPriorityTrigger, highPriorityTrigger }; // Act - var projectManager = new TestProjectSnapshotManager(triggers, Workspace, Dispatcher); + var projectManager = new TestProjectSnapshotManager(triggers, Workspace, ProjectEngineFactoryProvider, Dispatcher); // Assert Assert.Equal(new[] { "highPriority", "lowPriority" }, initializedOrder); @@ -663,13 +664,13 @@ public void SolutionClosing_ProjectChangedEventsCorrect() textLoader.Verify(d => d.LoadTextAndVersionAsync(It.IsAny(), It.IsAny()), Times.Never()); } - private class TestProjectSnapshotManager : DefaultProjectSnapshotManager + private class TestProjectSnapshotManager( + IEnumerable triggers, + Workspace workspace, + IProjectEngineFactoryProvider projectEngineFactoryProvider, + ProjectSnapshotManagerDispatcher dispatcher) + : DefaultProjectSnapshotManager(Mock.Of(MockBehavior.Strict), triggers, workspace, projectEngineFactoryProvider, dispatcher) { - public TestProjectSnapshotManager(IEnumerable triggers, Workspace workspace, ProjectSnapshotManagerDispatcher dispatcher) - : base(Mock.Of(MockBehavior.Strict), triggers, workspace, dispatcher) - { - } - public ProjectChangeKind? ListenersNotifiedOf { get; private set; } public bool NotifyChangedEvents { get; set; } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/DefaultRazorDynamicFileInfoProviderTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/DefaultRazorDynamicFileInfoProviderTest.cs index ba236f9c266..4786918e0a4 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/DefaultRazorDynamicFileInfoProviderTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/DefaultRazorDynamicFileInfoProviderTest.cs @@ -40,7 +40,7 @@ public DefaultRazorDynamicFileInfoProviderTest(ITestOutputHelper testOutput) { _documentServiceFactory = new DefaultRazorDocumentServiceProviderFactory(); _editorFeatureDetector = Mock.Of(MockBehavior.Strict); - _projectSnapshotManager = new TestProjectSnapshotManager(Workspace, new TestProjectSnapshotManagerDispatcher()) + _projectSnapshotManager = new TestProjectSnapshotManager(Workspace, ProjectEngineFactoryProvider, new TestProjectSnapshotManagerDispatcher()) { AllowNotifyListeners = true }; diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/DefaultWindowsRazorProjectHostTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/DefaultWindowsRazorProjectHostTest.cs index f9b18fa951b..6ccb8ef9ea7 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/DefaultWindowsRazorProjectHostTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/DefaultWindowsRazorProjectHostTest.cs @@ -3,13 +3,13 @@ #nullable disable -using System; using System.Collections.Generic; using System.Collections.Immutable; using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.AspNetCore.Razor.Test.Common.Editor; using Microsoft.VisualStudio.ProjectSystem; @@ -35,7 +35,7 @@ public class DefaultWindowsRazorProjectHostTest : ProjectSnapshotManagerDispatch public DefaultWindowsRazorProjectHostTest(ITestOutputHelper testOutput) : base(testOutput) { - _projectManager = new TestProjectSnapshotManager(Workspace, Dispatcher); + _projectManager = new TestProjectSnapshotManager(Workspace, ProjectEngineFactoryProvider, Dispatcher); var projectConfigurationFilePathStore = new Mock(MockBehavior.Strict); projectConfigurationFilePathStore.Setup(s => s.Remove(It.IsAny())).Verifiable(); @@ -1237,11 +1237,16 @@ public async Task OnProjectRenamed_RemovesHostProject_CopiesConfiguration() Assert.Empty(_projectManager.GetProjects()); } - private class TestProjectSnapshotManager : DefaultProjectSnapshotManager + private class TestProjectSnapshotManager( + Workspace workspace, + IProjectEngineFactoryProvider projectEngineFactoryProvider, + ProjectSnapshotManagerDispatcher dispatcher) + : DefaultProjectSnapshotManager( + Mock.Of(MockBehavior.Strict), + triggers: [], + workspace, + projectEngineFactoryProvider, + dispatcher) { - public TestProjectSnapshotManager(Workspace workspace, ProjectSnapshotManagerDispatcher dispatcher) - : base(Mock.Of(MockBehavior.Strict), Array.Empty(), workspace, dispatcher) - { - } } } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/FallbackWindowsRazorProjectHostTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/FallbackWindowsRazorProjectHostTest.cs index 0a46be9aa54..8e193de40ef 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/FallbackWindowsRazorProjectHostTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/FallbackWindowsRazorProjectHostTest.cs @@ -10,6 +10,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Test.Common.Editor; using Microsoft.VisualStudio.ProjectSystem; using Microsoft.VisualStudio.ProjectSystem.Properties; @@ -32,7 +33,7 @@ public class FallbackWindowsRazorProjectHostTest : ProjectSnapshotManagerDispatc public FallbackWindowsRazorProjectHostTest(ITestOutputHelper testOutput) : base(testOutput) { - _projectManager = new TestProjectSnapshotManager(Workspace, Dispatcher); + _projectManager = new TestProjectSnapshotManager(Workspace, ProjectEngineFactoryProvider, Dispatcher); var projectConfigurationFilePathStore = new Mock(MockBehavior.Strict); projectConfigurationFilePathStore.Setup(s => s.Remove(It.IsAny())).Verifiable(); @@ -664,11 +665,15 @@ protected override bool TryGetIntermediateOutputPath(IImmutableDictionary(MockBehavior.Strict), + triggers: [], + workspace, + projectEngineFactoryProvider, + dispatcher) { - public TestProjectSnapshotManager(Workspace workspace, ProjectSnapshotManagerDispatcher dispatcher) - : base(Mock.Of(MockBehavior.Strict), Array.Empty(), workspace, dispatcher) - { - } } } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/WorkspaceProjectStateChangeDetectorTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/WorkspaceProjectStateChangeDetectorTest.cs index 5597afaf675..1efb8e614d6 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/WorkspaceProjectStateChangeDetectorTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/WorkspaceProjectStateChangeDetectorTest.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using System.Threading; using Microsoft.AspNetCore.Razor.Language.Components; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Test.Common.Workspaces; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Razor.Workspaces; @@ -144,7 +145,7 @@ public async Task SolutionClosing_StopsActiveWork() _workQueueTestAccessor.NotifyBackgroundWorkStarting = new ManualResetEventSlim(initialState: false); Workspace.TryApplyChanges(_solutionWithTwoProjects); - var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace); + var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace, ProjectEngineFactoryProvider); await s_dispatcher.RunOnDispatcherThreadAsync(() => projectManager.ProjectAdded(_hostProjectOne), DisposalToken); workspaceStateGenerator.ClearQueue(); _workQueueTestAccessor.NotifyBackgroundWorkStarting.Wait(); @@ -183,7 +184,7 @@ public async Task WorkspaceChanged_DocumentEvents_EnqueuesUpdatesForDependentPro }; _workQueueTestAccessor.BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false); - var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace); + var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace, ProjectEngineFactoryProvider); await s_dispatcher.RunOnDispatcherThreadAsync(() => { @@ -233,7 +234,7 @@ public async Task WorkspaceChanged_ProjectEvents_EnqueuesUpdatesForDependentProj }; _workQueueTestAccessor.BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false); - var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace); + var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace, ProjectEngineFactoryProvider); await s_dispatcher.RunOnDispatcherThreadAsync(() => { @@ -283,7 +284,7 @@ public async Task WorkspaceChanged_SolutionEvents_EnqueuesUpdatesForProjectsInSo { NotifyWorkspaceChangedEventComplete = new ManualResetEventSlim(initialState: false), }; - var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace); + var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace, ProjectEngineFactoryProvider); await s_dispatcher.RunOnDispatcherThreadAsync(() => { projectManager.ProjectAdded(_hostProjectOne); @@ -319,7 +320,7 @@ public async Task WorkspaceChanged_SolutionEvents_EnqueuesStateClear_EnqueuesSol NotifyWorkspaceChangedEventComplete = new ManualResetEventSlim(initialState: false), }; - var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace); + var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace, ProjectEngineFactoryProvider); await s_dispatcher.RunOnDispatcherThreadAsync(() => { @@ -362,7 +363,7 @@ public async Task WorkspaceChanged_ProjectChangeEvents_UpdatesProjectState_After var detector = new WorkspaceProjectStateChangeDetector(workspaceStateGenerator, s_dispatcher, TestLanguageServerFeatureOptions.Instance, _workQueue); _workQueueTestAccessor.BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false); - var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace); + var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace, ProjectEngineFactoryProvider); await s_dispatcher.RunOnDispatcherThreadAsync(() => projectManager.ProjectAdded(_hostProjectOne), DisposalToken); var solution = _solutionWithTwoProjects.WithProjectAssemblyName(_projectNumberOne.Id, "Changed"); @@ -393,7 +394,7 @@ public async Task WorkspaceChanged_DocumentChanged_BackgroundVirtualCS_UpdatesPr _workQueueTestAccessor.BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false); Workspace.TryApplyChanges(_solutionWithTwoProjects); - var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace); + var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace, ProjectEngineFactoryProvider); await s_dispatcher.RunOnDispatcherThreadAsync(() => projectManager.ProjectAdded(_hostProjectOne), DisposalToken); workspaceStateGenerator.ClearQueue(); @@ -425,7 +426,7 @@ public async Task WorkspaceChanged_DocumentChanged_CSHTML_UpdatesProjectState_Af _workQueueTestAccessor.BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false); Workspace.TryApplyChanges(_solutionWithTwoProjects); - var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace); + var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace, ProjectEngineFactoryProvider); await s_dispatcher.RunOnDispatcherThreadAsync(() => projectManager.ProjectAdded(_hostProjectOne), DisposalToken); workspaceStateGenerator.ClearQueue(); @@ -457,7 +458,7 @@ public async Task WorkspaceChanged_DocumentChanged_Razor_UpdatesProjectState_Aft _workQueueTestAccessor.BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false); Workspace.TryApplyChanges(_solutionWithTwoProjects); - var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace); + var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace, ProjectEngineFactoryProvider); await s_dispatcher.RunOnDispatcherThreadAsync(() => projectManager.ProjectAdded(_hostProjectOne), DisposalToken); workspaceStateGenerator.ClearQueue(); @@ -489,7 +490,7 @@ public async Task WorkspaceChanged_DocumentChanged_PartialComponent_UpdatesProje _workQueueTestAccessor.BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false); Workspace.TryApplyChanges(_solutionWithTwoProjects); - var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace); + var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace, ProjectEngineFactoryProvider); await s_dispatcher.RunOnDispatcherThreadAsync(() => projectManager.ProjectAdded(_hostProjectOne), DisposalToken); workspaceStateGenerator.ClearQueue(); @@ -538,7 +539,7 @@ public async Task WorkspaceChanged_ProjectRemovedEvent_QueuesProjectStateRemoval { NotifyWorkspaceChangedEventComplete = new ManualResetEventSlim(initialState: false), }; - var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace); + var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace, ProjectEngineFactoryProvider); await s_dispatcher.RunOnDispatcherThreadAsync(() => { projectManager.ProjectAdded(_hostProjectOne); @@ -567,7 +568,7 @@ public async Task WorkspaceChanged_ProjectAddedEvent_AddsProject() { NotifyWorkspaceChangedEventComplete = new ManualResetEventSlim(initialState: false), }; - var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace); + var projectManager = new TestProjectSnapshotManager(new[] { detector }, Workspace, ProjectEngineFactoryProvider); await s_dispatcher.RunOnDispatcherThreadAsync(() => projectManager.ProjectAdded(_hostProjectThree), DisposalToken); var solution = _solutionWithOneProject; @@ -773,14 +774,17 @@ public interface IComponent {} Assert.False(result); } - private class TestProjectSnapshotManager : DefaultProjectSnapshotManager + private class TestProjectSnapshotManager( + IEnumerable triggers, + Workspace workspace, + IProjectEngineFactoryProvider projectEngineFactoryProvider) + : DefaultProjectSnapshotManager( + Mock.Of(MockBehavior.Strict), + triggers, + workspace, + projectEngineFactoryProvider, + s_dispatcher) { - public TestProjectSnapshotManager( - IEnumerable triggers, - Workspace workspace) - : base(Mock.Of(MockBehavior.Strict), triggers, workspace, s_dispatcher) - { - } } private class TestSVsServiceProvider : SVsServiceProvider diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/VsSolutionUpdatesProjectSnapshotChangeTriggerTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/VsSolutionUpdatesProjectSnapshotChangeTriggerTest.cs index 588541fa01e..656cb319b28 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/VsSolutionUpdatesProjectSnapshotChangeTriggerTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/VsSolutionUpdatesProjectSnapshotChangeTriggerTest.cs @@ -8,6 +8,7 @@ using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.ProjectSystem; using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.AspNetCore.Razor.Test.Common.ProjectSystem; @@ -40,8 +41,7 @@ public VsSolutionUpdatesProjectSnapshotChangeTriggerTest(ITestOutputHelper testO _someProject = new HostProject(TestProjectData.SomeProject.FilePath, TestProjectData.SomeProject.IntermediateOutputPath, FallbackRazorConfiguration.MVC_1_0, TestProjectData.SomeProject.RootNamespace); _someOtherProject = new HostProject(TestProjectData.AnotherProject.FilePath, TestProjectData.AnotherProject.IntermediateOutputPath, FallbackRazorConfiguration.MVC_2_0, TestProjectData.AnotherProject.RootNamespace); - var projectEngineFactory = Mock.Of(MockBehavior.Strict); - var testServices = TestServices.Create([projectEngineFactory], []); + var testServices = TestServices.Create([], []); _workspace = TestWorkspace.Create(testServices, w => @@ -123,7 +123,7 @@ await Task.Run(() => public async Task SolutionClosing_CancelsActiveWork() { // Arrange - var projectManager = new TestProjectSnapshotManager(_workspace, s_dispatcher) + var projectManager = new TestProjectSnapshotManager(_workspace, ProjectEngineFactories.DefaultProvider, s_dispatcher) { AllowNotifyListeners = true, }; @@ -163,7 +163,7 @@ await s_dispatcher.RunOnDispatcherThreadAsync(() => public async Task OnProjectBuiltAsync_KnownProject_EnqueuesProjectStateUpdate() { // Arrange - var projectManager = new TestProjectSnapshotManager(_workspace, s_dispatcher); + var projectManager = new TestProjectSnapshotManager(_workspace, ProjectEngineFactories.DefaultProvider, s_dispatcher); var expectedProjectPath = _someProject.FilePath; var expectedProjectSnapshot = await s_dispatcher.RunOnDispatcherThreadAsync(() => { @@ -204,11 +204,11 @@ public async Task OnProjectBuiltAsync_WithoutWorkspaceProject_DoesNotEnqueueUpda .Setup(s => s.GetService(It.Is(f => f == typeof(SVsSolutionBuildManager)))) .Returns(buildManager.Object); - var projectEngineFactory = Mock.Of(MockBehavior.Strict); + var projectEngineFactoryProvider = Mock.Of(MockBehavior.Strict); var projectSnapshot = new ProjectSnapshot( ProjectState.Create( - projectEngineFactory, + projectEngineFactoryProvider, new HostProject("/Some/Unknown/Path.csproj", "/Some/Unknown/obj", RazorConfiguration.Default, "Path"), ProjectWorkspaceState.Default)); var expectedProjectPath = projectSnapshot.FilePath; diff --git a/src/Razor/test/Microsoft.VisualStudio.LiveShare.Razor.Test/Guest/ProjectSnapshotSynchronizationServiceTest.cs b/src/Razor/test/Microsoft.VisualStudio.LiveShare.Razor.Test/Guest/ProjectSnapshotSynchronizationServiceTest.cs index 38664a46f22..09bcdaab56a 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LiveShare.Razor.Test/Guest/ProjectSnapshotSynchronizationServiceTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LiveShare.Razor.Test/Guest/ProjectSnapshotSynchronizationServiceTest.cs @@ -32,7 +32,7 @@ public ProjectSnapshotSynchronizationServiceTest(ITestOutputHelper testOutput) { _sessionContext = new TestCollaborationSession(isHost: false); - _projectSnapshotManager = new TestProjectSnapshotManager(Workspace, new TestProjectSnapshotManagerDispatcher()); + _projectSnapshotManager = new TestProjectSnapshotManager(Workspace, ProjectEngineFactoryProvider, new TestProjectSnapshotManagerDispatcher()); _projectWorkspaceStateWithTagHelpers = ProjectWorkspaceState.Create(ImmutableArray.Create( TagHelperDescriptorBuilder.Create("TestTagHelper", "TestAssembly").Build())); diff --git a/src/Razor/test/Microsoft.VisualStudio.LiveShare.Razor.Test/Host/DefaultProjectSnapshotManagerProxyTest.cs b/src/Razor/test/Microsoft.VisualStudio.LiveShare.Razor.Test/Host/DefaultProjectSnapshotManagerProxyTest.cs index 8b56ce768e5..c9bb68f180e 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LiveShare.Razor.Test/Host/DefaultProjectSnapshotManagerProxyTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LiveShare.Razor.Test/Host/DefaultProjectSnapshotManagerProxyTest.cs @@ -7,9 +7,9 @@ using System.Collections.Immutable; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; +using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.ProjectSystem; using Microsoft.AspNetCore.Razor.Test.Common.Editor; -using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Microsoft.VisualStudio.LiveShare.Razor.Test; using Microsoft.VisualStudio.Threading; @@ -27,14 +27,14 @@ public class DefaultProjectSnapshotManagerProxyTest : ProjectSnapshotManagerDisp public DefaultProjectSnapshotManagerProxyTest(ITestOutputHelper testOutput) : base(testOutput) { - var projectEngineFactory = Mock.Of(MockBehavior.Strict); + var projectEngineFactoryProvider = Mock.Of(MockBehavior.Strict); var projectWorkspaceState1 = ProjectWorkspaceState.Create(ImmutableArray.Create( TagHelperDescriptorBuilder.Create("test1", "TestAssembly1").Build())); _projectSnapshot1 = new ProjectSnapshot( ProjectState.Create( - projectEngineFactory, + projectEngineFactoryProvider, new HostProject("/host/path/to/project1.csproj", "/host/path/to/obj", RazorConfiguration.Default, "project1"), projectWorkspaceState1)); @@ -43,7 +43,7 @@ public DefaultProjectSnapshotManagerProxyTest(ITestOutputHelper testOutput) _projectSnapshot2 = new ProjectSnapshot( ProjectState.Create( - projectEngineFactory, + projectEngineFactoryProvider, new HostProject("/host/path/to/project2.csproj", "/host/path/to/obj", RazorConfiguration.Default, "project2"), projectWorkspaceState2)); } From f3922f6a07bae7bbc1c82795f388b831cac1e10f Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 19 Jan 2024 08:03:49 +1100 Subject: [PATCH 15/25] Modify the snapshot instead of using the project engine in MapCode --- .../MapCode/MapCodeEndpoint.cs | 26 +++---------------- .../MapCode/MapCodeTest.cs | 2 -- 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/MapCode/MapCodeEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/MapCode/MapCodeEndpoint.cs index dfc1b367813..344b156d0ee 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/MapCode/MapCodeEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/MapCode/MapCodeEndpoint.cs @@ -18,7 +18,6 @@ using Microsoft.AspNetCore.Razor.LanguageServer.Protocol; using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Razor.Workspaces.Extensions; using Microsoft.CodeAnalysis.Text; using Microsoft.CommonLanguageServerProtocol.Framework; @@ -76,11 +75,12 @@ internal sealed class MapCodeEndpoint( continue; } - var (projectEngine, importSources) = await InitializeProjectEngineAsync(documentContext.Snapshot).ConfigureAwait(false); var tagHelperContext = await documentContext.GetTagHelperContextAsync(cancellationToken).ConfigureAwait(false); var fileKind = FileKinds.GetFileKindFromFilePath(documentContext.FilePath); var extension = Path.GetExtension(documentContext.FilePath); + var snapshot = documentContext.Snapshot; + foreach (var content in mapping.Contents) { if (content is null) @@ -89,8 +89,8 @@ internal sealed class MapCodeEndpoint( } // We create a new Razor file based on each content in each mapping order to get the syntax tree that we'll later use to map. - var sourceDocument = RazorSourceDocument.Create(content, "Test" + extension); - var codeToMap = projectEngine.ProcessDesignTime(sourceDocument, fileKind, importSources, tagHelperContext.TagHelpers); + var newSnapshot = snapshot.WithText(SourceText.From(content)); + var codeToMap = await newSnapshot.GetGeneratedOutputAsync().ConfigureAwait(false); var mappingSuccess = await TryMapCodeAsync( codeToMap, mapping.FocusLocations, changes, documentContext, cancellationToken).ConfigureAwait(false); @@ -241,24 +241,6 @@ private async Task TryMapCodeAsync( return false; } - private static async Task<(RazorProjectEngine projectEngine, ImmutableArray importSources)> InitializeProjectEngineAsync( - IDocumentSnapshot originalSnapshot) - { - var engine = originalSnapshot.Project.GetProjectEngine(); - - var imports = originalSnapshot.GetImports(); - using var importSources = new PooledArrayBuilder(imports.Length); - - foreach (var import in imports) - { - var sourceText = await import.GetTextAsync().ConfigureAwait(false); - var source = RazorSourceDocument.Create(sourceText, RazorSourceDocumentProperties.Create(import.FilePath, import.TargetPath)); - importSources.Add(source); - } - - return (engine, importSources.DrainToImmutable()); - } - private static List ExtractValidNodesToMap(SyntaxNode rootNode) { var validNodesToMap = new List(); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/MapCode/MapCodeTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/MapCode/MapCodeTest.cs index 181774506d4..fe7ff459082 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/MapCode/MapCodeTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/MapCode/MapCodeTest.cs @@ -11,8 +11,6 @@ using Microsoft.AspNetCore.Razor.LanguageServer.Protocol; using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer; using Microsoft.AspNetCore.Razor.Test.Common.Mef; -using Microsoft.AspNetCore.Razor.Test.Common.Workspaces; -using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Razor.Workspaces.Extensions; using Microsoft.CodeAnalysis.Testing; using Microsoft.CodeAnalysis.Text; From 5c5fc3aa57d67c91b4b947e36e9c84e62d455f77 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jan 2024 10:41:30 -0800 Subject: [PATCH 16/25] Convert GeneratedDocumentPublisher to an interface --- .../DefaultGeneratedDocumentPublisher.cs | 273 ------------------ .../IServiceCollectionExtensions.cs | 4 +- .../GeneratedDocumentPublisher.cs | 265 ++++++++++++++++- .../GeneratedDocumentSynchronizer.cs | 4 +- .../IGeneratedDocumentPublisher.cs | 13 + .../DefaultGeneratedDocumentPublisherTest.cs | 28 +- .../GeneratedDocumentSynchronizerTest.cs | 10 +- 7 files changed, 295 insertions(+), 302 deletions(-) delete mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultGeneratedDocumentPublisher.cs create mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/IGeneratedDocumentPublisher.cs diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultGeneratedDocumentPublisher.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultGeneratedDocumentPublisher.cs deleted file mode 100644 index b10067b0a5e..00000000000 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultGeneratedDocumentPublisher.cs +++ /dev/null @@ -1,273 +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; -using System.Collections.Generic; -using System.Diagnostics; -using System.Threading; -using Microsoft.AspNetCore.Razor.LanguageServer.Common; -using Microsoft.AspNetCore.Razor.TextDifferencing; -using Microsoft.CodeAnalysis.Razor; -using Microsoft.CodeAnalysis.Razor.Logging; -using Microsoft.CodeAnalysis.Razor.ProjectSystem; -using Microsoft.CodeAnalysis.Razor.Workspaces; -using Microsoft.CodeAnalysis.Text; -using Microsoft.Extensions.Logging; - -namespace Microsoft.AspNetCore.Razor.LanguageServer; - -internal class DefaultGeneratedDocumentPublisher : GeneratedDocumentPublisher -{ - private readonly Dictionary _publishedCSharpData; - private readonly Dictionary _publishedHtmlData; - private readonly IClientConnection _clientConnection; - private readonly LanguageServerFeatureOptions _languageServerFeatureOptions; - private readonly ILogger _logger; - private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher; - private ProjectSnapshotManagerBase? _projectSnapshotManager; - - public DefaultGeneratedDocumentPublisher( - ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher, - IClientConnection clientConnection, - LanguageServerFeatureOptions languageServerFeatureOptions, - IRazorLoggerFactory loggerFactory) - { - if (projectSnapshotManagerDispatcher is null) - { - throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher)); - } - - if (clientConnection is null) - { - throw new ArgumentNullException(nameof(clientConnection)); - } - - if (languageServerFeatureOptions is null) - { - throw new ArgumentNullException(nameof(languageServerFeatureOptions)); - } - - if (loggerFactory is null) - { - throw new ArgumentNullException(nameof(loggerFactory)); - } - - _projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher; - _clientConnection = clientConnection; - _languageServerFeatureOptions = languageServerFeatureOptions; - _logger = loggerFactory.CreateLogger(); - _publishedCSharpData = new Dictionary(); - - // We don't generate individual Html documents per-project, so in order to ensure diffs are calculated correctly - // we don't use the project key for the key for this dictionary. This matches when we send edits to the client, - // as they are only tracking a single Html file for each Razor file path, thus edits need to be correct or we'll - // get out of sync. - _publishedHtmlData = new Dictionary(FilePathComparer.Instance); - } - - public override void Initialize(ProjectSnapshotManagerBase projectManager) - { - if (projectManager is null) - { - throw new ArgumentNullException(nameof(projectManager)); - } - - _projectSnapshotManager = projectManager; - _projectSnapshotManager.Changed += ProjectSnapshotManager_Changed; - } - - public override void PublishCSharp(ProjectKey projectKey, string filePath, SourceText sourceText, int hostDocumentVersion) - { - if (filePath is null) - { - throw new ArgumentNullException(nameof(filePath)); - } - - if (sourceText is null) - { - throw new ArgumentNullException(nameof(sourceText)); - } - - _projectSnapshotManagerDispatcher.AssertDispatcherThread(); - - // If our generated documents don't have unique file paths, then using project key information is problematic for the client. - // For example, when a document moves from the Misc Project to a real project, we will update it here, and each version would - // have a different project key. On the receiving end however, there is only one file path, therefore one version of the contents, - // so we must ensure we only have a single document to compute diffs from, or things get out of sync. - if (!_languageServerFeatureOptions.IncludeProjectKeyInGeneratedFilePath) - { - projectKey = default; - } - - var key = new DocumentKey(projectKey, filePath); - if (!_publishedCSharpData.TryGetValue(key, out var previouslyPublishedData)) - { - _logger.LogDebug("New publish data created for {project} and {filePath}", projectKey, filePath); - previouslyPublishedData = PublishData.Default; - } - - var textChanges = SourceTextDiffer.GetMinimalTextChanges(previouslyPublishedData.SourceText, sourceText); - if (textChanges.Count == 0 && hostDocumentVersion == previouslyPublishedData.HostDocumentVersion) - { - // Source texts match along with host document versions. We've already published something that looks like this. No-op. - return; - } - - if (_logger.IsEnabled(LogLevel.Trace)) - { - var previousDocumentLength = previouslyPublishedData.SourceText.Length; - var currentDocumentLength = sourceText.Length; - var documentLengthDelta = sourceText.Length - previousDocumentLength; - _logger.LogTrace( - "Updating C# buffer of {0} for project {1} to correspond with host document version {2}. {3} -> {4} = Change delta of {5} via {6} text changes.", - filePath, - projectKey, - hostDocumentVersion, - previousDocumentLength, - currentDocumentLength, - documentLengthDelta, - textChanges.Count); - } - - _publishedCSharpData[key] = new PublishData(sourceText, hostDocumentVersion); - - var request = new UpdateBufferRequest() - { - HostDocumentFilePath = filePath, - ProjectKeyId = projectKey.Id, - Changes = textChanges, - HostDocumentVersion = hostDocumentVersion, - PreviousWasEmpty = previouslyPublishedData.SourceText.Length == 0 - }; - - _ = _clientConnection.SendNotificationAsync(CustomMessageNames.RazorUpdateCSharpBufferEndpoint, request, CancellationToken.None); - } - - public override void PublishHtml(ProjectKey projectKey, string filePath, SourceText sourceText, int hostDocumentVersion) - { - if (filePath is null) - { - throw new ArgumentNullException(nameof(filePath)); - } - - if (sourceText is null) - { - throw new ArgumentNullException(nameof(sourceText)); - } - - _projectSnapshotManagerDispatcher.AssertDispatcherThread(); - - if (!_publishedHtmlData.TryGetValue(filePath, out var previouslyPublishedData)) - { - previouslyPublishedData = PublishData.Default; - } - - var textChanges = SourceTextDiffer.GetMinimalTextChanges(previouslyPublishedData.SourceText, sourceText); - if (textChanges.Count == 0 && hostDocumentVersion == previouslyPublishedData.HostDocumentVersion) - { - // Source texts match along with host document versions. We've already published something that looks like this. No-op. - return; - } - - if (_logger.IsEnabled(LogLevel.Trace)) - { - var previousDocumentLength = previouslyPublishedData.SourceText.Length; - var currentDocumentLength = sourceText.Length; - var documentLengthDelta = sourceText.Length - previousDocumentLength; - _logger.LogTrace( - "Updating HTML buffer of {0} to correspond with host document version {1}. {2} -> {3} = Change delta of {4} via {5} text changes.", - filePath, - hostDocumentVersion, - previousDocumentLength, - currentDocumentLength, - documentLengthDelta, - textChanges.Count); - } - - _publishedHtmlData[filePath] = new PublishData(sourceText, hostDocumentVersion); - - var request = new UpdateBufferRequest() - { - HostDocumentFilePath = filePath, - ProjectKeyId = projectKey.Id, - Changes = textChanges, - HostDocumentVersion = hostDocumentVersion, - PreviousWasEmpty = previouslyPublishedData.SourceText.Length == 0 - }; - - _ = _clientConnection.SendNotificationAsync(CustomMessageNames.RazorUpdateHtmlBufferEndpoint, request, CancellationToken.None); - } - - private void ProjectSnapshotManager_Changed(object? sender, ProjectChangeEventArgs args) - { - // Don't do any work if the solution is closing - if (args.SolutionIsClosing) - { - return; - } - - _projectSnapshotManagerDispatcher.AssertDispatcherThread(); - - Assumes.NotNull(_projectSnapshotManager); - - switch (args.Kind) - { - case ProjectChangeKind.DocumentChanged: - Assumes.NotNull(args.DocumentFilePath); - if (!_projectSnapshotManager.IsDocumentOpen(args.DocumentFilePath)) - { - // Document closed, evict published source text, unless the server doesn't want us to. - if (_languageServerFeatureOptions.UpdateBuffersForClosedDocuments) - { - // Some clients want us to keep generating code even if the document is closed, so if we evict our data, - // even though we don't send a didChange for it, the next didChange will be wrong. - return; - } - - var projectKey = args.ProjectKey; - if (!_languageServerFeatureOptions.IncludeProjectKeyInGeneratedFilePath) - { - projectKey = default; - } - - var key = new DocumentKey(projectKey, args.DocumentFilePath); - if (_publishedCSharpData.ContainsKey(key)) - { - var removed = _publishedCSharpData.Remove(key); - if (!removed) - { - _logger.LogError("Published data should be protected by the project snapshot manager's thread and should never fail to remove."); - Debug.Fail("Published data should be protected by the project snapshot manager's thread and should never fail to remove."); - } - } - - if (_publishedHtmlData.ContainsKey(args.DocumentFilePath)) - { - var removed = _publishedHtmlData.Remove(args.DocumentFilePath); - if (!removed) - { - _logger.LogError("Published data should be protected by the project snapshot manager's thread and should never fail to remove."); - Debug.Fail("Published data should be protected by the project snapshot manager's thread and should never fail to remove."); - } - } - } - - break; - } - } - - private sealed class PublishData - { - public static readonly PublishData Default = new PublishData(SourceText.From(string.Empty), null); - - public PublishData(SourceText sourceText, int? hostDocumentVersion) - { - SourceText = sourceText; - HostDocumentVersion = hostDocumentVersion; - } - - public SourceText SourceText { get; } - - public int? HostDocumentVersion { get; } - } -} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Extensions/IServiceCollectionExtensions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Extensions/IServiceCollectionExtensions.cs index 91b59c51e62..1f1a4245ddd 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Extensions/IServiceCollectionExtensions.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Extensions/IServiceCollectionExtensions.cs @@ -194,8 +194,8 @@ public static void AddOptionsServices(this IServiceCollection services, RazorLSP public static void AddDocumentManagementServices(this IServiceCollection services, LanguageServerFeatureOptions featureOptions) { - services.AddSingleton(); - services.AddSingleton((services) => services.GetRequiredService()); + services.AddSingleton(); + services.AddSingleton((services) => (GeneratedDocumentPublisher)services.GetRequiredService()); services.AddSingleton(); services.AddSingleton(sp => new Lazy(sp.GetRequiredService)); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/GeneratedDocumentPublisher.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/GeneratedDocumentPublisher.cs index ac078049486..090e233081e 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/GeneratedDocumentPublisher.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/GeneratedDocumentPublisher.cs @@ -1,16 +1,273 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Threading; +using Microsoft.AspNetCore.Razor.LanguageServer.Common; +using Microsoft.AspNetCore.Razor.TextDifferencing; +using Microsoft.CodeAnalysis.Razor; +using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.ProjectSystem; +using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Text; +using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Razor.LanguageServer; -internal abstract class GeneratedDocumentPublisher : IProjectSnapshotChangeTrigger +internal class GeneratedDocumentPublisher : IGeneratedDocumentPublisher, IProjectSnapshotChangeTrigger { - public abstract void Initialize(ProjectSnapshotManagerBase projectManager); + private readonly Dictionary _publishedCSharpData; + private readonly Dictionary _publishedHtmlData; + private readonly IClientConnection _clientConnection; + private readonly LanguageServerFeatureOptions _languageServerFeatureOptions; + private readonly ILogger _logger; + private readonly ProjectSnapshotManagerDispatcher _dispatcher; + private ProjectSnapshotManagerBase? _projectSnapshotManager; - public abstract void PublishCSharp(ProjectKey projectKey, string filePath, SourceText sourceText, int hostDocumentVersion); + public GeneratedDocumentPublisher( + ProjectSnapshotManagerDispatcher dispatcher, + IClientConnection clientConnection, + LanguageServerFeatureOptions languageServerFeatureOptions, + IRazorLoggerFactory loggerFactory) + { + if (dispatcher is null) + { + throw new ArgumentNullException(nameof(dispatcher)); + } - public abstract void PublishHtml(ProjectKey projectKey, string filePath, SourceText sourceText, int hostDocumentVersion); + if (clientConnection is null) + { + throw new ArgumentNullException(nameof(clientConnection)); + } + + if (languageServerFeatureOptions is null) + { + throw new ArgumentNullException(nameof(languageServerFeatureOptions)); + } + + if (loggerFactory is null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + + _dispatcher = dispatcher; + _clientConnection = clientConnection; + _languageServerFeatureOptions = languageServerFeatureOptions; + _logger = loggerFactory.CreateLogger(); + _publishedCSharpData = new Dictionary(); + + // We don't generate individual Html documents per-project, so in order to ensure diffs are calculated correctly + // we don't use the project key for the key for this dictionary. This matches when we send edits to the client, + // as they are only tracking a single Html file for each Razor file path, thus edits need to be correct or we'll + // get out of sync. + _publishedHtmlData = new Dictionary(FilePathComparer.Instance); + } + + public void Initialize(ProjectSnapshotManagerBase projectManager) + { + if (projectManager is null) + { + throw new ArgumentNullException(nameof(projectManager)); + } + + _projectSnapshotManager = projectManager; + _projectSnapshotManager.Changed += ProjectSnapshotManager_Changed; + } + + public void PublishCSharp(ProjectKey projectKey, string filePath, SourceText sourceText, int hostDocumentVersion) + { + if (filePath is null) + { + throw new ArgumentNullException(nameof(filePath)); + } + + if (sourceText is null) + { + throw new ArgumentNullException(nameof(sourceText)); + } + + _dispatcher.AssertDispatcherThread(); + + // If our generated documents don't have unique file paths, then using project key information is problematic for the client. + // For example, when a document moves from the Misc Project to a real project, we will update it here, and each version would + // have a different project key. On the receiving end however, there is only one file path, therefore one version of the contents, + // so we must ensure we only have a single document to compute diffs from, or things get out of sync. + if (!_languageServerFeatureOptions.IncludeProjectKeyInGeneratedFilePath) + { + projectKey = default; + } + + var key = new DocumentKey(projectKey, filePath); + if (!_publishedCSharpData.TryGetValue(key, out var previouslyPublishedData)) + { + _logger.LogDebug("New publish data created for {project} and {filePath}", projectKey, filePath); + previouslyPublishedData = PublishData.Default; + } + + var textChanges = SourceTextDiffer.GetMinimalTextChanges(previouslyPublishedData.SourceText, sourceText); + if (textChanges.Count == 0 && hostDocumentVersion == previouslyPublishedData.HostDocumentVersion) + { + // Source texts match along with host document versions. We've already published something that looks like this. No-op. + return; + } + + if (_logger.IsEnabled(LogLevel.Trace)) + { + var previousDocumentLength = previouslyPublishedData.SourceText.Length; + var currentDocumentLength = sourceText.Length; + var documentLengthDelta = sourceText.Length - previousDocumentLength; + _logger.LogTrace( + "Updating C# buffer of {0} for project {1} to correspond with host document version {2}. {3} -> {4} = Change delta of {5} via {6} text changes.", + filePath, + projectKey, + hostDocumentVersion, + previousDocumentLength, + currentDocumentLength, + documentLengthDelta, + textChanges.Count); + } + + _publishedCSharpData[key] = new PublishData(sourceText, hostDocumentVersion); + + var request = new UpdateBufferRequest() + { + HostDocumentFilePath = filePath, + ProjectKeyId = projectKey.Id, + Changes = textChanges, + HostDocumentVersion = hostDocumentVersion, + PreviousWasEmpty = previouslyPublishedData.SourceText.Length == 0 + }; + + _ = _clientConnection.SendNotificationAsync(CustomMessageNames.RazorUpdateCSharpBufferEndpoint, request, CancellationToken.None); + } + + public void PublishHtml(ProjectKey projectKey, string filePath, SourceText sourceText, int hostDocumentVersion) + { + if (filePath is null) + { + throw new ArgumentNullException(nameof(filePath)); + } + + if (sourceText is null) + { + throw new ArgumentNullException(nameof(sourceText)); + } + + _dispatcher.AssertDispatcherThread(); + + if (!_publishedHtmlData.TryGetValue(filePath, out var previouslyPublishedData)) + { + previouslyPublishedData = PublishData.Default; + } + + var textChanges = SourceTextDiffer.GetMinimalTextChanges(previouslyPublishedData.SourceText, sourceText); + if (textChanges.Count == 0 && hostDocumentVersion == previouslyPublishedData.HostDocumentVersion) + { + // Source texts match along with host document versions. We've already published something that looks like this. No-op. + return; + } + + if (_logger.IsEnabled(LogLevel.Trace)) + { + var previousDocumentLength = previouslyPublishedData.SourceText.Length; + var currentDocumentLength = sourceText.Length; + var documentLengthDelta = sourceText.Length - previousDocumentLength; + _logger.LogTrace( + "Updating HTML buffer of {0} to correspond with host document version {1}. {2} -> {3} = Change delta of {4} via {5} text changes.", + filePath, + hostDocumentVersion, + previousDocumentLength, + currentDocumentLength, + documentLengthDelta, + textChanges.Count); + } + + _publishedHtmlData[filePath] = new PublishData(sourceText, hostDocumentVersion); + + var request = new UpdateBufferRequest() + { + HostDocumentFilePath = filePath, + ProjectKeyId = projectKey.Id, + Changes = textChanges, + HostDocumentVersion = hostDocumentVersion, + PreviousWasEmpty = previouslyPublishedData.SourceText.Length == 0 + }; + + _ = _clientConnection.SendNotificationAsync(CustomMessageNames.RazorUpdateHtmlBufferEndpoint, request, CancellationToken.None); + } + + private void ProjectSnapshotManager_Changed(object? sender, ProjectChangeEventArgs args) + { + // Don't do any work if the solution is closing + if (args.SolutionIsClosing) + { + return; + } + + _dispatcher.AssertDispatcherThread(); + + Assumes.NotNull(_projectSnapshotManager); + + switch (args.Kind) + { + case ProjectChangeKind.DocumentChanged: + Assumes.NotNull(args.DocumentFilePath); + if (!_projectSnapshotManager.IsDocumentOpen(args.DocumentFilePath)) + { + // Document closed, evict published source text, unless the server doesn't want us to. + if (_languageServerFeatureOptions.UpdateBuffersForClosedDocuments) + { + // Some clients want us to keep generating code even if the document is closed, so if we evict our data, + // even though we don't send a didChange for it, the next didChange will be wrong. + return; + } + + var projectKey = args.ProjectKey; + if (!_languageServerFeatureOptions.IncludeProjectKeyInGeneratedFilePath) + { + projectKey = default; + } + + var key = new DocumentKey(projectKey, args.DocumentFilePath); + if (_publishedCSharpData.ContainsKey(key)) + { + var removed = _publishedCSharpData.Remove(key); + if (!removed) + { + _logger.LogError("Published data should be protected by the project snapshot manager's thread and should never fail to remove."); + Debug.Fail("Published data should be protected by the project snapshot manager's thread and should never fail to remove."); + } + } + + if (_publishedHtmlData.ContainsKey(args.DocumentFilePath)) + { + var removed = _publishedHtmlData.Remove(args.DocumentFilePath); + if (!removed) + { + _logger.LogError("Published data should be protected by the project snapshot manager's thread and should never fail to remove."); + Debug.Fail("Published data should be protected by the project snapshot manager's thread and should never fail to remove."); + } + } + } + + break; + } + } + + private sealed class PublishData + { + public static readonly PublishData Default = new PublishData(SourceText.From(string.Empty), null); + + public PublishData(SourceText sourceText, int? hostDocumentVersion) + { + SourceText = sourceText; + HostDocumentVersion = hostDocumentVersion; + } + + public SourceText SourceText { get; } + + public int? HostDocumentVersion { get; } + } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/GeneratedDocumentSynchronizer.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/GeneratedDocumentSynchronizer.cs index c391b83cf96..9302b44df3a 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/GeneratedDocumentSynchronizer.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/GeneratedDocumentSynchronizer.cs @@ -10,12 +10,12 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer; internal class GeneratedDocumentSynchronizer : DocumentProcessedListener { - private readonly GeneratedDocumentPublisher _publisher; + private readonly IGeneratedDocumentPublisher _publisher; private readonly IDocumentVersionCache _documentVersionCache; private readonly ProjectSnapshotManagerDispatcher _dispatcher; public GeneratedDocumentSynchronizer( - GeneratedDocumentPublisher publisher, + IGeneratedDocumentPublisher publisher, IDocumentVersionCache documentVersionCache, ProjectSnapshotManagerDispatcher dispatcher) { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/IGeneratedDocumentPublisher.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/IGeneratedDocumentPublisher.cs new file mode 100644 index 00000000000..8334fd99bd6 --- /dev/null +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/IGeneratedDocumentPublisher.cs @@ -0,0 +1,13 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis.Razor.ProjectSystem; +using Microsoft.CodeAnalysis.Text; + +namespace Microsoft.AspNetCore.Razor.LanguageServer; + +internal interface IGeneratedDocumentPublisher +{ + void PublishCSharp(ProjectKey projectKey, string filePath, SourceText sourceText, int hostDocumentVersion); + void PublishHtml(ProjectKey projectKey, string filePath, SourceText sourceText, int hostDocumentVersion); +} diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultGeneratedDocumentPublisherTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultGeneratedDocumentPublisherTest.cs index bb3903c1da1..e6a6de35c26 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultGeneratedDocumentPublisherTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultGeneratedDocumentPublisherTest.cs @@ -38,7 +38,7 @@ public DefaultGeneratedDocumentPublisherTest(ITestOutputHelper testOutput) public async Task PublishCSharp_FirstTime_PublishesEntireSourceText() { // Arrange - var publisher = new DefaultGeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); + var publisher = new GeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); var content = "// C# content"; var sourceText = SourceText.From(content); @@ -58,7 +58,7 @@ await RunOnDispatcherThreadAsync(() => public async Task PublishHtml_FirstTime_PublishesEntireSourceText() { // Arrange - var publisher = new DefaultGeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); + var publisher = new GeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); var content = "HTML content"; var sourceText = SourceText.From(content); @@ -78,7 +78,7 @@ await RunOnDispatcherThreadAsync(() => public async Task PublishCSharp_SecondTime_PublishesSourceTextDifferences() { // Arrange - var publisher = new DefaultGeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); + var publisher = new GeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); var initialSourceText = SourceText.From("// Initial content\n"); await RunOnDispatcherThreadAsync(() => publisher.PublishCSharp(_hostProject.Key, "/path/to/file.razor", initialSourceText, 123)); @@ -104,7 +104,7 @@ await RunOnDispatcherThreadAsync(() => public async Task PublishHtml_SecondTime_PublishesSourceTextDifferences() { // Arrange - var publisher = new DefaultGeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); + var publisher = new GeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); var initialSourceText = SourceText.From("HTML content\n"); await RunOnDispatcherThreadAsync(() => publisher.PublishHtml(_hostProject.Key, "/path/to/file.razor", initialSourceText, 123)); @@ -130,7 +130,7 @@ await RunOnDispatcherThreadAsync(() => public async Task PublishCSharp_SecondTime_IdenticalContent_NoTextChanges() { // Arrange - var publisher = new DefaultGeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); + var publisher = new GeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); var sourceTextContent = "// The content"; var initialSourceText = SourceText.From(sourceTextContent); await RunOnDispatcherThreadAsync(() => @@ -153,7 +153,7 @@ await RunOnDispatcherThreadAsync(() => public async Task PublishHtml_SecondTime_IdenticalContent_NoTextChanges() { // Arrange - var publisher = new DefaultGeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); + var publisher = new GeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); var sourceTextContent = "HTMl content"; var initialSourceText = SourceText.From(sourceTextContent); await RunOnDispatcherThreadAsync(() => @@ -176,7 +176,7 @@ await RunOnDispatcherThreadAsync(() => public async Task PublishCSharp_DifferentFileSameContent_PublishesEverything() { // Arrange - var publisher = new DefaultGeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); + var publisher = new GeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); var sourceTextContent = "// The content"; var initialSourceText = SourceText.From(sourceTextContent); await RunOnDispatcherThreadAsync(() => @@ -200,7 +200,7 @@ await RunOnDispatcherThreadAsync(() => public async Task PublishHtml_DifferentFileSameContent_PublishesEverything() { // Arrange - var publisher = new DefaultGeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); + var publisher = new GeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); var sourceTextContent = "HTML content"; var initialSourceText = SourceText.From(sourceTextContent); await RunOnDispatcherThreadAsync(() => @@ -224,7 +224,7 @@ await RunOnDispatcherThreadAsync(() => public async Task ProjectSnapshotManager_DocumentChanged_OpenDocument_PublishesEmptyTextChanges_CSharp() { // Arrange - var publisher = new DefaultGeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); + var publisher = new GeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); publisher.Initialize(_projectManager); var sourceTextContent = "// The content"; var initialSourceText = SourceText.From(sourceTextContent); @@ -248,7 +248,7 @@ await RunOnDispatcherThreadAsync(() => public async Task ProjectSnapshotManager_DocumentChanged_OpenDocument_VersionEquivalent_Noops_CSharp() { // Arrange - var publisher = new DefaultGeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); + var publisher = new GeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); publisher.Initialize(_projectManager); var sourceTextContent = "// The content"; var initialSourceText = SourceText.From(sourceTextContent); @@ -270,7 +270,7 @@ await RunOnDispatcherThreadAsync(() => public async Task ProjectSnapshotManager_DocumentChanged_OpenDocument_PublishesEmptyTextChanges_Html() { // Arrange - var publisher = new DefaultGeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); + var publisher = new GeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); publisher.Initialize(_projectManager); var sourceTextContent = ""; var initialSourceText = SourceText.From(sourceTextContent); @@ -294,7 +294,7 @@ await RunOnDispatcherThreadAsync(() => public async Task ProjectSnapshotManager_DocumentChanged_OpenDocument_VersionEquivalent_Noops_Html() { // Arrange - var publisher = new DefaultGeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); + var publisher = new GeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); publisher.Initialize(_projectManager); var sourceTextContent = ""; var initialSourceText = SourceText.From(sourceTextContent); @@ -316,7 +316,7 @@ await RunOnDispatcherThreadAsync(() => public async Task ProjectSnapshotManager_DocumentChanged_ClosedDocument_RepublishesTextChanges() { // Arrange - var publisher = new DefaultGeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); + var publisher = new GeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); publisher.Initialize(_projectManager); var sourceTextContent = "// The content"; var initialSourceText = SourceText.From(sourceTextContent); @@ -342,7 +342,7 @@ await RunOnDispatcherThreadAsync(() => public async Task ProjectSnapshotManager_DocumentMoved_DoesntRepublishWholeDocument() { // Arrange - var publisher = new DefaultGeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); + var publisher = new GeneratedDocumentPublisher(Dispatcher, _serverClient, TestLanguageServerFeatureOptions.Instance, LoggerFactory); publisher.Initialize(_projectManager); var sourceTextContent = """ public void Method() diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/GeneratedDocumentSynchronizerTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/GeneratedDocumentSynchronizerTest.cs index deeeaa42e9b..764b75a18d9 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/GeneratedDocumentSynchronizerTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/GeneratedDocumentSynchronizerTest.cs @@ -60,22 +60,18 @@ await Dispatcher.RunOnDispatcherThreadAsync(() => Assert.True(_publisher.PublishedHtml); } - private class TestGeneratedDocumentPublisher : GeneratedDocumentPublisher + private class TestGeneratedDocumentPublisher : IGeneratedDocumentPublisher { - public override void Initialize(ProjectSnapshotManagerBase projectManager) - { - } - public bool PublishedCSharp { get; private set; } public bool PublishedHtml { get; private set; } - public override void PublishCSharp(ProjectKey projectKey, string filePath, SourceText sourceText, int hostDocumentVersion) + public void PublishCSharp(ProjectKey projectKey, string filePath, SourceText sourceText, int hostDocumentVersion) { PublishedCSharp = true; } - public override void PublishHtml(ProjectKey projectKey, string filePath, SourceText sourceText, int hostDocumentVersion) + public void PublishHtml(ProjectKey projectKey, string filePath, SourceText sourceText, int hostDocumentVersion) { PublishedHtml = true; } From 2cd8a5a128a1766c4eecee21a652fdcb52fe790c Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jan 2024 10:49:44 -0800 Subject: [PATCH 17/25] Convert WorkspaceProjectStateChangeDetector to an interface --- .../DefaultProjectWorkspaceStateGenerator.cs | 20 +++++++++---------- .../IProjectWorkspaceStateGenerator.cs | 12 +++++++++++ .../WorkspaceProjectStateChangeDetector.cs | 10 +++++----- .../ProjectWorkspaceStateGenerator.cs | 14 ------------- ...tionUpdatesProjectSnapshotChangeTrigger.cs | 4 ++-- .../TestProjectWorkspaceStateGenerator.cs | 8 ++------ ...UpdatesProjectSnapshotChangeTriggerTest.cs | 4 ++-- 7 files changed, 33 insertions(+), 39 deletions(-) create mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectWorkspaceStateGenerator.cs delete mode 100644 src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectWorkspaceStateGenerator.cs diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectWorkspaceStateGenerator.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectWorkspaceStateGenerator.cs index 322f9ba82e5..19f29fb814b 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectWorkspaceStateGenerator.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectWorkspaceStateGenerator.cs @@ -19,15 +19,15 @@ namespace Microsoft.CodeAnalysis.Razor; [Shared] -[Export(typeof(ProjectWorkspaceStateGenerator))] +[Export(typeof(IProjectWorkspaceStateGenerator))] [Export(typeof(IProjectSnapshotChangeTrigger))] [method: ImportingConstructor] -internal class DefaultProjectWorkspaceStateGenerator(ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher, ITelemetryReporter telemetryReporter) : ProjectWorkspaceStateGenerator, IDisposable +internal class DefaultProjectWorkspaceStateGenerator(ProjectSnapshotManagerDispatcher dispatcher, ITelemetryReporter telemetryReporter) : IProjectWorkspaceStateGenerator, IProjectSnapshotChangeTrigger, IDisposable { // Internal for testing internal readonly Dictionary Updates = new(); - private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher ?? throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher)); + private readonly ProjectSnapshotManagerDispatcher _dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher)); private readonly ITelemetryReporter _telemetryReporter = telemetryReporter ?? throw new ArgumentNullException(nameof(telemetryReporter)); private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(initialCount: 1); @@ -41,7 +41,7 @@ internal class DefaultProjectWorkspaceStateGenerator(ProjectSnapshotManagerDispa // Used in unit tests to ensure we can know when background work finishes. public ManualResetEventSlim NotifyBackgroundWorkCompleted { get; set; } - public override void Initialize(ProjectSnapshotManagerBase projectManager) + public void Initialize(ProjectSnapshotManagerBase projectManager) { if (projectManager is null) { @@ -53,14 +53,14 @@ public override void Initialize(ProjectSnapshotManagerBase projectManager) _tagHelperResolver = _projectManager.Workspace.Services.GetRequiredService(); } - public override void Update(Project workspaceProject, IProjectSnapshot projectSnapshot, CancellationToken cancellationToken) + public void Update(Project workspaceProject, IProjectSnapshot projectSnapshot, CancellationToken cancellationToken) { if (projectSnapshot is null) { throw new ArgumentNullException(nameof(projectSnapshot)); } - _projectSnapshotManagerDispatcher.AssertDispatcherThread(); + _dispatcher.AssertDispatcherThread(); if (_disposed) { @@ -199,7 +199,7 @@ private async Task UpdateWorkspaceStateAsync(Project workspaceProject, IProjectS new Property("id", telemetryId), new Property("result", "error")); - await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync( + await _dispatcher.RunOnDispatcherThreadAsync( () => _projectManager.ReportError(ex, projectSnapshot), // Don't allow errors to be cancelled CancellationToken.None).ConfigureAwait(false); @@ -212,7 +212,7 @@ await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync( return; } - await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync( + await _dispatcher.RunOnDispatcherThreadAsync( () => { if (cancellationToken.IsCancellationRequested) @@ -232,7 +232,7 @@ await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync( catch (Exception ex) { // This is something totally unexpected, let's just send it over to the project manager. - await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync( + await _dispatcher.RunOnDispatcherThreadAsync( () => _projectManager.ReportError(ex), // Don't allow errors to be cancelled CancellationToken.None).ConfigureAwait(false); @@ -259,7 +259,7 @@ await _projectSnapshotManagerDispatcher.RunOnDispatcherThreadAsync( private void ReportWorkspaceStateChange(ProjectKey projectKey, ProjectWorkspaceState workspaceStateChange) { - _projectSnapshotManagerDispatcher.AssertDispatcherThread(); + _dispatcher.AssertDispatcherThread(); _projectManager.ProjectWorkspaceStateChanged(projectKey, workspaceStateChange); } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectWorkspaceStateGenerator.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectWorkspaceStateGenerator.cs new file mode 100644 index 00000000000..971aa53ee4c --- /dev/null +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectWorkspaceStateGenerator.cs @@ -0,0 +1,12 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using System.Threading; +using Microsoft.CodeAnalysis.Razor.ProjectSystem; + +namespace Microsoft.CodeAnalysis.Razor; + +internal interface IProjectWorkspaceStateGenerator +{ + void Update(Project? workspaceProject, IProjectSnapshot projectSnapshot, CancellationToken cancellationToken); +} diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/WorkspaceProjectStateChangeDetector.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/WorkspaceProjectStateChangeDetector.cs index 3a23869763e..bbb84d6076a 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/WorkspaceProjectStateChangeDetector.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/WorkspaceProjectStateChangeDetector.cs @@ -23,7 +23,7 @@ internal class WorkspaceProjectStateChangeDetector : IProjectSnapshotChangeTrigg private static readonly TimeSpan s_batchingDelay = TimeSpan.FromSeconds(1); private readonly object _disposedLock = new(); private readonly object _workQueueAccessLock = new(); - private readonly ProjectWorkspaceStateGenerator _workspaceStateGenerator; + private readonly IProjectWorkspaceStateGenerator _workspaceStateGenerator; private readonly ProjectSnapshotManagerDispatcher _dispatcher; private readonly LanguageServerFeatureOptions _options; private BatchingWorkQueue? _workQueue; @@ -35,7 +35,7 @@ private ProjectSnapshotManagerBase ProjectSnapshotManager [ImportingConstructor] public WorkspaceProjectStateChangeDetector( - ProjectWorkspaceStateGenerator workspaceStateGenerator, + IProjectWorkspaceStateGenerator workspaceStateGenerator, ProjectSnapshotManagerDispatcher dispatcher, LanguageServerFeatureOptions options) { @@ -46,7 +46,7 @@ public WorkspaceProjectStateChangeDetector( // Internal for testing internal WorkspaceProjectStateChangeDetector( - ProjectWorkspaceStateGenerator workspaceStateGenerator, + IProjectWorkspaceStateGenerator workspaceStateGenerator, ProjectSnapshotManagerDispatcher dispatcher, LanguageServerFeatureOptions options, BatchingWorkQueue workQueue) @@ -514,13 +514,13 @@ private class UpdateWorkspaceWorkItem : BatchableWorkItem { private readonly Project? _workspaceProject; private readonly IProjectSnapshot _projectSnapshot; - private readonly ProjectWorkspaceStateGenerator _workspaceStateGenerator; + private readonly IProjectWorkspaceStateGenerator _workspaceStateGenerator; private readonly ProjectSnapshotManagerDispatcher _dispatcher; public UpdateWorkspaceWorkItem( Project? workspaceProject, IProjectSnapshot projectSnapshot, - ProjectWorkspaceStateGenerator workspaceStateGenerator, + IProjectWorkspaceStateGenerator workspaceStateGenerator, ProjectSnapshotManagerDispatcher dispatcher) { _workspaceProject = workspaceProject; diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectWorkspaceStateGenerator.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectWorkspaceStateGenerator.cs deleted file mode 100644 index 5fb0ba4b6ef..00000000000 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectWorkspaceStateGenerator.cs +++ /dev/null @@ -1,14 +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.Threading; -using Microsoft.CodeAnalysis.Razor.ProjectSystem; - -namespace Microsoft.CodeAnalysis.Razor; - -internal abstract class ProjectWorkspaceStateGenerator : IProjectSnapshotChangeTrigger -{ - public abstract void Initialize(ProjectSnapshotManagerBase projectManager); - - public abstract void Update(Project? workspaceProject, IProjectSnapshot projectSnapshot, CancellationToken cancellationToken); -} diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VsSolutionUpdatesProjectSnapshotChangeTrigger.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VsSolutionUpdatesProjectSnapshotChangeTrigger.cs index 3341e34e403..2dba69dc50e 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VsSolutionUpdatesProjectSnapshotChangeTrigger.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VsSolutionUpdatesProjectSnapshotChangeTrigger.cs @@ -22,7 +22,7 @@ internal class VsSolutionUpdatesProjectSnapshotChangeTrigger : IProjectSnapshotC { private readonly IServiceProvider _services; private readonly TextBufferProjectService _projectService; - private readonly ProjectWorkspaceStateGenerator _workspaceStateGenerator; + private readonly IProjectWorkspaceStateGenerator _workspaceStateGenerator; private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher; private readonly JoinableTaskContext _joinableTaskContext; private ProjectSnapshotManagerBase? _projectManager; @@ -34,7 +34,7 @@ internal class VsSolutionUpdatesProjectSnapshotChangeTrigger : IProjectSnapshotC public VsSolutionUpdatesProjectSnapshotChangeTrigger( [Import(typeof(SVsServiceProvider))] IServiceProvider services, TextBufferProjectService projectService, - ProjectWorkspaceStateGenerator workspaceStateGenerator, + IProjectWorkspaceStateGenerator workspaceStateGenerator, ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher, JoinableTaskContext joinableTaskContext) { diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/TestProjectWorkspaceStateGenerator.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/TestProjectWorkspaceStateGenerator.cs index fedd53067a6..42de9398c87 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/TestProjectWorkspaceStateGenerator.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/TestProjectWorkspaceStateGenerator.cs @@ -11,7 +11,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor.Test; -internal class TestProjectWorkspaceStateGenerator : ProjectWorkspaceStateGenerator +internal class TestProjectWorkspaceStateGenerator : IProjectWorkspaceStateGenerator { private readonly List _updates; @@ -22,11 +22,7 @@ public TestProjectWorkspaceStateGenerator() public IReadOnlyList UpdateQueue => _updates; - public override void Initialize(ProjectSnapshotManagerBase projectManager) - { - } - - public override void Update(Project workspaceProject, IProjectSnapshot projectSnapshot, CancellationToken cancellationToken) + public void Update(Project workspaceProject, IProjectSnapshot projectSnapshot, CancellationToken cancellationToken) { var update = new TestUpdate(workspaceProject, projectSnapshot, cancellationToken); _updates.Add(update); diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/VsSolutionUpdatesProjectSnapshotChangeTriggerTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/VsSolutionUpdatesProjectSnapshotChangeTriggerTest.cs index 45efd7ba2da..d4df0cdffd7 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/VsSolutionUpdatesProjectSnapshotChangeTriggerTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/VsSolutionUpdatesProjectSnapshotChangeTriggerTest.cs @@ -78,7 +78,7 @@ public void Initialize_AttachesEventSink() var trigger = new VsSolutionUpdatesProjectSnapshotChangeTrigger( services.Object, Mock.Of(MockBehavior.Strict), - Mock.Of(MockBehavior.Strict), + Mock.Of(MockBehavior.Strict), s_dispatcher, JoinableTaskFactory.Context); @@ -107,7 +107,7 @@ public async Task Initialize_SwitchesToMainThread() var trigger = new VsSolutionUpdatesProjectSnapshotChangeTrigger( services.Object, Mock.Of(MockBehavior.Strict), - Mock.Of(MockBehavior.Strict), + Mock.Of(MockBehavior.Strict), s_dispatcher, context); From 9347251f1504cde9773e5c7fc72118964c1b4ee9 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jan 2024 11:28:58 -0800 Subject: [PATCH 18/25] Convert AdhocWorkspaceFactory to an interface and clean up --- .../AdhocWorkspaceFactory.cs | 18 ++++-- .../AutoInsert/OnAutoInsertEndpoint.cs | 2 +- .../Common/AdhocLanguageServices.cs | 42 ++++--------- .../Common/AdhocServices.cs | 45 +++++--------- .../Common/AdhocWorkspaceServices.cs | 59 ++++++------------- .../DefaultAdhocWorkspaceFactory.cs | 44 -------------- .../DefaultProjectSnapshotManagerAccessor.cs | 4 +- .../Formatting/FormattingContext.cs | 12 ++-- .../Formatting/RazorFormattingService.cs | 4 +- .../IAdhocWorkspaceFactory.cs | 12 ++++ .../InlineCompletionEndPoint.cs | 4 +- .../RazorLanguageServer.cs | 2 +- .../OnAutoInsertEndpointTest.NetFx.cs | 2 +- .../TestAdhocWorkspaceFactory.cs | 10 +--- 14 files changed, 89 insertions(+), 171 deletions(-) delete mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultAdhocWorkspaceFactory.cs create mode 100644 src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/IAdhocWorkspaceFactory.cs diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/AdhocWorkspaceFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/AdhocWorkspaceFactory.cs index ee69df7a71a..be6351ed174 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/AdhocWorkspaceFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/AdhocWorkspaceFactory.cs @@ -1,15 +1,25 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System.Collections.Generic; +using System.Collections.Immutable; +using Microsoft.AspNetCore.Razor.LanguageServer.Common; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Host; namespace Microsoft.AspNetCore.Razor.LanguageServer; -internal abstract class AdhocWorkspaceFactory +internal class AdhocWorkspaceFactory(HostServicesProvider hostServicesProvider) : IAdhocWorkspaceFactory { - public abstract AdhocWorkspace Create(); + public AdhocWorkspace Create(params IWorkspaceService[] workspaceServices) + { + workspaceServices ??= []; - public abstract AdhocWorkspace Create(IEnumerable workspaceServices); + var fallbackServices = hostServicesProvider.GetServices(); + var services = AdhocServices.Create( + workspaceServices: workspaceServices.ToImmutableArray(), + languageServices: ImmutableArray.Empty, + fallbackServices); + + return new AdhocWorkspace(services); + } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/AutoInsert/OnAutoInsertEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/AutoInsert/OnAutoInsertEndpoint.cs index b5c3470345b..78899c10c83 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/AutoInsert/OnAutoInsertEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/AutoInsert/OnAutoInsertEndpoint.cs @@ -88,7 +88,7 @@ public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, V var uri = request.TextDocument.Uri; var position = request.Position; - var workspaceFactory = requestContext.GetRequiredService(); + var workspaceFactory = requestContext.GetRequiredService(); using (var formattingContext = FormattingContext.Create(uri, documentContext.Snapshot, codeDocument, request.Options, workspaceFactory)) { for (var i = 0; i < applicableProviders.Count; i++) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocLanguageServices.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocLanguageServices.cs index 52e03e8f19a..1aea1e54e3f 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocLanguageServices.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocLanguageServices.cs @@ -2,47 +2,31 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; -using System.Collections.Generic; -using System.Linq; +using System.Collections.Immutable; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Razor; namespace Microsoft.AspNetCore.Razor.LanguageServer.Common; -internal class AdhocLanguageServices : HostLanguageServices +internal sealed class AdhocLanguageServices( + AdhocWorkspaceServices workspaceServices, + ImmutableArray languageServices) + : HostLanguageServices { - private readonly HostWorkspaceServices _workspaceServices; - private readonly IEnumerable _languageServices; - - public AdhocLanguageServices(HostWorkspaceServices workspaceServices, IEnumerable languageServices) - { - if (workspaceServices is null) - { - throw new ArgumentNullException(nameof(workspaceServices)); - } - - if (languageServices is null) - { - throw new ArgumentNullException(nameof(languageServices)); - } - - _workspaceServices = workspaceServices; - _languageServices = languageServices; - } - - public override HostWorkspaceServices WorkspaceServices => _workspaceServices; - public override string Language => RazorLanguage.Name; + public override HostWorkspaceServices WorkspaceServices => workspaceServices; + public override TLanguageService GetService() { - var service = _languageServices.OfType().FirstOrDefault(); - - if (service is null) + foreach (var service in languageServices) { - throw new InvalidOperationException(SR.FormatLanguage_Services_Missing_Service(typeof(TLanguageService).FullName)); + if (service is TLanguageService languageService) + { + return languageService; + } } - return service; + throw new InvalidOperationException(SR.FormatLanguage_Services_Missing_Service(typeof(TLanguageService).FullName)); } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocServices.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocServices.cs index ca145f3f4ee..77799fc1e16 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocServices.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocServices.cs @@ -2,7 +2,7 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; -using System.Collections.Generic; +using System.Collections.Immutable; using System.Reflection; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Host; @@ -11,42 +11,26 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Common; internal class AdhocServices : HostServices { - private readonly IEnumerable _workspaceServices; - private readonly IEnumerable _razorLanguageServices; + private readonly ImmutableArray _workspaceServices; + private readonly ImmutableArray _languageServices; private readonly HostServices _fallbackHostServices; private readonly MethodInfo _createWorkspaceServicesMethod; private AdhocServices( - IEnumerable workspaceServices, - IEnumerable razorLanguageServices, + ImmutableArray workspaceServices, + ImmutableArray languageServices, HostServices fallbackHostServices) { - if (workspaceServices is null) - { - throw new ArgumentNullException(nameof(workspaceServices)); - } - - if (razorLanguageServices is null) - { - throw new ArgumentNullException(nameof(razorLanguageServices)); - } - - if (fallbackHostServices is null) - { - throw new ArgumentNullException(nameof(fallbackHostServices)); - } - _workspaceServices = workspaceServices; - _razorLanguageServices = razorLanguageServices; + _languageServices = languageServices; _fallbackHostServices = fallbackHostServices; // We need to create workspace services from the provided fallback host services. To do that we need to invoke into Roslyn's // CreateWorkspaceServices method. Ultimately the reason behind this is to ensure that any services created by this class are // truly isolated from the passed in fallback services host workspace. - var createWorkspaceServicesMethod = typeof(HostServices).GetMethod(nameof(CreateWorkspaceServices), BindingFlags.Instance | BindingFlags.NonPublic); - Assumes.NotNull(createWorkspaceServicesMethod); - - _createWorkspaceServicesMethod = createWorkspaceServicesMethod; + _createWorkspaceServicesMethod = typeof(HostServices) + .GetMethod(nameof(CreateWorkspaceServices), BindingFlags.Instance | BindingFlags.NonPublic) + .AssumeNotNull(); } protected override HostWorkspaceServices CreateWorkspaceServices(Workspace workspace) @@ -57,20 +41,19 @@ protected override HostWorkspaceServices CreateWorkspaceServices(Workspace works } var fallbackServices = CreateFallbackWorkspaceServices(workspace); - return new AdhocWorkspaceServices(this, _workspaceServices, _razorLanguageServices, workspace, fallbackServices); + return new AdhocWorkspaceServices(this, _workspaceServices, _languageServices, workspace, fallbackServices); } public static HostServices Create( - IEnumerable workspaceServices, - IEnumerable razorLanguageServices, + ImmutableArray workspaceServices, + ImmutableArray languageServices, HostServices fallbackServices) - => new AdhocServices(workspaceServices, razorLanguageServices, fallbackServices); + => new AdhocServices(workspaceServices, languageServices, fallbackServices); private HostWorkspaceServices CreateFallbackWorkspaceServices(Workspace workspace) { var result = _createWorkspaceServicesMethod.Invoke(_fallbackHostServices, new[] { workspace }) as HostWorkspaceServices; - Assumes.NotNull(result); - return result; + return result.AssumeNotNull(); } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocWorkspaceServices.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocWorkspaceServices.cs index c9d6a975c77..7c3b5d8cb18 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocWorkspaceServices.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocWorkspaceServices.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; -using System.Linq; +using System.Collections.Immutable; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Razor; @@ -12,49 +12,24 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Common; internal class AdhocWorkspaceServices : HostWorkspaceServices { - private readonly HostServices _hostServices; - private readonly HostLanguageServices _razorLanguageServices; - private readonly IEnumerable _workspaceServices; + private readonly AdhocServices _hostServices; + private readonly AdhocLanguageServices _languageServices; + private readonly ImmutableArray _workspaceServices; private readonly Workspace _workspace; private readonly HostWorkspaceServices _fallbackServices; public AdhocWorkspaceServices( - HostServices hostServices, - IEnumerable workspaceServices, - IEnumerable languageServices, + AdhocServices hostServices, + ImmutableArray workspaceServices, + ImmutableArray languageServices, Workspace workspace, HostWorkspaceServices fallbackServices) { - if (hostServices is null) - { - throw new ArgumentNullException(nameof(hostServices)); - } - - if (workspaceServices is null) - { - throw new ArgumentNullException(nameof(workspaceServices)); - } - - if (languageServices is null) - { - throw new ArgumentNullException(nameof(languageServices)); - } - - if (workspace is null) - { - throw new ArgumentNullException(nameof(workspace)); - } - - if (fallbackServices is null) - { - throw new ArgumentNullException(nameof(fallbackServices)); - } - _hostServices = hostServices; _workspaceServices = workspaceServices; _workspace = workspace; _fallbackServices = fallbackServices; - _razorLanguageServices = new AdhocLanguageServices(this, languageServices); + _languageServices = new AdhocLanguageServices(this, languageServices); } public override HostServices HostServices => _hostServices; @@ -64,22 +39,23 @@ public AdhocWorkspaceServices( public override TWorkspaceService? GetService() where TWorkspaceService : default { - var service = _workspaceServices.OfType().FirstOrDefault(); - - if (service is null) + foreach (var service in _workspaceServices) { - // Fallback to default host services to resolve roslyn specific features. - service = _fallbackServices.GetService(); + if (service is TWorkspaceService workspaceService) + { + return workspaceService; + } } - return service; + // Fallback to default host services to resolve roslyn specific features. + return _fallbackServices.GetService(); } public override HostLanguageServices GetLanguageServices(string languageName) { if (languageName == RazorLanguage.Name) { - return _razorLanguageServices; + return _languageServices; } // Fallback to default host services to resolve roslyn specific features. @@ -90,5 +66,6 @@ public override HostLanguageServices GetLanguageServices(string languageName) public override bool IsSupported(string languageName) => languageName == RazorLanguage.Name; - public override IEnumerable FindLanguageServices(MetadataFilter filter) => throw new NotImplementedException(); + public override IEnumerable FindLanguageServices(MetadataFilter filter) + => throw new NotImplementedException(); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultAdhocWorkspaceFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultAdhocWorkspaceFactory.cs deleted file mode 100644 index 6ac0cf832fb..00000000000 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultAdhocWorkspaceFactory.cs +++ /dev/null @@ -1,44 +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; -using System.Collections.Generic; -using System.Linq; -using Microsoft.AspNetCore.Razor.LanguageServer.Common; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Host; - -namespace Microsoft.AspNetCore.Razor.LanguageServer; - -internal class DefaultAdhocWorkspaceFactory : AdhocWorkspaceFactory -{ - private readonly HostServicesProvider _hostServicesProvider; - - public DefaultAdhocWorkspaceFactory(HostServicesProvider hostWorkspaceServicesProvider) - { - if (hostWorkspaceServicesProvider is null) - { - throw new ArgumentNullException(nameof(hostWorkspaceServicesProvider)); - } - - _hostServicesProvider = hostWorkspaceServicesProvider; - } - - public override AdhocWorkspace Create() => Create(Enumerable.Empty()); - - public override AdhocWorkspace Create(IEnumerable workspaceServices) - { - if (workspaceServices is null) - { - throw new ArgumentNullException(nameof(workspaceServices)); - } - - var fallbackServices = _hostServicesProvider.GetServices(); - var services = AdhocServices.Create( - workspaceServices, - razorLanguageServices: Enumerable.Empty(), - fallbackServices); - var workspace = new AdhocWorkspace(services); - return workspace; - } -} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultProjectSnapshotManagerAccessor.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultProjectSnapshotManagerAccessor.cs index 84e1f95a1da..6775780aa52 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultProjectSnapshotManagerAccessor.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultProjectSnapshotManagerAccessor.cs @@ -13,13 +13,13 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer; internal class DefaultProjectSnapshotManagerAccessor( IEnumerable changeTriggers, IOptionsMonitor optionsMonitor, - AdhocWorkspaceFactory workspaceFactory, + IAdhocWorkspaceFactory workspaceFactory, ProjectSnapshotManagerDispatcher dispatcher, IErrorReporter errorReporter) : ProjectSnapshotManagerAccessor, IDisposable { private readonly IEnumerable _changeTriggers = changeTriggers; private readonly IOptionsMonitor _optionsMonitor = optionsMonitor; - private readonly AdhocWorkspaceFactory _workspaceFactory = workspaceFactory; + private readonly IAdhocWorkspaceFactory _workspaceFactory = workspaceFactory; private readonly ProjectSnapshotManagerDispatcher _dispatcher = dispatcher; private readonly IErrorReporter _errorReporter = errorReporter; private ProjectSnapshotManagerBase? _instance; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingContext.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingContext.cs index b6fd5db9750..cd4776456b8 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingContext.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/FormattingContext.cs @@ -21,7 +21,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Formatting; internal class FormattingContext : IDisposable { - private readonly AdhocWorkspaceFactory _workspaceFactory; + private readonly IAdhocWorkspaceFactory _workspaceFactory; private Document? _csharpWorkspaceDocument; private AdhocWorkspace? _csharpWorkspace; @@ -30,7 +30,7 @@ internal class FormattingContext : IDisposable private RazorProjectEngine? _engine; private ImmutableArray _importSources; - private FormattingContext(AdhocWorkspaceFactory workspaceFactory, Uri uri, IDocumentSnapshot originalSnapshot, RazorCodeDocument codeDocument, FormattingOptions options, + private FormattingContext(IAdhocWorkspaceFactory workspaceFactory, Uri uri, IDocumentSnapshot originalSnapshot, RazorCodeDocument codeDocument, FormattingOptions options, bool isFormatOnType, bool automaticallyAddUsings, int hostDocumentIndex, char triggerCharacter) { _workspaceFactory = workspaceFactory; @@ -44,7 +44,7 @@ private FormattingContext(AdhocWorkspaceFactory workspaceFactory, Uri uri, IDocu TriggerCharacter = triggerCharacter; } - private FormattingContext(RazorProjectEngine engine, ImmutableArray importSources, AdhocWorkspaceFactory workspaceFactory, Uri uri, IDocumentSnapshot originalSnapshot, RazorCodeDocument codeDocument, FormattingOptions options, + private FormattingContext(RazorProjectEngine engine, ImmutableArray importSources, IAdhocWorkspaceFactory workspaceFactory, Uri uri, IDocumentSnapshot originalSnapshot, RazorCodeDocument codeDocument, FormattingOptions options, bool isFormatOnType, bool automaticallyAddUsings, int hostDocumentIndex, char triggerCharacter) : this(workspaceFactory, uri, originalSnapshot, codeDocument, options, isFormatOnType, automaticallyAddUsings, hostDocumentIndex, triggerCharacter) { @@ -351,7 +351,7 @@ public static FormattingContext CreateForOnTypeFormatting( IDocumentSnapshot originalSnapshot, RazorCodeDocument codeDocument, FormattingOptions options, - AdhocWorkspaceFactory workspaceFactory, + IAdhocWorkspaceFactory workspaceFactory, bool automaticallyAddUsings, int hostDocumentIndex, char triggerCharacter) @@ -364,7 +364,7 @@ public static FormattingContext Create( IDocumentSnapshot originalSnapshot, RazorCodeDocument codeDocument, FormattingOptions options, - AdhocWorkspaceFactory workspaceFactory) + IAdhocWorkspaceFactory workspaceFactory) { return CreateCore(uri, originalSnapshot, codeDocument, options, workspaceFactory, isFormatOnType: false, automaticallyAddUsings: false, hostDocumentIndex: 0, triggerCharacter: '\0'); } @@ -374,7 +374,7 @@ private static FormattingContext CreateCore( IDocumentSnapshot originalSnapshot, RazorCodeDocument codeDocument, FormattingOptions options, - AdhocWorkspaceFactory workspaceFactory, + IAdhocWorkspaceFactory workspaceFactory, bool isFormatOnType, bool automaticallyAddUsings, int hostDocumentIndex, diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingService.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingService.cs index 775aab7ab3d..4abecb059e2 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingService.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Formatting/RazorFormattingService.cs @@ -19,11 +19,11 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Formatting; internal class RazorFormattingService : IRazorFormattingService { private readonly List _formattingPasses; - private readonly AdhocWorkspaceFactory _workspaceFactory; + private readonly IAdhocWorkspaceFactory _workspaceFactory; public RazorFormattingService( IEnumerable formattingPasses, - AdhocWorkspaceFactory workspaceFactory) + IAdhocWorkspaceFactory workspaceFactory) { if (formattingPasses is null) { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/IAdhocWorkspaceFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/IAdhocWorkspaceFactory.cs new file mode 100644 index 00000000000..084a0b01ae9 --- /dev/null +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/IAdhocWorkspaceFactory.cs @@ -0,0 +1,12 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT license. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Host; + +namespace Microsoft.AspNetCore.Razor.LanguageServer; + +internal interface IAdhocWorkspaceFactory +{ + AdhocWorkspace Create(params IWorkspaceService[] workspaceServices); +} diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/InlineCompletion/InlineCompletionEndPoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/InlineCompletion/InlineCompletionEndPoint.cs index 04ec225c75f..c99830ce86b 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/InlineCompletion/InlineCompletionEndPoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/InlineCompletion/InlineCompletionEndPoint.cs @@ -27,7 +27,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.InlineCompletion; internal sealed class InlineCompletionEndpoint( IRazorDocumentMappingService documentMappingService, IClientConnection clientConnection, - AdhocWorkspaceFactory adhocWorkspaceFactory, + IAdhocWorkspaceFactory adhocWorkspaceFactory, IRazorLoggerFactory loggerFactory) : IRazorRequestHandler, ICapabilitiesProvider { @@ -38,7 +38,7 @@ internal sealed class InlineCompletionEndpoint( private readonly IRazorDocumentMappingService _documentMappingService = documentMappingService ?? throw new ArgumentNullException(nameof(documentMappingService)); private readonly IClientConnection _clientConnection = clientConnection ?? throw new ArgumentNullException(nameof(clientConnection)); - private readonly AdhocWorkspaceFactory _adhocWorkspaceFactory = adhocWorkspaceFactory ?? throw new ArgumentNullException(nameof(adhocWorkspaceFactory)); + private readonly IAdhocWorkspaceFactory _adhocWorkspaceFactory = adhocWorkspaceFactory ?? throw new ArgumentNullException(nameof(adhocWorkspaceFactory)); private readonly ILogger _logger = loggerFactory.CreateLogger(); public bool MutatesSolutionState => false; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs index 4f277fd9cc0..3142e104236 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLanguageServer.cs @@ -117,7 +117,7 @@ protected override ILspServices ConstructLspServices() services.AddSingleton(_projectSnapshotManagerDispatcher); } - services.AddSingleton(); + services.AddSingleton(); var featureOptions = _featureOptions ?? new DefaultLanguageServerFeatureOptions(); services.AddSingleton(featureOptions); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/AutoInsert/OnAutoInsertEndpointTest.NetFx.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/AutoInsert/OnAutoInsertEndpointTest.NetFx.cs index 458acada11a..dbf99d15dfd 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/AutoInsert/OnAutoInsertEndpointTest.NetFx.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/AutoInsert/OnAutoInsertEndpointTest.NetFx.cs @@ -347,7 +347,7 @@ private async Task CreateOnAutoInsertRequestContextAsync(Ve { var lspServices = new Mock(MockBehavior.Strict); lspServices - .Setup(l => l.GetRequiredService()).Returns(TestAdhocWorkspaceFactory.Instance); + .Setup(l => l.GetRequiredService()).Returns(TestAdhocWorkspaceFactory.Instance); var formattingService = await TestRazorFormattingService.CreateWithFullSupportAsync(LoggerFactory, Dispatcher); lspServices .Setup(l => l.GetRequiredService()) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/TestAdhocWorkspaceFactory.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/TestAdhocWorkspaceFactory.cs index d7503697616..c90a7f4a3b2 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/TestAdhocWorkspaceFactory.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/TestAdhocWorkspaceFactory.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Razor.Test.Common.Workspaces; using Microsoft.CodeAnalysis; @@ -9,18 +8,15 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Test; -internal class TestAdhocWorkspaceFactory : AdhocWorkspaceFactory +internal class TestAdhocWorkspaceFactory : IAdhocWorkspaceFactory { - public static readonly TestAdhocWorkspaceFactory Instance = new TestAdhocWorkspaceFactory(); + public static readonly TestAdhocWorkspaceFactory Instance = new(); private TestAdhocWorkspaceFactory() { } - public override AdhocWorkspace Create() - => Create(Enumerable.Empty()); - - public override AdhocWorkspace Create(IEnumerable workspaceServices) + public AdhocWorkspace Create(params IWorkspaceService[] workspaceServices) { var services = TestServices.Create(workspaceServices, Enumerable.Empty()); var workspace = TestWorkspace.Create(services); From 3bd0ecbff631a67f479a1fd94344a02add85c0d9 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Tue, 16 Jan 2024 12:11:14 -0800 Subject: [PATCH 19/25] Convert ProjectSnapshotManagerAccessor to an interface --- .../DefaultRazorComponentSearchEngine.cs | 2 +- .../DocumentContextFactory.cs | 4 ++-- .../IServiceCollectionExtensions.cs | 2 +- ...s => LspProjectSnapshotManagerAccessor.cs} | 6 +++--- .../ProjectSystem/RazorProjectService.cs | 4 ++-- .../ProjectSystem/SnapshotResolver.cs | 4 ++-- .../Refactoring/RenameEndpoint.cs | 2 +- .../DefaultRazorDynamicFileInfoProvider.cs | 4 ++-- ....cs => IProjectSnapshotManagerAccessor.cs} | 4 ++-- .../ProjectSystem/FallbackProjectManager.cs | 4 ++-- .../CSharpVirtualDocumentFactory.cs | 4 ++-- .../RazorCustomMessageTarget.cs | 4 ++-- ...ioWindowsProjectSnapshotManagerAccessor.cs | 12 +++++++---- .../DefaultRazorComponentSearchEngineTest.cs | 13 ++++-------- .../DefaultRazorProjectServiceTest.cs | 2 +- .../TestProjectSnapshotManagerAccessor.cs | 11 ++-------- .../FallbackProjectManagerTest.cs | 2 +- .../CSharpVirtualDocumentFactoryTest.cs | 6 +++--- .../RazorCustomMessageTargetTest.cs | 20 +++++++++---------- ...DefaultRazorDynamicFileInfoProviderTest.cs | 2 +- .../InProcess/RazorProjectSystemInProcess.cs | 4 ++-- 21 files changed, 54 insertions(+), 62 deletions(-) rename src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/{DefaultProjectSnapshotManagerAccessor.cs => LspProjectSnapshotManagerAccessor.cs} (90%) rename src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/{ProjectSnapshotManagerAccessor.cs => IProjectSnapshotManagerAccessor.cs} (68%) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultRazorComponentSearchEngine.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultRazorComponentSearchEngine.cs index 001055f7a09..e39980b3e72 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultRazorComponentSearchEngine.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultRazorComponentSearchEngine.cs @@ -22,7 +22,7 @@ internal class DefaultRazorComponentSearchEngine : RazorComponentSearchEngine private readonly ILogger _logger; public DefaultRazorComponentSearchEngine( - ProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, + IProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, IRazorLoggerFactory loggerFactory) { if (loggerFactory is null) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DocumentContextFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DocumentContextFactory.cs index 4381c4bb246..7bee823187f 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DocumentContextFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DocumentContextFactory.cs @@ -20,13 +20,13 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer; [Export(typeof(IDocumentContextFactory)), Shared] [method: ImportingConstructor] internal sealed class DocumentContextFactory( - ProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, + IProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, ISnapshotResolver snapshotResolver, IDocumentVersionCache documentVersionCache, IRazorLoggerFactory loggerFactory) : IDocumentContextFactory { - private readonly ProjectSnapshotManagerAccessor _projectSnapshotManagerAccessor = projectSnapshotManagerAccessor; + private readonly IProjectSnapshotManagerAccessor _projectSnapshotManagerAccessor = projectSnapshotManagerAccessor; private readonly ISnapshotResolver _snapshotResolver = snapshotResolver; private readonly IDocumentVersionCache _documentVersionCache = documentVersionCache; private readonly ILogger _logger = loggerFactory.CreateLogger(); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Extensions/IServiceCollectionExtensions.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Extensions/IServiceCollectionExtensions.cs index 1f1a4245ddd..1556ba9fda9 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Extensions/IServiceCollectionExtensions.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Extensions/IServiceCollectionExtensions.cs @@ -239,7 +239,7 @@ public static void AddDocumentManagementServices(this IServiceCollection service services.AddSingleton(); - services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultProjectSnapshotManagerAccessor.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspProjectSnapshotManagerAccessor.cs similarity index 90% rename from src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultProjectSnapshotManagerAccessor.cs rename to src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspProjectSnapshotManagerAccessor.cs index 6775780aa52..425b497e2d5 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/DefaultProjectSnapshotManagerAccessor.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspProjectSnapshotManagerAccessor.cs @@ -10,12 +10,12 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer; -internal class DefaultProjectSnapshotManagerAccessor( +internal class LspProjectSnapshotManagerAccessor( IEnumerable changeTriggers, IOptionsMonitor optionsMonitor, IAdhocWorkspaceFactory workspaceFactory, ProjectSnapshotManagerDispatcher dispatcher, - IErrorReporter errorReporter) : ProjectSnapshotManagerAccessor, IDisposable + IErrorReporter errorReporter) : IProjectSnapshotManagerAccessor, IDisposable { private readonly IEnumerable _changeTriggers = changeTriggers; private readonly IOptionsMonitor _optionsMonitor = optionsMonitor; @@ -25,7 +25,7 @@ internal class DefaultProjectSnapshotManagerAccessor( private ProjectSnapshotManagerBase? _instance; private bool _disposed; - public override ProjectSnapshotManagerBase Instance + public ProjectSnapshotManagerBase Instance { get { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/RazorProjectService.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/RazorProjectService.cs index 0123422463f..39c97aece87 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/RazorProjectService.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/RazorProjectService.cs @@ -31,11 +31,11 @@ internal class RazorProjectService( RemoteTextLoaderFactory remoteTextLoaderFactory, ISnapshotResolver snapshotResolver, IDocumentVersionCache documentVersionCache, - ProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, + IProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, IRazorLoggerFactory loggerFactory) : IRazorProjectService { - private readonly ProjectSnapshotManagerAccessor _projectSnapshotManagerAccessor = projectSnapshotManagerAccessor ?? throw new ArgumentNullException(nameof(projectSnapshotManagerAccessor)); + private readonly IProjectSnapshotManagerAccessor _projectSnapshotManagerAccessor = projectSnapshotManagerAccessor ?? throw new ArgumentNullException(nameof(projectSnapshotManagerAccessor)); private readonly ProjectSnapshotManagerDispatcher _projectSnapshotManagerDispatcher = projectSnapshotManagerDispatcher ?? throw new ArgumentNullException(nameof(projectSnapshotManagerDispatcher)); private readonly RemoteTextLoaderFactory _remoteTextLoaderFactory = remoteTextLoaderFactory ?? throw new ArgumentNullException(nameof(remoteTextLoaderFactory)); private readonly ISnapshotResolver _snapshotResolver = snapshotResolver ?? throw new ArgumentNullException(nameof(snapshotResolver)); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/SnapshotResolver.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/SnapshotResolver.cs index 9bb2da71cbc..ea8f5f4598e 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/SnapshotResolver.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/ProjectSystem/SnapshotResolver.cs @@ -19,14 +19,14 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.ProjectSystem; [Export(typeof(ISnapshotResolver)), Shared] internal sealed class SnapshotResolver : ISnapshotResolver { - private readonly ProjectSnapshotManagerAccessor _projectSnapshotManagerAccessor; + private readonly IProjectSnapshotManagerAccessor _projectSnapshotManagerAccessor; private readonly ILogger _logger; // Internal for testing internal readonly HostProject MiscellaneousHostProject; [ImportingConstructor] - public SnapshotResolver(ProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, IRazorLoggerFactory loggerFactory) + public SnapshotResolver(IProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, IRazorLoggerFactory loggerFactory) { _projectSnapshotManagerAccessor = projectSnapshotManagerAccessor ?? throw new ArgumentNullException(nameof(projectSnapshotManagerAccessor)); _logger = loggerFactory.CreateLogger(); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Refactoring/RenameEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Refactoring/RenameEndpoint.cs index 8e0a9099fcc..88c3a51ceaf 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Refactoring/RenameEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Refactoring/RenameEndpoint.cs @@ -39,7 +39,7 @@ public RenameEndpoint( ProjectSnapshotManagerDispatcher projectSnapshotManagerDispatcher, IDocumentContextFactory documentContextFactory, RazorComponentSearchEngine componentSearchEngine, - ProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, + IProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, LanguageServerFeatureOptions languageServerFeatureOptions, IRazorDocumentMappingService documentMappingService, IClientConnection clientConnection, diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultRazorDynamicFileInfoProvider.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultRazorDynamicFileInfoProvider.cs index b03bd3c1575..6cc75191119 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultRazorDynamicFileInfoProvider.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultRazorDynamicFileInfoProvider.cs @@ -28,7 +28,7 @@ internal class DefaultRazorDynamicFileInfoProvider : RazorDynamicFileInfoProvide private readonly RazorDocumentServiceProviderFactory _factory; private readonly LSPEditorFeatureDetector _lspEditorFeatureDetector; private readonly FilePathService _filePathService; - private readonly ProjectSnapshotManagerAccessor _projectSnapshotManagerAccessor; + private readonly IProjectSnapshotManagerAccessor _projectSnapshotManagerAccessor; private readonly FallbackProjectManager _fallbackProjectManager; [ImportingConstructor] @@ -36,7 +36,7 @@ public DefaultRazorDynamicFileInfoProvider( RazorDocumentServiceProviderFactory factory, LSPEditorFeatureDetector lspEditorFeatureDetector, FilePathService filePathService, - ProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, + IProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, FallbackProjectManager fallbackProjectManager) { _factory = factory ?? throw new ArgumentNullException(nameof(factory)); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSnapshotManagerAccessor.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotManagerAccessor.cs similarity index 68% rename from src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSnapshotManagerAccessor.cs rename to src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotManagerAccessor.cs index 19a4fe68a98..2c636d0e4df 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSnapshotManagerAccessor.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/IProjectSnapshotManagerAccessor.cs @@ -5,7 +5,7 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces; -internal abstract class ProjectSnapshotManagerAccessor +internal interface IProjectSnapshotManagerAccessor { - public abstract ProjectSnapshotManagerBase Instance { get; } + ProjectSnapshotManagerBase Instance { get; } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/FallbackProjectManager.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/FallbackProjectManager.cs index b4a554c5763..d435c4170b3 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/FallbackProjectManager.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/FallbackProjectManager.cs @@ -21,12 +21,12 @@ namespace Microsoft.CodeAnalysis.Razor.ProjectSystem; internal sealed class FallbackProjectManager( ProjectConfigurationFilePathStore projectConfigurationFilePathStore, LanguageServerFeatureOptions languageServerFeatureOptions, - ProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, + IProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, ITelemetryReporter telemetryReporter) { private readonly ProjectConfigurationFilePathStore _projectConfigurationFilePathStore = projectConfigurationFilePathStore; private readonly LanguageServerFeatureOptions _languageServerFeatureOptions = languageServerFeatureOptions; - private readonly ProjectSnapshotManagerAccessor _projectSnapshotManagerAccessor = projectSnapshotManagerAccessor; + private readonly IProjectSnapshotManagerAccessor _projectSnapshotManagerAccessor = projectSnapshotManagerAccessor; private readonly ITelemetryReporter _telemetryReporter = telemetryReporter; internal void DynamicFileAdded(ProjectId projectId, ProjectKey razorProjectKey, string projectFilePath, string filePath) diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/CSharpVirtualDocumentFactory.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/CSharpVirtualDocumentFactory.cs index 432ecf7cd7b..594b11894c4 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/CSharpVirtualDocumentFactory.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/CSharpVirtualDocumentFactory.cs @@ -33,7 +33,7 @@ internal class CSharpVirtualDocumentFactory : VirtualDocumentFactoryBase private static IContentType? s_csharpContentType; private readonly FileUriProvider _fileUriProvider; private readonly FilePathService _filePathService; - private readonly ProjectSnapshotManagerAccessor _projectSnapshotManagerAccessor; + private readonly IProjectSnapshotManagerAccessor _projectSnapshotManagerAccessor; private readonly LanguageServerFeatureOptions _languageServerFeatureOptions; private readonly ILogger _logger; private readonly ITelemetryReporter _telemetryReporter; @@ -45,7 +45,7 @@ public CSharpVirtualDocumentFactory( ITextDocumentFactoryService textDocumentFactory, FileUriProvider fileUriProvider, FilePathService filePathService, - ProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, + IProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, LanguageServerFeatureOptions languageServerFeatureOptions, IRazorLoggerFactory loggerFactory, ITelemetryReporter telemetryReporter) diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/RazorCustomMessageTarget.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/RazorCustomMessageTarget.cs index f2d0980454b..866e04dd4b5 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/RazorCustomMessageTarget.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServerClient.Razor/RazorCustomMessageTarget.cs @@ -34,7 +34,7 @@ internal partial class RazorCustomMessageTarget : IRazorCustomMessageTarget private readonly LSPRequestInvoker _requestInvoker; private readonly ITelemetryReporter _telemetryReporter; private readonly LanguageServerFeatureOptions _languageServerFeatureOptions; - private readonly ProjectSnapshotManagerAccessor _projectSnapshotManagerAccessor; + private readonly IProjectSnapshotManagerAccessor _projectSnapshotManagerAccessor; private readonly SnippetCache _snippetCache; private readonly FormattingOptionsProvider _formattingOptionsProvider; private readonly IClientSettingsManager _editorSettingsManager; @@ -53,7 +53,7 @@ public RazorCustomMessageTarget( CSharpVirtualDocumentAddListener csharpVirtualDocumentAddListener, ITelemetryReporter telemetryReporter, LanguageServerFeatureOptions languageServerFeatureOptions, - ProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, + IProjectSnapshotManagerAccessor projectSnapshotManagerAccessor, SnippetCache snippetCache, IRazorLoggerFactory loggerFactory) { diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioWindowsProjectSnapshotManagerAccessor.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioWindowsProjectSnapshotManagerAccessor.cs index eee8a9a4a83..31daf257025 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioWindowsProjectSnapshotManagerAccessor.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioWindowsProjectSnapshotManagerAccessor.cs @@ -11,14 +11,16 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor; [System.Composition.Shared] -[Export(typeof(ProjectSnapshotManagerAccessor))] +[Export(typeof(IProjectSnapshotManagerAccessor))] [method: ImportingConstructor] -internal class VisualStudioWindowsProjectSnapshotManagerAccessor([Import(typeof(VisualStudioWorkspace))] Workspace workspace) : ProjectSnapshotManagerAccessor +internal class VisualStudioWindowsProjectSnapshotManagerAccessor( + [Import(typeof(VisualStudioWorkspace))] Workspace workspace) + : IProjectSnapshotManagerAccessor { private readonly Workspace _workspace = workspace; private ProjectSnapshotManagerBase? _projectManager; - public override ProjectSnapshotManagerBase Instance + public ProjectSnapshotManagerBase Instance { get { @@ -31,6 +33,8 @@ public override ProjectSnapshotManagerBase Instance [MemberNotNull(nameof(_projectManager))] private void EnsureInitialized() { - _projectManager ??= (ProjectSnapshotManagerBase)_workspace.Services.GetLanguageServices(RazorLanguage.Name).GetRequiredService(); + _projectManager ??= (ProjectSnapshotManagerBase)_workspace.Services + .GetLanguageServices(RazorLanguage.Name) + .GetRequiredService(); } } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorComponentSearchEngineTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorComponentSearchEngineTest.cs index 648eafacf66..b4caaba686d 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorComponentSearchEngineTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorComponentSearchEngineTest.cs @@ -23,7 +23,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Test; public class DefaultRazorComponentSearchEngineTest(ITestOutputHelper testOutput) : LanguageServerTestBase(testOutput) { - private static readonly ProjectSnapshotManagerAccessor s_projectSnapshotManager = CreateProjectSnapshotManagerAccessor(); + private static readonly IProjectSnapshotManagerAccessor s_projectSnapshotManager = CreateProjectSnapshotManagerAccessor(); [Fact] public async Task Handle_SearchFound_GenericComponent() @@ -161,7 +161,7 @@ internal static IDocumentSnapshot CreateRazorDocumentSnapshot(string text, strin return documentSnapshot; } - internal static ProjectSnapshotManagerAccessor CreateProjectSnapshotManagerAccessor() + internal static IProjectSnapshotManagerAccessor CreateProjectSnapshotManagerAccessor() { var firstProject = Mock.Of(p => p.FilePath == "c:/First/First.csproj" && @@ -178,13 +178,8 @@ internal static ProjectSnapshotManagerAccessor CreateProjectSnapshotManagerAcces return new TestProjectSnapshotManagerAccessor(projectSnapshotManager); } - internal class TestProjectSnapshotManagerAccessor : ProjectSnapshotManagerAccessor + internal class TestProjectSnapshotManagerAccessor(ProjectSnapshotManagerBase instance) : IProjectSnapshotManagerAccessor { - public TestProjectSnapshotManagerAccessor(ProjectSnapshotManagerBase instance) - { - Instance = instance; - } - - public override ProjectSnapshotManagerBase Instance { get; } + public ProjectSnapshotManagerBase Instance => instance; } } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorProjectServiceTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorProjectServiceTest.cs index 9ffdaadecab..378b69f6972 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorProjectServiceTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorProjectServiceTest.cs @@ -1254,7 +1254,7 @@ private RazorProjectService CreateProjectService( Mock.Get(documentVersionCache).Setup(c => c.TrackDocumentVersion(It.IsAny(), It.IsAny())).Verifiable(); } - var accessor = Mock.Of(a => a.Instance == projectSnapshotManager, MockBehavior.Strict); + var accessor = Mock.Of(a => a.Instance == projectSnapshotManager, MockBehavior.Strict); if (snapshotResolver is null) { snapshotResolver = new Mock(MockBehavior.Strict).Object; diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/TestProjectSnapshotManagerAccessor.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/TestProjectSnapshotManagerAccessor.cs index dff945d97dd..a28176a242b 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/TestProjectSnapshotManagerAccessor.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/TestProjectSnapshotManagerAccessor.cs @@ -1,19 +1,12 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -#nullable disable - using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Microsoft.CodeAnalysis.Razor.Workspaces; namespace Microsoft.AspNetCore.Razor.LanguageServer.Test; -internal class TestProjectSnapshotManagerAccessor : ProjectSnapshotManagerAccessor +internal class TestProjectSnapshotManagerAccessor(ProjectSnapshotManagerBase instance) : IProjectSnapshotManagerAccessor { - public TestProjectSnapshotManagerAccessor(ProjectSnapshotManagerBase instance) - { - Instance = instance; - } - - public override ProjectSnapshotManagerBase Instance { get; } + public ProjectSnapshotManagerBase Instance => instance; } diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/FallbackProjectManagerTest.cs b/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/FallbackProjectManagerTest.cs index d960a6161b7..ac55d7f1970 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/FallbackProjectManagerTest.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Razor.Workspaces.Test/ProjectSystem/FallbackProjectManagerTest.cs @@ -31,7 +31,7 @@ public FallbackProjectManagerTest(ITestOutputHelper testOutputHelper) var dispatcher = Mock.Of(MockBehavior.Strict); _projectSnapshotManager = new TestProjectSnapshotManager(Workspace, dispatcher); - var projectSnapshotManagerAccessor = Mock.Of(a => a.Instance == _projectSnapshotManager, MockBehavior.Strict); + var projectSnapshotManagerAccessor = Mock.Of(a => a.Instance == _projectSnapshotManager, MockBehavior.Strict); _fallbackProjectManger = new FallbackProjectManager(_projectConfigurationFilePathStore, languageServerFeatureOptions, projectSnapshotManagerAccessor, NoOpTelemetryReporter.Instance); } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServerClient.Razor.Test/CSharpVirtualDocumentFactoryTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServerClient.Razor.Test/CSharpVirtualDocumentFactoryTest.cs index 70114cb2701..92dcba8cd06 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServerClient.Razor.Test/CSharpVirtualDocumentFactoryTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServerClient.Razor.Test/CSharpVirtualDocumentFactoryTest.cs @@ -67,7 +67,7 @@ public void TryCreateMultipleFor_NonRazorLSPBuffer_ReturnsFalse() // Arrange var uri = new Uri("C:/path/to/file.razor"); var uriProvider = Mock.Of(provider => provider.GetOrCreate(It.IsAny()) == uri, MockBehavior.Strict); - var projectSnapshotManagerAccessor = Mock.Of(MockBehavior.Strict); + var projectSnapshotManagerAccessor = Mock.Of(MockBehavior.Strict); var factory = new CSharpVirtualDocumentFactory(_contentTypeRegistryService, _textBufferFactoryService, TextDocumentFactoryService, uriProvider, _filePathService, projectSnapshotManagerAccessor, TestLanguageServerFeatureOptions.Instance, LoggerFactory, telemetryReporter: null); // Act @@ -89,7 +89,7 @@ public void TryCreateMultipleFor_RazorLSPBuffer_ReturnsCSharpVirtualDocumentAndT var projectSnapshotManager = TestProjectSnapshotManager.Create(ErrorReporter, new TestDispatcher()); var project = projectSnapshotManager.CreateAndAddProject(@"C:\path\to\project.csproj"); projectSnapshotManager.CreateAndAddDocument(project, @"C:\path\to\file.razor"); - var projectSnapshotManagerAccessor = Mock.Of(a => a.Instance == projectSnapshotManager, MockBehavior.Strict); + var projectSnapshotManagerAccessor = Mock.Of(a => a.Instance == projectSnapshotManager, MockBehavior.Strict); var factory = new CSharpVirtualDocumentFactory(_contentTypeRegistryService, _textBufferFactoryService, TextDocumentFactoryService, uriProvider, _filePathService, projectSnapshotManagerAccessor, TestLanguageServerFeatureOptions.Instance, LoggerFactory, telemetryReporter: null); @@ -117,7 +117,7 @@ public void TryCreateMultipleFor_RazorLSPBuffer_ReturnsMultipleCSharpVirtualDocu project = TestProjectSnapshot.Create(@"C:\path\to\project2.csproj", @"C:\path\to\obj2", Array.Empty(), RazorConfiguration.Default, projectWorkspaceState: null); projectSnapshotManager.ProjectAdded(project.HostProject); projectSnapshotManager.CreateAndAddDocument(project, @"C:\path\to\file.razor"); - var projectSnapshotManagerAccessor = Mock.Of(a => a.Instance == projectSnapshotManager, MockBehavior.Strict); + var projectSnapshotManagerAccessor = Mock.Of(a => a.Instance == projectSnapshotManager, MockBehavior.Strict); var languageServerFeatureOptions = new TestLanguageServerFeatureOptions(includeProjectKeyInGeneratedFilePath: true); var filePathService = new FilePathService(languageServerFeatureOptions); diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServerClient.Razor.Test/RazorCustomMessageTargetTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServerClient.Razor.Test/RazorCustomMessageTargetTest.cs index 5fca1636a07..a87790335f6 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServerClient.Razor.Test/RazorCustomMessageTargetTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServerClient.Razor.Test/RazorCustomMessageTargetTest.cs @@ -66,7 +66,7 @@ public async Task UpdateCSharpBuffer_CannotLookupDocument_NoopsGracefully() new CSharpVirtualDocumentAddListener(LoggerFactory), Mock.Of(MockBehavior.Strict), TestLanguageServerFeatureOptions.Instance, - Mock.Of(MockBehavior.Strict), + Mock.Of(MockBehavior.Strict), new SnippetCache(), LoggerFactory); var request = new UpdateBufferRequest() @@ -106,7 +106,7 @@ public async Task UpdateCSharpBuffer_UpdatesDocument() new CSharpVirtualDocumentAddListener(LoggerFactory), Mock.Of(MockBehavior.Strict), TestLanguageServerFeatureOptions.Instance, - Mock.Of(MockBehavior.Strict), + Mock.Of(MockBehavior.Strict), new SnippetCache(), LoggerFactory); var request = new UpdateBufferRequest() @@ -157,7 +157,7 @@ public async Task UpdateCSharpBuffer_UpdatesCorrectDocument() new CSharpVirtualDocumentAddListener(LoggerFactory), Mock.Of(MockBehavior.Strict), new TestLanguageServerFeatureOptions(includeProjectKeyInGeneratedFilePath: true), - Mock.Of(MockBehavior.Strict), + Mock.Of(MockBehavior.Strict), new SnippetCache(), LoggerFactory); var request = new UpdateBufferRequest() @@ -196,7 +196,7 @@ public async Task ProvideCodeActionsAsync_CannotLookupDocument_ReturnsNullAsync( new CSharpVirtualDocumentAddListener(LoggerFactory), Mock.Of(MockBehavior.Strict), TestLanguageServerFeatureOptions.Instance, - Mock.Of(MockBehavior.Strict), + Mock.Of(MockBehavior.Strict), new SnippetCache(), LoggerFactory); var request = new DelegatedCodeActionParams() @@ -267,7 +267,7 @@ async IAsyncEnumerable> var target = new RazorCustomMessageTarget( documentManager.Object, JoinableTaskContext, requestInvoker.Object, - TestFormattingOptionsProvider.Default, _editorSettingsManager, documentSynchronizer, csharpVirtualDocumentAddListener, telemetryReporter.Object, TestLanguageServerFeatureOptions.Instance, Mock.Of(MockBehavior.Strict), new SnippetCache(), LoggerFactory); + TestFormattingOptionsProvider.Default, _editorSettingsManager, documentSynchronizer, csharpVirtualDocumentAddListener, telemetryReporter.Object, TestLanguageServerFeatureOptions.Instance, Mock.Of(MockBehavior.Strict), new SnippetCache(), LoggerFactory); var request = new DelegatedCodeActionParams() { @@ -343,7 +343,7 @@ async IAsyncEnumerable> GetExpectedRe var target = new RazorCustomMessageTarget( documentManager, JoinableTaskContext, requestInvoker.Object, - TestFormattingOptionsProvider.Default, _editorSettingsManager, documentSynchronizer.Object, csharpVirtualDocumentAddListener, telemetryReporter.Object, TestLanguageServerFeatureOptions.Instance, Mock.Of(MockBehavior.Strict), new SnippetCache(), LoggerFactory); + TestFormattingOptionsProvider.Default, _editorSettingsManager, documentSynchronizer.Object, csharpVirtualDocumentAddListener, telemetryReporter.Object, TestLanguageServerFeatureOptions.Instance, Mock.Of(MockBehavior.Strict), new SnippetCache(), LoggerFactory); var codeAction = new VSInternalCodeAction() { @@ -381,7 +381,7 @@ public async Task ProvideSemanticTokensAsync_CannotLookupDocument_ReturnsNullAsy new CSharpVirtualDocumentAddListener(LoggerFactory), Mock.Of(MockBehavior.Strict), TestLanguageServerFeatureOptions.Instance, - Mock.Of(MockBehavior.Strict), + Mock.Of(MockBehavior.Strict), new SnippetCache(), LoggerFactory); var request = new ProvideSemanticTokensRangesParams( @@ -427,7 +427,7 @@ public async Task ProvideSemanticTokensAsync_CannotLookupVirtualDocument_Returns new CSharpVirtualDocumentAddListener(LoggerFactory), Mock.Of(MockBehavior.Strict), TestLanguageServerFeatureOptions.Instance, - Mock.Of(MockBehavior.Strict), + Mock.Of(MockBehavior.Strict), new SnippetCache(), LoggerFactory); var request = new ProvideSemanticTokensRangesParams( @@ -494,7 +494,7 @@ public async Task ProvideSemanticTokensAsync_ContainsRange_ReturnsSemanticTokens var target = new RazorCustomMessageTarget( documentManager.Object, JoinableTaskContext, requestInvoker.Object, - TestFormattingOptionsProvider.Default, _editorSettingsManager, documentSynchronizer.Object, csharpVirtualDocumentAddListener, telemetryReporter.Object, TestLanguageServerFeatureOptions.Instance, Mock.Of(MockBehavior.Strict), new SnippetCache(), LoggerFactory); + TestFormattingOptionsProvider.Default, _editorSettingsManager, documentSynchronizer.Object, csharpVirtualDocumentAddListener, telemetryReporter.Object, TestLanguageServerFeatureOptions.Instance, Mock.Of(MockBehavior.Strict), new SnippetCache(), LoggerFactory); var request = new ProvideSemanticTokensRangesParams( textDocument: new TextDocumentIdentifier() { @@ -560,7 +560,7 @@ public async Task ProvideSemanticTokensAsync_EmptyRange_ReturnsNoSemanticTokens( var target = new RazorCustomMessageTarget( documentManager.Object, JoinableTaskContext, requestInvoker.Object, - TestFormattingOptionsProvider.Default, _editorSettingsManager, documentSynchronizer.Object, csharpVirtualDocumentAddListener, telemetryReporter.Object, TestLanguageServerFeatureOptions.Instance, Mock.Of(MockBehavior.Strict), new SnippetCache(), LoggerFactory); + TestFormattingOptionsProvider.Default, _editorSettingsManager, documentSynchronizer.Object, csharpVirtualDocumentAddListener, telemetryReporter.Object, TestLanguageServerFeatureOptions.Instance, Mock.Of(MockBehavior.Strict), new SnippetCache(), LoggerFactory); var request = new ProvideSemanticTokensRangesParams( textDocument: new TextDocumentIdentifier() { diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/DefaultRazorDynamicFileInfoProviderTest.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/DefaultRazorDynamicFileInfoProviderTest.cs index ba236f9c266..01217eae028 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/DefaultRazorDynamicFileInfoProviderTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/ProjectSystem/DefaultRazorDynamicFileInfoProviderTest.cs @@ -56,7 +56,7 @@ public DefaultRazorDynamicFileInfoProviderTest(ITestOutputHelper testOutput) var languageServerFeatureOptions = new TestLanguageServerFeatureOptions(includeProjectKeyInGeneratedFilePath: true); var filePathService = new FilePathService(languageServerFeatureOptions); - var projectSnapshotManagerAccessor = Mock.Of(a => a.Instance == _projectSnapshotManager, MockBehavior.Strict); + var projectSnapshotManagerAccessor = Mock.Of(a => a.Instance == _projectSnapshotManager, MockBehavior.Strict); var projectConfigurationFilePathStore = Mock.Of(MockBehavior.Strict); var fallbackProjectManager = new FallbackProjectManager(projectConfigurationFilePathStore, languageServerFeatureOptions, projectSnapshotManagerAccessor, NoOpTelemetryReporter.Instance); diff --git a/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/InProcess/RazorProjectSystemInProcess.cs b/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/InProcess/RazorProjectSystemInProcess.cs index f0c2d0a7e49..f0dd329e65e 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/InProcess/RazorProjectSystemInProcess.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/InProcess/RazorProjectSystemInProcess.cs @@ -36,7 +36,7 @@ await Helper.RetryAsync(ct => public async Task WaitForProjectFileAsync(string projectFilePath, CancellationToken cancellationToken) { - var accessor = await TestServices.Shell.GetComponentModelServiceAsync(cancellationToken); + var accessor = await TestServices.Shell.GetComponentModelServiceAsync(cancellationToken); var projectSnapshotManager = accessor.Instance; Assert.NotNull(accessor); await Helper.RetryAsync(ct => @@ -55,7 +55,7 @@ await Helper.RetryAsync(ct => public async Task WaitForRazorFileInProjectAsync(string projectFilePath, string filePath, CancellationToken cancellationToken) { - var accessor = await TestServices.Shell.GetComponentModelServiceAsync(cancellationToken); + var accessor = await TestServices.Shell.GetComponentModelServiceAsync(cancellationToken); var projectSnapshotManager = accessor.Instance; Assert.NotNull(accessor); await Helper.RetryAsync(ct => From bdcf34e1bdc3dc10ddac2640a087a34d4977f910 Mon Sep 17 00:00:00 2001 From: Andrew Hall Date: Thu, 18 Jan 2024 17:53:06 -0800 Subject: [PATCH 20/25] Fix folding text for html (#9834) Fixes #9708 Prior to this, HTML and C# could have different folded text. This normalizes us to client default in all cases --- .../Folding/FoldingRangeEndpoint.cs | 10 +- .../CodeFoldingTests.cs | 245 +++++++++++------- 2 files changed, 156 insertions(+), 99 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Folding/FoldingRangeEndpoint.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Folding/FoldingRangeEndpoint.cs index 25198785cb0..6430f9cc1b5 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Folding/FoldingRangeEndpoint.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Folding/FoldingRangeEndpoint.cs @@ -156,14 +156,6 @@ private FoldingRange FixFoldingRangeStart(FoldingRange range, RazorCodeDocument { Debug.Assert(range.StartLine < range.EndLine); - // If the range has collapsed text set, we don't need - // to adjust anything. Just take that value as what - // should be shown - if (!string.IsNullOrEmpty(range.CollapsedText)) - { - return range; - } - var sourceText = codeDocument.GetSourceText(); var startLine = range.StartLine; @@ -186,7 +178,9 @@ private FoldingRange FixFoldingRangeStart(FoldingRange range, RazorCodeDocument // +1 to the offset value because the helper goes to the character position // that we want to be after. Make sure we don't exceed the line end var newCharacter = Math.Min(offset.Value + 1, lineSpan.Length); + range.StartCharacter = newCharacter; + range.CollapsedText = null; // Let the client deside what to show return range; } diff --git a/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/CodeFoldingTests.cs b/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/CodeFoldingTests.cs index 6e6875aaa10..993f4ee213e 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/CodeFoldingTests.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/CodeFoldingTests.cs @@ -77,6 +77,12 @@ private async Task AssertFoldableBlocksAsync(params string[] blockTexts) Assert.Fail($"Missing Lines: {missingSpanText}Actual Lines: {linesText}"); } + Assert.All(outlines, o => + { + Assert.Equal("...", o.CollapsedForm); + Assert.True(o.IsCollapsible); + }); + Assert.Empty(missingLines); static (ImmutableArray missingSpans, ImmutableArray extraSpans) GetOutlineDiff(ICollapsible[] outlines, ImmutableArray foldableSpans, ITextView textView) @@ -129,21 +135,23 @@ public async Task CodeFolding_CodeBlock() await TestServices.SolutionExplorer.AddFileAsync( RazorProjectConstants.BlazorProjectName, "Test.razor", - @" -@page ""/Test"" + """ -Test + @page "/Test" -

Test

+ Test -@code { - private int currentCount = 0; +

Test

- private void IncrementCount() - { - currentCount++; - } -}", + @code { + private int currentCount = 0; + + private void IncrementCount() + { + currentCount++; + } + } + """, open: true, ControlledHangMitigatingCancellationToken); @@ -152,18 +160,22 @@ private void IncrementCount() TestServices.Input.Send("{ENTER}"); await AssertFoldableBlocksAsync( -@"@code { - private int currentCount = 0; + """ + @code { + private int currentCount = 0; - private void IncrementCount() - { - currentCount++; - } -}", -@"private void IncrementCount() - { - currentCount++; - }"); + private void IncrementCount() + { + currentCount++; + } + } + """, + """ + private void IncrementCount() + { + currentCount++; + } + """); } [IdeFact] @@ -172,25 +184,27 @@ public async Task CodeFolding_IfBlock() await TestServices.SolutionExplorer.AddFileAsync( RazorProjectConstants.BlazorProjectName, "Test.razor", - @" -@page ""/Test"" + """ -Test + @page "/Test" -

Test

+ Test -@if(true) -{ - if (true) - { - M(); - } -} +

Test

-@code { - string M() => ""M""; -} -", + @if(true) + { + if (true) + { + M(); + } + } + + @code { + string M() => "M"; + } + + """, open: true, ControlledHangMitigatingCancellationToken); @@ -199,20 +213,26 @@ await TestServices.SolutionExplorer.AddFileAsync( TestServices.Input.Send("{ENTER}"); await AssertFoldableBlocksAsync( -@"@if(true) -{ - if (true) - { - M(); - } -}", -@"if (true) - { - M(); - }", -@"@code { - string M() => ""M""; -}"); + """ + @if(true) + { + if (true) + { + M(); + } + } + """, + """ + if (true) + { + M(); + } + """, + """ + @code { + string M() => "M"; + } + """); } [IdeFact] @@ -221,22 +241,24 @@ public async Task CodeFolding_ForEach() await TestServices.SolutionExplorer.AddFileAsync( RazorProjectConstants.BlazorProjectName, "Test.razor", - @" -@page ""/Test"" + """ -Test + @page "/Test" -

Test

+ Test -@foreach (var s in GetStuff()) -{ -

s

-} +

Test

-@code { - string[] GetStuff() => new string[0]; -} -", + @foreach (var s in GetStuff()) + { +

s

+ } + + @code { + string[] GetStuff() => new string[0]; + } + + """, open: true, ControlledHangMitigatingCancellationToken); @@ -245,13 +267,17 @@ await TestServices.SolutionExplorer.AddFileAsync( TestServices.Input.Send("{ENTER}"); await AssertFoldableBlocksAsync( -@"@foreach (var s in GetStuff()) -{ -

s

-}", -@"@code { - string[] GetStuff() => new string[0]; -}"); + """ + @foreach (var s in GetStuff()) + { +

s

+ } + """, + """ + @code { + string[] GetStuff() => new string[0]; + } + """); } [IdeFact] @@ -260,20 +286,62 @@ public async Task CodeFolding_CodeBlock_Region() await TestServices.SolutionExplorer.AddFileAsync( RazorProjectConstants.BlazorProjectName, "Test.razor", - @" -@page ""/Test"" + """ -Test + @page "/Test" -

Test

+ Test -@code { - #region Methods - void M1() { } - void M2() { } - #endregion -} -", +

Test

+ + @code { + #region Methods + void M1() { } + void M2() { } + #endregion + } + + """, + open: true, + ControlledHangMitigatingCancellationToken); + + await TestServices.Editor.WaitForComponentClassificationAsync(ControlledHangMitigatingCancellationToken); + + TestServices.Input.Send("{ENTER}"); + + await AssertFoldableBlocksAsync( + """ + #region Methods + void M1() { } + void M2() { } + #endregion + """, + """ + @code { + #region Methods + void M1() { } + void M2() { } + #endregion + } + """); + } + + [IdeFact] + public async Task CodeFolding_Div() + { + await TestServices.SolutionExplorer.AddFileAsync( + RazorProjectConstants.BlazorProjectName, + "Test.razor", + """ + @page "/Test" + + Test + +
+

Test

+
+ + """, open: true, ControlledHangMitigatingCancellationToken); @@ -282,15 +350,10 @@ void M2() { } TestServices.Input.Send("{ENTER}"); await AssertFoldableBlocksAsync( -@"#region Methods - void M1() { } - void M2() { } - #endregion", -@"@code { - #region Methods - void M1() { } - void M2() { } - #endregion -}"); + """ +
+

Test

+
+ """); } } From 4cbafea1bc6ec1a7bb0dca0fb41f0bdb1e176292 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 19 Jan 2024 14:50:23 +1100 Subject: [PATCH 21/25] Remove unnecessary mock setups --- .../Formatting_NetFx/FormattingContentValidationPassTest.cs | 3 --- .../Formatting_NetFx/FormattingTestBase.cs | 3 --- 2 files changed, 6 deletions(-) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingContentValidationPassTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingContentValidationPassTest.cs index b9ae8aa24dd..ab457ca9092 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingContentValidationPassTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingContentValidationPassTest.cs @@ -155,9 +155,6 @@ private static (RazorCodeDocument, IDocumentSnapshot) CreateCodeDocumentAndSnaps documentSnapshot .Setup(d => d.GetGeneratedOutputAsync()) .ReturnsAsync(codeDocument); - documentSnapshot - .Setup(d => d.Project.GetProjectEngine()) - .Returns(projectEngine); documentSnapshot .Setup(d => d.TargetPath) .Returns(path); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingTestBase.cs index 04e12f1f128..d723c11537b 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingTestBase.cs @@ -283,9 +283,6 @@ internal static IDocumentSnapshot CreateDocumentSnapshot(string path, ImmutableA documentSnapshot .Setup(d => d.GetImports()) .Returns(imports); - documentSnapshot - .Setup(d => d.Project.GetProjectEngine()) - .Returns(projectEngine); documentSnapshot .Setup(d => d.FilePath) .Returns(path); From 9b6bf6de496e144c7cc3bc056ca7ae5bc7113d0a Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 19 Jan 2024 10:22:23 -0800 Subject: [PATCH 22/25] Mark several types as sealed --- .../AdhocWorkspaceFactory.cs | 2 +- .../Common/AdhocServices.cs | 2 +- .../Common/AdhocWorkspaceServices.cs | 2 +- .../GeneratedDocumentPublisher.cs | 2 +- .../LspProjectSnapshotManagerAccessor.cs | 2 +- .../DefaultProjectWorkspaceStateGenerator.cs | 2 +- .../VisualStudioWindowsProjectSnapshotManagerAccessor.cs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/AdhocWorkspaceFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/AdhocWorkspaceFactory.cs index be6351ed174..4556e21d674 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/AdhocWorkspaceFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/AdhocWorkspaceFactory.cs @@ -8,7 +8,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer; -internal class AdhocWorkspaceFactory(HostServicesProvider hostServicesProvider) : IAdhocWorkspaceFactory +internal sealed class AdhocWorkspaceFactory(HostServicesProvider hostServicesProvider) : IAdhocWorkspaceFactory { public AdhocWorkspace Create(params IWorkspaceService[] workspaceServices) { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocServices.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocServices.cs index 77799fc1e16..45364d4990c 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocServices.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocServices.cs @@ -9,7 +9,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Common; -internal class AdhocServices : HostServices +internal sealed class AdhocServices : HostServices { private readonly ImmutableArray _workspaceServices; private readonly ImmutableArray _languageServices; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocWorkspaceServices.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocWorkspaceServices.cs index 7c3b5d8cb18..629f30c4852 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocWorkspaceServices.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Common/AdhocWorkspaceServices.cs @@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Common; -internal class AdhocWorkspaceServices : HostWorkspaceServices +internal sealed class AdhocWorkspaceServices : HostWorkspaceServices { private readonly AdhocServices _hostServices; private readonly AdhocLanguageServices _languageServices; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/GeneratedDocumentPublisher.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/GeneratedDocumentPublisher.cs index 090e233081e..4abcd2dbc6f 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/GeneratedDocumentPublisher.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/GeneratedDocumentPublisher.cs @@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer; -internal class GeneratedDocumentPublisher : IGeneratedDocumentPublisher, IProjectSnapshotChangeTrigger +internal sealed class GeneratedDocumentPublisher : IGeneratedDocumentPublisher, IProjectSnapshotChangeTrigger { private readonly Dictionary _publishedCSharpData; private readonly Dictionary _publishedHtmlData; diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspProjectSnapshotManagerAccessor.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspProjectSnapshotManagerAccessor.cs index 425b497e2d5..3a91139f14c 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspProjectSnapshotManagerAccessor.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspProjectSnapshotManagerAccessor.cs @@ -10,7 +10,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer; -internal class LspProjectSnapshotManagerAccessor( +internal sealed class LspProjectSnapshotManagerAccessor( IEnumerable changeTriggers, IOptionsMonitor optionsMonitor, IAdhocWorkspaceFactory workspaceFactory, diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectWorkspaceStateGenerator.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectWorkspaceStateGenerator.cs index 19f29fb814b..2041f4cff93 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectWorkspaceStateGenerator.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectWorkspaceStateGenerator.cs @@ -22,7 +22,7 @@ namespace Microsoft.CodeAnalysis.Razor; [Export(typeof(IProjectWorkspaceStateGenerator))] [Export(typeof(IProjectSnapshotChangeTrigger))] [method: ImportingConstructor] -internal class DefaultProjectWorkspaceStateGenerator(ProjectSnapshotManagerDispatcher dispatcher, ITelemetryReporter telemetryReporter) : IProjectWorkspaceStateGenerator, IProjectSnapshotChangeTrigger, IDisposable +internal sealed class DefaultProjectWorkspaceStateGenerator(ProjectSnapshotManagerDispatcher dispatcher, ITelemetryReporter telemetryReporter) : IProjectWorkspaceStateGenerator, IProjectSnapshotChangeTrigger, IDisposable { // Internal for testing internal readonly Dictionary Updates = new(); diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioWindowsProjectSnapshotManagerAccessor.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioWindowsProjectSnapshotManagerAccessor.cs index 31daf257025..088db557ecd 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioWindowsProjectSnapshotManagerAccessor.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioWindowsProjectSnapshotManagerAccessor.cs @@ -13,7 +13,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor; [System.Composition.Shared] [Export(typeof(IProjectSnapshotManagerAccessor))] [method: ImportingConstructor] -internal class VisualStudioWindowsProjectSnapshotManagerAccessor( +internal sealed class VisualStudioWindowsProjectSnapshotManagerAccessor( [Import(typeof(VisualStudioWorkspace))] Workspace workspace) : IProjectSnapshotManagerAccessor { From baa8944fe1bc303d27372e3d166be2b3e3b62eb7 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 19 Jan 2024 10:41:15 -0800 Subject: [PATCH 23/25] Rename some classes --- ...erator.cs => ProjectWorkspaceStateGenerator.cs} | 5 ++++- ... VisualStudioProjectSnapshotManagerAccessor.cs} | 2 +- ...erTest.cs => GeneratedDocumentPublisherTest.cs} | 4 ++-- ...ctServiceTest.cs => RazorProjectServiceTest.cs} | 2 +- ...st.cs => ProjectWorkspaceStateGeneratorTest.cs} | 14 +++++++------- 5 files changed, 15 insertions(+), 12 deletions(-) rename src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/{DefaultProjectWorkspaceStateGenerator.cs => ProjectWorkspaceStateGenerator.cs} (97%) rename src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/{VisualStudioWindowsProjectSnapshotManagerAccessor.cs => VisualStudioProjectSnapshotManagerAccessor.cs} (94%) rename src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/{DefaultGeneratedDocumentPublisherTest.cs => GeneratedDocumentPublisherTest.cs} (99%) rename src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/{DefaultRazorProjectServiceTest.cs => RazorProjectServiceTest.cs} (99%) rename src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/{DefaultProjectWorkspaceStateGeneratorTest.cs => ProjectWorkspaceStateGeneratorTest.cs} (88%) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectWorkspaceStateGenerator.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectWorkspaceStateGenerator.cs similarity index 97% rename from src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectWorkspaceStateGenerator.cs rename to src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectWorkspaceStateGenerator.cs index 2041f4cff93..6d019bcb0d0 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/DefaultProjectWorkspaceStateGenerator.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectWorkspaceStateGenerator.cs @@ -22,7 +22,10 @@ namespace Microsoft.CodeAnalysis.Razor; [Export(typeof(IProjectWorkspaceStateGenerator))] [Export(typeof(IProjectSnapshotChangeTrigger))] [method: ImportingConstructor] -internal sealed class DefaultProjectWorkspaceStateGenerator(ProjectSnapshotManagerDispatcher dispatcher, ITelemetryReporter telemetryReporter) : IProjectWorkspaceStateGenerator, IProjectSnapshotChangeTrigger, IDisposable +internal sealed class ProjectWorkspaceStateGenerator( + ProjectSnapshotManagerDispatcher dispatcher, + ITelemetryReporter telemetryReporter) + : IProjectWorkspaceStateGenerator, IProjectSnapshotChangeTrigger, IDisposable { // Internal for testing internal readonly Dictionary Updates = new(); diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioWindowsProjectSnapshotManagerAccessor.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioProjectSnapshotManagerAccessor.cs similarity index 94% rename from src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioWindowsProjectSnapshotManagerAccessor.cs rename to src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioProjectSnapshotManagerAccessor.cs index 088db557ecd..caed7bb092b 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioWindowsProjectSnapshotManagerAccessor.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioProjectSnapshotManagerAccessor.cs @@ -13,7 +13,7 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor; [System.Composition.Shared] [Export(typeof(IProjectSnapshotManagerAccessor))] [method: ImportingConstructor] -internal sealed class VisualStudioWindowsProjectSnapshotManagerAccessor( +internal sealed class VisualStudioProjectSnapshotManagerAccessor( [Import(typeof(VisualStudioWorkspace))] Workspace workspace) : IProjectSnapshotManagerAccessor { diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultGeneratedDocumentPublisherTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/GeneratedDocumentPublisherTest.cs similarity index 99% rename from src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultGeneratedDocumentPublisherTest.cs rename to src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/GeneratedDocumentPublisherTest.cs index e6a6de35c26..92b8bd87750 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultGeneratedDocumentPublisherTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/GeneratedDocumentPublisherTest.cs @@ -13,7 +13,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer; -public class DefaultGeneratedDocumentPublisherTest : LanguageServerTestBase +public class GeneratedDocumentPublisherTest : LanguageServerTestBase { private readonly TestClient _serverClient; private readonly TestProjectSnapshotManager _projectManager; @@ -21,7 +21,7 @@ public class DefaultGeneratedDocumentPublisherTest : LanguageServerTestBase private readonly HostProject _hostProject2; private readonly HostDocument _hostDocument; - public DefaultGeneratedDocumentPublisherTest(ITestOutputHelper testOutput) + public GeneratedDocumentPublisherTest(ITestOutputHelper testOutput) : base(testOutput) { _serverClient = new TestClient(); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorProjectServiceTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorProjectServiceTest.cs similarity index 99% rename from src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorProjectServiceTest.cs rename to src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorProjectServiceTest.cs index 378b69f6972..8f1caea1c0c 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/DefaultRazorProjectServiceTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/RazorProjectServiceTest.cs @@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer; -public class DefaultRazorProjectServiceTest(ITestOutputHelper testOutput) : LanguageServerTestBase(testOutput) +public class RazorProjectServiceTest(ITestOutputHelper testOutput) : LanguageServerTestBase(testOutput) { [Fact] public async Task UpdateProject_UpdatesProjectWorkspaceState() diff --git a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectWorkspaceStateGeneratorTest.cs b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/ProjectWorkspaceStateGeneratorTest.cs similarity index 88% rename from src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectWorkspaceStateGeneratorTest.cs rename to src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/ProjectWorkspaceStateGeneratorTest.cs index 30ebb3ffcee..b283a8fe705 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectWorkspaceStateGeneratorTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/ProjectWorkspaceStateGeneratorTest.cs @@ -24,7 +24,7 @@ namespace Microsoft.CodeAnalysis.Razor.Workspaces; -public class DefaultProjectWorkspaceStateGeneratorTest : ProjectSnapshotManagerDispatcherTestBase +public class ProjectWorkspaceStateGeneratorTest : ProjectSnapshotManagerDispatcherTestBase { private readonly ImmutableArray _resolvableTagHelpers; private readonly Workspace _workspace; @@ -32,7 +32,7 @@ public class DefaultProjectWorkspaceStateGeneratorTest : ProjectSnapshotManagerD private readonly ProjectSnapshot _projectSnapshot; private readonly ProjectWorkspaceState _projectWorkspaceStateWithTagHelpers; - public DefaultProjectWorkspaceStateGeneratorTest(ITestOutputHelper testOutput) + public ProjectWorkspaceStateGeneratorTest(ITestOutputHelper testOutput) : base(testOutput) { var projectEngineFactory = Mock.Of(MockBehavior.Strict); @@ -66,7 +66,7 @@ public DefaultProjectWorkspaceStateGeneratorTest(ITestOutputHelper testOutput) public void Dispose_MakesUpdateNoop() { // Arrange - using (var stateGenerator = new DefaultProjectWorkspaceStateGenerator(Dispatcher, NoOpTelemetryReporter.Instance)) + using (var stateGenerator = new ProjectWorkspaceStateGenerator(Dispatcher, NoOpTelemetryReporter.Instance)) { stateGenerator.BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false); @@ -83,7 +83,7 @@ public void Dispose_MakesUpdateNoop() public void Update_StartsUpdateTask() { // Arrange - using (var stateGenerator = new DefaultProjectWorkspaceStateGenerator(Dispatcher, NoOpTelemetryReporter.Instance)) + using (var stateGenerator = new ProjectWorkspaceStateGenerator(Dispatcher, NoOpTelemetryReporter.Instance)) { stateGenerator.BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false); @@ -100,7 +100,7 @@ public void Update_StartsUpdateTask() public void Update_SoftCancelsIncompleteTaskForSameProject() { // Arrange - using (var stateGenerator = new DefaultProjectWorkspaceStateGenerator(Dispatcher, NoOpTelemetryReporter.Instance)) + using (var stateGenerator = new ProjectWorkspaceStateGenerator(Dispatcher, NoOpTelemetryReporter.Instance)) { stateGenerator.BlockBackgroundWorkStart = new ManualResetEventSlim(initialState: false); stateGenerator.Update(_workspaceProject, _projectSnapshot, DisposalToken); @@ -118,7 +118,7 @@ public void Update_SoftCancelsIncompleteTaskForSameProject() public async Task Update_NullWorkspaceProject_ClearsProjectWorkspaceState() { // Arrange - using (var stateGenerator = new DefaultProjectWorkspaceStateGenerator(Dispatcher, NoOpTelemetryReporter.Instance)) + using (var stateGenerator = new ProjectWorkspaceStateGenerator(Dispatcher, NoOpTelemetryReporter.Instance)) { stateGenerator.NotifyBackgroundWorkCompleted = new ManualResetEventSlim(initialState: false); var projectManager = new TestProjectSnapshotManager(_workspace, Dispatcher); @@ -142,7 +142,7 @@ public async Task Update_NullWorkspaceProject_ClearsProjectWorkspaceState() public async Task Update_ResolvesTagHelpersAndUpdatesWorkspaceState() { // Arrange - using (var stateGenerator = new DefaultProjectWorkspaceStateGenerator(Dispatcher, NoOpTelemetryReporter.Instance)) + using (var stateGenerator = new ProjectWorkspaceStateGenerator(Dispatcher, NoOpTelemetryReporter.Instance)) { stateGenerator.NotifyBackgroundWorkCompleted = new ManualResetEventSlim(initialState: false); var projectManager = new TestProjectSnapshotManager(_workspace, Dispatcher); From 8695d9a2316f0e335269a92ce38177eba148e554 Mon Sep 17 00:00:00 2001 From: Dustin Campbell Date: Fri, 19 Jan 2024 11:44:48 -0800 Subject: [PATCH 24/25] Clean up `IProjectEngineFactory` and `IProjectEngineFactoryProvider` contracts This change removes several warts of from `IProjectEngineFactory`: 1. The `SupportsSerialization` property has been removed. Now that we don't really support custom project engine factories, this really isn't needed. 2. The API no longer allows a "fallback factory" to be provided. The fallback is always just an `EmptyProjectEngineFactory`, which is what everything was passing anyway. --- ...aticProjectSnapshotProjectEngineFactory.cs | 8 +-- .../RazorProjectInfoSerializer.cs | 3 +- .../Cohost/CohostProjectSnapshot.cs | 6 +- .../LspProjectEngineFactoryProvider.cs | 10 +-- .../DefaultProjectEngineFactory.cs | 1 - .../EmptyProjectEngineFactory.cs | 2 - .../IProjectEngineFactory.cs | 1 - .../IProjectEngineFactoryProvider.cs | 7 +- .../ProjectEngineHost/ProjectEngineFactory.cs | 1 - .../ProjectEngineFactoryProvider.cs | 12 +--- .../ProjectEngineFactory_Unsupported.cs | 1 - .../IProjectEngineFactoryExtensions.cs | 18 ++---- .../ProjectSystem/ProjectState.cs | 3 +- .../OOPTagHelperResolver.cs | 64 +++++++------------ .../OOPTagHelperResolverFactory.cs | 5 +- .../DefaultVisualStudioRazorParser.cs | 5 +- .../EphemeralProjectSnapshot.cs | 3 +- ...isualStudioProjectEngineFactoryProvider.cs | 9 +-- .../TestProjectEngineFactoryProvider.cs | 8 +-- .../OOPTagHelperResolverTest.TestResolver.cs | 20 +++--- .../OOPTagHelperResolverTest.cs | 21 +++--- ...ProjectSnapshotProjectEngineFactoryTest.cs | 12 ++-- ...tVisualStudioRazorParserIntegrationTest.cs | 2 +- .../DefaultVisualStudioRazorParserTest.cs | 2 +- 24 files changed, 75 insertions(+), 149 deletions(-) diff --git a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs index d2be110cb9e..8dfad478ad0 100644 --- a/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs +++ b/src/Razor/benchmarks/Microsoft.AspNetCore.Razor.Microbenchmarks/ProjectSystem/ProjectSnapshotManagerBenchmarkBase.StaticProjectSnapshotProjectEngineFactory.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; -using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Mvc.Razor.Extensions; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.ProjectEngineHost; @@ -19,11 +18,7 @@ private StaticProjectEngineFactoryProvider() { } - [return: NotNullIfNotNull(nameof(fallbackFactory))] - public IProjectEngineFactory? GetFactory( - RazorConfiguration configuration, - IProjectEngineFactory? fallbackFactory = null, - bool requireSerializationSupport = false) + public IProjectEngineFactory GetFactory(RazorConfiguration configuration) => Factory.Instance; private sealed class Factory : IProjectEngineFactory @@ -35,7 +30,6 @@ private Factory() } public string ConfigurationName => "Static"; - public bool SupportsSerialization => false; public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure) => RazorProjectEngine.Create(configuration, fileSystem, RazorExtensions.Register); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace/RazorProjectInfoSerializer.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace/RazorProjectInfoSerializer.cs index 0b10016bb18..587c88b2438 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace/RazorProjectInfoSerializer.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ExternalAccess.RoslynWorkspace/RazorProjectInfoSerializer.cs @@ -70,8 +70,7 @@ public static async Task SerializeAsync(Project project, string configurationFil builder.SetSupportLocalizedComponentNames(); // ProjectState in MS.CA.Razor.Workspaces does this, so I'm doing it too! }; - var engineFactory = ProjectEngineFactories.DefaultProvider.GetFactory( - configuration, ProjectEngineFactories.Empty); + var engineFactory = ProjectEngineFactories.DefaultProvider.GetFactory(configuration); var engine = engineFactory.Create( configuration, diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Cohost/CohostProjectSnapshot.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Cohost/CohostProjectSnapshot.cs index aa72196c6c7..d681ca7ca2a 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Cohost/CohostProjectSnapshot.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Cohost/CohostProjectSnapshot.cs @@ -43,11 +43,9 @@ public CohostProjectSnapshot(Project project, DocumentSnapshotFactory documentSn _lazyConfiguration = new Lazy(CreateRazorConfiguration); _lazyProjectEngine = new Lazy(() => { - var factory = ProjectEngineFactories.DefaultProvider.GetFactory(Configuration, ProjectEngineFactories.Empty); - - return factory.Create( + return ProjectEngineFactories.DefaultProvider.Create( Configuration, - fileSystem: RazorProjectFileSystem.Create(Path.GetDirectoryName(FilePath)), + rootDirectoryPath: Path.GetDirectoryName(FilePath).AssumeNotNull(), configure: builder => { builder.SetRootNamespace(RootNamespace); diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspProjectEngineFactoryProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspProjectEngineFactoryProvider.cs index b9892a84e36..533cc923094 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspProjectEngineFactoryProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/LspProjectEngineFactoryProvider.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; -using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.Extensions.Options; @@ -16,13 +15,9 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer; ///
internal sealed class LspProjectEngineFactoryProvider(IOptionsMonitor optionsMonitor) : IProjectEngineFactoryProvider { - [return: NotNullIfNotNull(nameof(fallbackFactory))] - public IProjectEngineFactory? GetFactory( - RazorConfiguration configuration, - IProjectEngineFactory? fallbackFactory = null, - bool requireSerializationSupport = false) + public IProjectEngineFactory GetFactory(RazorConfiguration configuration) { - var factory = ProjectEngineFactories.DefaultProvider.GetFactory(configuration, ProjectEngineFactories.Empty); + var factory = ProjectEngineFactories.DefaultProvider.GetFactory(configuration); return new Factory(factory, optionsMonitor); } @@ -30,7 +25,6 @@ internal sealed class LspProjectEngineFactoryProvider(IOptionsMonitor optionsMonitor) : IProjectEngineFactory { public string ConfigurationName => innerFactory.ConfigurationName; - public bool SupportsSerialization => false; public RazorProjectEngine Create( RazorConfiguration configuration, diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/DefaultProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/DefaultProjectEngineFactory.cs index 098316dbfce..1b736a489e0 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/DefaultProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/DefaultProjectEngineFactory.cs @@ -10,7 +10,6 @@ namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; internal class DefaultProjectEngineFactory : IProjectEngineFactory { public string ConfigurationName => "Default"; - public bool SupportsSerialization => true; public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure) { diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/EmptyProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/EmptyProjectEngineFactory.cs index d1c0d7fd4b1..95c24f4cb23 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/EmptyProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/EmptyProjectEngineFactory.cs @@ -9,8 +9,6 @@ namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; internal sealed class EmptyProjectEngineFactory : IProjectEngineFactory { public string ConfigurationName => "Empty"; - public bool SupportsSerialization => true; - public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure) { if (configuration is null) diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/IProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/IProjectEngineFactory.cs index 4dcdbe90179..639de55199e 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/IProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/IProjectEngineFactory.cs @@ -9,7 +9,6 @@ namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; internal interface IProjectEngineFactory { string ConfigurationName { get; } - bool SupportsSerialization { get; } RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/IProjectEngineFactoryProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/IProjectEngineFactoryProvider.cs index 4eebe20b1b5..6ac2713d66a 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/IProjectEngineFactoryProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/IProjectEngineFactoryProvider.cs @@ -1,16 +1,11 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Razor.Language; namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; internal interface IProjectEngineFactoryProvider { - [return: NotNullIfNotNull(nameof(fallbackFactory))] - IProjectEngineFactory? GetFactory( - RazorConfiguration configuration, - IProjectEngineFactory? fallbackFactory = null, - bool requireSerializationSupport = false); + IProjectEngineFactory GetFactory(RazorConfiguration configuration); } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory.cs index 697ceac6149..1bd878b5bf8 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory.cs @@ -16,7 +16,6 @@ internal sealed partial class ProjectEngineFactory(string configurationName, str private readonly string _assemblyName = assemblyName; public string ConfigurationName => configurationName; - public bool SupportsSerialization => true; public RazorProjectEngine Create( RazorConfiguration configuration, diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactoryProvider.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactoryProvider.cs index 95d3b40a84b..e9d46c0bd14 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactoryProvider.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactoryProvider.cs @@ -2,28 +2,22 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System.Collections.Immutable; -using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Razor.Language; namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; internal class ProjectEngineFactoryProvider(ImmutableArray factories) : IProjectEngineFactoryProvider { - [return: NotNullIfNotNull(nameof(fallbackFactory))] - public IProjectEngineFactory? GetFactory( - RazorConfiguration configuration, - IProjectEngineFactory? fallbackFactory = null, - bool requireSerializationSupport = false) + public IProjectEngineFactory GetFactory(RazorConfiguration configuration) { foreach (var factory in factories) { - if (factory.ConfigurationName == configuration.ConfigurationName && - (!requireSerializationSupport || factory.SupportsSerialization)) + if (factory.ConfigurationName == configuration.ConfigurationName) { return factory; } } - return fallbackFactory; + return ProjectEngineFactories.Empty; } } diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_Unsupported.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_Unsupported.cs index b0475e00ab8..b50451f8202 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_Unsupported.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.ProjectEngineHost/ProjectEngineHost/ProjectEngineFactory_Unsupported.cs @@ -10,7 +10,6 @@ namespace Microsoft.AspNetCore.Razor.ProjectEngineHost; internal class ProjectEngineFactory_Unsupported : IProjectEngineFactory { public string ConfigurationName => UnsupportedRazorConfiguration.Instance.ConfigurationName; - public bool SupportsSerialization => true; public RazorProjectEngine Create(RazorConfiguration configuration, RazorProjectFileSystem fileSystem, Action? configure) { diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectEngineHost/IProjectEngineFactoryExtensions.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectEngineHost/IProjectEngineFactoryExtensions.cs index 7d80a113aed..2e3b846d3b6 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectEngineHost/IProjectEngineFactoryExtensions.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectEngineHost/IProjectEngineFactoryExtensions.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; -using System.Diagnostics.CodeAnalysis; using System.IO; using Microsoft.AspNetCore.Razor.Language; using Microsoft.CodeAnalysis.Razor.ProjectSystem; @@ -20,26 +19,23 @@ public static RazorProjectEngine Create( RazorProjectFileSystem.Create(Path.GetDirectoryName(projectSnapshot.FilePath)), configure); - [return: NotNullIfNotNull(nameof(fallbackFactory))] - public static RazorProjectEngine? Create( + public static RazorProjectEngine Create( this IProjectEngineFactoryProvider factoryProvider, IProjectSnapshot projectSnapshot, - IProjectEngineFactory? fallbackFactory = null, Action? configure = null) => factoryProvider.Create( projectSnapshot.Configuration, rootDirectoryPath: Path.GetDirectoryName(projectSnapshot.FilePath).AssumeNotNull(), - fallbackFactory, configure); - [return: NotNullIfNotNull(nameof(fallbackFactory))] - public static RazorProjectEngine? Create( + public static RazorProjectEngine Create( this IProjectEngineFactoryProvider factoryProvider, RazorConfiguration configuration, string rootDirectoryPath, - IProjectEngineFactory? fallbackFactory = null, Action? configure = null) - => factoryProvider.GetFactory(configuration, fallbackFactory) is IProjectEngineFactory factory - ? factory.Create(configuration, RazorProjectFileSystem.Create(rootDirectoryPath), configure) - : null; + { + var factory = factoryProvider.GetFactory(configuration); + + return factory.Create(configuration, RazorProjectFileSystem.Create(rootDirectoryPath), configure); + } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ProjectState.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ProjectState.cs index c030a138868..586b6dae2e6 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ProjectState.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/ProjectSystem/ProjectState.cs @@ -204,9 +204,8 @@ RazorProjectEngine CreateProjectEngine() { var configuration = HostProject.Configuration; var rootDirectoryPath = Path.GetDirectoryName(HostProject.FilePath).AssumeNotNull(); - var fallbackFactory = ProjectEngineFactories.Empty; - return _projectEngineFactoryProvider.Create(configuration, rootDirectoryPath, fallbackFactory, builder => + return _projectEngineFactoryProvider.Create(configuration, rootDirectoryPath, builder => { builder.SetRootNamespace(HostProject.RootNamespace); builder.SetCSharpLanguageVersion(CSharpLanguageVersion); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs index 763bc4e36ff..0b63a48cfbb 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolver.cs @@ -8,7 +8,6 @@ using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.PooledObjects; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Serialization; using Microsoft.AspNetCore.Razor.Telemetry; using Microsoft.AspNetCore.Razor.Utilities; @@ -21,15 +20,13 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; internal class OOPTagHelperResolver : ITagHelperResolver { - private readonly TagHelperResultCache _resultCache; - private readonly CompilationTagHelperResolver _innerResolver; - private readonly IProjectEngineFactoryProvider _projectEngineFactoryProvider; - private readonly IErrorReporter _errorReporter; private readonly Workspace _workspace; + private readonly IErrorReporter _errorReporter; + private readonly CompilationTagHelperResolver _innerResolver; + private readonly TagHelperResultCache _resultCache; - public OOPTagHelperResolver(IProjectEngineFactoryProvider projectEngineFactoryProvider, IErrorReporter errorReporter, Workspace workspace, ITelemetryReporter telemetryReporter) + public OOPTagHelperResolver(Workspace workspace, IErrorReporter errorReporter, ITelemetryReporter telemetryReporter) { - _projectEngineFactoryProvider = projectEngineFactoryProvider ?? throw new ArgumentNullException(nameof(projectEngineFactoryProvider)); _errorReporter = errorReporter ?? throw new ArgumentNullException(nameof(errorReporter)); _workspace = workspace ?? throw new ArgumentNullException(nameof(workspace)); @@ -42,49 +39,36 @@ public async ValueTask> GetTagHelpersAsync( IProjectSnapshot projectSnapshot, CancellationToken cancellationToken) { - // Not every custom factory supports the OOP host. Our priority system should work like this: - // - // 1. Use custom factory out of process - // 2. Use custom factory in process - // 3. Use fallback factory in process - - var factory = _projectEngineFactoryProvider.GetFactory(projectSnapshot.Configuration, requireSerializationSupport: true); - - ImmutableArray result = default; + // First, try to retrieve tag helpers out-of-proc. If that fails, try in-proc. - if (factory != null) + try { - try - { - result = await ResolveTagHelpersOutOfProcessAsync(factory, workspaceProject, projectSnapshot, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) when (ex is not OperationCanceledException) + var result = await ResolveTagHelpersOutOfProcessAsync(workspaceProject, projectSnapshot, cancellationToken).ConfigureAwait(false); + + // We received tag helpers, so we're done. + if (!result.IsDefault) { - throw new InvalidOperationException( - "An unexpected exception occurred when resolving tag helpers out-of-process.", - ex); + return result; } } - - // Was unable to get tag helpers OOP, fallback to default behavior. - if (result.IsDefault) + catch (Exception ex) when (ex is not OperationCanceledException) { - try - { - result = await ResolveTagHelpersInProcessAsync(workspaceProject, projectSnapshot, cancellationToken).ConfigureAwait(false); - } - catch (Exception ex) when (ex is not OperationCanceledException) - { - throw new InvalidOperationException( - $"An unexpected exception occurred when invoking '{typeof(CompilationTagHelperResolver).FullName}.{nameof(GetTagHelpersAsync)}' on the Razor language service.", - ex); - } + _errorReporter.ReportError(ex, projectSnapshot); + return default; } - return result; + try + { + return await ResolveTagHelpersInProcessAsync(workspaceProject, projectSnapshot, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) when (ex is not OperationCanceledException) + { + _errorReporter.ReportError(ex, projectSnapshot); + return default; + } } - protected virtual async ValueTask> ResolveTagHelpersOutOfProcessAsync(IProjectEngineFactory factory, Project workspaceProject, IProjectSnapshot projectSnapshot, CancellationToken cancellationToken) + protected virtual async ValueTask> ResolveTagHelpersOutOfProcessAsync(Project workspaceProject, IProjectSnapshot projectSnapshot, CancellationToken cancellationToken) { // We're being overly defensive here because the OOP host can return null for the client/session/operation // when it's disconnected (user stops the process). diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolverFactory.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolverFactory.cs index ba953cd7c0c..8197dae7862 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolverFactory.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/OOPTagHelperResolverFactory.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System.Composition; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Telemetry; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host.Mef; @@ -15,14 +14,12 @@ namespace Microsoft.CodeAnalysis.Remote.Razor; [ExportWorkspaceServiceFactory(typeof(ITagHelperResolver), ServiceLayer.Host)] [method: ImportingConstructor] internal class OOPTagHelperResolverFactory( - IProjectEngineFactoryProvider projectEngineFactoryProvider, IErrorReporter errorReporter, ITelemetryReporter telemetryReporter) : IWorkspaceServiceFactory { public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices) => new OOPTagHelperResolver( - projectEngineFactoryProvider, - errorReporter, workspaceServices.Workspace, + errorReporter, telemetryReporter); } diff --git a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs index d750070da95..ef800e5ef15 100644 --- a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs +++ b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/DefaultVisualStudioRazorParser.cs @@ -250,10 +250,7 @@ internal void StartParser() var projectSnapshot = _documentTracker.ProjectSnapshot.AssumeNotNull(); - _projectEngine = _projectEngineFactoryProvider.Create( - projectSnapshot, - fallbackFactory: ProjectEngineFactories.Empty, - ConfigureProjectEngine).AssumeNotNull(); + _projectEngine = _projectEngineFactoryProvider.Create(projectSnapshot, ConfigureProjectEngine).AssumeNotNull(); Debug.Assert(_projectEngine.Engine is not null); Debug.Assert(_projectEngine.FileSystem is not null); diff --git a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/EphemeralProjectSnapshot.cs b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/EphemeralProjectSnapshot.cs index 8814a5faaa7..ddb88fb82a9 100644 --- a/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/EphemeralProjectSnapshot.cs +++ b/src/Razor/src/Microsoft.VisualStudio.Editor.Razor/EphemeralProjectSnapshot.cs @@ -90,7 +90,6 @@ public RazorProjectEngine GetProjectEngine() private RazorProjectEngine CreateProjectEngine() { - var factory = _projectEngineFactoryProvider.GetFactory(Configuration, ProjectEngineFactories.Empty); - return factory.Create(this); + return _projectEngineFactoryProvider.Create(this); } } diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioProjectEngineFactoryProvider.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioProjectEngineFactoryProvider.cs index 4521eb8ccc7..96cb97f54df 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioProjectEngineFactoryProvider.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/VisualStudioProjectEngineFactoryProvider.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System.ComponentModel.Composition; -using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.ProjectEngineHost; @@ -11,10 +10,6 @@ namespace Microsoft.VisualStudio.LanguageServices.Razor; [Export(typeof(IProjectEngineFactoryProvider))] internal sealed class VisualStudioProjectEngineFactoryProvider : IProjectEngineFactoryProvider { - [return: NotNullIfNotNull(nameof(fallbackFactory))] - public IProjectEngineFactory? GetFactory( - RazorConfiguration configuration, - IProjectEngineFactory? fallbackFactory = null, - bool requireSerializationSupport = false) - => ProjectEngineFactories.DefaultProvider.GetFactory(configuration, fallbackFactory, requireSerializationSupport); + public IProjectEngineFactory GetFactory(RazorConfiguration configuration) + => ProjectEngineFactories.DefaultProvider.GetFactory(configuration); } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectEngineFactoryProvider.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectEngineFactoryProvider.cs index 18991be1d46..d1f7342fa82 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectEngineFactoryProvider.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/ProjectSystem/TestProjectEngineFactoryProvider.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See License.txt in the project root for license information. using System; -using System.Diagnostics.CodeAnalysis; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.ProjectEngineHost; @@ -12,11 +11,7 @@ internal class TestProjectEngineFactoryProvider : IProjectEngineFactoryProvider { public Action? Configure { get; set; } - [return: NotNullIfNotNull(nameof(fallbackFactory))] - public IProjectEngineFactory? GetFactory( - RazorConfiguration configuration, - IProjectEngineFactory? fallbackFactory = null, - bool requireSerializationSupport = false) + public IProjectEngineFactory GetFactory(RazorConfiguration configuration) { return new Factory(Configure); } @@ -24,7 +19,6 @@ internal class TestProjectEngineFactoryProvider : IProjectEngineFactoryProvider private sealed class Factory(Action? outerConfigure) : IProjectEngineFactory { public string ConfigurationName => "Test"; - public bool SupportsSerialization => false; public RazorProjectEngine Create( RazorConfiguration configuration, diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestResolver.cs b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestResolver.cs index 524cb98b3dd..a46ae2744d4 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestResolver.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.TestResolver.cs @@ -6,7 +6,6 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; -using Microsoft.AspNetCore.Razor.ProjectEngineHost; using Microsoft.AspNetCore.Razor.Serialization; using Microsoft.AspNetCore.Razor.Telemetry; using Microsoft.AspNetCore.Razor.Utilities; @@ -14,31 +13,32 @@ using Microsoft.CodeAnalysis.Razor.ProjectSystem; using Xunit; +#pragma warning disable VSTHRD110 // Observe result of async calls + namespace Microsoft.CodeAnalysis.Remote.Razor; public partial class OOPTagHelperResolverTest { private class TestResolver( - IProjectEngineFactoryProvider projectEngineFactoryProvider, - IErrorReporter errorReporter, Workspace workspace, + IErrorReporter errorReporter, ITelemetryReporter telemetryReporter) - : OOPTagHelperResolver(projectEngineFactoryProvider, errorReporter, workspace, telemetryReporter) + : OOPTagHelperResolver(workspace, errorReporter, telemetryReporter) { - public Func>>? OnResolveOutOfProcess { get; init; } + public Func>>? OnResolveOutOfProcess { get; init; } public Func>>? OnResolveInProcess { get; init; } - protected override ValueTask> ResolveTagHelpersOutOfProcessAsync(IProjectEngineFactory factory, Project workspaceProject, IProjectSnapshot projectSnapshot, CancellationToken cancellationToken) + protected override ValueTask> ResolveTagHelpersOutOfProcessAsync(Project workspaceProject, IProjectSnapshot projectSnapshot, CancellationToken cancellationToken) { - Assert.NotNull(OnResolveOutOfProcess); - return OnResolveOutOfProcess(factory, projectSnapshot); + return OnResolveOutOfProcess?.Invoke(projectSnapshot) + ?? new ValueTask>(default(ImmutableArray)); } protected override ValueTask> ResolveTagHelpersInProcessAsync(Project project, IProjectSnapshot projectSnapshot, CancellationToken cancellationToken) { - Assert.NotNull(OnResolveInProcess); - return OnResolveInProcess(projectSnapshot); + return OnResolveInProcess?.Invoke(projectSnapshot) + ?? new ValueTask>(default(ImmutableArray)); } public ImmutableArray PublicProduceChecksumsFromDelta(ProjectId projectId, int lastResultId, TagHelperDeltaResult deltaResult) diff --git a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.cs b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.cs index 1e1a73aaefc..d91c8feccac 100644 --- a/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.cs +++ b/src/Razor/test/Microsoft.CodeAnalysis.Remote.Razor.Test/OOPTagHelperResolverTest.cs @@ -63,8 +63,6 @@ static IProjectEngineFactory CreateFactory(string configurationName) mock.SetupGet(x => x.ConfigurationName) .Returns(configurationName); - mock.SetupGet(x => x.SupportsSerialization) - .Returns(true); return mock.Object; } @@ -80,13 +78,12 @@ public async Task GetTagHelpersAsync_WithSerializableCustomFactory_GoesOutOfProc var calledOutOfProcess = false; - var resolver = new TestResolver(_projectEngineFactoryProvider, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance) + var resolver = new TestResolver(_workspace, ErrorReporter, NoOpTelemetryReporter.Instance) { - OnResolveOutOfProcess = (f, p) => + OnResolveOutOfProcess = (p) => { calledOutOfProcess = true; - Assert.Same(_customFactories[0], f); Assert.Same(projectSnapshot, p); return new(ImmutableArray.Empty); @@ -110,7 +107,7 @@ public async Task GetTagHelpersAsync_WithNonSerializableCustomFactory_StaysInPro var calledInProcess = false; - var resolver = new TestResolver(_projectEngineFactoryProvider, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance) + var resolver = new TestResolver(_workspace, ErrorReporter, NoOpTelemetryReporter.Instance) { OnResolveInProcess = (p) => { @@ -141,7 +138,7 @@ public async Task GetTagHelpersAsync_OperationCanceledException_DoesNotGetWrappe var calledInProcess = false; var cancellationToken = new CancellationToken(canceled: true); - var resolver = new TestResolver(_projectEngineFactoryProvider, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance) + var resolver = new TestResolver(_workspace, ErrorReporter, NoOpTelemetryReporter.Instance) { OnResolveInProcess = (p) => { @@ -150,7 +147,7 @@ public async Task GetTagHelpersAsync_OperationCanceledException_DoesNotGetWrappe return new(ImmutableArray.Empty); }, - OnResolveOutOfProcess = (f, p) => + OnResolveOutOfProcess = (p) => { calledOutOfProcess = true; Assert.Same(projectSnapshot, p); @@ -169,7 +166,7 @@ public async Task GetTagHelpersAsync_OperationCanceledException_DoesNotGetWrappe public void CalculateTagHelpersFromDelta_NewProject() { // Arrange - var resolver = new TestResolver(_projectEngineFactoryProvider, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance); + var resolver = new TestResolver(_workspace, ErrorReporter, NoOpTelemetryReporter.Instance); var initialDelta = new TagHelperDeltaResult(IsDelta: false, ResultId: 1, Project1TagHelperChecksums, ImmutableArray.Empty); // Act @@ -183,7 +180,7 @@ public void CalculateTagHelpersFromDelta_NewProject() public void CalculateTagHelpersFromDelta_DeltaFailedToApplyToKnownProject() { // Arrange - var resolver = new TestResolver(_projectEngineFactoryProvider, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance); + var resolver = new TestResolver(_workspace, ErrorReporter, NoOpTelemetryReporter.Instance); var initialDelta = new TagHelperDeltaResult(IsDelta: false, ResultId: 1, Project1TagHelperChecksums, ImmutableArray.Empty); resolver.PublicProduceChecksumsFromDelta(Project1Id, lastResultId: -1, initialDelta); var newTagHelperSet = ImmutableArray.Create(TagHelper1_Project1.Checksum); @@ -200,7 +197,7 @@ public void CalculateTagHelpersFromDelta_DeltaFailedToApplyToKnownProject() public void CalculateTagHelpersFromDelta_NoopResult() { // Arrange - var resolver = new TestResolver(_projectEngineFactoryProvider, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance); + var resolver = new TestResolver(_workspace, ErrorReporter, NoOpTelemetryReporter.Instance); var initialDelta = new TagHelperDeltaResult(IsDelta: false, ResultId: 1, Project1TagHelperChecksums, ImmutableArray.Empty); resolver.PublicProduceChecksumsFromDelta(Project1Id, lastResultId: -1, initialDelta); var noopDelta = new TagHelperDeltaResult(IsDelta: true, initialDelta.ResultId, ImmutableArray.Empty, ImmutableArray.Empty); @@ -216,7 +213,7 @@ public void CalculateTagHelpersFromDelta_NoopResult() public void CalculateTagHelpersFromDelta_ReplacedTagHelpers() { // Arrange - var resolver = new TestResolver(_projectEngineFactoryProvider, ErrorReporter, _workspace, NoOpTelemetryReporter.Instance); + var resolver = new TestResolver(_workspace, ErrorReporter, NoOpTelemetryReporter.Instance); var initialDelta = new TagHelperDeltaResult(IsDelta: false, ResultId: 1, Project1TagHelperChecksums, ImmutableArray.Empty); resolver.PublicProduceChecksumsFromDelta(Project1Id, lastResultId: -1, initialDelta); var changedDelta = new TagHelperDeltaResult(IsDelta: true, initialDelta.ResultId + 1, ImmutableArray.Create(TagHelper2_Project2.Checksum), ImmutableArray.Create(TagHelper2_Project1.Checksum)); diff --git a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectSnapshotProjectEngineFactoryTest.cs b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectSnapshotProjectEngineFactoryTest.cs index f8bedee32ee..e6ca3908a4d 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectSnapshotProjectEngineFactoryTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultProjectSnapshotProjectEngineFactoryTest.cs @@ -77,7 +77,7 @@ public void Create_CreatesDesignTimeTemplateEngine_ForVersion3_0() var provider = new ProjectEngineFactoryProvider(_customFactories); // Act - var factory = provider.GetFactory(snapshot.Configuration, ProjectEngineFactories.Empty); + var factory = provider.GetFactory(snapshot.Configuration); var engine = factory.Create(snapshot, b => b.Features.Add(new MyCoolNewFeature())); // Assert @@ -96,7 +96,7 @@ public void Create_CreatesDesignTimeTemplateEngine_ForVersion2_1() var provider = new ProjectEngineFactoryProvider(_customFactories); // Act - var factory = provider.GetFactory(snapshot.Configuration, ProjectEngineFactories.Empty); + var factory = provider.GetFactory(snapshot.Configuration); var engine = factory.Create(snapshot, b => b.Features.Add(new MyCoolNewFeature())); // Assert @@ -117,7 +117,7 @@ public void Create_CreatesDesignTimeTemplateEngine_ForVersion2_0() var provider = new ProjectEngineFactoryProvider(_customFactories); // Act - var factory = provider.GetFactory(snapshot.Configuration, ProjectEngineFactories.Empty); + var factory = provider.GetFactory(snapshot.Configuration); var engine = factory.Create(snapshot, b => b.Features.Add(new MyCoolNewFeature())); // Assert @@ -136,7 +136,7 @@ public void Create_CreatesTemplateEngine_ForVersion1_1() var provider = new ProjectEngineFactoryProvider(_customFactories); // Act - var factory = provider.GetFactory(snapshot.Configuration, ProjectEngineFactories.Empty); + var factory = provider.GetFactory(snapshot.Configuration); var engine = factory.Create(snapshot, b => b.Features.Add(new MyCoolNewFeature())); // Assert @@ -155,7 +155,7 @@ public void Create_DoesNotSupportViewComponentTagHelpers_ForVersion1_0() var provider = new ProjectEngineFactoryProvider(_customFactories); // Act - var factory = provider.GetFactory(snapshot.Configuration, ProjectEngineFactories.Empty); + var factory = provider.GetFactory(snapshot.Configuration); var engine = factory.Create(snapshot, b => b.Features.Add(new MyCoolNewFeature())); // Assert @@ -182,7 +182,7 @@ public void Create_ForUnknownConfiguration_UsesFallbackFactory() var provider = new ProjectEngineFactoryProvider(_customFactories); // Act - var factory = provider.GetFactory(snapshot.Configuration, ProjectEngineFactories.Empty); + var factory = provider.GetFactory(snapshot.Configuration); var engine = factory.Create(snapshot, b => b.Features.Add(new MyCoolNewFeature())); // Assert diff --git a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserIntegrationTest.cs b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserIntegrationTest.cs index 556b899d83f..72a148c9d00 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserIntegrationTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserIntegrationTest.cs @@ -605,7 +605,7 @@ private static IProjectEngineFactoryProvider CreateProjectEngineFactoryProvider( var providerMock = new Mock(MockBehavior.Strict); providerMock - .Setup(x => x.GetFactory(It.IsAny(), It.IsAny(), It.IsAny())) + .Setup(x => x.GetFactory(It.IsAny())) .Returns(factoryMock.Object); return providerMock.Object; diff --git a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs index 8c6f897c8c5..e8742cfedca 100644 --- a/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs +++ b/src/Razor/test/Microsoft.VisualStudio.Editor.Razor.Test/DefaultVisualStudioRazorParserTest.cs @@ -38,7 +38,7 @@ public DefaultVisualStudioRazorParserTest(ITestOutputHelper testOutput) var factoryProviderMock = new Mock(MockBehavior.Strict); factoryProviderMock - .Setup(x => x.GetFactory(It.IsAny(), It.IsAny(), It.IsAny())) + .Setup(x => x.GetFactory(It.IsAny())) .Returns(factoryMock.Object); _projectEngineFactoryProvider = factoryProviderMock.Object; From 415ed12c60861323b639a1041a1f2c121bdae041 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" Date: Mon, 22 Jan 2024 14:01:18 +0000 Subject: [PATCH 25/25] Update dependencies from https://github.com/dotnet/source-build-reference-packages build 20240117.1 Microsoft.SourceBuild.Intermediate.source-build-reference-packages From Version 9.0.0-alpha.1.24059.3 -> To Version 9.0.0-alpha.1.24067.1 --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 822d62f800d..5e70f23dc10 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -5,9 +5,9 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-runtime 839cdfb0ecca5e0be3dbccd926e7651ef50fdf10
- + https://github.com/dotnet/source-build-reference-packages - f2c3fed62861b918dfe300f01b497551813a56df + 549aadff1660b230bdfffa562eea3edf59dd0bb4 diff --git a/eng/Versions.props b/eng/Versions.props index 6173c50e11e..d62e54b5652 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -51,7 +51,7 @@ 6.0.2-servicing.22064.6 6.0.1 - 9.0.0-alpha.1.24059.3 + 9.0.0-alpha.1.24067.1 4.9.0-3.23613.4 4.9.0-3.23613.4 4.9.0-3.23613.4