Repository navigation
test(sourcegen): parse fixtures as a real build in all generator test harnesses #7319
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using Microsoft.CodeAnalysis; | ||
| using Microsoft.CodeAnalysis.CSharp; | ||
|
|
||
| namespace TUnit.Tests.Shared; | ||
|
|
||
| /// <summary> | ||
| /// Parse options and input checks shared by the source-generator test harnesses. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// The repository builds with <c>LangVersion=preview</c> (Directory.Build.props). Default parse options reject newer | ||
| /// syntax such as collection expressions, so a generator under test would see broken trees and the snapshots would | ||
| /// not match a real build (#7162, #7190). | ||
| /// </remarks> | ||
| internal static class GeneratorTestInput | ||
| { | ||
| /// <summary>Parse options matching the repository's language version.</summary> | ||
| public static CSharpParseOptions ParseOptions { get; } = new(LanguageVersion.Preview); | ||
|
|
||
| /// <summary>Parses <paramref name="source"/> with <see cref="ParseOptions"/>.</summary> | ||
| public static SyntaxTree Parse(string source, string path = "") | ||
| { | ||
| return CSharpSyntaxTree.ParseText(source, ParseOptions, path); | ||
| } | ||
|
|
||
| // Fixtures are not required to compile here: some reference packages or types that the harness | ||
| // does not load. Syntax errors and the binding errors that a too-old compiler reports for valid | ||
| // newer syntax are different, because the generator then sees a tree a real build never produces | ||
| // and the snapshot silently records the wrong output (#7162). | ||
| private static readonly HashSet<string> UnsupportedSyntaxDiagnosticIds = | ||
| [ | ||
| "CS0182", // attribute argument must be constant: collection expressions in attributes on Roslyn < 4.8 | ||
| "CS0225", // params parameter must be an array: params collections on Roslyn < 4.12 | ||
| "CS8652", // feature is in preview | ||
| ]; | ||
|
|
||
| /// <summary> | ||
| /// Throws when the input has syntax errors, or binding errors that only a compiler too old for the syntax reports. | ||
| /// </summary> | ||
| public static void ThrowIfInputCannotBeParsed(Compilation compilation) | ||
| { | ||
| var errors = compilation.SyntaxTrees | ||
| .SelectMany(tree => tree.GetDiagnostics()) | ||
| .Concat(compilation.GetDeclarationDiagnostics().Where(d => UnsupportedSyntaxDiagnosticIds.Contains(d.Id))) | ||
| .Where(d => d.Severity == DiagnosticSeverity.Error) | ||
| .Select(d => d.ToString()) | ||
| .Distinct() | ||
| .ToArray(); | ||
|
|
||
| if (errors.Length > 0) | ||
| { | ||
| throw new InvalidOperationException( | ||
| $"The test input does not parse as a real build would:{Environment.NewLine}{string.Join(Environment.NewLine, errors)}"); | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
tests/TUnit.Assertions.SourceGenerator.Tests/GeneratorTestInputTests.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| using Microsoft.CodeAnalysis; | ||
| using Microsoft.CodeAnalysis.CSharp; | ||
| using TUnit.Tests.Shared; | ||
|
|
||
| namespace TUnit.Assertions.SourceGenerator.Tests; | ||
|
|
||
| /// <summary> | ||
| /// The harness must bind fixtures the way a real build does (#7190): newer syntax has to parse and bind on the | ||
| /// Roslyn this project hosts, and input a real build would reject has to fail the test instead of being snapshotted. | ||
| /// </summary> | ||
| public class GeneratorTestInputTests | ||
| { | ||
| [Test] | ||
| public async Task Newer_Syntax_Is_Accepted() | ||
| { | ||
| var compilation = Compile( | ||
| """ | ||
| using System; | ||
| using System.Collections.Generic; | ||
|
|
||
| [AttributeUsage(AttributeTargets.Class)] | ||
| public sealed class ValuesAttribute(int[] values) : Attribute | ||
| { | ||
| public int[] Values { get; } = values; | ||
| } | ||
|
|
||
| [Values([1, 2, 3])] | ||
| public class UsesCollectionExpressionInAttribute | ||
| { | ||
| public static int Sum(params IEnumerable<int> values) | ||
| { | ||
| var total = 0; | ||
| foreach (var value in values) | ||
| { | ||
| total += value; | ||
| } | ||
|
|
||
| return total; | ||
| } | ||
| } | ||
| """); | ||
|
|
||
| await Assert.That(() => GeneratorTestInput.ThrowIfInputCannotBeParsed(compilation)).ThrowsNothing(); | ||
| } | ||
|
|
||
| [Test] | ||
| public async Task Syntax_Errors_Are_Rejected() | ||
| { | ||
| var compilation = Compile("public class Broken {"); | ||
|
|
||
| await Assert.That(() => GeneratorTestInput.ThrowIfInputCannotBeParsed(compilation)) | ||
| .Throws<InvalidOperationException>(); | ||
| } | ||
|
|
||
| private static CSharpCompilation Compile(string source) | ||
| { | ||
| return CSharpCompilation.Create( | ||
| nameof(GeneratorTestInputTests), | ||
| [GeneratorTestInput.Parse(source)], | ||
| ReferencesHelper.References, | ||
| new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.