Skip to content

Commit ca61816

Browse files
committed
More tests.
1 parent dfa9b5c commit ca61816

File tree

2 files changed

+133
-88
lines changed

2 files changed

+133
-88
lines changed

AspNetCoreAnalyzers.Tests/ASP009LowercaseUrlsTests/CodeFix.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,5 +47,45 @@ public IActionResult GetId(string id)
4747
}".AssertReplace("\"api/orders/{id}\"", after);
4848
AnalyzerAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, code, fixedCode);
4949
}
50+
51+
[TestCase("\"api/↓Orders\"", "\"api/orders\"")]
52+
public void WhenRouteAttribute(string before, string after)
53+
{
54+
var code = @"
55+
namespace ValidCode
56+
{
57+
using Microsoft.AspNetCore.Mvc;
58+
59+
[Route(""api/Orders"")]
60+
[ApiController]
61+
public class OrdersController : Controller
62+
{
63+
[HttpGet(""{id}"")]
64+
public IActionResult GetId(string id)
65+
{
66+
return this.Ok(id);
67+
}
68+
}
69+
}".AssertReplace("\"api/Orders\"", before);
70+
71+
var fixedCode = @"
72+
namespace ValidCode
73+
{
74+
using Microsoft.AspNetCore.Mvc;
75+
76+
[Route(""api/orders"")]
77+
[ApiController]
78+
public class OrdersController : Controller
79+
{
80+
[HttpGet(""{id}"")]
81+
public IActionResult GetId(string id)
82+
{
83+
return this.Ok(id);
84+
}
85+
}
86+
}".AssertReplace("\"api/orders\"", after);
87+
AnalyzerAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, code, fixedCode);
88+
}
89+
}
5090
}
5191
}

AspNetCoreAnalyzers/Analyzers/AttributeAnalyzer.cs

