-
Notifications
You must be signed in to change notification settings - Fork 68
Expand file tree
/
Copy pathAutoToStringGenerator.cs
More file actions
91 lines (77 loc) · 3.01 KB
/
AutoToStringGenerator.cs
File metadata and controls
91 lines (77 loc) · 3.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace CodeGen
{
[Generator]
public class AutoToStringGenerator : ISourceGenerator
{
public void Execute(GeneratorExecutionContext context)
{
var syntaxReceiver = (AutoToStringSyntaxReciever)context.SyntaxReceiver;
var userClass = syntaxReceiver.IdentifiedClass;
if (userClass is null)
{
return;
}
var properties = userClass.DescendantNodes().OfType<PropertyDeclarationSyntax>();
var code = GetSource(userClass.Identifier.Text, properties);
context.AddSource(
$"{userClass.Identifier.Text}.generated",
SourceText.From(code, Encoding.UTF8)
);
}
private string GetSource(string className,IEnumerable<PropertyDeclarationSyntax> properties)
{
var toStringContend = string.Join(",", properties.Select(x => $"{x.Identifier.Text}={{{x.Identifier.Text}}}"));
var code = $@"
namespace Client {{
public partial class {className}
{{
public string ToString()=>$""{toStringContend}"";
}}
}}";
return code;
}
public void Initialize(GeneratorInitializationContext context)
{
context.RegisterForSyntaxNotifications(() => new AutoToStringSyntaxReciever());
}
private class AutoToStringSyntaxReciever : ISyntaxReceiver
{
public ClassDeclarationSyntax IdentifiedClass { get; private set; }
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
{
if (syntaxNode is ClassDeclarationSyntax classDeclaration)
{
var attributes = classDeclaration.DescendantNodes().OfType<AttributeSyntax>();
if (attributes.Any())
{
var autoToStringAttribute = attributes.FirstOrDefault(x => ExtractName(x.Name) == "AutoToString");
if (autoToStringAttribute != null) IdentifiedClass = classDeclaration;
}
}
}
private static string ExtractName(TypeSyntax type)
{
while (type != null)
{
switch (type)
{
case IdentifierNameSyntax ins:
return ins.Identifier.Text;
case QualifiedNameSyntax qns:
type = qns.Right;
break;
default:
return null;
}
}
return null;
}
}
}
}