11// Licensed to the .NET Foundation under one or more agreements.
22// The .NET Foundation licenses this file to you under the MIT license.
33
4+ using System ;
45using System . Collections . Immutable ;
56using System . Linq ;
67using Microsoft . AspNetCore . Analyzers . RouteEmbeddedLanguage . Infrastructure ;
@@ -21,8 +22,13 @@ public static bool IsEnumerable(this ITypeSymbol type, INamedTypeSymbol enumerab
2122 return type . ImplementsInterface ( enumerable ) || SymbolEqualityComparer . Default . Equals ( type , enumerable ) ;
2223 }
2324
24- public static bool ImplementsValidationAttribute ( this ITypeSymbol typeSymbol , INamedTypeSymbol validationAttributeSymbol )
25+ public static bool ImplementsValidationAttribute ( this ITypeSymbol typeSymbol , INamedTypeSymbol ? validationAttributeSymbol )
2526 {
27+ if ( validationAttributeSymbol is null )
28+ {
29+ return false ;
30+ }
31+
2632 var baseType = typeSymbol . BaseType ;
2733 while ( baseType != null )
2834 {
@@ -36,8 +42,9 @@ public static bool ImplementsValidationAttribute(this ITypeSymbol typeSymbol, IN
3642 return false ;
3743 }
3844
39- public static ITypeSymbol UnwrapType ( this ITypeSymbol type , INamedTypeSymbol enumerable )
45+ public static ITypeSymbol UnwrapType ( this ITypeSymbol type , INamedTypeSymbol ? enumerable )
4046 {
47+
4148 if ( type . OriginalDefinition . SpecialType == SpecialType . System_Nullable_T &&
4249 type is INamedTypeSymbol { TypeArguments . Length : 1 } )
4350 {
@@ -52,6 +59,11 @@ public static ITypeSymbol UnwrapType(this ITypeSymbol type, INamedTypeSymbol enu
5259 type = type . WithNullableAnnotation ( NullableAnnotation . NotAnnotated ) ;
5360 }
5461
62+ if ( enumerable is null )
63+ {
64+ return type ;
65+ }
66+
5567 if ( type is INamedTypeSymbol namedType && namedType . IsEnumerable ( enumerable ) && namedType . TypeArguments . Length == 1 )
5668 {
5769 // Extract the T from an IEnumerable<T> or List<T>
@@ -61,8 +73,13 @@ public static ITypeSymbol UnwrapType(this ITypeSymbol type, INamedTypeSymbol enu
6173 return type ;
6274 }
6375
64- internal static bool ImplementsInterface ( this ITypeSymbol type , ITypeSymbol interfaceType )
76+ internal static bool ImplementsInterface ( this ITypeSymbol type , ITypeSymbol ? interfaceType )
6577 {
78+ if ( interfaceType is null )
79+ {
80+ return false ;
81+ }
82+
6683 foreach ( var iface in type . AllInterfaces )
6784 {
6885 if ( SymbolEqualityComparer . Default . Equals ( interfaceType , iface ) )
@@ -73,8 +90,13 @@ internal static bool ImplementsInterface(this ITypeSymbol type, ITypeSymbol inte
7390 return false ;
7491 }
7592
76- internal static ImmutableArray < INamedTypeSymbol > ? GetJsonDerivedTypes ( this ITypeSymbol type , INamedTypeSymbol jsonDerivedTypeAttribute )
93+ internal static ImmutableArray < INamedTypeSymbol > ? GetJsonDerivedTypes ( this ITypeSymbol type , INamedTypeSymbol ? jsonDerivedTypeAttribute )
7794 {
95+ if ( jsonDerivedTypeAttribute is null )
96+ {
97+ return null ;
98+ }
99+
78100 var derivedTypes = ImmutableArray . CreateBuilder < INamedTypeSymbol > ( ) ;
79101 foreach ( var attribute in type . GetAttributes ( ) )
80102 {
@@ -95,7 +117,9 @@ internal static bool ImplementsInterface(this ITypeSymbol type, ITypeSymbol inte
95117 // types themselves so we short-circuit on them.
96118 internal static bool IsExemptType ( this ITypeSymbol type , WellKnownTypes wellKnownTypes )
97119 {
98- return SymbolEqualityComparer . Default . Equals ( type , wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . Microsoft_AspNetCore_Http_HttpContext ) )
120+ try
121+ {
122+ return SymbolEqualityComparer . Default . Equals ( type , wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . Microsoft_AspNetCore_Http_HttpContext ) )
99123 || SymbolEqualityComparer . Default . Equals ( type , wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . Microsoft_AspNetCore_Http_HttpRequest ) )
100124 || SymbolEqualityComparer . Default . Equals ( type , wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . Microsoft_AspNetCore_Http_HttpResponse ) )
101125 || SymbolEqualityComparer . Default . Equals ( type , wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . System_Threading_CancellationToken ) )
@@ -104,6 +128,12 @@ internal static bool IsExemptType(this ITypeSymbol type, WellKnownTypes wellKnow
104128 || SymbolEqualityComparer . Default . Equals ( type , wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . Microsoft_AspNetCore_Http_IFormFile ) )
105129 || SymbolEqualityComparer . Default . Equals ( type , wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . System_IO_Stream ) )
106130 || SymbolEqualityComparer . Default . Equals ( type , wellKnownTypes . Get ( WellKnownTypeData . WellKnownType . System_IO_Pipelines_PipeReader ) ) ;
131+
132+ }
133+ catch ( InvalidOperationException )
134+ {
135+ return false ;
136+ }
107137 }
108138
109139 internal static IPropertySymbol ? FindPropertyIncludingBaseTypes ( this INamedTypeSymbol typeSymbol , string propertyName )
@@ -132,8 +162,13 @@ internal static bool IsExemptType(this ITypeSymbol type, WellKnownTypes wellKnow
132162 /// <param name="parameter">The parameter to check.</param>
133163 /// <param name="fromServiceMetadataSymbol">The symbol representing the [FromService] attribute.</param>
134164 /// <param name="fromKeyedServiceAttributeSymbol">The symbol representing the [FromKeyedService] attribute.</param>
135- internal static bool IsServiceParameter ( this IParameterSymbol parameter , INamedTypeSymbol fromServiceMetadataSymbol , INamedTypeSymbol fromKeyedServiceAttributeSymbol )
165+ internal static bool IsServiceParameter ( this IParameterSymbol parameter , INamedTypeSymbol ? fromServiceMetadataSymbol , INamedTypeSymbol ? fromKeyedServiceAttributeSymbol )
136166 {
167+ if ( fromServiceMetadataSymbol is null || fromKeyedServiceAttributeSymbol is null )
168+ {
169+ return false ;
170+ }
171+
137172 return parameter . GetAttributes ( ) . Any ( attr =>
138173 attr . AttributeClass is not null &&
139174 ( attr . AttributeClass . ImplementsInterface ( fromServiceMetadataSymbol ) ||
@@ -146,8 +181,13 @@ attr.AttributeClass is not null &&
146181 /// <param name="property">The property to check.</param>
147182 /// <param name="fromServiceMetadataSymbol">The symbol representing the [FromServices] attribute.</param>
148183 /// <param name="fromKeyedServiceAttributeSymbol">The symbol representing the [FromKeyedServices] attribute.</param>
149- internal static bool IsServiceProperty ( this IPropertySymbol property , INamedTypeSymbol fromServiceMetadataSymbol , INamedTypeSymbol fromKeyedServiceAttributeSymbol )
184+ internal static bool IsServiceProperty ( this IPropertySymbol property , INamedTypeSymbol ? fromServiceMetadataSymbol , INamedTypeSymbol ? fromKeyedServiceAttributeSymbol )
150185 {
186+ if ( fromServiceMetadataSymbol is null || fromKeyedServiceAttributeSymbol is null )
187+ {
188+ return false ;
189+ }
190+
151191 return property . GetAttributes ( ) . Any ( attr =>
152192 attr . AttributeClass is not null &&
153193 ( attr . AttributeClass . ImplementsInterface ( fromServiceMetadataSymbol ) ||
@@ -159,19 +199,29 @@ attr.AttributeClass is not null &&
159199 /// </summary>
160200 /// <param name="property">The property to check.</param>
161201 /// <param name="jsonIgnoreAttributeSymbol">The symbol representing the [JsonIgnore] attribute.</param>
162- internal static bool IsJsonIgnoredProperty ( this IPropertySymbol property , INamedTypeSymbol jsonIgnoreAttributeSymbol )
202+ internal static bool IsJsonIgnoredProperty ( this IPropertySymbol property , INamedTypeSymbol ? jsonIgnoreAttributeSymbol )
163203 {
204+ if ( jsonIgnoreAttributeSymbol is null )
205+ {
206+ return false ;
207+ }
208+
164209 return property . GetAttributes ( ) . Any ( attr =>
165210 attr . AttributeClass is not null &&
166211 SymbolEqualityComparer . Default . Equals ( attr . AttributeClass , jsonIgnoreAttributeSymbol ) ) ;
167212 }
168213
169- internal static bool IsSkippedValidationProperty ( this IPropertySymbol property , INamedTypeSymbol skipValidationAttributeSymbol )
214+ internal static bool IsSkippedValidationProperty ( this IPropertySymbol property , INamedTypeSymbol ? skipValidationAttributeSymbol )
170215 {
216+ if ( skipValidationAttributeSymbol is null )
217+ {
218+ return false ;
219+ }
220+
171221 return property . HasAttribute ( skipValidationAttributeSymbol ) || property . Type . HasAttribute ( skipValidationAttributeSymbol ) ;
172222 }
173223
174- internal static bool IsSkippedValidationParameter ( this IParameterSymbol parameter , INamedTypeSymbol skipValidationAttributeSymbol )
224+ internal static bool IsSkippedValidationParameter ( this IParameterSymbol parameter , INamedTypeSymbol ? skipValidationAttributeSymbol )
175225 {
176226 return parameter . HasAttribute ( skipValidationAttributeSymbol ) || parameter . Type . HasAttribute ( skipValidationAttributeSymbol ) ;
177227 }
0 commit comments