Skip to content

Commit 4d90040

Browse files
committed
Refactor FilterGenerator to use IIncrementalGenerator instead of deprecated ISourceGenerator
This also gets rid of unused code
1 parent 39c7454 commit 4d90040

4 files changed

Lines changed: 60 additions & 97 deletions

File tree

src/AutoFilterer.Generators/AttributeSyntaxReceiver.cs

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/AutoFilterer.Generators/FilterGenerator.cs

Lines changed: 58 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,74 +2,85 @@
22
using Microsoft.CodeAnalysis.Text;
33
using System;
44
using System.Collections.Generic;
5+
using System.Collections.Immutable;
56
using System.Linq;
67
using System.Text;
7-
using System.Threading.Tasks;
88
using Microsoft.CodeAnalysis.CSharp.Syntax;
9-
using DotNurse.CodeAnalysis;
10-
using AutoFilterer.Generators.Extensions;
119
using Microsoft.CodeAnalysis.CSharp;
12-
using System.Diagnostics;
1310

1411
namespace AutoFilterer.Generators;
1512

13+
using Extensions;
14+
1615
[Generator]
17-
public class FilterGenerator : ISourceGenerator
16+
public class FilterGenerator : IIncrementalGenerator
1817
{
19-
public void Initialize(GeneratorInitializationContext context)
18+
public void Initialize(IncrementalGeneratorInitializationContext context)
2019
{
21-
context.RegisterForSyntaxNotifications(() => new AttributeSyntaxReceiver<GenerateAutoFilterAttribute>());
20+
var classDeclarations = context.SyntaxProvider
21+
.CreateSyntaxProvider(
22+
predicate: static (s, _) => s is ClassDeclarationSyntax { AttributeLists.Count: > 0 },
23+
transform: static (ctx, _) => GetSemanticTargetForGeneration(ctx))
24+
.Where(static m => m is not null);
25+
26+
var compilationAndClasses = context.CompilationProvider.Combine(classDeclarations.Collect());
27+
28+
context.RegisterSourceOutput(compilationAndClasses, (spc, source) => Execute(source.Left, source.Right, spc));
2229
}
2330

24-
public void Execute(GeneratorExecutionContext context)
31+
private static ClassDeclarationSyntax GetSemanticTargetForGeneration(GeneratorSyntaxContext context)
2532
{
26-
if (!(context.SyntaxReceiver is AttributeSyntaxReceiver<GenerateAutoFilterAttribute> receiver))
27-
return;
33+
var classDeclaration = (ClassDeclarationSyntax)context.Node;
2834

29-
//if (!Debugger.IsAttached)
30-
//{
31-
// Debugger.Launch();
32-
//}
33-
34-
foreach (var classSyntax in receiver.Classes)
35+
foreach (var attributeList in classDeclaration.AttributeLists)
3536
{
36-
var attribute = classSyntax.AttributeLists.SelectMany(sm => sm.Attributes).FirstOrDefault(x => x.Name.ToString().EnsureEndsWith("Attribute").Equals(typeof(GenerateAutoFilterAttribute).Name));
37-
var namespaceParam = attribute.ArgumentList?.Arguments.FirstOrDefault(); // Temprorary... Attribute has only one argument for now.
38-
39-
var model = context.Compilation.GetSemanticModel(classSyntax.SyntaxTree);
40-
var symbol = model.GetDeclaredSymbol(classSyntax);
41-
var attrs = symbol.GetAttributes();
42-
43-
var realNamespace = GetNamespaceRecursively(symbol.ContainingNamespace);
37+
foreach (var attribute in attributeList.Attributes)
38+
{
39+
var symbolInfo = context.SemanticModel.GetSymbolInfo(attribute);
40+
var attributeSymbol = symbolInfo.Symbol as IMethodSymbol;
4441

45-
var properties = symbol.GetMembers().OfType<IPropertySymbol>()
46-
.Where(x => !x.IsStatic && !x.ContainingType.IsGenericType && x.Kind == SymbolKind.Property);
42+
var fullName = attributeSymbol?.ContainingType.ToDisplayString()
43+
?? attribute.Name.ToString();
4744

48-
context.AddSource($"{symbol.Name}FilterDto.g.cs",
49-
SourceText.From(GetFilterDtoCode(symbol.Name, properties, namespaceParam?.ToString().Trim('\"') ?? realNamespace), Encoding.UTF8));
45+
if (fullName.EnsureEndsWith("Attribute").EndsWith(nameof(GenerateAutoFilterAttribute)))
46+
{
47+
return classDeclaration;
48+
}
49+
}
5050
}
51+
52+
return null;
5153
}
5254

53-
private static Dictionary<INamedTypeSymbol, IList<AttributeData>> GetClassAttributePairs(GeneratorExecutionContext context,
54-
SyntaxReceiver receiver)
55+
private static void Execute(Compilation compilation, ImmutableArray<ClassDeclarationSyntax> classes, SourceProductionContext context)
5556
{
56-
var compilation = context.Compilation;
57-
var classSymbols = new Dictionary<INamedTypeSymbol, IList<AttributeData>>();
58-
foreach (var clazz in receiver.CandidateClasses)
57+
if (classes.IsDefaultOrEmpty) {
58+
return;
59+
}
60+
61+
foreach (var classSyntax in classes)
5962
{
60-
var model = compilation.GetSemanticModel(clazz.SyntaxTree);
61-
var classSymbol = model.GetDeclaredSymbol(clazz);
62-
var attributes = classSymbol.GetAttributes();
63-
if (attributes.Any(ad => ad.AttributeClass.Name == nameof(GenerateAutoFilterAttribute)))
63+
var model = compilation.GetSemanticModel(classSyntax.SyntaxTree);
64+
if (model.GetDeclaredSymbol(classSyntax) is not { } symbol)
6465
{
65-
classSymbols.Add((INamedTypeSymbol)classSymbol, attributes.ToList());
66+
continue;
6667
}
67-
}
6868

69-
return classSymbols;
69+
var attribute = symbol.GetAttributes()
70+
.FirstOrDefault(a => a.AttributeClass?.Name == nameof(GenerateAutoFilterAttribute));
71+
var namespaceParam = attribute?.ConstructorArguments.FirstOrDefault().Value?.ToString().Trim('\"'); // Temprorary... Attribute has only one argument for now.
72+
var realNamespace = GetNamespaceRecursively(symbol.ContainingNamespace);
73+
74+
var properties = symbol.GetMembers().OfType<IPropertySymbol>()
75+
.Where(x => !x.IsStatic && !x.ContainingType.IsGenericType && x.Kind == SymbolKind.Property);
76+
77+
var sourceCode = GetFilterDtoCode(symbol.Name, properties, namespaceParam ?? realNamespace);
78+
79+
context.AddSource($"{symbol.Name}FilterDto.g.cs", SourceText.From(sourceCode, Encoding.UTF8));
80+
}
7081
}
7182

