Simplify syntax

This commit is contained in:
2024-10-02 19:57:07 +02:00
parent 45327d1618
commit 6bb766862f
8 changed files with 65 additions and 24 deletions
@@ -4,12 +4,11 @@ using Net.Sdk.Web.Extensions.SourceGenerators.Tests.Models;
namespace Net.Sdk.Web.Extensions.SourceGenerators.Tests.Routes; namespace Net.Sdk.Web.Extensions.SourceGenerators.Tests.Routes;
[GenerateRoute(Pattern = "simple")] [GenerateController("simple")]
[RouteFilter(RouteFilterType = typeof(SimpleFilter))] [RouteFilter<SimpleFilter>]
[RouteFilter(RouteFilterType = typeof(SimpleFilter))]
public sealed class SimpleRoute public sealed class SimpleRoute
{ {
[GenerateMapGet(Pattern = "get/{api}/{id}")] [GenerateGet("get/{api}/{id}")]
public async Task<IResult> GetSimple(string api, string id, [FromBody] SimpleRequest reques) public async Task<IResult> GetSimple(string api, string id, [FromBody] SimpleRequest reques)
{ {
return Results.Ok(); return Results.Ok();
@@ -1,11 +1,11 @@
namespace Net.Sdk.Web.Extensions.SourceGenerators.Tests.Routes; namespace Net.Sdk.Web.Extensions.SourceGenerators.Tests.Routes;
[GenerateRoute] [GenerateController]
public class SimpleRoute2 public class SimpleRoute2
{ {
[GenerateMapPost(Pattern = "somethingSimple")] [GeneratePost("somethingSimple")]
public async Task<IResult> GetSomething() public async Task<IResult> GetSomething()
{ {
return Results.Ok();
} }
} }
@@ -62,6 +62,7 @@ public static class Constants
public const string DeleteAttributeShortName = "GenerateDelete"; public const string DeleteAttributeShortName = "GenerateDelete";
public const string PatternPropertyName = "Pattern"; public const string PatternPropertyName = "Pattern";
public const string PatternArgumentName = "pattern";
public const string MapAllRoutes = "MapAllRoutes"; public const string MapAllRoutes = "MapAllRoutes";
public const string UseRoutesMethodName = "UseRoutes"; public const string UseRoutesMethodName = "UseRoutes";
@@ -77,4 +78,7 @@ public static class Constants
public const string RouteFilterAttributeName = "RouteFilterAttribute"; public const string RouteFilterAttributeName = "RouteFilterAttribute";
public const string RouteFilterAttributeShortName = "RouteFilter"; public const string RouteFilterAttributeShortName = "RouteFilter";
public const string RouteFilterTypePropertyName = "RouteFilterType"; public const string RouteFilterTypePropertyName = "RouteFilterType";
public const string T = "T";
public const string IEndpointFilterName = "IEndpointFilter";
} }
@@ -20,14 +20,20 @@ public class ControllerAttributeGenerator : IIncrementalGenerator
.WithClass(SyntaxBuilder.CreateClass(Constants.RouteAttributeName) .WithClass(SyntaxBuilder.CreateClass(Constants.RouteAttributeName)
.WithBaseClass(nameof(Attribute)) .WithBaseClass(nameof(Attribute))
.WithModifiers($"{Constants.Public} {Constants.Sealed}") .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") .WithAttribute(SyntaxBuilder.CreateAttribute("AttributeUsage")
.WithArgument(AttributeTargets.Class) .WithArgument(AttributeTargets.Class)
.WithArgument("Inherited", false) .WithArgument("Inherited", false)
.WithArgument("AllowMultiple", false)) .WithArgument("AllowMultiple", false))
.WithProperty(SyntaxBuilder.CreateProperty(Constants.StringType, Constants.PatternPropertyName) .WithProperty(SyntaxBuilder.CreateProperty(Constants.StringType, Constants.PatternPropertyName)
.WithModifier(Constants.Public) .WithModifier(Constants.Public)
.WithAccessor(SyntaxBuilder.CreateGetter()) .WithAccessor(SyntaxBuilder.CreateGetter()))));
.WithAccessor(SyntaxBuilder.CreateSetter()))));
var syntax = builder.Build(); var syntax = builder.Build();
var source = syntax.ToFullString(); var source = syntax.ToFullString();
@@ -27,7 +27,12 @@ public class MapAttributeGenerator : IIncrementalGenerator
.WithClass(SyntaxBuilder.CreateClass(attributeName) .WithClass(SyntaxBuilder.CreateClass(attributeName)
.WithModifier(Constants.Public) .WithModifier(Constants.Public)
.WithConstructor(SyntaxBuilder.CreateConstructor(attributeName) .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") .WithAttribute(SyntaxBuilder.CreateAttribute("AttributeUsage")
.WithArgument(AttributeTargets.Method) .WithArgument(AttributeTargets.Method)
.WithArgument("Inherited", false) .WithArgument("Inherited", false)
@@ -35,8 +40,7 @@ public class MapAttributeGenerator : IIncrementalGenerator
.WithBaseClass(nameof(Attribute)) .WithBaseClass(nameof(Attribute))
.WithProperty(SyntaxBuilder.CreateProperty(Constants.StringType, Constants.PatternPropertyName) .WithProperty(SyntaxBuilder.CreateProperty(Constants.StringType, Constants.PatternPropertyName)
.WithModifier(Constants.Public) .WithModifier(Constants.Public)
.WithAccessor(SyntaxBuilder.CreateGetter()) .WithAccessor(SyntaxBuilder.CreateGetter()))));
.WithAccessor(SyntaxBuilder.CreateSetter()))));
var syntax = builder.Build(); var syntax = builder.Build();
var source = syntax.ToFullString(); var source = syntax.ToFullString();
@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<Version>0.8.14</Version> <Version>0.8.15</Version>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>Alexandru Macocian</Authors> <Authors>Alexandru Macocian</Authors>
@@ -20,8 +20,12 @@ public class RouteFilterAttributeGenerator : IIncrementalGenerator
SyntaxBuilder.CreateNamespace(Constants.Namespace) SyntaxBuilder.CreateNamespace(Constants.Namespace)
.WithClass(SyntaxBuilder.CreateClass(Constants.RouteFilterAttributeName) .WithClass(SyntaxBuilder.CreateClass(Constants.RouteFilterAttributeName)
.WithModifier(Constants.Public) .WithModifier(Constants.Public)
.WithTypeParameter(SyntaxBuilder.CreateTypeParameter(Constants.T))
.WithTypeParameterConstraint(SyntaxBuilder.CreateTypeParameterConstraint(Constants.T)
.WithType(Constants.IEndpointFilterName))
.WithConstructor(SyntaxBuilder.CreateConstructor(Constants.RouteFilterAttributeName) .WithConstructor(SyntaxBuilder.CreateConstructor(Constants.RouteFilterAttributeName)
.WithModifier(Constants.Public)) .WithModifier(Constants.Public)
.WithBody($"this.{Constants.RouteFilterTypePropertyName} = typeof({Constants.T});"))
.WithAttribute(SyntaxBuilder.CreateAttribute("AttributeUsage") .WithAttribute(SyntaxBuilder.CreateAttribute("AttributeUsage")
.WithArgument(AttributeTargets.All) .WithArgument(AttributeTargets.All)
.WithArgument("Inherited", false) .WithArgument("Inherited", false)
@@ -29,8 +33,7 @@ public class RouteFilterAttributeGenerator : IIncrementalGenerator
.WithBaseClass(nameof(Attribute)) .WithBaseClass(nameof(Attribute))
.WithProperty(SyntaxBuilder.CreateProperty($"{Constants.TypeType}?", Constants.RouteFilterTypePropertyName) .WithProperty(SyntaxBuilder.CreateProperty($"{Constants.TypeType}?", Constants.RouteFilterTypePropertyName)
.WithModifier(Constants.Public) .WithModifier(Constants.Public)
.WithAccessor(SyntaxBuilder.CreateGetter()) .WithAccessor(SyntaxBuilder.CreateGetter()))));
.WithAccessor(SyntaxBuilder.CreateSetter()))));
var syntax = builder.Build(); var syntax = builder.Build();
@@ -5,6 +5,7 @@ using Sybil;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@@ -122,8 +123,9 @@ public class UseRoutesGenerator : IIncrementalGenerator
.SelectMany(l => l.Attributes) .SelectMany(l => l.Attributes)
.OfType<AttributeSyntax>().ToList(); .OfType<AttributeSyntax>().ToList();
var basePattern = classAttributes.FirstOrDefault(a => a.Name.ToString() == Constants.RouteAttributeName || a.Name.ToString() == Constants.RouteAttributeShortName)? var basePattern = classAttributes.FirstOrDefault(a => a.Name.ToString() == Constants.RouteAttributeName || a.Name.ToString() == Constants.RouteAttributeShortName)?
.ArgumentList?.Arguments.OfType<AttributeArgumentSyntax>() .ArgumentList?.Arguments
.FirstOrDefault(a => a.NameEquals?.Name.Identifier.Text == Constants.PatternPropertyName)?.Expression.ToString().Trim('"'); .FirstOrDefault()?
.ToString().Trim('"');
basePattern ??= string.Empty; basePattern ??= string.Empty;
foreach(var methodDeclarationSyntax in methodDeclarationSyntaxes) foreach(var methodDeclarationSyntax in methodDeclarationSyntaxes)
{ {
@@ -139,9 +141,8 @@ public class UseRoutesGenerator : IIncrementalGenerator
or Constants.DeleteAttributeName or Constants.DeleteAttributeName
or Constants.DeleteAttributeShortName) or Constants.DeleteAttributeShortName)
.ArgumentList?.Arguments .ArgumentList?.Arguments
.OfType<AttributeArgumentSyntax>() .FirstOrDefault()?
.FirstOrDefault(a => a.NameEquals?.Name.Identifier.Text == Constants.PatternPropertyName) .ToString().Trim('"');
?.Expression.ToString().Trim('"');
if (string.IsNullOrWhiteSpace(basePattern) && if (string.IsNullOrWhiteSpace(basePattern) &&
string.IsNullOrWhiteSpace(pattern)) string.IsNullOrWhiteSpace(pattern))
@@ -196,19 +197,43 @@ public class UseRoutesGenerator : IIncrementalGenerator
HashSet<string> usings) HashSet<string> usings)
{ {
// Go over all attributes on the method and parent class and find all RouteFilters // Go over all attributes on the method and parent class and find all RouteFilters
var semanticModel = compilation.GetSemanticModel(methodDeclarationSyntax.SyntaxTree);
var routeFilterSb = new StringBuilder(); var routeFilterSb = new StringBuilder();
foreach(var attribute in methodDeclarationSyntax.AttributeLists foreach(var attribute in methodDeclarationSyntax.AttributeLists
.Concat(classDeclarationSyntax.AttributeLists) .Concat(classDeclarationSyntax.AttributeLists)
.SelectMany(a => a.Attributes) .SelectMany(a => a.Attributes)
.OfType<AttributeSyntax>() .OfType<AttributeSyntax>()
.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; 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("."); var namespaceIndex = routeFilterType.LastIndexOf(".");
if (namespaceIndex > 0) if (namespaceIndex > 0)
{ {