diff --git a/Net.Sdk.Web.Extensions.Azure/Net.Sdk.Web.Extensions.Azure.csproj b/Net.Sdk.Web.Extensions.Azure/Net.Sdk.Web.Extensions.Azure.csproj
index 3145016..0c5b07a 100644
--- a/Net.Sdk.Web.Extensions.Azure/Net.Sdk.Web.Extensions.Azure.csproj
+++ b/Net.Sdk.Web.Extensions.Azure/Net.Sdk.Web.Extensions.Azure.csproj
@@ -6,7 +6,7 @@
enable
Library
true
- 0.8
+ 0.8.1
Alexandru Macocian
LICENSE
true
diff --git a/Net.Sdk.Web.Extensions.SourceGenerators/Constants.cs b/Net.Sdk.Web.Extensions.SourceGenerators/Constants.cs
index da6d409..1678dda 100644
--- a/Net.Sdk.Web.Extensions.SourceGenerators/Constants.cs
+++ b/Net.Sdk.Web.Extensions.SourceGenerators/Constants.cs
@@ -71,5 +71,8 @@ public static class Constants
public const string EndpointRouteBuilderExtensionsName = "EndpointRouteBuilderExtensions";
public const string IEndpointRouteBuilderTypeName = "IEndpointRouteBuilder";
+ public const string WebApplicationBuilderExtensionsName = "WebApplicationBuilderExtension";
+ public const string WebApplicationBuilderTypeName = "WebApplicationBuilder";
+ public const string WithRoutesName = "WithRoutes";
public const string BuilderParameterName = "builder";
}
diff --git a/Net.Sdk.Web.Extensions.SourceGenerators/Net.Sdk.Web.Extensions.SourceGenerators.csproj b/Net.Sdk.Web.Extensions.SourceGenerators/Net.Sdk.Web.Extensions.SourceGenerators.csproj
index 8c7b45a..d870250 100644
--- a/Net.Sdk.Web.Extensions.SourceGenerators/Net.Sdk.Web.Extensions.SourceGenerators.csproj
+++ b/Net.Sdk.Web.Extensions.SourceGenerators/Net.Sdk.Web.Extensions.SourceGenerators.csproj
@@ -2,7 +2,7 @@
netstandard2.0
- 0.8
+ 0.8.1
latest
true
Alexandru Macocian
diff --git a/Net.Sdk.Web.Extensions.SourceGenerators/WithRoutesGenerator.cs b/Net.Sdk.Web.Extensions.SourceGenerators/WithRoutesGenerator.cs
new file mode 100644
index 0000000..775ad4c
--- /dev/null
+++ b/Net.Sdk.Web.Extensions.SourceGenerators/WithRoutesGenerator.cs
@@ -0,0 +1,119 @@
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using Sybil;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Text;
+
+namespace Net.Sdk.Web.Extensions.SourceGenerators;
+
+[Generator(LanguageNames.CSharp)]
+#nullable enable
+public class WithRoutesGenerator : IIncrementalGenerator
+{
+ public void Initialize(IncrementalGeneratorInitializationContext context)
+ {
+ var classDeclarations = context.SyntaxProvider.CreateSyntaxProvider(
+ predicate: static (s, _) => s is ClassDeclarationSyntax,
+ transform: static (ctx, _) => GetFilteredClassDeclarationSyntax(ctx)).Where(static c => c is not null);
+ var compilationAndClasses = context.CompilationProvider.Combine(classDeclarations.Collect());
+ context.RegisterSourceOutput(compilationAndClasses, (sourceProductionContext, tuple) => Execute(tuple.Left, tuple.Right, sourceProductionContext));
+ }
+
+ private static ClassDeclarationSyntax? GetFilteredClassDeclarationSyntax(GeneratorSyntaxContext context)
+ {
+ var classDeclarationSyntax = (ClassDeclarationSyntax)context.Node;
+ if (classDeclarationSyntax.AttributeLists
+ .SelectMany(l => l.Attributes)
+ .OfType()
+ .Any(s => s.Name.ToString() == Constants.GetAttributeName || s.Name.ToString() == Constants.GetAttributeShortName ||
+ s.Name.ToString() == Constants.PostAttributeName || s.Name.ToString() == Constants.PostAttributeShortName ||
+ s.Name.ToString() == Constants.PutAttributeName || s.Name.ToString() == Constants.PutAttributeShortName ||
+ s.Name.ToString() == Constants.DeleteAttributeName || s.Name.ToString() == Constants.DeleteAttributeShortName))
+ {
+ return classDeclarationSyntax;
+ }
+
+ return default;
+ }
+
+ private static void Execute(Compilation compilation, ImmutableArray classes, SourceProductionContext sourceProductionContext)
+ {
+ if (classes.IsDefaultOrEmpty)
+ {
+ return;
+ }
+
+ var maybeLanguageVersion = (compilation.SyntaxTrees.FirstOrDefault()?.Options as CSharpParseOptions)?.LanguageVersion;
+ if (!maybeLanguageVersion.HasValue)
+ {
+ return;
+ }
+
+ var languageVersion = maybeLanguageVersion.Value;
+ var builder = SyntaxBuilder.CreateCompilationUnit()
+ .WithUsing(Constants.UsingSystemThreading)
+ .WithUsing(Constants.UsingMicrosoftAspNetCoreRouting)
+ .WithUsing(Constants.UsingMicrosoftAspNetCoreHttp)
+ .WithUsing(Constants.UsingMicrosoftAspNetCoreBuilder);
+
+ var routeUsings = new HashSet();
+
+ var namespaceBuilder = languageVersion >= LanguageVersion.CSharp10 ? SyntaxBuilder.CreateFileScopedNamespace(Constants.Namespace) : SyntaxBuilder.CreateNamespace(Constants.Namespace);
+ builder.WithNamespace(namespaceBuilder);
+
+ var extensionClassBuilder = SyntaxBuilder.CreateClass(Constants.WebApplicationBuilderExtensionsName)
+ .WithModifiers($"{Constants.Public} {Constants.Static}");
+ namespaceBuilder.WithClass(extensionClassBuilder);
+
+ var methodBuilder = SyntaxBuilder.CreateMethod(Constants.WebApplicationBuilderTypeName, Constants.WithRoutesName)
+ .WithModifiers($"{Constants.Public} {Constants.Static}")
+ .WithThisParameter(Constants.WebApplicationBuilderTypeName, Constants.BuilderParameterName);
+
+ extensionClassBuilder.WithMethod(methodBuilder);
+ var body = new StringBuilder();
+ foreach(var classDeclarationSyntax in classes)
+ {
+ if (classDeclarationSyntax is null)
+ {
+ continue;
+ }
+
+ if (GetParentOfType(classDeclarationSyntax) is BaseNamespaceDeclarationSyntax baseNamespaceDeclarationSyntax)
+ {
+ routeUsings.Add(baseNamespaceDeclarationSyntax.Name.ToString());
+ }
+
+ body.AppendLine($"builder.Services.AddScoped<{classDeclarationSyntax.Identifier}>();");
+ }
+
+ body.AppendLine("return builder;");
+ methodBuilder.WithBody(body.ToString());
+ foreach(var classUsing in routeUsings)
+ {
+ builder.WithUsing(classUsing);
+ }
+
+ var fileSource = builder.Build().ToFullString();
+ sourceProductionContext.AddSource($"{Constants.WebApplicationBuilderExtensionsName}.g", fileSource);
+ }
+
+ private static T? GetParentOfType(SyntaxNode syntaxNode)
+ {
+ if (syntaxNode.Parent is null)
+ {
+ return default;
+ }
+
+ if (syntaxNode.Parent is T parentNode)
+ {
+ return parentNode;
+ }
+
+ return GetParentOfType(syntaxNode.Parent);
+ }
+}
+
+#nullable disable
\ No newline at end of file
diff --git a/Net.Sdk.Web.Extensions/Net.Sdk.Web.Extensions.csproj b/Net.Sdk.Web.Extensions/Net.Sdk.Web.Extensions.csproj
index 1999831..fd1032f 100644
--- a/Net.Sdk.Web.Extensions/Net.Sdk.Web.Extensions.csproj
+++ b/Net.Sdk.Web.Extensions/Net.Sdk.Web.Extensions.csproj
@@ -6,7 +6,7 @@
enable
Library
true
- 0.8
+ 0.8.1
Alexandru Macocian
LICENSE
true