Skip to content

Commit b433d94

Browse files
committed
More tests for ASP003
1 parent 5ecad9b commit b433d94

5 files changed

Lines changed: 56 additions & 76 deletions

File tree

AspNetCoreAnalyzers.Tests/ASP003ParameterTypeTests/CodeFix.cs

Lines changed: 9 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -13,94 +13,48 @@ public class CodeFix
1313

1414
[TestCase("api/orders/{id:int}", "int id")]
1515
[TestCase("api/orders/{id:bool}", "bool id")]
16+
[TestCase("api/orders/{id:datetime}", "System.DateTime id")]
1617
[TestCase("api/orders/{id:decimal}", "decimal id")]
1718
[TestCase("api/orders/{id:double}", "double id")]
1819
[TestCase("api/orders/{id:float}", "float id")]
19-
20+
[TestCase("api/orders/{id:guid}", "System.Guid id")]
21+
[TestCase("api/orders/{id:long}", "long id")]
22+
[TestCase("api/orders/{id:alpha}", "string id")]
2023
public void ExplicitType(string template, string parameter)
2124
{
22-
var order = @"
23-
namespace ValidCode
24-
{
25-
public class Order
26-
{
27-
public int Id { get; set; }
28-
}
29-
}";
30-
31-
var db = @"
32-
namespace ValidCode
33-
{
34-
using Microsoft.EntityFrameworkCore;
35-
36-
public class Db : DbContext
37-
{
38-
public DbSet<Order> Orders { get; set; }
39-
}
40-
}";
4125
var code = @"
4226
namespace ValidCode
4327
{
44-
using System.Threading.Tasks;
4528
using Microsoft.AspNetCore.Mvc;
46-
using Microsoft.EntityFrameworkCore;
4729
4830
[ApiController]
4931
public class OrdersController : Controller
5032
{
51-
private readonly Db db;
52-
53-
public OrdersController(Db db)
54-
{
55-
this.db = db;
56-
}
57-
5833
[HttpGet(""api/orders/{id:int}"")]
59-
public async Task<IActionResult> GetOrder(↓byte id)
34+
public IActionResult GetId(↓byte id)
6035
{
61-
var match = await this.db.Orders.FirstOrDefaultAsync(x => x.Id == id);
62-
if (match == null)
63-
{
64-
return this.NotFound();
65-
}
66-
67-
return this.Ok(match);
36+
return this.Ok(id);
6837
}
6938
}
7039
}".AssertReplace("api/orders/{id:int}", template);
7140

7241
var fixedCode = @"
7342
namespace ValidCode
7443
{
75-
using System.Threading.Tasks;
7644
using Microsoft.AspNetCore.Mvc;
77-
using Microsoft.EntityFrameworkCore;
7845
7946
[ApiController]
8047
public class OrdersController : Controller
8148
{
82-
private readonly Db db;
83-
84-
public OrdersController(Db db)
85-
{
86-
this.db = db;
87-
}
88-
8949
[HttpGet(""api/orders/{id:int}"")]
90-
public async Task<IActionResult> GetOrder(byte id)
50+
public IActionResult GetId(byte id)
9151
{
92-
var match = await this.db.Orders.FirstOrDefaultAsync(x => x.Id == id);
93-
if (match == null)
94-
{
95-
return this.NotFound();
96-
}
97-
98-
return this.Ok(match);
52+
return this.Ok(id);
9953
}
10054
}
10155
}".AssertReplace("api/orders/{id:int}", template)
10256
.AssertReplace("byte id", parameter);
103-
AnalyzerAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, new[] { order, db, code }, fixedCode);
57+
AnalyzerAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, code, fixedCode);
10458
}
10559
}
10660
}

