From 2006a235fdaa04aaee470ea6d5cdf7aa620ccc6e Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Thu, 30 May 2024 23:55:14 -0400 Subject: [PATCH] Starting on source generator --- .../MediatorSourceGenerator.cs | 45 ++++++++++++++----- .../RegisterHandlerAttributeSyntaxReceiver.cs | 25 +++++++++++ 2 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 src/Shiny.Mediator.SourceGenerators/RegisterHandlerAttributeSyntaxReceiver.cs diff --git a/src/Shiny.Mediator.SourceGenerators/MediatorSourceGenerator.cs b/src/Shiny.Mediator.SourceGenerators/MediatorSourceGenerator.cs index 8b77844..05ce5fa 100644 --- a/src/Shiny.Mediator.SourceGenerators/MediatorSourceGenerator.cs +++ b/src/Shiny.Mediator.SourceGenerators/MediatorSourceGenerator.cs @@ -1,4 +1,7 @@ -using Microsoft.CodeAnalysis; +using System.Text; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Text; +using SourceGeneratorsKit; namespace Shiny.Mediator.SourceGenerators; @@ -6,22 +9,44 @@ namespace Shiny.Mediator.SourceGenerators; [Generator] public class MediatorSourceGenerator : ISourceGenerator { + readonly SyntaxReceiver syntaxReceiver = new RegisterHandlerAttributeSyntaxReceiver(); // SyntaxReceiver syntaxReceiver = new ClassesWithInterfacesReceiver("IEnumerable"); + public void Initialize(GeneratorInitializationContext context) { - // context.RegisterForSyntaxNotifications(() => syntaxReceiver); + context.RegisterForPostInitialization(x => x.AddSource("RegisterHandlerAttribute.g.cs", SourceText.From( + """ + namespace Shiny.Mediator; + + [System.AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)] + public class RegisterHandlerAttribute : System.Attribute {} + """ + ))); + context.RegisterForSyntaxNotifications(() => syntaxReceiver); } public void Execute(GeneratorExecutionContext context) { - // if (!(context.SyntaxContextReceiver is SyntaxReceiver receiver)) - // { - // return; - // } - // foreach (INamedTypeSymbol classSymbol in this.syntaxReceiver.Classes) - // { - // // process your class here. - // } + if (!(context.SyntaxContextReceiver is SyntaxReceiver receiver)) + return; + + var sb = new StringBuilder(); + sb + .AppendLine("namespace Shiny.Mediator;") + .AppendLine() + .AppendLine("public static class __ShinyMediatorSourceGenExtensions {") + .AppendLine( + "\tpublic static global::Microsoft.Extensions.DependencyInjection.IServiceCollection AddDiscoveredMediatorHandlers(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services) {"); + + foreach (var classSymbol in this.syntaxReceiver.Classes) + sb.AppendLine($"\t\tservices.AddSingletonAsImplementedInterfaces<{classSymbol.ToDisplayString()}>();"); + + sb + .AppendLine("\treturn services;") + .AppendLine("\t}") + .AppendLine("}"); + + context.AddSource("__MediatorHandlersRegistration.g.cs", SourceText.From(sb.ToString())); } } \ No newline at end of file diff --git a/src/Shiny.Mediator.SourceGenerators/RegisterHandlerAttributeSyntaxReceiver.cs b/src/Shiny.Mediator.SourceGenerators/RegisterHandlerAttributeSyntaxReceiver.cs new file mode 100644 index 0000000..81abb8b --- /dev/null +++ b/src/Shiny.Mediator.SourceGenerators/RegisterHandlerAttributeSyntaxReceiver.cs @@ -0,0 +1,25 @@ +using Microsoft.CodeAnalysis; +using SourceGeneratorsKit; + +namespace Shiny.Mediator.SourceGenerators; + + +public class RegisterHandlerAttributeSyntaxReceiver : SyntaxReceiver +{ + public override bool CollectClassSymbol => true; + + protected override bool ShouldCollectClassSymbol(INamedTypeSymbol classSymbol) + { + var hasAttribute = classSymbol.HasAttribute("RegisterHandlerAttribute"); + if (!hasAttribute) + return false; + + if (classSymbol.IsImplements("Shiny.Mediator.IEventHandler`1")) + return false; + + if (classSymbol.IsImplements("Shiny.Mediator.IRequestHandler`1")) + return false; + + return false; + } +} \ No newline at end of file