@@ -14,6 +14,10 @@ public sealed class MinimalApiGenerator : IIncrementalGenerator
1414{
1515 private const string BaseNamespace = "Microsoft.AspNetCore.Generated" ;
1616 private const string AttributesNamespace = $ "{ BaseNamespace } .Attributes";
17+ private static readonly string [ ] AttributesNamespaceParts = AttributesNamespace . Split ( '.' ) ;
18+ private static readonly string [ ] AspNetCoreHttpNamespaceParts = new [ ] { "Microsoft" , "AspNetCore" , "Http" } ;
19+ private static readonly string [ ] AspNetCoreAuthorizationNamespaceParts = new [ ] { "Microsoft" , "AspNetCore" , "Authorization" } ;
20+ private static readonly string [ ] AspNetCoreRoutingNamespaceParts = new [ ] { "Microsoft" , "AspNetCore" , "Routing" } ;
1721
1822 private static readonly ImmutableArray < HttpAttributeDefinition > HttpAttributeDefinitions =
1923 [
@@ -47,7 +51,7 @@ public sealed class MinimalApiGenerator : IIncrementalGenerator
4751 private const string DisableAntiforgeryAttributeFullyQualifiedName = $ "{ AttributesNamespace } .{ DisableAntiforgeryAttributeName } ";
4852 private const string DisableAntiforgeryAttributeHint = $ "{ DisableAntiforgeryAttributeFullyQualifiedName } .gs.cs";
4953
50- private const string AllowAnonymousAttributeFullyQualifiedName = "Microsoft.AspNetCore.Authorization. AllowAnonymousAttribute" ;
54+ private const string AllowAnonymousAttributeName = "AllowAnonymousAttribute" ;
5155
5256 private const string AcceptsAttributeName = "AcceptsAttribute" ;
5357 private const string AcceptsAttributeFullyQualifiedName = $ "{ AttributesNamespace } .{ AcceptsAttributeName } ";
@@ -716,96 +720,108 @@ ref bool hasRequireAuthorizationAttribute
716720 if ( attributeClass is null )
717721 continue ;
718722
719- var fullyQualifiedName = attributeClass . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat ) ;
720-
721- if ( IsGeneratedAttribute ( fullyQualifiedName , AcceptsAttributeName ) )
723+ if ( IsGeneratedAttribute ( attributeClass , AcceptsAttributeName ) )
722724 {
723725 TryAddAcceptsMetadata ( attribute , attributeClass , ref accepts ) ;
724726 continue ;
725727 }
726728
727- if ( IsGeneratedAttribute ( fullyQualifiedName , ProducesResponseAttributeName ) )
729+ if ( IsGeneratedAttribute ( attributeClass , ProducesResponseAttributeName ) )
728730 {
729731 TryAddProducesMetadata ( attribute , attributeClass , ref produces ) ;
730732 continue ;
731733 }
732734
733- switch ( fullyQualifiedName )
735+ if ( IsAttribute ( attributeClass , "TagsAttribute" , AspNetCoreHttpNamespaceParts ) )
734736 {
735- case "global::Microsoft.AspNetCore.Http.TagsAttribute" :
736- if ( attribute . ConstructorArguments . Length > 0 )
737- {
738- var arg = attribute . ConstructorArguments [ 0 ] ;
739- if ( arg . Values . Length > 0 )
740- {
741- var values = arg . Values
742- . Select ( v => v . Value as string )
743- . Where ( s => ! string . IsNullOrWhiteSpace ( s ) )
744- . Select ( s => s ! . Trim ( ) ) ;
745-
746- MergeInto ( ref tags , values ) ;
747- }
748- }
749- break ;
750- case $ "global::{ RequireAuthorizationAttributeFullyQualifiedName } ":
751- requireAuthorization = true ;
752- hasRequireAuthorizationAttribute = true ;
753- if ( attribute . ConstructorArguments . Length == 1 )
737+ if ( attribute . ConstructorArguments . Length > 0 )
738+ {
739+ var arg = attribute . ConstructorArguments [ 0 ] ;
740+ if ( arg . Values . Length > 0 )
754741 {
755- var arg = attribute . ConstructorArguments [ 0 ] ;
756- if ( arg . Values . Length > 0 )
757- {
758- var values = arg . Values
759- . Select ( v => v . Value as string )
760- . Where ( s => ! string . IsNullOrWhiteSpace ( s ) )
761- . Select ( s => s ! . Trim ( ) ) ;
762-
763- MergeInto ( ref authorizationPolicies , values ) ;
764- }
742+ var values = arg . Values
743+ . Select ( v => v . Value as string )
744+ . Where ( s => ! string . IsNullOrWhiteSpace ( s ) )
745+ . Select ( s => s ! . Trim ( ) ) ;
746+
747+ MergeInto ( ref tags , values ) ;
765748 }
766- break ;
767- case $ "global::{ DisableAntiforgeryAttributeFullyQualifiedName } ":
768- disableAntiforgery = true ;
769- break ;
770- case $ "global::{ AllowAnonymousAttributeFullyQualifiedName } ":
771- allowAnonymous = true ;
772- hasAllowAnonymousAttribute = true ;
773- break ;
774- case "global::Microsoft.AspNetCore.Routing.ExcludeFromDescriptionAttribute" :
775- excludeFromDescription = true ;
776- break ;
777- case $ "global::{ ProducesProblemAttributeFullyQualifiedName } ":
778- {
779- var statusCode = attribute . ConstructorArguments . Length > 0 && attribute . ConstructorArguments [ 0 ] . Value is int producesProblemStatusCode
780- ? producesProblemStatusCode
781- : 500 ;
782- var contentType = attribute . ConstructorArguments . Length > 1
783- ? NormalizeOptionalContentType ( attribute . ConstructorArguments [ 1 ] . Value as string )
784- : null ;
785- var additionalContentTypes = attribute . ConstructorArguments . Length > 2
786- ? GetStringArrayValues ( attribute . ConstructorArguments [ 2 ] )
787- : null ;
788-
789- var producesProblemList = producesProblem ??= [ ] ;
790- producesProblemList . Add ( new ProducesProblemMetadata ( statusCode , contentType , additionalContentTypes ) ) ;
791- break ;
792749 }
793- case $ "global::{ ProducesValidationProblemAttributeFullyQualifiedName } ":
750+
751+ continue ;
752+ }
753+
754+ if ( IsGeneratedAttribute ( attributeClass , RequireAuthorizationAttributeName ) )
755+ {
756+ requireAuthorization = true ;
757+ hasRequireAuthorizationAttribute = true ;
758+ if ( attribute . ConstructorArguments . Length == 1 )
794759 {
795- var statusCode = attribute . ConstructorArguments . Length > 0 && attribute . ConstructorArguments [ 0 ] . Value is int producesValidationProblemStatusCode
796- ? producesValidationProblemStatusCode
797- : 400 ;
798- var contentType = attribute . ConstructorArguments . Length > 1
799- ? NormalizeOptionalContentType ( attribute . ConstructorArguments [ 1 ] . Value as string )
800- : null ;
801- var additionalContentTypes = attribute . ConstructorArguments . Length > 2
802- ? GetStringArrayValues ( attribute . ConstructorArguments [ 2 ] )
803- : null ;
804-
805- var producesValidationProblemList = producesValidationProblem ??= [ ] ;
806- producesValidationProblemList . Add ( new ProducesValidationProblemMetadata ( statusCode , contentType , additionalContentTypes ) ) ;
807- break ;
760+ var arg = attribute . ConstructorArguments [ 0 ] ;
761+ if ( arg . Values . Length > 0 )
762+ {
763+ var values = arg . Values
764+ . Select ( v => v . Value as string )
765+ . Where ( s => ! string . IsNullOrWhiteSpace ( s ) )
766+ . Select ( s => s ! . Trim ( ) ) ;
767+
768+ MergeInto ( ref authorizationPolicies , values ) ;
769+ }
808770 }
771+
772+ continue ;
773+ }
774+
775+ if ( IsGeneratedAttribute ( attributeClass , DisableAntiforgeryAttributeName ) )
776+ {
777+ disableAntiforgery = true ;
778+ continue ;
779+ }
780+
781+ if ( IsAttribute ( attributeClass , AllowAnonymousAttributeName , AspNetCoreAuthorizationNamespaceParts ) )
782+ {
783+ allowAnonymous = true ;
784+ hasAllowAnonymousAttribute = true ;
785+ continue ;
786+ }
787+
788+ if ( IsAttribute ( attributeClass , "ExcludeFromDescriptionAttribute" , AspNetCoreRoutingNamespaceParts ) )
789+ {
790+ excludeFromDescription = true ;
791+ continue ;
792+ }
793+
794+ if ( IsGeneratedAttribute ( attributeClass , ProducesProblemAttributeName ) )
795+ {
796+ var statusCode = attribute . ConstructorArguments . Length > 0 && attribute . ConstructorArguments [ 0 ] . Value is int producesProblemStatusCode
797+ ? producesProblemStatusCode
798+ : 500 ;
799+ var contentType = attribute . ConstructorArguments . Length > 1
800+ ? NormalizeOptionalContentType ( attribute . ConstructorArguments [ 1 ] . Value as string )
801+ : null ;
802+ var additionalContentTypes = attribute . ConstructorArguments . Length > 2
803+ ? GetStringArrayValues ( attribute . ConstructorArguments [ 2 ] )
804+ : null ;
805+
806+ var producesProblemList = producesProblem ??= [ ] ;
807+ producesProblemList . Add ( new ProducesProblemMetadata ( statusCode , contentType , additionalContentTypes ) ) ;
808+ continue ;
809+ }
810+
811+ if ( IsGeneratedAttribute ( attributeClass , ProducesValidationProblemAttributeName ) )
812+ {
813+ var statusCode = attribute . ConstructorArguments . Length > 0 && attribute . ConstructorArguments [ 0 ] . Value is int producesValidationProblemStatusCode
814+ ? producesValidationProblemStatusCode
815+ : 400 ;
816+ var contentType = attribute . ConstructorArguments . Length > 1
817+ ? NormalizeOptionalContentType ( attribute . ConstructorArguments [ 1 ] . Value as string )
818+ : null ;
819+ var additionalContentTypes = attribute . ConstructorArguments . Length > 2
820+ ? GetStringArrayValues ( attribute . ConstructorArguments [ 2 ] )
821+ : null ;
822+
823+ var producesValidationProblemList = producesValidationProblem ??= [ ] ;
824+ producesValidationProblemList . Add ( new ProducesValidationProblemMetadata ( statusCode , contentType , additionalContentTypes ) ) ;
809825 }
810826 }
811827 }
@@ -846,10 +862,29 @@ private static string NormalizeRequiredContentType(string? contentType, string d
846862 return builder . Count > 0 ? builder . ToEquatableImmutable ( ) : null ;
847863 }
848864
849- private static bool IsGeneratedAttribute ( string fullyQualifiedName , string attributeName )
865+ private static bool IsGeneratedAttribute ( INamedTypeSymbol attributeClass , string attributeName )
850866 {
851- var prefix = $ "global::{ AttributesNamespace } .{ attributeName } ";
852- return fullyQualifiedName . StartsWith ( prefix , StringComparison . Ordinal ) ;
867+ var definition = attributeClass . OriginalDefinition ;
868+ return definition . Name == attributeName && IsInNamespace ( definition . ContainingNamespace , AttributesNamespaceParts ) ;
869+ }
870+
871+ private static bool IsAttribute ( INamedTypeSymbol attributeClass , string attributeName , string [ ] namespaceParts )
872+ {
873+ var definition = attributeClass . OriginalDefinition ;
874+ return definition . Name == attributeName && IsInNamespace ( definition . ContainingNamespace , namespaceParts ) ;
875+ }
876+
877+ private static bool IsInNamespace ( INamespaceSymbol ? namespaceSymbol , string [ ] namespaceParts )
878+ {
879+ for ( var i = namespaceParts . Length - 1 ; i >= 0 ; i -- )
880+ {
881+ if ( namespaceSymbol is null || namespaceSymbol . Name != namespaceParts [ i ] )
882+ return false ;
883+
884+ namespaceSymbol = namespaceSymbol . ContainingNamespace ;
885+ }
886+
887+ return namespaceSymbol is null || namespaceSymbol . IsGlobalNamespace ;
853888 }
854889
855890 private static void TryAddAcceptsMetadata (
0 commit comments