AspNetCoreAnalyzers.Tests/ASP003ParameterTypeTests/ValidCode.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ public async Task<IActionResult> GetOrder(int id)
127127
[TestCase("api/orders/{id:length(1)}")]
128128
[TestCase("api/orders/{id:length(1,3)}")]
129129
[TestCase("api/orders/{id:alpha}")]
130+
[TestCase("api/orders/{id:regex(a-(0|1))}")]
130131
[TestCase("api/orders/{id:required}")]
131132
public void ExplicitString(string template)
132133
{

AspNetCoreAnalyzers/Analyzers/AttributeAnalyzer.cs

Lines changed: 41 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -63,27 +63,16 @@ context.ContainingSymbol is IMethodSymbol method &&
6363

6464
foreach (var pair in pairs)
6565
{
66-
if (pair.Template?.Type is TextAndLocation templateType &&
67-
pair.Method is IParameterSymbol parameter)
66+
if (TryGetParameterType(pair, out var typeName) &&
67+
methodDeclaration.TryFindParameter(pair.Method?.Name, out parameterSyntax))
6868
{
69-
switch (templateType.Text)
70-
{
71-
// https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-2.2#route-constraint-reference
72-
case "bool" when parameter.Type != KnownSymbol.Boolean && methodDeclaration.TryFindParameter(parameter.Name, out parameterSyntax):
73-
case "decimal" when parameter.Type != KnownSymbol.Decimal && methodDeclaration.TryFindParameter(parameter.Name, out parameterSyntax):
74-
case "double" when parameter.Type != KnownSymbol.Float && methodDeclaration.TryFindParameter(parameter.Name, out parameterSyntax):
75-
case "float" when parameter.Type != KnownSymbol.Double && methodDeclaration.TryFindParameter(parameter.Name, out parameterSyntax):
76-
case "int" when parameter.Type != KnownSymbol.Int32 && methodDeclaration.TryFindParameter(parameter.Name, out parameterSyntax):
77-
case "long" when parameter.Type != KnownSymbol.Int64 && methodDeclaration.TryFindParameter(parameter.Name, out parameterSyntax):
78-
context.ReportDiagnostic(
79-
Diagnostic.Create(
80-
ASP003ParameterType.Descriptor,
81-
parameterSyntax.Type.GetLocation(),
82-
ImmutableDictionary<string, string>.Empty.Add(
83-
nameof(TypeSyntax),
84-
templateType.Text)));
85-
break;
86-
}
69+
context.ReportDiagnostic(
70+
Diagnostic.Create(
71+
ASP003ParameterType.Descriptor,
72+
parameterSyntax.Type.GetLocation(),
73+
ImmutableDictionary<string, string>.Empty.Add(
74+
nameof(TypeSyntax),
75+
typeName)));
8776
}
8877
}
8978
}
@@ -149,5 +138,37 @@ private static PooledList<ParameterPair> GetPairs(UrlTemplate template, IMethodS
149138

150139
return list;
151140
}
141+
142+
private static bool TryGetParameterType(ParameterPair pair, out string typeName)
143+
{
144+
if (pair.Template?.Type is TextAndLocation templateType &&
145+
pair.Method is IParameterSymbol parameter)
146+
{
147+
switch (templateType.Text)
148+
{
149+
// https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-2.2#route-constraint-reference
150+
case "bool" when parameter.Type != KnownSymbol.Boolean:
151+
case "decimal" when parameter.Type != KnownSymbol.Decimal:
152+
case "double" when parameter.Type != KnownSymbol.Float:
153+
case "float" when parameter.Type != KnownSymbol.Double:
154+
case "int" when parameter.Type != KnownSymbol.Int32:
155+
case "long" when parameter.Type != KnownSymbol.Int64:
156+
typeName = templateType.Text;
157+
return true;
158+
case "datetime" when parameter.Type != KnownSymbol.DateTime:
159+
typeName = "System.DateTime";
160+
return true;
161+
case "guid" when parameter.Type != KnownSymbol.Guid:
162+
typeName = "System.Guid";
163+
return true;
164+
case "alpha" when parameter.Type != KnownSymbol.String:
165+
typeName = "string";
166+
return true;
167+
}
168+
}
169+
170+
typeName = null;
171+
return false;
172+
}
152173
}
153174
}

AspNetCoreAnalyzers/CodeFixes/ParameterTypeFix.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContex
2626
$"Change to {typeName}",
2727
(e, _) => e.ReplaceNode(
2828
typeSyntax,
29-
x => SyntaxFactory.ParseTypeName(typeName).WithTriviaFrom(x)),
29+
x => SyntaxFactory.ParseTypeName(typeName)
30+
.WithSimplifiedNames()
31+
.WithTriviaFrom(x)),
3032
nameof(ParameterTypeFix),
3133
diagnostic);
3234
}

AspNetCoreAnalyzers/Helpers/KnownSymbols/KnownSymbol.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ internal static class KnownSymbol
77
internal static readonly ObjectType Object = new ObjectType();
88
internal static readonly StringType String = new StringType();
99
internal static readonly QualifiedType Boolean = Create("System.Boolean", "bool");
10+
internal static readonly QualifiedType DateTime = Create("System.DateTime");
1011
internal static readonly QualifiedType Decimal = Create("System.Decimal", "decimal");
1112
internal static readonly QualifiedType Double = Create("System.Double", "double");
1213
internal static readonly QualifiedType Float = Create("System.Single", "float");
14+
internal static readonly QualifiedType Guid = Create("System.Guid");
1315
internal static readonly QualifiedType Int32 = Create("System.Int32", "int");
1416
internal static readonly QualifiedType Int64 = Create("System.Int64", "long");
1517
internal static readonly QualifiedType Attribute = Create("System.Attribute");

0 commit comments

Comments
 (0)