Skip to content

Commit 6c8f5d1

Browse files
committed
use Basic.Reference.Assemblies.Net100 for Source Generator testing
1 parent 90da749 commit 6c8f5d1

File tree

3 files changed

+130
-138
lines changed

3 files changed

+130
-138
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CSharp;
3+
using Microsoft.CodeAnalysis.Diagnostics;
4+
using System.Collections.Immutable;
5+
using System.Diagnostics.CodeAnalysis;
6+
using System.Runtime.CompilerServices;
7+
8+
namespace ToonEncoder.Tests;
9+
10+
public class CSharpGeneratorRunner
11+
{
12+
Compilation baseCompilation = default!;
13+
14+
public CSharpGeneratorRunner()
15+
{
16+
var globalUsings = """
17+
global using System;
18+
global using Cysharp.AI;
19+
""";
20+
;
21+
22+
var compilation = CSharpCompilation.Create("generatortest",
23+
references: Basic.Reference.Assemblies.Net100.References.All,
24+
syntaxTrees: [CSharpSyntaxTree.ParseText(globalUsings, path: "GlobalUsings.cs")],
25+
options: new CSharpCompilationOptions(OutputKind.ConsoleApplication, allowUnsafe: true)); // .exe
26+
27+
baseCompilation = compilation;
28+
}
29+
30+
public (Compilation, ImmutableArray<Diagnostic>) RunGenerator([StringSyntax("C#-test")] string source, string[]? preprocessorSymbols = null, AnalyzerConfigOptionsProvider? options = null)
31+
{
32+
if (preprocessorSymbols == null)
33+
{
34+
preprocessorSymbols = new[] { "NET10_0_OR_GREATER" };
35+
}
36+
var parseOptions = new CSharpParseOptions(LanguageVersion.CSharp14, preprocessorSymbols: preprocessorSymbols); // C# 14
37+
38+
var driver = CSharpGeneratorDriver.Create(new Cysharp.AI.ToonEncoderGenerator()).WithUpdatedParseOptions(parseOptions);
39+
if (options != null)
40+
{
41+
driver = (Microsoft.CodeAnalysis.CSharp.CSharpGeneratorDriver)driver.WithUpdatedAnalyzerConfigOptions(options);
42+
}
43+
44+
var compilation = baseCompilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(source, parseOptions));
45+
46+
driver.RunGeneratorsAndUpdateCompilation(compilation, out var newCompilation, out var diagnostics);
47+
return (newCompilation, diagnostics);
48+
}
49+
}
50+
51+
public class VerifyHelper
52+
{
53+
readonly string idPrefix = "TEG";
54+
55+
[ClassDataSource<CSharpGeneratorRunner>(Shared = SharedType.PerTestSession)]
56+
public required CSharpGeneratorRunner Runner { get; init; }
57+
58+
public async Task Ok([StringSyntax("C#-test")] string code, [CallerArgumentExpression("code")] string? codeExpr = null)
59+
{
60+
Console.WriteLine(codeExpr!);
61+
62+
var (compilation, diagnostics) = Runner.RunGenerator(code);
63+
foreach (var item in diagnostics)
64+
{
65+
Console.WriteLine(item.ToString());
66+
}
67+
OutputGeneratedCode(compilation);
68+
69+
await Assert.That(diagnostics.Length).IsZero();
70+
}
71+
72+
public async Task Verify(int id, [StringSyntax("C#-test")] string code, string diagnosticsCodeSpan, [CallerArgumentExpression("code")] string? codeExpr = null)
73+
{
74+
Console.WriteLine(codeExpr!);
75+
76+
var (compilation, diagnostics) = Runner.RunGenerator(code);
77+
foreach (var item in diagnostics)
78+
{
79+
Console.WriteLine(item.ToString());
80+
}
81+
OutputGeneratedCode(compilation);
82+
83+
await Assert.That(diagnostics.Length).IsEqualTo(1);
84+
await Assert.That(diagnostics[0].Id).IsEqualTo(idPrefix + id.ToString("000"));
85+
86+
var text = GetLocationText(diagnostics[0], compilation.SyntaxTrees);
87+
await Assert.That(text).IsEqualTo(diagnosticsCodeSpan);
88+
}
89+
90+
public (string, string)[] Verify([StringSyntax("C#-test")] string code, [CallerArgumentExpression("code")] string? codeExpr = null)
91+
{
92+
Console.WriteLine(codeExpr!);
93+
94+
var (compilation, diagnostics) = Runner.RunGenerator(code);
95+
OutputGeneratedCode(compilation);
96+
return diagnostics.Select(x => (x.Id, GetLocationText(x, compilation.SyntaxTrees))).ToArray();
97+
}
98+
99+
string GetLocationText(Diagnostic diagnostic, IEnumerable<SyntaxTree> syntaxTrees)
100+
{
101+
var location = diagnostic.Location;
102+
103+
var textSpan = location.SourceSpan;
104+
var sourceTree = location.SourceTree;
105+
if (sourceTree == null)
106+
{
107+
var lineSpan = location.GetLineSpan();
108+
if (lineSpan.Path == null) return "";
109+
110+
sourceTree = syntaxTrees.FirstOrDefault(x => x.FilePath == lineSpan.Path);
111+
if (sourceTree == null) return "";
112+
}
113+
114+
var text = sourceTree.GetText().GetSubText(textSpan).ToString();
115+
return text;
116+
}
117+
118+
void OutputGeneratedCode(Compilation compilation)
119+
{
120+
foreach (var syntaxTree in compilation.SyntaxTrees)
121+
{
122+
if (!syntaxTree.FilePath.Contains("g.cs")) continue;
123+
Console.WriteLine(syntaxTree.ToString());
124+
}
125+
}
126+
}