Lines changed: 93 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -34,117 +34,119 @@ private static void Handle(SyntaxNodeAnalysisContext context)
3434
{
3535
if (!context.IsExcludedFromAnalysis() &&
3636
context.Node is AttributeSyntax attribute &&
37-
context.ContainingSymbol is IMethodSymbol method &&
38-
attribute.TryFirstAncestor(out MethodDeclarationSyntax methodDeclaration) &&
3937
TryGetTemplate(attribute, context, out var template))
4038
{
41-
using (var pairs = GetPairs(template, method))
39+
if (context.ContainingSymbol is IMethodSymbol method &&
40+
attribute.TryFirstAncestor(out MethodDeclarationSyntax methodDeclaration))
4241
{
43-
if (pairs.TrySingle(x => x.Route == null, out var withMethodParameter) &&
44-
methodDeclaration.TryFindParameter(withMethodParameter.Symbol.Name, out var parameterSyntax) &&
45-
pairs.TrySingle(x => x.Symbol == null, out var withTemplateParameter) &&
46-
withTemplateParameter.Route is TemplateParameter templateParameter)
42+
using (var pairs = GetPairs(template, method))
4743
{
48-
context.ReportDiagnostic(
49-
Diagnostic.Create(
50-
ASP001ParameterSymbolName.Descriptor,
51-
parameterSyntax.Identifier.GetLocation(),
52-
ImmutableDictionary<string, string>.Empty.Add(
53-
nameof(NameSyntax),
54-
templateParameter.Name.ToString())));
55-
56-
context.ReportDiagnostic(
57-
Diagnostic.Create(
58-
ASP002RouteParameterName.Descriptor,
59-
templateParameter.Name.GetLocation(),
60-
ImmutableDictionary<string, string>.Empty.Add(
61-
nameof(Text),
62-
withMethodParameter.Symbol.Name)));
63-
}
64-
else if (pairs.Count(x => x.Route == null) > 1 &&
65-
pairs.Count(x => x.Symbol == null) > 1)
66-
{
67-
context.ReportDiagnostic(
68-
Diagnostic.Create(
69-
ASP001ParameterSymbolName.Descriptor,
70-
methodDeclaration.ParameterList.GetLocation()));
71-
}
72-
73-
if (pairs.TryFirst(x => x.Symbol == null, out _) &&
74-
!pairs.TryFirst(x => x.Route == null, out _))
75-
{
76-
context.ReportDiagnostic(
77-
Diagnostic.Create(
78-
ASP007MissingParameter.Descriptor,
79-
methodDeclaration.ParameterList.GetLocation()));
80-
}
81-
82-
foreach (var pair in pairs)
83-
{
84-
if (HasWrongType(pair, out var typeName, out var constraintLocation, out var text) &&
85-
methodDeclaration.TryFindParameter(pair.Symbol?.Name, out parameterSyntax))
44+
if (pairs.TrySingle(x => x.Route == null, out var withMethodParameter) &&
45+
methodDeclaration.TryFindParameter(withMethodParameter.Symbol.Name, out var parameterSyntax) &&
46+
pairs.TrySingle(x => x.Symbol == null, out var withTemplateParameter) &&
47+
withTemplateParameter.Route is TemplateParameter templateParameter)
8648
{
8749
context.ReportDiagnostic(
8850
Diagnostic.Create(
89-
ASP003ParameterSymbolType.Descriptor,
90-
parameterSyntax.Type.GetLocation(),
91-
ImmutableDictionary<string, string>.Empty.Add(nameof(TypeSyntax), typeName)));
51+
ASP001ParameterSymbolName.Descriptor,
52+
parameterSyntax.Identifier.GetLocation(),
53+
ImmutableDictionary<string, string>.Empty.Add(
54+
nameof(NameSyntax),
55+
templateParameter.Name.ToString())));
9256

9357
context.ReportDiagnostic(
9458
Diagnostic.Create(
95-
ASP004RouteParameterType.Descriptor,
96-
constraintLocation,
97-
text == null
98-
? ImmutableDictionary<string, string>.Empty
99-
: ImmutableDictionary<string, string>.Empty.Add(nameof(Text), text)));
59+
ASP002RouteParameterName.Descriptor,
60+
templateParameter.Name.GetLocation(),
61+
ImmutableDictionary<string, string>.Empty.Add(
62+
nameof(Text),
63+
withMethodParameter.Symbol.Name)));
10064
}
101-
}
102-
103-
foreach (var segment in template.Path)
104-
{
105-
if (HasWrongSyntax(segment, out var location, out var syntax))
65+
else if (pairs.Count(x => x.Route == null) > 1 &&
66+
pairs.Count(x => x.Symbol == null) > 1)
10667
{
10768
context.ReportDiagnostic(
10869
Diagnostic.Create(
109-
ASP005ParameterSyntax.Descriptor,
110-
location,
111-
syntax == null
112-
? ImmutableDictionary<string, string>.Empty
113-
: ImmutableDictionary<string, string>.Empty.Add(nameof(Text), syntax)));
70+
ASP001ParameterSymbolName.Descriptor,
71+
methodDeclaration.ParameterList.GetLocation()));
11472
}
11573

116-
if (HasWrongRegexSyntax(segment, out location, out syntax))
74+
if (pairs.TryFirst(x => x.Symbol == null, out _) &&
75+
!pairs.TryFirst(x => x.Route == null, out _))
11776
{
11877
context.ReportDiagnostic(
11978
Diagnostic.Create(
120-
ASP006ParameterRegex.Descriptor,
121-
location,
122-
syntax == null
123-
? ImmutableDictionary<string, string>.Empty
124-
: ImmutableDictionary<string, string>.Empty.Add(nameof(Text), syntax)));
79+
ASP007MissingParameter.Descriptor,
80+
methodDeclaration.ParameterList.GetLocation()));
12581
}
12682

127-
if (HasInvalidName(segment, out location, out var name))
83+
foreach (var pair in pairs)
12884
{
129-
context.ReportDiagnostic(
130-
Diagnostic.Create(
131-
ASP008ValidRouteParameterName.Descriptor,
132-
location,
133-
name == null
134-
? ImmutableDictionary<string, string>.Empty
135-
: ImmutableDictionary<string, string>.Empty.Add(nameof(Text), name)));
85+
if (HasWrongType(pair, out var typeName, out var constraintLocation, out var text) &&
86+
methodDeclaration.TryFindParameter(pair.Symbol?.Name, out parameterSyntax))
87+
{
88+
context.ReportDiagnostic(
89+
Diagnostic.Create(
90+
ASP003ParameterSymbolType.Descriptor,
91+
parameterSyntax.Type.GetLocation(),
92+
ImmutableDictionary<string, string>.Empty.Add(nameof(TypeSyntax), typeName)));
93+
94+
context.ReportDiagnostic(
95+
Diagnostic.Create(
96+
ASP004RouteParameterType.Descriptor,
97+
constraintLocation,
98+
text == null
99+
? ImmutableDictionary<string, string>.Empty
100+
: ImmutableDictionary<string, string>.Empty.Add(nameof(Text), text)));
101+
}
136102
}
103+
}
104+
}
137105

