55using System . Collections . Immutable ;
66using System . Linq ;
77using Microsoft . AspNetCore . Analyzers . Infrastructure ;
8+ using Microsoft . AspNetCore . App . Analyzers . Infrastructure ;
89using Microsoft . AspNetCore . Http . RequestDelegateGenerator . StaticRouteHandlerModel ;
910using Microsoft . CodeAnalysis ;
1011using Microsoft . CodeAnalysis . CSharp ;
@@ -18,7 +19,7 @@ public sealed partial class ValidationsGenerator : IIncrementalGenerator
1819 globalNamespaceStyle : SymbolDisplayGlobalNamespaceStyle . Included ,
1920 typeQualificationStyle : SymbolDisplayTypeQualificationStyle . NameAndContainingTypesAndNamespaces ) ;
2021
21- internal ImmutableArray < ValidatableType > ExtractValidatableTypes ( IInvocationOperation operation , RequiredSymbols requiredSymbols )
22+ internal ImmutableArray < ValidatableType > ExtractValidatableTypes ( IInvocationOperation operation , WellKnownTypes wellKnownTypes )
2223 {
2324 AnalyzerDebug . Assert ( operation . SemanticModel != null , "SemanticModel should not be null." ) ;
2425 var parameters = operation . TryGetRouteHandlerMethod ( operation . SemanticModel , out var method )
@@ -28,12 +29,12 @@ internal ImmutableArray<ValidatableType> ExtractValidatableTypes(IInvocationOper
2829 List < ITypeSymbol > visitedTypes = [ ] ;
2930 foreach ( var parameter in parameters )
3031 {
31- _ = TryExtractValidatableType ( parameter . Type . UnwrapType ( requiredSymbols . IEnumerable ) , requiredSymbols , ref validatableTypes , ref visitedTypes ) ;
32+ _ = TryExtractValidatableType ( parameter . Type . UnwrapType ( wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . System_Collections_IEnumerable ) ) , wellKnownTypes , ref validatableTypes , ref visitedTypes ) ;
3233 }
3334 return [ .. validatableTypes ] ;
3435 }
3536
36- internal bool TryExtractValidatableType ( ITypeSymbol typeSymbol , RequiredSymbols requiredSymbols , ref HashSet < ValidatableType > validatableTypes , ref List < ITypeSymbol > visitedTypes )
37+ internal bool TryExtractValidatableType ( ITypeSymbol typeSymbol , WellKnownTypes wellKnownTypes , ref HashSet < ValidatableType > validatableTypes , ref List < ITypeSymbol > visitedTypes )
3738 {
3839 if ( typeSymbol . SpecialType != SpecialType . None )
3940 {
@@ -45,7 +46,7 @@ internal bool TryExtractValidatableType(ITypeSymbol typeSymbol, RequiredSymbols
4546 return true ;
4647 }
4748
48- if ( typeSymbol . IsExemptType ( requiredSymbols ) )
49+ if ( typeSymbol . IsExemptType ( wellKnownTypes ) )
4950 {
5051 return false ;
5152 }
@@ -57,19 +58,23 @@ internal bool TryExtractValidatableType(ITypeSymbol typeSymbol, RequiredSymbols
5758 var hasValidatableBaseType = false ;
5859 while ( current != null && current . SpecialType != SpecialType . System_Object )
5960 {
60- hasValidatableBaseType |= TryExtractValidatableType ( current , requiredSymbols , ref validatableTypes , ref visitedTypes ) ;
61+ hasValidatableBaseType |= TryExtractValidatableType ( current , wellKnownTypes , ref validatableTypes , ref visitedTypes ) ;
6162 current = current . BaseType ;
6263 }
6364
6465 // Extract validatable types discovered in members of this type and add them to the top-level list.
65- var members = ExtractValidatableMembers ( typeSymbol , requiredSymbols , ref validatableTypes , ref visitedTypes ) ;
66+ ImmutableArray < ValidatableProperty > members = [ ] ;
67+ if ( ParsabilityHelper . GetParsability ( typeSymbol , wellKnownTypes ) is Parsability . NotParsable )
68+ {
69+ members = ExtractValidatableMembers ( typeSymbol , wellKnownTypes , ref validatableTypes , ref visitedTypes ) ;
70+ }
6671
6772 // Extract the validatable types discovered in the JsonDerivedTypeAttributes of this type and add them to the top-level list.
68- var derivedTypes = typeSymbol . GetJsonDerivedTypes ( requiredSymbols . JsonDerivedTypeAttribute ) ;
73+ var derivedTypes = typeSymbol . GetJsonDerivedTypes ( wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . System_Text_Json_Serialization_JsonDerivedTypeAttribute ) ) ;
6974 var hasValidatableDerivedTypes = false ;
7075 foreach ( var derivedType in derivedTypes ?? [ ] )
7176 {
72- hasValidatableDerivedTypes |= TryExtractValidatableType ( derivedType , requiredSymbols , ref validatableTypes , ref visitedTypes ) ;
77+ hasValidatableDerivedTypes |= TryExtractValidatableType ( derivedType , wellKnownTypes , ref validatableTypes , ref visitedTypes ) ;
7378 }
7479
7580 // No validatable members or derived types found, so we don't need to add this type.
@@ -86,7 +91,7 @@ internal bool TryExtractValidatableType(ITypeSymbol typeSymbol, RequiredSymbols
8691 return true ;
8792 }
8893
89- internal ImmutableArray < ValidatableProperty > ExtractValidatableMembers ( ITypeSymbol typeSymbol , RequiredSymbols requiredSymbols , ref HashSet < ValidatableType > validatableTypes , ref List < ITypeSymbol > visitedTypes )
94+ internal ImmutableArray < ValidatableProperty > ExtractValidatableMembers ( ITypeSymbol typeSymbol , WellKnownTypes wellKnownTypes , ref HashSet < ValidatableType > validatableTypes , ref List < ITypeSymbol > visitedTypes )
9095 {
9196 var members = new List < ValidatableProperty > ( ) ;
9297 var resolvedRecordProperty = new List < IPropertySymbol > ( ) ;
@@ -121,17 +126,17 @@ internal ImmutableArray<ValidatableProperty> ExtractValidatableMembers(ITypeSymb
121126 // Check if the property's type is validatable, this resolves
122127 // validatable types in the inheritance hierarchy
123128 var hasValidatableType = TryExtractValidatableType (
124- correspondingProperty . Type . UnwrapType ( requiredSymbols . IEnumerable ) ,
125- requiredSymbols ,
129+ correspondingProperty . Type . UnwrapType ( wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . System_Collections_IEnumerable ) ) ,
130+ wellKnownTypes ,
126131 ref validatableTypes ,
127132 ref visitedTypes ) ;
128133
129134 members . Add ( new ValidatableProperty (
130135 ContainingType : correspondingProperty . ContainingType ,
131136 Type : correspondingProperty . Type ,
132137 Name : correspondingProperty . Name ,
133- DisplayName : parameter . GetDisplayName ( requiredSymbols . DisplayAttribute ) ??
134- correspondingProperty . GetDisplayName ( requiredSymbols . DisplayAttribute ) ,
138+ DisplayName : parameter . GetDisplayName ( wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . System_ComponentModel_DataAnnotations_DisplayAttribute ) ) ??
139+ correspondingProperty . GetDisplayName ( wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . System_ComponentModel_DataAnnotations_DisplayAttribute ) ) ,
135140 Attributes : [ ] ) ) ;
136141 }
137142 }
@@ -148,8 +153,8 @@ internal ImmutableArray<ValidatableProperty> ExtractValidatableMembers(ITypeSymb
148153 continue ;
149154 }
150155
151- var hasValidatableType = TryExtractValidatableType ( member . Type . UnwrapType ( requiredSymbols . IEnumerable ) , requiredSymbols , ref validatableTypes , ref visitedTypes ) ;
152- var attributes = ExtractValidationAttributes ( member , requiredSymbols , out var isRequired ) ;
156+ var hasValidatableType = TryExtractValidatableType ( member . Type . UnwrapType ( wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . System_Collections_IEnumerable ) ) , wellKnownTypes , ref validatableTypes , ref visitedTypes ) ;
157+ var attributes = ExtractValidationAttributes ( member , wellKnownTypes , out var isRequired ) ;
153158
154159 // If the member has no validation attributes or validatable types and is not required, skip it.
155160 if ( attributes . IsDefaultOrEmpty && ! hasValidatableType && ! isRequired )
@@ -161,14 +166,14 @@ internal ImmutableArray<ValidatableProperty> ExtractValidatableMembers(ITypeSymb
161166 ContainingType : member . ContainingType ,
162167 Type : member . Type ,
163168 Name : member . Name ,
164- DisplayName : member . GetDisplayName ( requiredSymbols . DisplayAttribute ) ,
169+ DisplayName : member . GetDisplayName ( wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . System_ComponentModel_DataAnnotations_DisplayAttribute ) ) ,
165170 Attributes : attributes ) ) ;
166171 }
167172
168173 return [ .. members ] ;
169174 }
170175
171- internal static ImmutableArray < ValidationAttribute > ExtractValidationAttributes ( ISymbol symbol , RequiredSymbols requiredSymbols , out bool isRequired )
176+ internal static ImmutableArray < ValidationAttribute > ExtractValidationAttributes ( ISymbol symbol , WellKnownTypes wellKnownTypes , out bool isRequired )
172177 {
173178 var attributes = symbol . GetAttributes ( ) ;
174179 if ( attributes . Length == 0 )
@@ -179,15 +184,15 @@ internal static ImmutableArray<ValidationAttribute> ExtractValidationAttributes(
179184
180185 var validationAttributes = attributes
181186 . Where ( attribute => attribute . AttributeClass != null )
182- . Where ( attribute => attribute . AttributeClass ! . ImplementsValidationAttribute ( requiredSymbols . ValidationAttribute ) ) ;
183- isRequired = validationAttributes . Any ( attr => SymbolEqualityComparer . Default . Equals ( attr . AttributeClass , requiredSymbols . RequiredAttribute ) ) ;
187+ . Where ( attribute => attribute . AttributeClass ! . ImplementsValidationAttribute ( wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . System_ComponentModel_DataAnnotations_ValidationAttribute ) ) ) ;
188+ isRequired = validationAttributes . Any ( attr => SymbolEqualityComparer . Default . Equals ( attr . AttributeClass , wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . System_ComponentModel_DataAnnotations_RequiredAttribute ) ) ) ;
184189 return [ .. validationAttributes
185- . Where ( attr => ! SymbolEqualityComparer . Default . Equals ( attr . AttributeClass , requiredSymbols . ValidationAttribute ) )
190+ . Where ( attr => ! SymbolEqualityComparer . Default . Equals ( attr . AttributeClass , wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . System_ComponentModel_DataAnnotations_ValidationAttribute ) ) )
186191 . Select ( attribute => new ValidationAttribute (
187192 Name : symbol . Name + attribute . AttributeClass ! . Name ,
188193 ClassName : attribute . AttributeClass ! . ToDisplayString ( _symbolDisplayFormat ) ,
189194 Arguments : [ .. attribute . ConstructorArguments . Select ( a => a . ToCSharpString ( ) ) ] ,
190195 NamedArguments : attribute . NamedArguments . ToDictionary ( namedArgument => namedArgument . Key , namedArgument => namedArgument . Value . ToCSharpString ( ) ) ,
191- IsCustomValidationAttribute : SymbolEqualityComparer . Default . Equals ( attribute . AttributeClass , requiredSymbols . CustomValidationAttribute ) ) ) ] ;
196+ IsCustomValidationAttribute : SymbolEqualityComparer . Default . Equals ( attribute . AttributeClass , wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . System_ComponentModel_DataAnnotations_CustomValidationAttribute ) ) ) ) ] ;
192197 }
193198}
0 commit comments