tests/ToonEncoder.Tests/GeneratorTest.cs

Lines changed: 3 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -1,143 +1,8 @@
1-
using Microsoft.CodeAnalysis;
2-
using Microsoft.CodeAnalysis.CSharp;
3-
using Microsoft.CodeAnalysis.Diagnostics;
4-
using System.Collections.Immutable;
5-
using System.Diagnostics.CodeAnalysis;
6-
using System.Runtime.CompilerServices;
1+
namespace ToonEncoder.Tests;
72

8-
namespace ToonEncoder.Tests;
9-
10-
#region Helper for Source Generator Testing
11-
12-
public static class CSharpGeneratorRunner
3+
[ClassDataSource<VerifyHelper>]
4+
public class GeneratorTest(VerifyHelper verifier)
135
{
14-
static Compilation baseCompilation = default!;
15-
16-
[ModuleInitializer]
17-
public static void InitializeCompilation()
18-
{
19-
var globalUsings = """
20-
global using System;
21-
global using Cysharp.AI;
22-
""";
23-
24-
var references = AppDomain.CurrentDomain.GetAssemblies()
25-
.Where(x => !x.IsDynamic && !string.IsNullOrWhiteSpace(x.Location))
26-
.Select(x => MetadataReference.CreateFromFile(x.Location));
27-
//.Concat([
28-
// MetadataReference.CreateFromFile(typeof(Console).Assembly.Location), // System.Console.dll
29-
// MetadataReference.CreateFromFile(typeof(IServiceProvider).Assembly.Location), // System.ComponentModel.dll
30-
// MetadataReference.CreateFromFile(typeof(System.ComponentModel.DataAnnotations.RequiredAttribute).Assembly.Location), // System.ComponentModel.DataAnnotations
31-
// MetadataReference.CreateFromFile(typeof(System.Text.Json.JsonDocument).Assembly.Location), // System.Text.Json.dll
32-
//]);
33-
34-
var compilation = CSharpCompilation.Create("generatortest",
35-
references: references,
36-
syntaxTrees: [CSharpSyntaxTree.ParseText(globalUsings, path: "GlobalUsings.cs")],
37-
options: new CSharpCompilationOptions(OutputKind.ConsoleApplication, allowUnsafe: true)); // .exe
38-
39-
baseCompilation = compilation;
40-
}
41-
42-
public static (Compilation, ImmutableArray<Diagnostic>) RunGenerator([StringSyntax("C#-test")] string source, string[]? preprocessorSymbols = null, AnalyzerConfigOptionsProvider? options = null)
43-
{
44-
if (preprocessorSymbols == null)
45-
{
46-
preprocessorSymbols = new[] { "NET10_0_OR_GREATER" };
47-
}
48-
var parseOptions = new CSharpParseOptions(LanguageVersion.CSharp14, preprocessorSymbols: preprocessorSymbols); // C# 14
49-
50-
var driver = CSharpGeneratorDriver.Create(new Cysharp.AI.ToonEncoderGenerator()).WithUpdatedParseOptions(parseOptions);
51-
if (options != null)
52-
{
53-
driver = (Microsoft.CodeAnalysis.CSharp.CSharpGeneratorDriver)driver.WithUpdatedAnalyzerConfigOptions(options);
54-
}
55-
56-
var compilation = baseCompilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(source, parseOptions));
57-
58-
driver.RunGeneratorsAndUpdateCompilation(compilation, out var newCompilation, out var diagnostics);
59-
return (newCompilation, diagnostics);
60-
}
61-
}
62-
63-
public class VerifyHelper(string idPrefix)
64-
{
65-
public async Task Ok([StringSyntax("C#-test")] string code, [CallerArgumentExpression("code")] string? codeExpr = null)
66-
{
67-
Console.WriteLine(codeExpr!);
68-
69-
var (compilation, diagnostics) = CSharpGeneratorRunner.RunGenerator(code);
70-
foreach (var item in diagnostics)
71-
{
72-
Console.WriteLine(item.ToString());
73-
}
74-
OutputGeneratedCode(compilation);
75-
76-
await Assert.That(diagnostics.Length).IsZero();
77-
}
78-
79-
public async Task Verify(int id, [StringSyntax("C#-test")] string code, string diagnosticsCodeSpan, [CallerArgumentExpression("code")] string? codeExpr = null)
80-
{
81-
Console.WriteLine(codeExpr!);
82-
83-
var (compilation, diagnostics) = CSharpGeneratorRunner.RunGenerator(code);
84-
foreach (var item in diagnostics)
85-
{
86-
Console.WriteLine(item.ToString());
87-
}
88-
OutputGeneratedCode(compilation);
89-
90-
await Assert.That(diagnostics.Length).IsEqualTo(1);
91-
await Assert.That(diagnostics[0].Id).IsEqualTo(idPrefix + id.ToString("000"));
92-
93-
var text = GetLocationText(diagnostics[0], compilation.SyntaxTrees);
94-
await Assert.That(text).IsEqualTo(diagnosticsCodeSpan);
95-
}
96-
97-
public (string, string)[] Verify([StringSyntax("C#-test")] string code, [CallerArgumentExpression("code")] string? codeExpr = null)
98-
{
99-
Console.WriteLine(codeExpr!);
100-
101-
var (compilation, diagnostics) = CSharpGeneratorRunner.RunGenerator(code);
102-
OutputGeneratedCode(compilation);
103-
return diagnostics.Select(x => (x.Id, GetLocationText(x, compilation.SyntaxTrees))).ToArray();
104-
}
105-
106-
string GetLocationText(Diagnostic diagnostic, IEnumerable<SyntaxTree> syntaxTrees)
107-
{
108-
var location = diagnostic.Location;
109-
110-
var textSpan = location.SourceSpan;
111-
var sourceTree = location.SourceTree;
112-
if (sourceTree == null)
113-
{
114-
var lineSpan = location.GetLineSpan();
115-
if (lineSpan.Path == null) return "";
116-
117-
sourceTree = syntaxTrees.FirstOrDefault(x => x.FilePath == lineSpan.Path);
118-
if (sourceTree == null) return "";
119-
}
120-
121-
var text = sourceTree.GetText().GetSubText(textSpan).ToString();
122-
return text;
123-
}
124-
125-
void OutputGeneratedCode(Compilation compilation)
126-
{
127-
foreach (var syntaxTree in compilation.SyntaxTrees)
128-
{
129-
if (!syntaxTree.FilePath.Contains("g.cs")) continue;
130-
Console.WriteLine(syntaxTree.ToString());
131-
}
132-
}
133-
}
134-
135-
#endregion
136-
137-
public class GeneratorTest
138-
{
139-
VerifyHelper verifier = new VerifyHelper("TEG");
140-
1416
[Test]
1427
public async Task TabularArrayGenerator()
1438
{

tests/ToonEncoder.Tests/ToonEncoder.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
</PropertyGroup>
99

1010
<ItemGroup>
11+
<PackageReference Include="Basic.Reference.Assemblies.Net100" Version="1.8.4" />
1112
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="5.0.0" />
1213
<PackageReference Include="TUnit" Version="1.6.25" />
1314
</ItemGroup>

0 commit comments

Comments
 (0)