Skip to content

Commit 5a1b2e9

Browse files
committed
writer writer
1 parent b188553 commit 5a1b2e9

File tree

4 files changed

+178
-20
lines changed

4 files changed

+178
-20
lines changed

sandbox/GeneratorSandbox/Program.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
app.Add<Test>();
1111
app.Run(args);
1212

13+
14+
15+
16+
1317
public class Test
1418
{
1519
public void Show(string aaa, [Range(0, 1)] double value) => ConsoleApp.Log($"{value}");

src/ConsoleAppFramework/ConsoleAppGenerator.cs

Lines changed: 102 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,88 @@
11
using Microsoft.CodeAnalysis;
22
using Microsoft.CodeAnalysis.CSharp;
33
using Microsoft.CodeAnalysis.CSharp.Syntax;
4+
using System.Collections.Concurrent;
45
using System.Collections.Immutable;
56
using System.Reflection;
7+
using System.Text;
68
using static ConsoleAppFramework.Emitter;
79

810
namespace ConsoleAppFramework;
911

12+
13+
public static class StringWriterPool
14+
{
15+
static readonly ConcurrentQueue<StringWriter> pool = new();
16+
17+
public static StringWriter Rent()
18+
{
19+
if (!pool.TryDequeue(out var writer))
20+
{
21+
writer = new StringWriter();
22+
}
23+
return writer;
24+
}
25+
26+
public static void Return(StringWriter writer)
27+
{
28+
writer.GetStringBuilder().Clear();
29+
pool.Enqueue(writer);
30+
}
31+
}
32+
33+
34+
public class SyntaxNodeTextEqualityComparer : IEqualityComparer<SyntaxNode>
35+
{
36+
37+
38+
public bool Equals(SyntaxNode x, SyntaxNode y)
39+
{
40+
41+
42+
43+
throw new NotImplementedException();
44+
}
45+
46+
public int GetHashCode(SyntaxNode obj)
47+
{
48+
throw new NotImplementedException();
49+
}
50+
}
51+
52+
53+
public class RunNode(InvocationExpressionSyntax node, SemanticModel model) : IEquatable<RunNode>
54+
{
55+
public InvocationExpressionSyntax Node => node;
56+
public SemanticModel SemanticModel => model;
57+
58+
public bool Equals(RunNode other)
59+
{
60+
//var eq = this.Node.Equals(other.Node);
61+
62+
var left = StringWriterPool.Rent();
63+
64+
var txt = other.Node.GetText();
65+
66+
// other.Node.WriteTo
67+
68+
// new StringBuilder().Equals();
69+
// StringWriter sw = new StringWriter();
70+
71+
other.Node.WriteTo(sw);
72+
var txt = other.Node.Expression.GetText();
73+
74+
75+
return true;
76+
// return eq;
77+
}
78+
79+
public override int GetHashCode()
80+
{
81+
var hash = node.GetHashCode();
82+
return hash;
83+
}
84+
}
85+
1086
[Generator(LanguageNames.CSharp)]
1187
public partial class ConsoleAppGenerator : IIncrementalGenerator
1288
{
@@ -15,28 +91,30 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
1591
context.RegisterPostInitializationOutput(EmitConsoleAppTemplateSource);
1692

1793
// ConsoleApp.Run
18-
var runSource = context.SyntaxProvider.CreateSyntaxProvider((node, ct) =>
19-
{
20-
if (node.IsKind(SyntaxKind.InvocationExpression))
94+
var runSource = context.SyntaxProvider
95+
.CreateSyntaxProvider((node, ct) =>
2196
{
22-
var invocationExpression = (node as InvocationExpressionSyntax);
23-
if (invocationExpression == null) return false;
24-
25-
var expr = invocationExpression.Expression as MemberAccessExpressionSyntax;
26-
if ((expr?.Expression as IdentifierNameSyntax)?.Identifier.Text == "ConsoleApp")
97+
if (node.IsKind(SyntaxKind.InvocationExpression))
2798
{
28-
var methodName = expr?.Name.Identifier.Text;
29-
if (methodName is "Run" or "RunAsync")
99+
var invocationExpression = (node as InvocationExpressionSyntax);
100+
if (invocationExpression == null) return false;
101+
102+
var expr = invocationExpression.Expression as MemberAccessExpressionSyntax;
103+
if ((expr?.Expression as IdentifierNameSyntax)?.Identifier.Text == "ConsoleApp")
30104
{
31-
return true;
105+
var methodName = expr?.Name.Identifier.Text;
106+
if (methodName is "Run" or "RunAsync")
107+
{
108+
return true;
109+
}
32110
}
111+
112+
return false;
33113
}
34114

35115
return false;
36-
}
37-
38-
return false;
39-
}, (context, ct) => ((InvocationExpressionSyntax)context.Node, context.SemanticModel));
116+
}, (context, ct) => new RunNode((InvocationExpressionSyntax)context.Node, context.SemanticModel))
117+
.WithTrackingName("ConsoleApp.Run.CreateSyntaxProvider");
40118

41119
context.RegisterSourceOutput(runSource, EmitConsoleAppRun);
42120

@@ -64,13 +142,17 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
64142
(InvocationExpressionSyntax)context.Node,
65143
((context.Node as InvocationExpressionSyntax)!.Expression as MemberAccessExpressionSyntax)!.Name.Identifier.Text,
66144
context.SemanticModel))
145+
.WithTrackingName("ConsoleApp.Builder.CreateSyntaxProvider")
67146
.Where(x =>
68147
{
69148
var model = x.SemanticModel.GetTypeInfo((x.Item1.Expression as MemberAccessExpressionSyntax)!.Expression);
70149
return model.Type?.Name == "ConsoleAppBuilder";
71-
});
150+
})
151+
.WithTrackingName("ConsoleApp.Builder.Where")
152+
.Collect()
153+
.WithTrackingName("ConsoleApp.Builder.Collect");
72154

