From 6bb766862f32e31346f90a49f59be150ef7e2a6a Mon Sep 17 00:00:00 2001 From: Alex Macocian Date: Wed, 2 Oct 2024 19:57:07 +0200 Subject: [PATCH] Simplify syntax --- .../Routes/SimpleRoute.cs | 7 ++-- .../Routes/SimpleRoute2.cs | 6 +-- .../Constants.cs | 4 ++ .../ControllerAttributeGenerator.cs | 10 ++++- .../MapAttributeGenerator.cs | 10 +++-- ...Sdk.Web.Extensions.SourceGenerators.csproj | 2 +- .../RouteFilterAttributeGenerator.cs | 9 ++-- .../UseRoutesGenerator.cs | 41 +++++++++++++++---- 8 files changed, 65 insertions(+), 24 deletions(-) diff --git a/Net.Sdk.Web.Extensions.SourceGenerators.Tests/Routes/SimpleRoute.cs b/Net.Sdk.Web.Extensions.SourceGenerators.Tests/Routes/SimpleRoute.cs index 894e91a..6496dd6 100644 --- a/Net.Sdk.Web.Extensions.SourceGenerators.Tests/Routes/SimpleRoute.cs +++ b/Net.Sdk.Web.Extensions.SourceGenerators.Tests/Routes/SimpleRoute.cs @@ -4,12 +4,11 @@ using Net.Sdk.Web.Extensions.SourceGenerators.Tests.Models; namespace Net.Sdk.Web.Extensions.SourceGenerators.Tests.Routes; -[GenerateRoute(Pattern = "simple")] -[RouteFilter(RouteFilterType = typeof(SimpleFilter))] -[RouteFilter(RouteFilterType = typeof(SimpleFilter))] +[GenerateController("simple")] +[RouteFilter] public sealed class SimpleRoute { - [GenerateMapGet(Pattern = "get/{api}/{id}")] + [GenerateGet("get/{api}/{id}")] public async Task GetSimple(string api, string id, [FromBody] SimpleRequest reques) { return Results.Ok(); diff --git a/Net.Sdk.Web.Extensions.SourceGenerators.Tests/Routes/SimpleRoute2.cs b/Net.Sdk.Web.Extensions.SourceGenerators.Tests/Routes/SimpleRoute2.cs index 3acaf11..40a8888 100644 --- a/Net.Sdk.Web.Extensions.SourceGenerators.Tests/Routes/SimpleRoute2.cs +++ b/Net.Sdk.Web.Extensions.SourceGenerators.Tests/Routes/SimpleRoute2.cs @@ -1,11 +1,11 @@ namespace Net.Sdk.Web.Extensions.SourceGenerators.Tests.Routes; -[GenerateRoute] +[GenerateController] public class SimpleRoute2 { - [GenerateMapPost(Pattern = "somethingSimple")] + [GeneratePost("somethingSimple")] public async Task GetSomething() { - + return Results.Ok(); } } diff --git a/Net.Sdk.Web.Extensions.SourceGenerators/Constants.cs b/Net.Sdk.Web.Extensions.SourceGenerators/Constants.cs index 95df0e9..d612496 100644 --- a/Net.Sdk.Web.Extensions.SourceGenerators/Constants.cs +++ b/Net.Sdk.Web.Extensions.SourceGenerators/Constants.cs @@ -62,6 +62,7 @@ public static class Constants public const string DeleteAttributeShortName = "GenerateDelete"; public const string PatternPropertyName = "Pattern"; + public const string PatternArgumentName = "pattern"; public const string MapAllRoutes = "MapAllRoutes"; public const string UseRoutesMethodName = "UseRoutes"; @@ -77,4 +78,7 @@ public static class Constants public const string RouteFilterAttributeName = "RouteFilterAttribute"; public const string RouteFilterAttributeShortName = "RouteFilter"; public const string RouteFilterTypePropertyName = "RouteFilterType"; + + public const string T = "T"; + public const string IEndpointFilterName = "IEndpointFilter"; } diff --git a/Net.Sdk.Web.Extensions.SourceGenerators/ControllerAttributeGenerator.cs b/Net.Sdk.Web.Extensions.SourceGenerators/ControllerAttributeGenerator.cs index e08afed..3a3b513 100644 --- a/Net.Sdk.Web.Extensions.SourceGenerators/ControllerAttributeGenerator.cs +++ b/Net.Sdk.Web.Extensions.SourceGenerators/ControllerAttributeGenerator.cs @@ -20,14 +20,20 @@ public class ControllerAttributeGenerator : IIncrementalGenerator .WithClass(SyntaxBuilder.CreateClass(Constants.RouteAttributeName) .WithBaseClass(nameof(Attribute)) .WithModifiers($"{Constants.Public} {Constants.Sealed}") + .WithConstructor(SyntaxBuilder.CreateConstructor(Constants.RouteAttributeName) + .WithModifier(Constants.Public) + .WithBody($"this.{Constants.PatternPropertyName} = string.Empty;")) + .WithConstructor(SyntaxBuilder.CreateConstructor(Constants.RouteAttributeName) + .WithModifier(Constants.Public) + .WithParameter(Constants.StringType, Constants.PatternArgumentName) + .WithBody($"this.{Constants.PatternPropertyName} = {Constants.PatternArgumentName};")) .WithAttribute(SyntaxBuilder.CreateAttribute("AttributeUsage") .WithArgument(AttributeTargets.Class) .WithArgument("Inherited", false) .WithArgument("AllowMultiple", false)) .WithProperty(SyntaxBuilder.CreateProperty(Constants.StringType, Constants.PatternPropertyName) .WithModifier(Constants.Public) - .WithAccessor(SyntaxBuilder.CreateGetter()) - .WithAccessor(SyntaxBuilder.CreateSetter())))); + .WithAccessor(SyntaxBuilder.CreateGetter())))); var syntax = builder.Build(); var source = syntax.ToFullString(); diff --git a/Net.Sdk.Web.Extensions.SourceGenerators/MapAttributeGenerator.cs b/Net.Sdk.Web.Extensions.SourceGenerators/MapAttributeGenerator.cs index 53c92ff..52cf767 100644 --- a/Net.Sdk.Web.Extensions.SourceGenerators/MapAttributeGenerator.cs +++ b/Net.Sdk.Web.Extensions.SourceGenerators/MapAttributeGenerator.cs @@ -27,7 +27,12 @@ public class MapAttributeGenerator : IIncrementalGenerator .WithClass(SyntaxBuilder.CreateClass(attributeName) .WithModifier(Constants.Public) .WithConstructor(SyntaxBuilder.CreateConstructor(attributeName) - .WithModifier(Constants.Public)) + .WithModifier(Constants.Public) + .WithBody($"this.{Constants.PatternPropertyName} = string.Empty;")) + .WithConstructor(SyntaxBuilder.CreateConstructor(attributeName) + .WithModifier(Constants.Public) + .WithParameter(Constants.StringType, Constants.PatternArgumentName) + .WithBody($"this.{Constants.PatternPropertyName} = {Constants.PatternArgumentName};")) .WithAttribute(SyntaxBuilder.CreateAttribute("AttributeUsage") .WithArgument(AttributeTargets.Method) .WithArgument("Inherited", false) @@ -35,8 +40,7 @@ public class MapAttributeGenerator : IIncrementalGenerator .WithBaseClass(nameof(Attribute)) .WithProperty(SyntaxBuilder.CreateProperty(Constants.StringType, Constants.PatternPropertyName) .WithModifier(Constants.Public) - .WithAccessor(SyntaxBuilder.CreateGetter()) - .WithAccessor(SyntaxBuilder.CreateSetter())))); + .WithAccessor(SyntaxBuilder.CreateGetter())))); var syntax = builder.Build(); var source = syntax.ToFullString(); 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 b24e09a..32e16f0 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.14 + 0.8.15 latest true Alexandru Macocian diff --git a/Net.Sdk.Web.Extensions.SourceGenerators/RouteFilterAttributeGenerator.cs b/Net.Sdk.Web.Extensions.SourceGenerators/RouteFilterAttributeGenerator.cs index 0bdeb06..a5bfaa8 100644 --- a/Net.Sdk.Web.Extensions.SourceGenerators/RouteFilterAttributeGenerator.cs +++ b/Net.Sdk.Web.Extensions.SourceGenerators/RouteFilterAttributeGenerator.cs @@ -20,8 +20,12 @@ public class RouteFilterAttributeGenerator : IIncrementalGenerator SyntaxBuilder.CreateNamespace(Constants.Namespace) .WithClass(SyntaxBuilder.CreateClass(Constants.RouteFilterAttributeName) .WithModifier(Constants.Public) + .WithTypeParameter(SyntaxBuilder.CreateTypeParameter(Constants.T)) + .WithTypeParameterConstraint(SyntaxBuilder.CreateTypeParameterConstraint(Constants.T) + .WithType(Constants.IEndpointFilterName)) .WithConstructor(SyntaxBuilder.CreateConstructor(Constants.RouteFilterAttributeName) - .WithModifier(Constants.Public)) + .WithModifier(Constants.Public) + .WithBody($"this.{Constants.RouteFilterTypePropertyName} = typeof({Constants.T});")) .WithAttribute(SyntaxBuilder.CreateAttribute("AttributeUsage") .WithArgument(AttributeTargets.All) .WithArgument("Inherited", false) @@ -29,8 +33,7 @@ public class RouteFilterAttributeGenerator : IIncrementalGenerator .WithBaseClass(nameof(Attribute)) .WithProperty(SyntaxBuilder.CreateProperty($"{Constants.TypeType}?", Constants.RouteFilterTypePropertyName) .WithModifier(Constants.Public) - .WithAccessor(SyntaxBuilder.CreateGetter()) - .WithAccessor(SyntaxBuilder.CreateSetter())))); + .WithAccessor(SyntaxBuilder.CreateGetter())))); var syntax = builder.Build(); diff --git a/Net.Sdk.Web.Extensions.SourceGenerators/UseRoutesGenerator.cs b/Net.Sdk.Web.Extensions.SourceGenerators/UseRoutesGenerator.cs index fe13ab8..482893f 100644 --- a/Net.Sdk.Web.Extensions.SourceGenerators/UseRoutesGenerator.cs +++ b/Net.Sdk.Web.Extensions.SourceGenerators/UseRoutesGenerator.cs @@ -5,6 +5,7 @@ using Sybil; using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; using System.Linq; using System.Text; @@ -122,8 +123,9 @@ public class UseRoutesGenerator : IIncrementalGenerator .SelectMany(l => l.Attributes) .OfType().ToList(); var basePattern = classAttributes.FirstOrDefault(a => a.Name.ToString() == Constants.RouteAttributeName || a.Name.ToString() == Constants.RouteAttributeShortName)? - .ArgumentList?.Arguments.OfType() - .FirstOrDefault(a => a.NameEquals?.Name.Identifier.Text == Constants.PatternPropertyName)?.Expression.ToString().Trim('"'); + .ArgumentList?.Arguments + .FirstOrDefault()? + .ToString().Trim('"'); basePattern ??= string.Empty; foreach(var methodDeclarationSyntax in methodDeclarationSyntaxes) { @@ -139,9 +141,8 @@ public class UseRoutesGenerator : IIncrementalGenerator or Constants.DeleteAttributeName or Constants.DeleteAttributeShortName) .ArgumentList?.Arguments - .OfType() - .FirstOrDefault(a => a.NameEquals?.Name.Identifier.Text == Constants.PatternPropertyName) - ?.Expression.ToString().Trim('"'); + .FirstOrDefault()? + .ToString().Trim('"'); if (string.IsNullOrWhiteSpace(basePattern) && string.IsNullOrWhiteSpace(pattern)) @@ -196,19 +197,43 @@ public class UseRoutesGenerator : IIncrementalGenerator HashSet usings) { // Go over all attributes on the method and parent class and find all RouteFilters + var semanticModel = compilation.GetSemanticModel(methodDeclarationSyntax.SyntaxTree); var routeFilterSb = new StringBuilder(); foreach(var attribute in methodDeclarationSyntax.AttributeLists .Concat(classDeclarationSyntax.AttributeLists) .SelectMany(a => a.Attributes) .OfType() - .Where(a => a.Name.ToString() == Constants.RouteFilterAttributeName || a.Name.ToString() == Constants.RouteFilterAttributeShortName)) + .Where(attribute => + { + var attributeSymbol = semanticModel.GetSymbolInfo(attribute).Symbol as IMethodSymbol; + if (attributeSymbol?.ContainingType == null) + { + return false; + } + + var attributeType = attributeSymbol.ContainingType; + if (attributeType.Name is not Constants.RouteFilterAttributeName or Constants.RouteFilterAttributeShortName) + { + return false; + } + + return true; + })) { - var semanticModel = compilation.GetSemanticModel(methodDeclarationSyntax.SyntaxTree); - if (GetRouteFilterTypeName(semanticModel, attribute) is not string routeFilterType) + + if (attribute.Name is not GenericNameSyntax genericNameSyntax || genericNameSyntax.TypeArgumentList.Arguments.Count != 1) { continue; } + var routeFilterTypeSyntax = genericNameSyntax.TypeArgumentList.Arguments[0]; + var routeFilterTypeSymbol = semanticModel.GetSymbolInfo(routeFilterTypeSyntax).Symbol as ITypeSymbol; + if (routeFilterTypeSymbol is null) + { + continue; + } + + var routeFilterType = routeFilterTypeSymbol.ToDisplayString(); var namespaceIndex = routeFilterType.LastIndexOf("."); if (namespaceIndex > 0) {