138-
if (IsUpperCase(segment, out var lowercase))
139-
{
140-
context.ReportDiagnostic(
141-
Diagnostic.Create(
142-
ASP009LowercaseUrl.Descriptor,
143-
segment.Span.GetLocation(),
144-
lowercase == null
145-
? ImmutableDictionary<string, string>.Empty
146-
: ImmutableDictionary<string, string>.Empty.Add(nameof(Text), lowercase)));
147-
}
106+
foreach (var segment in template.Path)
107+
{
108+
if (HasWrongSyntax(segment, out var location, out var syntax))
109+
{
110+
context.ReportDiagnostic(
111+
Diagnostic.Create(
112+
ASP005ParameterSyntax.Descriptor,
113+
location,
114+
syntax == null
115+
? ImmutableDictionary<string, string>.Empty
116+
: ImmutableDictionary<string, string>.Empty.Add(nameof(Text), syntax)));
117+
}
118+
119+
if (HasWrongRegexSyntax(segment, out location, out syntax))
120+
{
121+
context.ReportDiagnostic(
122+
Diagnostic.Create(
123+
ASP006ParameterRegex.Descriptor,
124+
location,
125+
syntax == null
126+
? ImmutableDictionary<string, string>.Empty
127+
: ImmutableDictionary<string, string>.Empty.Add(nameof(Text), syntax)));
128+
}
129+
130+
if (HasInvalidName(segment, out location, out var name))
131+
{
132+
context.ReportDiagnostic(
133+
Diagnostic.Create(
134+
ASP008ValidRouteParameterName.Descriptor,
135+
location,
136+
name == null
137+
? ImmutableDictionary<string, string>.Empty
138+
: ImmutableDictionary<string, string>.Empty.Add(nameof(Text), name)));
139+
}
140+
141+
if (IsUpperCase(segment, out var lowercase))
142+
{
143+
context.ReportDiagnostic(
144+
Diagnostic.Create(
145+
ASP009LowercaseUrl.Descriptor,
146+
segment.Span.GetLocation(),
147+
lowercase == null
148+
? ImmutableDictionary<string, string>.Empty
149+
: ImmutableDictionary<string, string>.Empty.Add(nameof(Text), lowercase)));
148150
}
149151
}
150152
}
@@ -158,9 +160,12 @@ argument.Expression is LiteralExpressionSyntax literal &&
158160
literal.IsKind(SyntaxKind.StringLiteralExpression) &&
159161
(Attribute.IsType(attribute, KnownSymbol.HttpDeleteAttribute, context.SemanticModel, context.CancellationToken) ||
160162
Attribute.IsType(attribute, KnownSymbol.HttpGetAttribute, context.SemanticModel, context.CancellationToken) ||
163+
Attribute.IsType(attribute, KnownSymbol.HttpHeadAttribute, context.SemanticModel, context.CancellationToken) ||
164+
Attribute.IsType(attribute, KnownSymbol.HttpOptionsAttribute, context.SemanticModel, context.CancellationToken) ||
161165
Attribute.IsType(attribute, KnownSymbol.HttpPatchAttribute, context.SemanticModel, context.CancellationToken) ||
162166
Attribute.IsType(attribute, KnownSymbol.HttpPostAttribute, context.SemanticModel, context.CancellationToken) ||
163-
Attribute.IsType(attribute, KnownSymbol.HttpPutAttribute, context.SemanticModel, context.CancellationToken)) &&
167+
Attribute.IsType(attribute, KnownSymbol.HttpPutAttribute, context.SemanticModel, context.CancellationToken) ||
168+
Attribute.IsType(attribute, KnownSymbol.RouteAttribute, context.SemanticModel, context.CancellationToken)) &&
164169
UrlTemplate.TryParse(literal, out template))
165170
{
166171
return true;

0 commit comments

Comments
 (0)