73-
context.RegisterSourceOutput(builderSource.Collect(), EmitConsoleAppBuilder);
155+
context.RegisterSourceOutput(builderSource, EmitConsoleAppBuilder);
74156
}
75157

76158
public const string ConsoleAppBaseCode = """
@@ -553,10 +635,10 @@ namespace ConsoleAppFramework;
553635
554636
""";
555637

556-
static void EmitConsoleAppRun(SourceProductionContext sourceProductionContext, (InvocationExpressionSyntax, SemanticModel) generatorSyntaxContext)
638+
static void EmitConsoleAppRun(SourceProductionContext sourceProductionContext, RunNode runNode)
557639
{
558-
var node = generatorSyntaxContext.Item1;
559-
var model = generatorSyntaxContext.Item2;
640+
var node = runNode.Node;
641+
var model = runNode.SemanticModel;
560642

561643
var wellKnownTypes = new WellKnownTypes(model.Compilation);
562644

tests/ConsoleAppFramework.GeneratorTests/CSharpGeneratorRunner.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,39 @@ public static (Compilation, ImmutableArray<Diagnostic>, string) CompileAndExecut
8787
{
8888
Console.SetOut(originalOut);
8989
}
90+
}
91+
92+
public static void CheckIncrementalGenerator(params string[] sources)
93+
{
94+
var parseOptions = new CSharpParseOptions(LanguageVersion.CSharp12); // 12
95+
var driver = CSharpGeneratorDriver.Create(
96+
[new ConsoleAppGenerator().AsSourceGenerator()],
97+
driverOptions: new GeneratorDriverOptions(IncrementalGeneratorOutputKind.None, trackIncrementalGeneratorSteps: true))
98+
.WithUpdatedParseOptions(parseOptions);
99+
100+
var generatorResults = sources
101+
.Select(source =>
102+
{
103+
var compilation = baseCompilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(source, parseOptions));
104+
driver = driver.RunGenerators(compilation);
105+
return driver.GetRunResult().Results[0];
106+
})
107+
.ToArray();
108+
109+
var reasons = generatorResults
110+
.Select(x => x.TrackedSteps
111+
.Where(x => x.Key.StartsWith("ConsoleApp"))
112+
.Select(x => new
113+
{
114+
x.Key,
115+
Reasons = string.Join(", ", x.Value.SelectMany(x => x.Outputs).Select(x => x.Reason).ToArray())
116+
})
117+
.ToArray())
118+
.ToArray();
119+
120+
121+
122+
90123
}
91124
}
92125

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
using Microsoft.CodeAnalysis;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
8+
namespace ConsoleAppFramework.GeneratorTests;
9+
10+
public class IncrementalGeneratorTest
11+
{
12+
[Fact]
13+
public void CheckIncrementalStep()
14+
{
15+
var step1 = """
16+
using ConsoleAppFramework;
17+
18+
ConsoleApp.Run(args, () => { });
19+
""";
20+
21+
var step2 = """
22+
using ConsoleAppFramework;
23+
24+
ConsoleApp.Run(args, () => { });
25+
26+
Console.WriteLine("foo"); // unrelated line
27+
""";
28+
29+
var step3 = """
30+
using ConsoleAppFramework;
31+
32+
ConsoleApp.Run(args, (int x, int y) => { }); // change signature
33+
34+
Console.WriteLine("foo"); // unrelated line
35+
""";
36+
37+
CSharpGeneratorRunner.CheckIncrementalGenerator(step1, step2, step3);
38+
}
39+
}

0 commit comments

Comments
 (0)