@@ -20,47 +20,51 @@ private static void DetectMismatchedParameterOptionality(
20
20
IInvocationOperation invocation ,
21
21
IMethodSymbol methodSymbol )
22
22
{
23
+ if ( invocation . Arguments . Length < 2 )
24
+ {
25
+ return ;
26
+ }
27
+
23
28
var value = invocation . Arguments [ 1 ] . Value ;
24
29
if ( value . ConstantValue is not { HasValue : true } constant ||
25
30
constant . Value is not string routeTemplate )
26
31
{
27
32
return ;
28
33
}
29
34
30
- var parametersInArguments = methodSymbol . Parameters ;
31
- var parametersInRoute = GetParametersFromRoute ( routeTemplate ) ;
32
-
33
- foreach ( var parameter in parametersInArguments )
35
+ var allDeclarations = methodSymbol . GetAllMethodSymbolsOfPartialParts ( ) ;
36
+ foreach ( var method in allDeclarations )
34
37
{
35
- var isOptional = parameter . IsOptional || parameter . NullableAnnotation != NullableAnnotation . NotAnnotated ;
36
- var location = parameter . DeclaringSyntaxReferences . SingleOrDefault ( ) ? . GetSyntax ( ) . GetLocation ( ) ;
37
- var paramName = parameter . Name ;
38
- var parameterFound = parametersInRoute . TryGetValue ( paramName , out var routeParam ) ;
38
+ var parametersInArguments = method . Parameters ;
39
+ var enumerator = new RouteTokenEnumerator ( routeTemplate ) ;
39
40
40
- if ( ! isOptional && parameterFound && routeParam . IsOptional )
41
+ while ( enumerator . MoveNext ( ) )
41
42
{
42
- context . ReportDiagnostic ( Diagnostic . Create (
43
- DiagnosticDescriptors . DetectMismatchedParameterOptionality ,
44
- location ,
45
- paramName ) ) ;
43
+ foreach ( var parameter in parametersInArguments )
44
+ {
45
+ var paramName = parameter . Name ;
46
+ // If this is not the methpd parameter associated with the route
47
+ // parameter then continue looking for it in the list
48
+ if ( ! enumerator . CurrentName . Equals ( paramName . AsSpan ( ) , StringComparison . OrdinalIgnoreCase ) )
49
+ {
50
+ continue ;
51
+ }
52
+ var argumentIsOptional = parameter . IsOptional || parameter . NullableAnnotation != NullableAnnotation . NotAnnotated ;
53
+ var location = parameter . DeclaringSyntaxReferences . SingleOrDefault ( ) ? . GetSyntax ( ) . GetLocation ( ) ;
54
+ var routeParamIsOptional = enumerator . CurrentQualifiers . IndexOf ( '?' ) > - 1 ;
55
+
56
+ if ( ! argumentIsOptional && routeParamIsOptional )
57
+ {
58
+ context . ReportDiagnostic ( Diagnostic . Create (
59
+ DiagnosticDescriptors . DetectMismatchedParameterOptionality ,
60
+ location ,
61
+ paramName ) ) ;
62
+ }
63
+ }
46
64
}
47
65
}
48
66
}
49
67
50
- private static IDictionary < string , RouteParameter > GetParametersFromRoute ( string routeTemplate )
51
- {
52
- var enumerator = new RouteTokenEnumerator ( routeTemplate ) ;
53
- Dictionary < string , RouteParameter > result = new ( StringComparer . OrdinalIgnoreCase ) ;
54
- while ( enumerator . MoveNext ( ) )
55
- {
56
- var isOptional = enumerator . CurrentQualifiers . IndexOf ( '?' ) > - 1 ;
57
- result . Add (
58
- enumerator . CurrentName . ToString ( ) ,
59
- new RouteParameter ( enumerator . CurrentName . ToString ( ) , isOptional ) ) ;
60
- }
61
- return result ;
62
- }
63
-
64
68
internal ref struct RouteTokenEnumerator
65
69
{
66
70
private ReadOnlySpan < char > _routeTemplate ;
@@ -132,6 +136,4 @@ private static int IndexOf(ReadOnlySpan<char> span, int startIndex, char c)
132
136
133
137
return - 1 ;
134
138
}
135
-
136
- internal record RouteParameter ( string Name , bool IsOptional ) ;
137
139
}
0 commit comments