From 619f27078901a574d0ab7f9f0a912d8d5e921681 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 2 Apr 2021 11:54:47 -0700 Subject: [PATCH 1/3] Update to Microsoft.CodeAnalysis 3.9.0 --- eng/Versions.props | 14 +++++++------- ...ourceGenerators.Testing.MSTest.UnitTests.vbproj | 3 --- ...SourceGenerators.Testing.NUnit.UnitTests.vbproj | 3 --- ...Basic.SourceGenerators.Testing.UnitTests.vbproj | 3 --- ...SourceGenerators.Testing.XUnit.UnitTests.vbproj | 3 --- 5 files changed, 7 insertions(+), 19 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index 0a32958aeb..2444a3f630 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -10,7 +10,7 @@ true true true - 3.9.0-4.final + 3.9.0 16.1.1 @@ -18,11 +18,11 @@ 3.3.2 - 3.8.0 - 3.8.0 - 3.8.0 - 3.8.0 - 3.8.0 + 3.9.0 + 3.9.0 + 3.9.0 + 3.9.0 + 3.9.0 8.0.0 8.0.1 @@ -61,7 +61,7 @@ 1.4.4 2.6.1 - 3.8.0 + 3.9.0 1.0.1-beta1.20374.2 1.2.7 0.1.49-beta diff --git a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.MSTest.UnitTests/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.MSTest.UnitTests.vbproj b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.MSTest.UnitTests/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.MSTest.UnitTests.vbproj index eb722fcc56..1f647e8800 100644 --- a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.MSTest.UnitTests/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.MSTest.UnitTests.vbproj +++ b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.MSTest.UnitTests/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.MSTest.UnitTests.vbproj @@ -4,9 +4,6 @@ $(SourceGeneratorTestTargetFrameworks) Microsoft.CodeAnalysis.Testing - - - diff --git a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.NUnit.UnitTests/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.NUnit.UnitTests.vbproj b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.NUnit.UnitTests/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.NUnit.UnitTests.vbproj index de29452ac1..c3e4c50e71 100644 --- a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.NUnit.UnitTests/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.NUnit.UnitTests.vbproj +++ b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.NUnit.UnitTests/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.NUnit.UnitTests.vbproj @@ -4,9 +4,6 @@ $(SourceGeneratorTestTargetFrameworks) Microsoft.CodeAnalysis.Testing - - - diff --git a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.UnitTests/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.UnitTests.vbproj b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.UnitTests/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.UnitTests.vbproj index c122f56592..fd1bf81c10 100644 --- a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.UnitTests/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.UnitTests.vbproj +++ b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.UnitTests/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.UnitTests.vbproj @@ -4,9 +4,6 @@ $(SourceGeneratorTestTargetFrameworks) Microsoft.CodeAnalysis.Testing - - - diff --git a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.XUnit.UnitTests/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.XUnit.UnitTests.vbproj b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.XUnit.UnitTests/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.XUnit.UnitTests.vbproj index bad6cd6264..7cbe9495c0 100644 --- a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.XUnit.UnitTests/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.XUnit.UnitTests.vbproj +++ b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.XUnit.UnitTests/Microsoft.CodeAnalysis.VisualBasic.SourceGenerators.Testing.XUnit.UnitTests.vbproj @@ -4,9 +4,6 @@ $(SourceGeneratorTestTargetFrameworks) Microsoft.CodeAnalysis.Testing - - - From 4a3307857f83d0fd3ef2806c370b3014debe7548 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 2 Apr 2021 11:56:35 -0700 Subject: [PATCH 2/3] Improve error messages for mismatched encodings --- .../CodeRefactoringTest`1.cs | 4 ++-- .../SourceGeneratorTest`1.cs | 2 +- .../SourceGeneratorValidationTests.cs | 22 +++++++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeRefactoring.Testing/CodeRefactoringTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeRefactoring.Testing/CodeRefactoringTest`1.cs index 734a461add..441845d598 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeRefactoring.Testing/CodeRefactoringTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeRefactoring.Testing/CodeRefactoringTest`1.cs @@ -165,7 +165,7 @@ private async Task VerifyRefactoringAsync( { var actual = await GetSourceTextFromDocumentAsync(updatedDocuments[i], cancellationToken).ConfigureAwait(false); verifier.EqualOrDiff(newState.Sources[i].content.ToString(), actual.ToString(), $"content of '{newState.Sources[i].filename}' did not match. Diff shown with expected as baseline:"); - verifier.Equal(newState.Sources[i].content.Encoding, actual.Encoding, $"encoding of '{newState.Sources[i].filename}' was expected to be '{newState.Sources[i].content.Encoding}' but was '{actual.Encoding}'"); + verifier.Equal(newState.Sources[i].content.Encoding, actual.Encoding, $"encoding of '{newState.Sources[i].filename}' was expected to be '{newState.Sources[i].content.Encoding?.WebName}' but was '{actual.Encoding?.WebName}'"); verifier.Equal(newState.Sources[i].content.ChecksumAlgorithm, actual.ChecksumAlgorithm, $"checksum algorithm of '{newState.Sources[i].filename}' was expected to be '{newState.Sources[i].content.ChecksumAlgorithm}' but was '{actual.ChecksumAlgorithm}'"); verifier.Equal(newState.Sources[i].filename, updatedDocuments[i].Name, $"file name was expected to be '{newState.Sources[i].filename}' but was '{updatedDocuments[i].Name}'"); } @@ -178,7 +178,7 @@ private async Task VerifyRefactoringAsync( { var actual = await updatedAdditionalDocuments[i].GetTextAsync(cancellationToken).ConfigureAwait(false); verifier.EqualOrDiff(newState.AdditionalFiles[i].content.ToString(), actual.ToString(), $"content of '{newState.AdditionalFiles[i].filename}' did not match. Diff shown with expected as baseline:"); - verifier.Equal(newState.AdditionalFiles[i].content.Encoding, actual.Encoding, $"encoding of '{newState.AdditionalFiles[i].filename}' was expected to be '{newState.AdditionalFiles[i].content.Encoding}' but was '{actual.Encoding}'"); + verifier.Equal(newState.AdditionalFiles[i].content.Encoding, actual.Encoding, $"encoding of '{newState.AdditionalFiles[i].filename}' was expected to be '{newState.AdditionalFiles[i].content.Encoding?.WebName}' but was '{actual.Encoding?.WebName}'"); verifier.Equal(newState.AdditionalFiles[i].content.ChecksumAlgorithm, actual.ChecksumAlgorithm, $"checksum algorithm of '{newState.AdditionalFiles[i].filename}' was expected to be '{newState.AdditionalFiles[i].content.ChecksumAlgorithm}' but was '{actual.ChecksumAlgorithm}'"); verifier.Equal(newState.AdditionalFiles[i].filename, updatedAdditionalDocuments[i].Name, $"file name was expected to be '{newState.AdditionalFiles[i].filename}' but was '{updatedAdditionalDocuments[i].Name}'"); } diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing/SourceGeneratorTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing/SourceGeneratorTest`1.cs index 74df7f76d8..9e86aafbae 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing/SourceGeneratorTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing/SourceGeneratorTest`1.cs @@ -83,7 +83,7 @@ private async Task> VerifySourceGeneratorAsync( { var actual = await GetSourceTextFromDocumentAsync(updatedDocuments[i], cancellationToken).ConfigureAwait(false); verifier.EqualOrDiff(expectedSources[i].content.ToString(), actual.ToString(), $"content of '{expectedSources[i].filename}' did not match. Diff shown with expected as baseline:"); - verifier.Equal(expectedSources[i].content.Encoding, actual.Encoding, $"encoding of '{expectedSources[i].filename}' was expected to be '{expectedSources[i].content.Encoding}' but was '{actual.Encoding}'"); + verifier.Equal(expectedSources[i].content.Encoding, actual.Encoding, $"encoding of '{expectedSources[i].filename}' was expected to be '{expectedSources[i].content.Encoding?.WebName}' but was '{actual.Encoding?.WebName}'"); verifier.Equal(expectedSources[i].content.ChecksumAlgorithm, actual.ChecksumAlgorithm, $"checksum algorithm of '{expectedSources[i].filename}' was expected to be '{expectedSources[i].content.ChecksumAlgorithm}' but was '{actual.ChecksumAlgorithm}'"); verifier.Equal(expectedSources[i].filename, updatedDocuments[i].Name, $"file name was expected to be '{expectedSources[i].filename}' but was '{updatedDocuments[i].Name}'"); } diff --git a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests/SourceGeneratorValidationTests.cs b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests/SourceGeneratorValidationTests.cs index 06de2efdc9..1eb60e036c 100644 --- a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests/SourceGeneratorValidationTests.cs +++ b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests/SourceGeneratorValidationTests.cs @@ -90,6 +90,28 @@ public async Task AddSimpleFileToEmptyProject() }.RunAsync(); } + [Fact] + public async Task AddSimpleFileWithWrongExpectedEncoding() + { + var exception = await Assert.ThrowsAsync(async () => + { + await new CSharpSourceGeneratorTest + { + TestState = + { + GeneratedSources = + { + (typeof(AddEmptyFile), "EmptyGeneratedFile.cs", SourceText.From(string.Empty, Encoding.Unicode)), + }, + }, + }.RunAsync(); + }); + + var expectedMessage = @"Context: Source generator application +encoding of 'Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests\Microsoft.CodeAnalysis.Testing.TestGenerators.AddEmptyFile\EmptyGeneratedFile.cs' was expected to be 'utf-16' but was 'utf-8'"; + new DefaultVerifier().EqualOrDiff(expectedMessage, exception.Message); + } + [Fact] public async Task AddSimpleFileWithDiagnostic() { From aedc893c44a0d6632393af156ef877f160b0e7b0 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Fri, 2 Apr 2021 12:27:31 -0700 Subject: [PATCH 3/3] Fix failure to validate compiler errors in generated sources --- .../AnalyzerTest`1.cs | 12 +- .../PublicAPI.Unshipped.txt | 3 +- .../CodeFixTest`1.cs | 4 +- .../PublicAPI.Unshipped.txt | 1 + .../SourceGeneratorTest`1.cs | 6 + .../SourceGeneratorValidationTests.cs | 104 +++++++++++++++++- .../TestGenerators/AddFileWithCompileError.cs | 32 ++++++ 7 files changed, 155 insertions(+), 7 deletions(-) create mode 100644 tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests/TestGenerators/AddFileWithCompileError.cs diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs index 35e74fade3..770326c4f9 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/AnalyzerTest`1.cs @@ -978,7 +978,7 @@ private async Task> GetSortedDiagnosticsAsync(Evaluat additionalDiagnostics = additionalDiagnostics.AddRange(project.AdditionalDiagnostics); } - return await GetSortedDiagnosticsAsync(solution, analyzers, additionalDiagnostics, CompilerDiagnostics, cancellationToken); + return await GetSortedDiagnosticsAsync(solution, analyzers, additionalDiagnostics, CompilerDiagnostics, verifier, cancellationToken); } /// @@ -989,10 +989,11 @@ private async Task> GetSortedDiagnosticsAsync(Evaluat /// The analyzer to run on the documents. /// Additional diagnostics reported for the solution, which need to be verified. /// The behavior of compiler diagnostics in validation scenarios. + /// The verifier to use for test assertions. /// The that the task will observe. /// A collection of s that surfaced in the source code, sorted by /// . - protected async Task> GetSortedDiagnosticsAsync(Solution solution, ImmutableArray analyzers, ImmutableArray additionalDiagnostics, CompilerDiagnostics compilerDiagnostics, CancellationToken cancellationToken) + protected async Task> GetSortedDiagnosticsAsync(Solution solution, ImmutableArray analyzers, ImmutableArray additionalDiagnostics, CompilerDiagnostics compilerDiagnostics, IVerifier verifier, CancellationToken cancellationToken) { if (analyzers.IsEmpty) { @@ -1002,7 +1003,7 @@ protected async Task> GetSortedDiagnosticsAsync(Solut var diagnostics = ImmutableArray.CreateBuilder(); foreach (var project in solution.Projects) { - var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false); + var compilation = await GetProjectCompilationAsync(project, verifier, cancellationToken).ConfigureAwait(false); var compilationWithAnalyzers = compilation.WithAnalyzers(analyzers, GetAnalyzerOptions(project), cancellationToken); var allDiagnostics = await compilationWithAnalyzers.GetAllDiagnosticsAsync().ConfigureAwait(false); @@ -1014,6 +1015,11 @@ protected async Task> GetSortedDiagnosticsAsync(Solut return results.ToImmutableArray(); } + protected virtual Task GetProjectCompilationAsync(Project project, IVerifier verifier, CancellationToken cancellationToken) + { + return project.GetCompilationAsync(cancellationToken); + } + private static bool IsCompilerDiagnostic(Diagnostic diagnostic) { return diagnostic.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.Compiler); diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/PublicAPI.Unshipped.txt b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/PublicAPI.Unshipped.txt index 0609c72fdc..cd1037a9e2 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/PublicAPI.Unshipped.txt +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.Analyzer.Testing/PublicAPI.Unshipped.txt @@ -8,7 +8,7 @@ Microsoft.CodeAnalysis.Testing.AnalyzerTest.DiagnosticVerifier.set -> Microsoft.CodeAnalysis.Testing.AnalyzerTest.DisabledDiagnostics.get -> System.Collections.Generic.List Microsoft.CodeAnalysis.Testing.AnalyzerTest.ExpectedDiagnostics.get -> System.Collections.Generic.List Microsoft.CodeAnalysis.Testing.AnalyzerTest.FormatVerifierMessage(System.Collections.Immutable.ImmutableArray analyzers, Microsoft.CodeAnalysis.Diagnostic actual, Microsoft.CodeAnalysis.Testing.DiagnosticResult expected, string message) -> string -Microsoft.CodeAnalysis.Testing.AnalyzerTest.GetSortedDiagnosticsAsync(Microsoft.CodeAnalysis.Solution solution, System.Collections.Immutable.ImmutableArray analyzers, System.Collections.Immutable.ImmutableArray additionalDiagnostics, Microsoft.CodeAnalysis.Testing.CompilerDiagnostics compilerDiagnostics, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> +Microsoft.CodeAnalysis.Testing.AnalyzerTest.GetSortedDiagnosticsAsync(Microsoft.CodeAnalysis.Solution solution, System.Collections.Immutable.ImmutableArray analyzers, System.Collections.Immutable.ImmutableArray additionalDiagnostics, Microsoft.CodeAnalysis.Testing.CompilerDiagnostics compilerDiagnostics, Microsoft.CodeAnalysis.Testing.IVerifier verifier, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task> Microsoft.CodeAnalysis.Testing.AnalyzerTest.MarkupOptions.get -> Microsoft.CodeAnalysis.Testing.MarkupOptions Microsoft.CodeAnalysis.Testing.AnalyzerTest.MarkupOptions.set -> void Microsoft.CodeAnalysis.Testing.AnalyzerTest.MatchDiagnosticsTimeout.get -> System.TimeSpan @@ -326,6 +326,7 @@ virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.DefaultFilePathPr virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.DefaultTestProjectName.get -> string virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.GetAnalyzerOptions(Microsoft.CodeAnalysis.Project project) -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerOptions virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.GetDefaultDiagnostic(Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer[] analyzers) -> Microsoft.CodeAnalysis.DiagnosticDescriptor +virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.GetProjectCompilationAsync(Microsoft.CodeAnalysis.Project project, Microsoft.CodeAnalysis.Testing.IVerifier verifier, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.IsCompilerDiagnosticIncluded(Microsoft.CodeAnalysis.Diagnostic diagnostic, Microsoft.CodeAnalysis.Testing.CompilerDiagnostics compilerDiagnostics) -> bool virtual Microsoft.CodeAnalysis.Testing.AnalyzerTest.RunAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task virtual Microsoft.CodeAnalysis.Testing.CodeActionTest.FilterCodeActions(System.Collections.Immutable.ImmutableArray actions) -> System.Collections.Immutable.ImmutableArray diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/CodeFixTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/CodeFixTest`1.cs index 2d77a92fb6..0ee1628190 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/CodeFixTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.CodeFix.Testing/CodeFixTest`1.cs @@ -461,7 +461,7 @@ private async Task VerifyFixAsync( bool done; do { - var analyzerDiagnostics = await GetSortedDiagnosticsAsync(project.Solution, analyzers, additionalDiagnostics: ImmutableArray.Empty, CompilerDiagnostics, cancellationToken).ConfigureAwait(false); + var analyzerDiagnostics = await GetSortedDiagnosticsAsync(project.Solution, analyzers, additionalDiagnostics: ImmutableArray.Empty, CompilerDiagnostics, verifier, cancellationToken).ConfigureAwait(false); if (analyzerDiagnostics.Length == 0) { break; @@ -590,7 +590,7 @@ private async Task VerifyFixAsync( bool done; do { - var analyzerDiagnostics = await GetSortedDiagnosticsAsync(project.Solution, analyzers, additionalDiagnostics: ImmutableArray.Empty, CompilerDiagnostics, cancellationToken).ConfigureAwait(false); + var analyzerDiagnostics = await GetSortedDiagnosticsAsync(project.Solution, analyzers, additionalDiagnostics: ImmutableArray.Empty, CompilerDiagnostics, verifier, cancellationToken).ConfigureAwait(false); if (analyzerDiagnostics.Length == 0) { break; diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing/PublicAPI.Unshipped.txt b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing/PublicAPI.Unshipped.txt index 89d2b2dec6..c5004ff9db 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing/PublicAPI.Unshipped.txt +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing/PublicAPI.Unshipped.txt @@ -10,4 +10,5 @@ Microsoft.CodeAnalysis.Testing.SourceGeneratorVerifier.CreateGeneratorDriver(Microsoft.CodeAnalysis.Project project, System.Collections.Immutable.ImmutableArray sourceGenerators) -> Microsoft.CodeAnalysis.GeneratorDriver abstract Microsoft.CodeAnalysis.Testing.SourceGeneratorTest.GetSourceGenerators() -> System.Collections.Generic.IEnumerable override Microsoft.CodeAnalysis.Testing.SourceGeneratorTest.GetDiagnosticAnalyzers() -> System.Collections.Generic.IEnumerable +override Microsoft.CodeAnalysis.Testing.SourceGeneratorTest.GetProjectCompilationAsync(Microsoft.CodeAnalysis.Project project, Microsoft.CodeAnalysis.Testing.IVerifier verifier, System.Threading.CancellationToken cancellationToken) -> System.Threading.Tasks.Task override Microsoft.CodeAnalysis.Testing.SourceGeneratorTest.RunAsync(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task diff --git a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing/SourceGeneratorTest`1.cs b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing/SourceGeneratorTest`1.cs index 9e86aafbae..f7ac4fb3fd 100644 --- a/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing/SourceGeneratorTest`1.cs +++ b/src/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing/SourceGeneratorTest`1.cs @@ -45,6 +45,12 @@ public override async Task RunAsync(CancellationToken cancellationToken = defaul await VerifyDiagnosticsAsync(new EvaluatedProjectState(testState, ReferenceAssemblies).WithAdditionalDiagnostics(diagnostics), testState.AdditionalProjects.Values.Select(additionalProject => new EvaluatedProjectState(additionalProject, ReferenceAssemblies)).ToImmutableArray(), testState.ExpectedDiagnostics.ToArray(), Verify.PushContext("Diagnostics of test state"), cancellationToken).ConfigureAwait(false); } + protected override async Task GetProjectCompilationAsync(Project project, IVerifier verifier, CancellationToken cancellationToken) + { + var (finalProject, diagnostics) = await ApplySourceGeneratorAsync(GetSourceGenerators().ToImmutableArray(), project, verifier, cancellationToken).ConfigureAwait(false); + return (await finalProject.GetCompilationAsync(cancellationToken).ConfigureAwait(false))!; + } + /// /// Called to test a C# source generator when applied on the input source as a string. /// diff --git a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests/SourceGeneratorValidationTests.cs b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests/SourceGeneratorValidationTests.cs index 1eb60e036c..0259f43b30 100644 --- a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests/SourceGeneratorValidationTests.cs +++ b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests/SourceGeneratorValidationTests.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.Collections.Immutable; using System.Text; @@ -9,6 +10,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Testing.TestGenerators; using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis.VisualBasic; using Xunit; namespace Microsoft.CodeAnalysis.Testing @@ -112,6 +114,74 @@ public async Task AddSimpleFileWithWrongExpectedEncoding() new DefaultVerifier().EqualOrDiff(expectedMessage, exception.Message); } + [Fact] + public async Task AddSimpleFileVerifiesCompilerDiagnostics_CSharp() + { + var exception = await Assert.ThrowsAsync(async () => + { + await new CSharpSourceGeneratorTest + { + TestState = + { + Sources = + { + @"class A {", + }, + GeneratedSources = + { + (typeof(AddFileWithCompileError), "ErrorGeneratedFile.cs", @"class C {"), + }, + }, + }.RunAsync(); + }); + + var expectedMessage = @"Context: Diagnostics of test state +Mismatch between number of diagnostics returned, expected ""0"" actual ""2"" + +Diagnostics: +// /0/Test0.cs(1,10): error CS1513: } expected +DiagnosticResult.CompilerError(""CS1513"").WithSpan(1, 10, 1, 10), +// Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests\Microsoft.CodeAnalysis.Testing.TestGenerators.AddFileWithCompileError\ErrorGeneratedFile.cs(1,10): error CS1513: } expected +DiagnosticResult.CompilerError(""CS1513"").WithSpan(""Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests\Microsoft.CodeAnalysis.Testing.TestGenerators.AddFileWithCompileError\ErrorGeneratedFile.cs"", 1, 10, 1, 10), + +"; + new DefaultVerifier().EqualOrDiff(expectedMessage, exception.Message); + } + + [Fact] + public async Task AddSimpleFileVerifiesCompilerDiagnostics_VisualBasic() + { + var exception = await Assert.ThrowsAsync(async () => + { + await new VisualBasicSourceGeneratorTest + { + TestState = + { + Sources = + { + "Class A", + }, + GeneratedSources = + { + (typeof(AddFileWithCompileError), "ErrorGeneratedFile.vb", "Class C"), + }, + }, + }.RunAsync(); + }); + + var expectedMessage = @"Context: Diagnostics of test state +Mismatch between number of diagnostics returned, expected ""0"" actual ""2"" + +Diagnostics: +// /0/Test0.vb(1) : error BC30481: 'Class' statement must end with a matching 'End Class'. +DiagnosticResult.CompilerError(""BC30481"").WithSpan(1, 1, 1, 8), +// Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests\Microsoft.CodeAnalysis.Testing.TestGenerators.AddFileWithCompileError\ErrorGeneratedFile.vb(1) : error BC30481: 'Class' statement must end with a matching 'End Class'. +DiagnosticResult.CompilerError(""BC30481"").WithSpan(""Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests\Microsoft.CodeAnalysis.Testing.TestGenerators.AddFileWithCompileError\ErrorGeneratedFile.vb"", 1, 1, 1, 8), + +"; + new DefaultVerifier().EqualOrDiff(expectedMessage, exception.Message); + } + [Fact] public async Task AddSimpleFileWithDiagnostic() { @@ -180,7 +250,39 @@ protected override CompilationOptions CreateCompilationOptions() protected override ParseOptions CreateParseOptions() { - return new CSharpParseOptions(LanguageVersion.Default, DocumentationMode.Diagnose); + return new CSharpParseOptions(CSharp.LanguageVersion.Default, DocumentationMode.Diagnose); + } + + protected override IEnumerable GetSourceGenerators() + { + yield return new TSourceGenerator(); + } + } + + private class VisualBasicSourceGeneratorTest : SourceGeneratorTest + where TSourceGenerator : ISourceGenerator, new() + { + public override string Language => LanguageNames.VisualBasic; + + protected override string DefaultFileExt => "vb"; + + protected override GeneratorDriver CreateGeneratorDriver(Project project, ImmutableArray sourceGenerators) + { + return VisualBasicGeneratorDriver.Create( + sourceGenerators, + project.AnalyzerOptions.AdditionalFiles, + (VisualBasicParseOptions)project.ParseOptions!, + project.AnalyzerOptions.AnalyzerConfigOptionsProvider); + } + + protected override CompilationOptions CreateCompilationOptions() + { + return new VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary); + } + + protected override ParseOptions CreateParseOptions() + { + return new VisualBasicParseOptions(VisualBasic.LanguageVersion.Default, DocumentationMode.Diagnose); } protected override IEnumerable GetSourceGenerators() diff --git a/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests/TestGenerators/AddFileWithCompileError.cs b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests/TestGenerators/AddFileWithCompileError.cs new file mode 100644 index 0000000000..cbd5566c98 --- /dev/null +++ b/tests/Microsoft.CodeAnalysis.Testing/Microsoft.CodeAnalysis.SourceGenerators.Testing.UnitTests/TestGenerators/AddFileWithCompileError.cs @@ -0,0 +1,32 @@ +// Licensed to the .NET Foundation under one or more agreements. +// 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; + +namespace Microsoft.CodeAnalysis.Testing.TestGenerators +{ + public class AddFileWithCompileError : ISourceGenerator + { + public void Initialize(GeneratorInitializationContext context) + { + } + + public virtual void Execute(GeneratorExecutionContext context) + { + switch (context.Compilation.Language) + { + case LanguageNames.CSharp: + context.AddSource("ErrorGeneratedFile", "class C {"); + break; + + case LanguageNames.VisualBasic: + context.AddSource("ErrorGeneratedFile", "Class C"); + break; + + default: + throw new NotSupportedException(); + } + } + } +}