From 79c8b92af799856919bb3844b6635e8606970366 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 21 Dec 2021 15:35:14 -0800 Subject: [PATCH 1/2] Support TestWorkspace with multiple source generated files --- .../Core/SourceGeneration/TestGenerators.cs | 24 ++++++++++---- .../CSharpTest/NavigateTo/NavigateToTests.cs | 32 +++++++++++++++++++ .../TestWorkspace_XmlConsumption.cs | 11 +++++-- 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/src/Compilers/Test/Core/SourceGeneration/TestGenerators.cs b/src/Compilers/Test/Core/SourceGeneration/TestGenerators.cs index 57217b7bdad0a..f5da455501648 100644 --- a/src/Compilers/Test/Core/SourceGeneration/TestGenerators.cs +++ b/src/Compilers/Test/Core/SourceGeneration/TestGenerators.cs @@ -3,7 +3,8 @@ // See the LICENSE file in the project root for more information. using System; -using System.IO; +using System.Collections.Generic; +using System.Linq; using System.Text; using System.Threading; using Microsoft.CodeAnalysis; @@ -13,18 +14,27 @@ namespace Roslyn.Test.Utilities.TestGenerators { internal class SingleFileTestGenerator : ISourceGenerator { - private readonly string _content; - private readonly string _hintName; + private readonly List<(string content, string hintName)> _sources = new(); - public SingleFileTestGenerator(string content, string hintName = "generatedFile") + public SingleFileTestGenerator() { - _content = content; - _hintName = hintName; + } + + public SingleFileTestGenerator(string content, string? hintName = null) + { + AddSource(content, hintName); + } + + public void AddSource(string content, string? hintName = null) + { + hintName ??= "generatedFile" + (_sources.Any() ? (_sources.Count + 1).ToString() : ""); + _sources.Add((content, hintName)); } public void Execute(GeneratorExecutionContext context) { - context.AddSource(this._hintName, SourceText.From(_content, Encoding.UTF8)); + foreach (var (content, hintName) in _sources) + context.AddSource(hintName, SourceText.From(content, Encoding.UTF8)); } public void Initialize(GeneratorInitializationContext context) diff --git a/src/EditorFeatures/CSharpTest/NavigateTo/NavigateToTests.cs b/src/EditorFeatures/CSharpTest/NavigateTo/NavigateToTests.cs index 8156a2a56398e..00b8e03512eb6 100644 --- a/src/EditorFeatures/CSharpTest/NavigateTo/NavigateToTests.cs +++ b/src/EditorFeatures/CSharpTest/NavigateTo/NavigateToTests.cs @@ -1473,6 +1473,38 @@ public class C }, await _aggregator.GetItemsAsync("C")); } + + [Fact] + public async Task DoIncludeSymbolsFromMultipleSourceGeneratedFiles() + { + using var workspace = TestWorkspace.Create(@" + + + + public partial class C + { + } + + + public partial class C + { + } + + + +", composition: EditorTestCompositions.EditorFeatures); + + _provider = new NavigateToItemProvider(workspace, AsynchronousOperationListenerProvider.NullListener, workspace.GetService()); + _aggregator = new NavigateToTestAggregator(_provider); + + VerifyNavigateToResultItems( + new() + { + new NavigateToItem("C", NavigateToItemKind.Class, "csharp", null, null, s_emptyExactPatternMatch, null), + new NavigateToItem("C", NavigateToItemKind.Class, "csharp", null, null, s_emptyExactPatternMatch, null), + }, + await _aggregator.GetItemsAsync("C")); + } } } #pragma warning restore CS0618 // MatchKind is obsolete diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs index 6dc371b3c01a4..09326b5f40882 100644 --- a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs +++ b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs @@ -14,7 +14,6 @@ using System.IO; using System.Linq; using System.Runtime.CompilerServices; -using System.ServiceModel.Description; using System.Threading; using System.Xml.Linq; using Microsoft.CodeAnalysis.CSharp; @@ -29,7 +28,6 @@ using Microsoft.CodeAnalysis.UnitTests; using Microsoft.CodeAnalysis.VisualBasic; using Microsoft.VisualStudio.Composition; -using Microsoft.VisualStudio.Text; using Roslyn.Test.Utilities; using Roslyn.Test.Utilities.TestGenerators; using Roslyn.Utilities; @@ -338,8 +336,15 @@ private static TestHostProject CreateProject( documents.Add(document); } + SingleFileTestGenerator testGenerator = null; foreach (var sourceGeneratedDocumentElement in projectElement.Elements(DocumentFromSourceGeneratorElementName)) { + if (testGenerator is null) + { + testGenerator = new SingleFileTestGenerator(); + analyzers.Add(new TestGeneratorReference(testGenerator)); + } + var name = GetFileName(workspace, sourceGeneratedDocumentElement, ref documentId); var markupCode = sourceGeneratedDocumentElement.NormalizedValue(); @@ -350,7 +355,7 @@ private static TestHostProject CreateProject( var document = new TestHostDocument(exportProvider, languageServices, code, name, documentFilePath, cursorPosition, spans, isSourceGenerated: true); documents.Add(document); - analyzers.Add(new TestGeneratorReference(new SingleFileTestGenerator(code, name))); + testGenerator.AddSource(code, name); } var additionalDocuments = new List(); From 7812951bd074f434af813135f87bf2bfd52cc82c Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 21 Dec 2021 15:41:40 -0800 Subject: [PATCH 2/2] Support TestWorkspace with source generated files without full XML syntax --- .../CrefCompletionProviderTests.cs | 2 +- .../OverrideCompletionProviderTests.cs | 2 +- .../CSharpTest/NavigateTo/NavigateToTests.cs | 31 +++++++++---------- ...osticsClassificationTaggerProviderTests.cs | 2 +- .../DiagnosticsSquiggleTaggerProviderTests.cs | 10 +++--- .../Workspaces/TestWorkspace_Create.cs | 14 ++++++--- .../TestWorkspace_XmlConsumption.cs | 1 + .../Workspaces/TestWorkspace_XmlCreation.cs | 24 +++++++++++--- .../CrefCompletionProviderTests.vb | 2 +- 9 files changed, 53 insertions(+), 35 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/CrefCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/CrefCompletionProviderTests.cs index b9e38257411fe..7bf6a90253c83 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/CrefCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/CrefCompletionProviderTests.cs @@ -440,7 +440,7 @@ public async Task CrefCompletionSpeculatesOutsideTrivia() class C { }"; - using var workspace = TestWorkspace.Create(LanguageNames.CSharp, new CSharpCompilationOptions(OutputKind.ConsoleApplication), new CSharpParseOptions(), new[] { text }, ExportProvider); + using var workspace = TestWorkspace.Create(LanguageNames.CSharp, new CSharpCompilationOptions(OutputKind.ConsoleApplication), new CSharpParseOptions(), new[] { text }, exportProvider: ExportProvider); var called = false; var hostDocument = workspace.DocumentWithCursor; diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs index 7beee24d167d8..043ff896b0a6a 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/OverrideCompletionProviderTests.cs @@ -2777,7 +2777,7 @@ static void Main(string[] args) override $$ } }"; - using var workspace = TestWorkspace.Create(LanguageNames.CSharp, new CSharpCompilationOptions(OutputKind.ConsoleApplication), new CSharpParseOptions(), new[] { text }, ExportProvider); + using var workspace = TestWorkspace.Create(LanguageNames.CSharp, new CSharpCompilationOptions(OutputKind.ConsoleApplication), new CSharpParseOptions(), new[] { text }, exportProvider: ExportProvider); var provider = new OverrideCompletionProvider(); var testDocument = workspace.Documents.Single(); var document = workspace.CurrentSolution.GetRequiredDocument(testDocument.Id); diff --git a/src/EditorFeatures/CSharpTest/NavigateTo/NavigateToTests.cs b/src/EditorFeatures/CSharpTest/NavigateTo/NavigateToTests.cs index 00b8e03512eb6..0aa8e949a25e4 100644 --- a/src/EditorFeatures/CSharpTest/NavigateTo/NavigateToTests.cs +++ b/src/EditorFeatures/CSharpTest/NavigateTo/NavigateToTests.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; @@ -1477,22 +1478,20 @@ public class C [Fact] public async Task DoIncludeSymbolsFromMultipleSourceGeneratedFiles() { - using var workspace = TestWorkspace.Create(@" - - - - public partial class C - { - } - - - public partial class C - { - } - - - -", composition: EditorTestCompositions.EditorFeatures); + using var workspace = TestWorkspace.CreateCSharp( + files: Array.Empty(), + sourceGeneratedFiles: new[] + { + @" +public partial class C +{ +}", + @" +public partial class C +{ +}", + }, + composition: EditorTestCompositions.EditorFeatures); _provider = new NavigateToItemProvider(workspace, AsynchronousOperationListenerProvider.NullListener, workspace.GetService()); _aggregator = new NavigateToTestAggregator(_provider); diff --git a/src/EditorFeatures/Test/Diagnostics/DiagnosticsClassificationTaggerProviderTests.cs b/src/EditorFeatures/Test/Diagnostics/DiagnosticsClassificationTaggerProviderTests.cs index 87d71ba66948d..bd36ed6d69eb6 100644 --- a/src/EditorFeatures/Test/Diagnostics/DiagnosticsClassificationTaggerProviderTests.cs +++ b/src/EditorFeatures/Test/Diagnostics/DiagnosticsClassificationTaggerProviderTests.cs @@ -37,7 +37,7 @@ public async Task Test_FadingSpans() { LanguageNames.CSharp, ImmutableArray.Create(analyzer) } }; - using var workspace = TestWorkspace.CreateCSharp(new string[] { "class A { }", "class E { }" }, CSharpParseOptions.Default, composition: SquiggleUtilities.CompositionWithSolutionCrawler); + using var workspace = TestWorkspace.CreateCSharp(new string[] { "class A { }", "class E { }" }, parseOptions: CSharpParseOptions.Default, composition: SquiggleUtilities.CompositionWithSolutionCrawler); using var wrapper = new DiagnosticTaggerWrapper(workspace, analyzerMap); var tagger = wrapper.TaggerProvider.CreateTagger(workspace.Documents.First().GetTextBuffer()); using var disposable = tagger as IDisposable; diff --git a/src/EditorFeatures/Test/Diagnostics/DiagnosticsSquiggleTaggerProviderTests.cs b/src/EditorFeatures/Test/Diagnostics/DiagnosticsSquiggleTaggerProviderTests.cs index f84913a7e50a7..6f7aa429bfae8 100644 --- a/src/EditorFeatures/Test/Diagnostics/DiagnosticsSquiggleTaggerProviderTests.cs +++ b/src/EditorFeatures/Test/Diagnostics/DiagnosticsSquiggleTaggerProviderTests.cs @@ -41,7 +41,7 @@ public async Task Test_TagSourceDiffer() { LanguageNames.CSharp, ImmutableArray.Create(analyzer) } }; - using var workspace = TestWorkspace.CreateCSharp(new string[] { "class A { }", "class E { }" }, CSharpParseOptions.Default); + using var workspace = TestWorkspace.CreateCSharp(new string[] { "class A { }", "class E { }" }, parseOptions: CSharpParseOptions.Default); using var wrapper = new DiagnosticTaggerWrapper(workspace, analyzerMap); var tagger = wrapper.TaggerProvider.CreateTagger(workspace.Documents.First().GetTextBuffer()); using var disposable = tagger as IDisposable; @@ -69,7 +69,7 @@ public async Task Test_TagSourceDiffer() [WpfFact, Trait(Traits.Feature, Traits.Features.Diagnostics)] public async Task MultipleTaggersAndDispose() { - using var workspace = TestWorkspace.CreateCSharp(new string[] { "class A {" }, CSharpParseOptions.Default); + using var workspace = TestWorkspace.CreateCSharp(new string[] { "class A {" }, parseOptions: CSharpParseOptions.Default); using var wrapper = new DiagnosticTaggerWrapper(workspace); // Make two taggers. var tagger1 = wrapper.TaggerProvider.CreateTagger(workspace.Documents.First().GetTextBuffer()); @@ -89,7 +89,7 @@ public async Task MultipleTaggersAndDispose() [WpfFact, Trait(Traits.Feature, Traits.Features.Diagnostics)] public async Task TaggerProviderCreatedAfterInitialDiagnosticsReported() { - using var workspace = TestWorkspace.CreateCSharp(new string[] { "class C {" }, CSharpParseOptions.Default); + using var workspace = TestWorkspace.CreateCSharp(new string[] { "class C {" }, parseOptions: CSharpParseOptions.Default); using var wrapper = new DiagnosticTaggerWrapper(workspace, analyzerMap: null, createTaggerProvider: false); // First, make sure all diagnostics have been reported. await wrapper.WaitForTags(); @@ -119,7 +119,7 @@ public async Task TestWithMockDiagnosticService_TaggerProviderCreatedBeforeIniti using var workspace = TestWorkspace.CreateCSharp( new string[] { "class A { }" }, - CSharpParseOptions.Default, + parseOptions: CSharpParseOptions.Default, composition: s_compositionWithMockDiagnosticService); var listenerProvider = workspace.ExportProvider.GetExportedValue(); @@ -156,7 +156,7 @@ public async Task TestWithMockDiagnosticService_TaggerProviderCreatedAfterInitia using var workspace = TestWorkspace.CreateCSharp( new string[] { "class A { }" }, - CSharpParseOptions.Default, + parseOptions: CSharpParseOptions.Default, composition: s_compositionWithMockDiagnosticService); var listenerProvider = workspace.ExportProvider.GetExportedValue(); diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_Create.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_Create.cs index 4fe217f35f5d9..5da952c24d78a 100644 --- a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_Create.cs +++ b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_Create.cs @@ -4,6 +4,7 @@ #nullable disable +using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; @@ -128,6 +129,7 @@ internal static TestWorkspace Create( CompilationOptions compilationOptions, ParseOptions parseOptions, string[] files, + string[] sourceGeneratedFiles = null, ExportProvider exportProvider = null, TestComposition composition = null, string[] metadataReferences = null, @@ -137,7 +139,7 @@ internal static TestWorkspace Create( bool openDocuments = false, IDocumentServiceProvider documentServiceProvider = null) { - var workspaceElement = CreateWorkspaceElement(language, compilationOptions, parseOptions, files, metadataReferences, extension, commonReferences); + var workspaceElement = CreateWorkspaceElement(language, compilationOptions, parseOptions, files, sourceGeneratedFiles, metadataReferences, extension, commonReferences); return Create(workspaceElement, openDocuments, exportProvider, composition, workspaceKind, documentServiceProvider); } @@ -193,11 +195,12 @@ public static TestWorkspace CreateCSharp( string[] metadataReferences = null, bool openDocuments = false) { - return CreateCSharp(new[] { file }, parseOptions, compilationOptions, exportProvider, composition, metadataReferences, openDocuments); + return CreateCSharp(new[] { file }, Array.Empty(), parseOptions, compilationOptions, exportProvider, composition, metadataReferences, openDocuments); } public static TestWorkspace CreateCSharp( string[] files, + string[] sourceGeneratedFiles = null, ParseOptions parseOptions = null, CompilationOptions compilationOptions = null, ExportProvider exportProvider = null, @@ -205,7 +208,7 @@ public static TestWorkspace CreateCSharp( string[] metadataReferences = null, bool openDocuments = false) { - return Create(LanguageNames.CSharp, compilationOptions, parseOptions, files, exportProvider, composition, metadataReferences, openDocuments: openDocuments); + return Create(LanguageNames.CSharp, compilationOptions, parseOptions, files, sourceGeneratedFiles, exportProvider, composition, metadataReferences, openDocuments: openDocuments); } public static TestWorkspace CreateCSharp2( @@ -230,11 +233,12 @@ public static TestWorkspace CreateVisualBasic( string[] metadataReferences = null, bool openDocuments = false) { - return CreateVisualBasic(new[] { file }, parseOptions, compilationOptions, exportProvider, composition, metadataReferences, openDocuments); + return CreateVisualBasic(new[] { file }, Array.Empty(), parseOptions, compilationOptions, exportProvider, composition, metadataReferences, openDocuments); } public static TestWorkspace CreateVisualBasic( string[] files, + string[] sourceGeneratedFiles = null, ParseOptions parseOptions = null, CompilationOptions compilationOptions = null, ExportProvider exportProvider = null, @@ -242,7 +246,7 @@ public static TestWorkspace CreateVisualBasic( string[] metadataReferences = null, bool openDocuments = false) { - return Create(LanguageNames.VisualBasic, compilationOptions, parseOptions, files, exportProvider, composition, metadataReferences, openDocuments: openDocuments); + return Create(LanguageNames.VisualBasic, compilationOptions, parseOptions, files, sourceGeneratedFiles, exportProvider, composition, metadataReferences, openDocuments: openDocuments); } /// Can pass in multiple file contents with individual source kind: files will be named test1.vb, test2.vbx, etc. diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs index 09326b5f40882..bd2b15e80b91e 100644 --- a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs +++ b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlConsumption.cs @@ -101,6 +101,7 @@ internal void InitializeDocuments( compilationOptions, parseOptions, files, + sourceGeneratedFiles: Array.Empty(), metadataReferences, extension, commonReferences); diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlCreation.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlCreation.cs index 0b7c578644977..6a10834bdce79 100644 --- a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlCreation.cs +++ b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace_XmlCreation.cs @@ -4,12 +4,10 @@ #nullable disable -using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.VisualBasic; using Roslyn.Utilities; @@ -22,23 +20,31 @@ internal static XElement CreateWorkspaceElement( CompilationOptions compilationOptions = null, ParseOptions parseOptions = null, string[] files = null, + string[] sourceGeneratedFiles = null, string[] metadataReferences = null, string extension = null, bool commonReferences = true) { var documentElements = new List(); + var index = 0; + extension ??= (language == LanguageNames.CSharp) ? CSharpExtension : VisualBasicExtension; if (files != null) { - var index = 0; - extension ??= (language == LanguageNames.CSharp) ? CSharpExtension : VisualBasicExtension; - foreach (var file in files) { documentElements.Add(CreateDocumentElement(file, GetDefaultTestSourceDocumentName(index++, extension), parseOptions)); } } + if (sourceGeneratedFiles != null) + { + foreach (var file in sourceGeneratedFiles) + { + documentElements.Add(CreateDocumentFromSourceGeneratorElement(file, GetDefaultTestSourceDocumentName(index++, extension), parseOptions)); + } + } + if (metadataReferences != null) { foreach (var reference in metadataReferences) @@ -171,6 +177,14 @@ protected static XElement CreateDocumentElement(string code, string filePath, Pa code.Replace("\r\n", "\n")); } + protected static XElement CreateDocumentFromSourceGeneratorElement(string code, string hintName, ParseOptions parseOptions = null) + { + return new XElement(DocumentFromSourceGeneratorElementName, + new XAttribute(FilePathAttributeName, hintName), + CreateParseOptionsElement(parseOptions), + code.Replace("\r\n", "\n")); + } + private static XElement CreateParseOptionsElement(ParseOptions parseOptions) { return parseOptions == null diff --git a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/CrefCompletionProviderTests.vb b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/CrefCompletionProviderTests.vb index 3c809d3e366e1..6bc616e38ba64 100644 --- a/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/CrefCompletionProviderTests.vb +++ b/src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/CrefCompletionProviderTests.vb @@ -414,7 +414,7 @@ Class C End Sub End Class]]>.Value.NormalizeLineEndings() - Using workspace = TestWorkspace.Create(LanguageNames.VisualBasic, New VisualBasicCompilationOptions(OutputKind.ConsoleApplication), New VisualBasicParseOptions(), {text}, ExportProvider) + Using workspace = TestWorkspace.Create(LanguageNames.VisualBasic, New VisualBasicCompilationOptions(OutputKind.ConsoleApplication), New VisualBasicParseOptions(), {text}, exportProvider:=ExportProvider) Dim called = False Dim hostDocument = workspace.DocumentWithCursor