@@ -21,7 +21,8 @@ public class AttributeAnalyzer : DiagnosticAnalyzer
2121 ASP004RouteParameterType . Descriptor ,
2222 ASP005ParameterSyntax . Descriptor ,
2323 ASP006ParameterRegex . Descriptor ,
24- ASP007MissingParameter . Descriptor ) ;
24+ ASP007MissingParameter . Descriptor ,
25+ ASP008ValidRouteParameterName . Descriptor ) ;
2526
2627 public override void Initialize ( AnalysisContext context )
2728 {
@@ -86,19 +87,15 @@ context.ContainingSymbol is IMethodSymbol method &&
8687 Diagnostic . Create (
8788 ASP003ParameterSymbolType . Descriptor ,
8889 parameterSyntax . Type . GetLocation ( ) ,
89- ImmutableDictionary < string , string > . Empty . Add (
90- nameof ( TypeSyntax ) ,
91- typeName ) ) ) ;
90+ ImmutableDictionary < string , string > . Empty . Add ( nameof ( TypeSyntax ) , typeName ) ) ) ;
9291
9392 context . ReportDiagnostic (
9493 Diagnostic . Create (
9594 ASP004RouteParameterType . Descriptor ,
9695 constraintLocation ,
9796 text == null
9897 ? ImmutableDictionary < string , string > . Empty
99- : ImmutableDictionary < string , string > . Empty . Add (
100- nameof ( Text ) ,
101- text ) ) ) ;
98+ : ImmutableDictionary < string , string > . Empty . Add ( nameof ( Text ) , text ) ) ) ;
10299 }
103100 }
104101
@@ -112,9 +109,7 @@ context.ContainingSymbol is IMethodSymbol method &&
112109 location ,
113110 syntax == null
114111 ? ImmutableDictionary < string , string > . Empty
115- : ImmutableDictionary < string , string > . Empty . Add (
116- nameof ( Text ) ,
117- syntax ) ) ) ;
112+ : ImmutableDictionary < string , string > . Empty . Add ( nameof ( Text ) , syntax ) ) ) ;
118113 }
119114
120115 if ( HasWrongRegexSyntax ( segment , out location , out syntax ) )
@@ -125,9 +120,18 @@ context.ContainingSymbol is IMethodSymbol method &&
125120 location ,
126121 syntax == null
127122 ? ImmutableDictionary < string , string > . Empty
128- : ImmutableDictionary < string , string > . Empty . Add (
129- nameof ( Text ) ,
130- syntax ) ) ) ;
123+ : ImmutableDictionary < string , string > . Empty . Add ( nameof ( Text ) , syntax ) ) ) ;
124+ }
125+
126+ if ( HasInvalidName ( segment , out location , out var name ) )
127+ {
128+ context . ReportDiagnostic (
129+ Diagnostic . Create (
130+ ASP008ValidRouteParameterName . Descriptor ,
131+ location ,
132+ name == null
133+ ? ImmutableDictionary < string , string > . Empty
134+ : ImmutableDictionary < string , string > . Empty . Add ( nameof ( Text ) , name ) ) ) ;
131135 }
132136 }
133137 }
@@ -154,21 +158,6 @@ argument.Expression is LiteralExpressionSyntax literal &&
154158 return false ;
155159 }
156160
157- private static bool IsFromRoute ( IParameterSymbol p )
158- {
159- foreach ( var attributeData in p . GetAttributes ( ) )
160- {
161- if ( attributeData . AttributeClass == KnownSymbol . FromRouteAttribute )
162- {
163- continue ;
164- }
165-
166- return false ;
167- }
168-
169- return true ;
170- }
171-
172161 private static PooledList < ParameterPair > GetPairs ( UrlTemplate template , IMethodSymbol method )
173162 {
174163 var list = PooledList < ParameterPair > . Borrow ( ) ;
@@ -192,6 +181,21 @@ private static PooledList<ParameterPair> GetPairs(UrlTemplate template, IMethodS
192181 }
193182
194183 return list ;
184+
185+ bool IsFromRoute ( IParameterSymbol p )
186+ {
187+ foreach ( var attributeData in p . GetAttributes ( ) )
188+ {
189+ if ( attributeData . AttributeClass == KnownSymbol . FromRouteAttribute )
190+ {
191+ continue ;
192+ }
193+
194+ return false ;
195+ }
196+
197+ return true ;
198+ }
195199 }
196200
197201 private static bool HasWrongType ( ParameterPair pair , out string correctType , out Location constraintLocation , out string correctConstraint )
@@ -317,7 +321,8 @@ string GetCorrectConstraintType(RouteConstraint constraint)
317321 constraint . Span . Equals ( "datetime" , StringComparison . Ordinal ) ||
318322 constraint . Span . Equals ( "guid" , StringComparison . Ordinal ) )
319323 {
320- return parameterSymbol . Type . ToDisplayString ( SymbolDisplayFormat . MinimallyQualifiedFormat ) . ToLower ( ) ;
324+ return parameterSymbol . Type . ToDisplayString ( SymbolDisplayFormat . MinimallyQualifiedFormat )
325+ . ToLower ( ) ;
321326 }
322327
323328 return null ;
@@ -487,5 +492,23 @@ bool NotEscapedChar(char c)
487492 correctSyntax = null ;
488493 return false ;
489494 }
495+
496+ private static bool HasInvalidName ( PathSegment segment , out Location location , out string correctName )
497+ {
498+ if ( segment . Parameter is TemplateParameter parameter )
499+ {
500+ if ( parameter . Name . StartsWith ( " " , StringComparison . OrdinalIgnoreCase ) ||
501+ parameter . Name . EndsWith ( " " , StringComparison . OrdinalIgnoreCase ) )
502+ {
503+ location = parameter . Name . GetLocation ( ) ;
504+ correctName = parameter . Name . ToString ( ) . Trim ( ) ;
505+ return true ;
506+ }
507+ }
508+
509+ location = null ;
510+ correctName = null ;
511+ return false ;
512+ }
490513 }
491514}
0 commit comments