Skip to content

Commit

Permalink
feat: useForAttributeWithMetadataName instead of `CreateSyntaxProvi…
Browse files Browse the repository at this point in the history
…der` (#327)
  • Loading branch information
TimothyMakkison committed Apr 14, 2023
1 parent 36830e8 commit 3b9c2f9
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 31 deletions.
35 changes: 4 additions & 31 deletions src/Riok.Mapperly/MapperGenerator.cs
Expand Up @@ -14,43 +14,17 @@ namespace Riok.Mapperly;
public class MapperGenerator : IIncrementalGenerator
{
private const string GeneratedFileSuffix = ".g.cs";
private static readonly string _mapperAttributeName = typeof(MapperAttribute).FullName;

public static readonly string MapperAttributeName = typeof(MapperAttribute).FullName;

public void Initialize(IncrementalGeneratorInitializationContext context)
{
var mapperClassDeclarations = context.SyntaxProvider
.CreateSyntaxProvider(
static (s, _) => IsSyntaxTargetForGeneration(s),
static (ctx, _) => GetSemanticTargetForGeneration(ctx))
.WhereNotNull();
var mapperClassDeclarations = SyntaxProvider.GetClassDeclarations(context);

var compilationAndMappers = context.CompilationProvider.Combine(mapperClassDeclarations.Collect());
context.RegisterImplementationSourceOutput(compilationAndMappers, static (spc, source) => Execute(source.Left, source.Right, spc));
}

private static bool IsSyntaxTargetForGeneration(SyntaxNode node)
=> node is ClassDeclarationSyntax { AttributeLists.Count: > 0 };

private static ClassDeclarationSyntax? GetSemanticTargetForGeneration(GeneratorSyntaxContext ctx)
{
var classDeclaration = (ClassDeclarationSyntax)ctx.Node;
foreach (var attributeListSyntax in classDeclaration.AttributeLists)
{
foreach (var attributeSyntax in attributeListSyntax.Attributes)
{
if (ctx.SemanticModel.GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol)
continue;

var attributeContainingTypeSymbol = attributeSymbol.ContainingType;
var fullName = attributeContainingTypeSymbol.ToDisplayString();
if (fullName == _mapperAttributeName)
return classDeclaration;
}
}

return null;
}

private static void Execute(Compilation compilation, ImmutableArray<ClassDeclarationSyntax> mappers, SourceProductionContext ctx)
{
if (mappers.IsDefaultOrEmpty)
Expand All @@ -59,8 +33,7 @@ private static void Execute(Compilation compilation, ImmutableArray<ClassDeclara
#if DEBUG_SOURCE_GENERATOR
DebuggerUtil.AttachDebugger();
#endif

var mapperAttributeSymbol = compilation.GetTypeByMetadataName(_mapperAttributeName);
var mapperAttributeSymbol = compilation.GetTypeByMetadataName(MapperAttributeName);
if (mapperAttributeSymbol == null)
return;

Expand Down
43 changes: 43 additions & 0 deletions src/Riok.Mapperly/SyntaxProvider.Roslyn4.0.cs
@@ -0,0 +1,43 @@
#if !ROSLYN4_4_OR_GREATER

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Riok.Mapperly.Helpers;

namespace Riok.Mapperly;

internal static class SyntaxProvider
{
public static IncrementalValuesProvider<ClassDeclarationSyntax> GetClassDeclarations(IncrementalGeneratorInitializationContext context)
{
return context.SyntaxProvider
.CreateSyntaxProvider(
static (s, _) => IsSyntaxTargetForGeneration(s),
static (ctx, _) => GetSemanticTargetForGeneration(ctx))
.WhereNotNull();
}

private static bool IsSyntaxTargetForGeneration(SyntaxNode node)
=> node is ClassDeclarationSyntax { AttributeLists.Count: > 0 };

private static ClassDeclarationSyntax? GetSemanticTargetForGeneration(GeneratorSyntaxContext ctx)
{
var classDeclaration = (ClassDeclarationSyntax)ctx.Node;
foreach (var attributeListSyntax in classDeclaration.AttributeLists)
{
foreach (var attributeSyntax in attributeListSyntax.Attributes)
{
if (ctx.SemanticModel.GetSymbolInfo(attributeSyntax).Symbol is not IMethodSymbol attributeSymbol)
continue;

var attributeContainingTypeSymbol = attributeSymbol.ContainingType;
var fullName = attributeContainingTypeSymbol.ToDisplayString();
if (fullName == MapperGenerator.MapperAttributeName)
return classDeclaration;
}
}

return null;
}
}
#endif
22 changes: 22 additions & 0 deletions src/Riok.Mapperly/SyntaxProvider.Roslyn4.4.cs
@@ -0,0 +1,22 @@
#if ROSLYN4_4_OR_GREATER

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Riok.Mapperly.Helpers;

namespace Riok.Mapperly;

internal static class SyntaxProvider
{

public static IncrementalValuesProvider<ClassDeclarationSyntax> GetClassDeclarations(IncrementalGeneratorInitializationContext context)
{
return context.SyntaxProvider
.ForAttributeWithMetadataName(MapperGenerator.MapperAttributeName,
static (s, _) => s is ClassDeclarationSyntax,
static (ctx, _) => ctx.TargetNode as ClassDeclarationSyntax)
.WhereNotNull();
}

}
#endif

0 comments on commit 3b9c2f9

Please sign in to comment.