72-
internal string GetFilterDtoCode(string className, IEnumerable<IPropertySymbol> properties,
83+
private static string GetFilterDtoCode(string className, IEnumerable<IPropertySymbol> properties,
7384
string @namespace = null)
7485
{
7586
var start = $@"
@@ -88,10 +99,11 @@ public partial class {className}Filter : PaginationFilterBase
8899

89100
foreach (var property in properties)
90101
{
91-
string propertyType = property.Type.ToDisplayString(NullableFlowState.None);
102+
var propertyType = property.Type.ToDisplayString(NullableFlowState.None);
92103

93-
if (TypeMapping.Mappings.TryGetValue(propertyType, out var mapped))
104+
if (TypeMapping.Mappings.TryGetValue(propertyType, out var mapped)) {
94105
propertyType = mapped;
106+
}
95107

96108
if (propertyType.Equals(nameof(String), StringComparison.InvariantCultureIgnoreCase))
97109
{
@@ -100,13 +112,10 @@ public partial class {className}Filter : PaginationFilterBase
100112
body.AppendLine($"\t\tpublic virtual {propertyType} {property.Name} {{ get; set; }}");
101113
}
102114

103-
var end = "\t}\n}";
104-
105-
106-
return start + body.ToString() + end;
115+
return start + body + "\t}\n}";
107116
}
108117

109-
private string GetNamespaceRecursively(INamespaceSymbol symbol)
118+
private static string GetNamespaceRecursively(INamespaceSymbol symbol)
110119
{
111120
if (symbol.ContainingNamespace == null)
112121
{
@@ -115,4 +124,4 @@ private string GetNamespaceRecursively(INamespaceSymbol symbol)
115124

116125
return (GetNamespaceRecursively(symbol.ContainingNamespace) + "." + symbol.Name).Trim('.');
117126
}
118-
}
127+
}

src/AutoFilterer.Generators/GenerateAutoFilterAttribute.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ public GenerateAutoFilterAttribute()
99

1010
public GenerateAutoFilterAttribute(string @namespace)
1111
{
12-
Namespace = @Namespace;
12+
Namespace = @namespace;
1313
}
1414

1515
public string Namespace { get; }
16-
}
16+
}

src/AutoFilterer.Generators/SyntaxReceiver.cs

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)