Skip to content

Commit

Permalink
Initial source generator working
Browse files Browse the repository at this point in the history
  • Loading branch information
aritchie committed Jun 7, 2024
1 parent fa8e91b commit 4299b16
Show file tree
Hide file tree
Showing 9 changed files with 58 additions and 36 deletions.
4 changes: 1 addition & 3 deletions Sample/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ public static MauiApp CreateMauiApp()
.UseMaui()
.UseBlazor()
);
builder.Services.AddSingletonAsImplementedInterfaces<SingletonEventHandler>();
builder.Services.AddSingletonAsImplementedInterfaces<SingletonRequestHandler>();
builder.Services.AddSingletonAsImplementedInterfaces<MyRequestMiddleware>();
builder.Services.AddDiscoveredMediatorHandlersFromSample();

builder.Services.AddSingleton<AppSqliteConnection>();
builder.Services.AddMauiBlazorWebView();
Expand Down
2 changes: 1 addition & 1 deletion Sample/MyRequestMiddleware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
namespace Sample;


// [RegisterMiddleware]
[RegisterMiddleware]
public class MyRequestMiddleware(AppSqliteConnection conn) : IRequestMiddleware<MyMessageRequest, MyMessageResponse>
{
public async Task<MyMessageResponse> Process(MyMessageRequest request, RequestHandlerDelegate<MyMessageResponse> next, IRequestHandler<MyMessageRequest, MyMessageResponse> requestHandler, CancellationToken cancellationToken)
Expand Down
4 changes: 3 additions & 1 deletion Sample/Sample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@
<ProjectReference Include="..\src\Shiny.Mediator.Blazor\Shiny.Mediator.Blazor.csproj" />
<ProjectReference Include="..\src\Shiny.Mediator.Contracts\Shiny.Mediator.Contracts.csproj"/>
<ProjectReference Include="..\src\Shiny.Mediator.Maui\Shiny.Mediator.Maui.csproj"/>
<ProjectReference Include="..\src\Shiny.Mediator.SourceGenerators\Shiny.Mediator.SourceGenerators.csproj"/>
<ProjectReference Include="..\src\Shiny.Mediator\Shiny.Mediator.csproj"/>
<ProjectReference Include="..\src\Shiny.Mediator.SourceGenerators\Shiny.Mediator.SourceGenerators.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
</ItemGroup>
</Project>
1 change: 1 addition & 0 deletions Sample/SingletonEventHandler.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace Sample;


[RegisterHandler]
public class SingletonEventHandler(IMediator mediator, AppSqliteConnection data) : IEventHandler<MyMessageEvent>
{
public async Task Handle(MyMessageEvent @event, CancellationToken cancellationToken)
Expand Down
2 changes: 1 addition & 1 deletion Sample/SingletonRequestHandler.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
namespace Sample;


// [RegisterHandler]
[RegisterHandler]
public class SingletonRequestHandler(IMediator mediator, AppSqliteConnection data) : IRequestHandler<MyMessageRequest, MyMessageResponse>
{
public async Task<MyMessageResponse> Handle(MyMessageRequest request, CancellationToken cancellationToken)
Expand Down
13 changes: 13 additions & 0 deletions src/Shiny.Mediator.SourceGenerators/Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Microsoft.CodeAnalysis;

namespace Shiny.Mediator.SourceGenerators;


static class Extensions
{
public static string? GetMSBuildProperty(this GeneratorExecutionContext context, string propertyName)
{
context.AnalyzerConfigOptions.GlobalOptions.TryGetValue($"build_property.{propertyName}", out var value);
return value;
}
}
39 changes: 23 additions & 16 deletions src/Shiny.Mediator.SourceGenerators/MediatorSourceGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Text;
using System;
using System.Linq;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Text;
using SourceGeneratorsKit;
Expand Down Expand Up @@ -26,14 +28,14 @@ public void Initialize(GeneratorInitializationContext context)
#nullable disable
[System.AttributeUsage(System.AttributeTargets.Class, AllowMultiple = false)]
internal sealed class RegisterHandlerAttribute: System.Attribute
public sealed class RegisterHandlerAttribute: System.Attribute
{
public RegisterHandlerAttribute(bool IsSingleton = true) {}
public RegisterHandlerAttribute() {}
}
internal sealed class RegisterMiddlewareAttribute: System.Attribute
public sealed class RegisterMiddlewareAttribute: System.Attribute
{
public RegisterMiddlewareAttribute(bool IsSingleton = true) {}
public RegisterMiddlewareAttribute() {}
}
""",
Encoding.UTF8
Expand All @@ -48,26 +50,31 @@ public void Execute(GeneratorExecutionContext context)
if (!(context.SyntaxContextReceiver is SyntaxReceiver))
return;

// TODO: detect double registration of request handlers
// TODO: I need the namespace to be the global namespace
// TODO: detect double registration of request handlers?
// TODO: scopes
// TODO: open middleware
// TODO: this will be registered with multiple AddDiscoveredMediatorHandlers in the main app


var nameSpace = context.GetMSBuildProperty("RootNamespace") ?? context.Compilation.AssemblyName;
var assName = context.Compilation.AssemblyName?.Replace(".", "_");

var sb = new StringBuilder();
sb
.AppendLine("namespace Shiny.Mediator;")
.AppendLine($"namespace {nameSpace};")
.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()}>();");
.AppendLine($"\tpublic static global::Microsoft.Extensions.DependencyInjection.IServiceCollection AddDiscoveredMediatorHandlersFrom{assName}(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services)")
.AppendLine("\t{");

var classes = this.syntaxReceiver.Classes.Select(x => x.ToDisplayString()).Distinct();
foreach (var cls in classes)
sb.AppendLine($"\t\tservices.AddSingletonAsImplementedInterfaces<{cls}>();");

sb
.AppendLine("\treturn services;")
.AppendLine("\t\treturn services;")
.AppendLine("\t}")
.AppendLine("}");

context.AddSource("__MediatorHandlersRegistration.g.cs", SourceText.From(sb.ToString()));
context.AddSource("__MediatorHandlersRegistration.g.cs", SourceText.From(sb.ToString(), Encoding.UTF8));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,20 @@ protected override bool ShouldCollectClassSymbol(INamedTypeSymbol classSymbol)
{
var hasAttribute = classSymbol.HasAttribute("RegisterHandlerAttribute");
if (hasAttribute)
{
// TODO: log error
if (classSymbol.IsImplements("Shiny.Mediator.IEventHandler`1"))
return false;

if (classSymbol.IsImplements("Shiny.Mediator.IRequestHandler`1"))
return false;
}
hasAttribute = classSymbol.HasAttribute("RegisterMiddleware");
return true;
// if (hasAttribute)
// {
// // TODO: log error
// if (classSymbol.IsImplements("Shiny.Mediator.IEventHandler`1"))
// return false;
//
// if (classSymbol.IsImplements("Shiny.Mediator.IRequestHandler`1"))
// return false;
// }
hasAttribute = classSymbol.HasAttribute("RegisterMiddlewareAttribute");
if (hasAttribute)
{
return true;
}

return false;
}
}
6 changes: 3 additions & 3 deletions src/Shiny.Mediator/Shiny.Mediator.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

<ItemGroup>
<ProjectReference Include="..\Shiny.Mediator.Contracts\Shiny.Mediator.Contracts.csproj" />
<ProjectReference Include="..\Shiny.Mediator.SourceGenerators\Shiny.Mediator.SourceGenerators.csproj"
OutputItemType="Analyzer"
ReferenceOutputAssembly="false" />
<!-- <ProjectReference Include="..\Shiny.Mediator.SourceGenerators\Shiny.Mediator.SourceGenerators.csproj"-->
<!-- OutputItemType="Analyzer"-->
<!-- ReferenceOutputAssembly="false" />-->
</ItemGroup>

<ItemGroup>
Expand Down

0 comments on commit 4299b16

Please sign in to comment.