Skip to content

Commit 1d09aa9

Browse files
committed
ASP004 check syntax of route parameters. #22
Stub implementation & happy path tests.
1 parent 8e532df commit 1d09aa9

7 files changed

Lines changed: 191 additions & 1 deletion

File tree

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
namespace AspNetCoreAnalyzers.Tests.ASP004ParameterSyntaxTests
2+
{
3+
using Gu.Roslyn.Asserts;
4+
using Microsoft.CodeAnalysis.Diagnostics;
5+
using NUnit.Framework;
6+
7+
public class ValidCode
8+
{
9+
private static readonly DiagnosticAnalyzer Analyzer = new AttributeAnalyzer();
10+
11+
[TestCase("{value:bool}", "bool")]
12+
[TestCase("{value:datetime}", "System.DateTime")]
13+
[TestCase("{value:decimal}", "decimal")]
14+
[TestCase("{value:double}", "double")]
15+
[TestCase("{value:float}", "float")]
16+
[TestCase("{value:int}", "int")]
17+
[TestCase("api/orders/{value:int:min(1)}", "int")]
18+
[TestCase("api/orders/{value:int:max(1)}", "int")]
19+
[TestCase("api/orders/{value:int:range(1,10)}", "int")]
20+
[TestCase("api/orders/{value:int:required}", "int")]
21+
[TestCase("{value:long}", "long")]
22+
[TestCase("api/orders/{value:min(1)}", "long")]
23+
[TestCase("api/orders/{value:max(1)}", "long")]
24+
[TestCase("api/orders/{value:range(1,10)}", "long")]
25+
[TestCase("api/orders/{value:required}", "long")]
26+
[TestCase("{value:guid}", "System.Guid")]
27+
[TestCase("api/orders/{value:minlength(1)}", "string")]
28+
[TestCase("api/orders/{value:maxlength(1)}", "string")]
29+
[TestCase("api/orders/{value:length(1)}", "string")]
30+
[TestCase("api/orders/{value:length(1,3)}", "string")]
31+
[TestCase("api/orders/{value:alpha}", "string")]
32+
[TestCase("api/orders/{value:regex(a-(0|1))}", "string")]
33+
[TestCase("api/orders/{value:regex(^\\\\d{{3}}-\\\\d{{2}}-\\\\d{{4}}$)}", "string")]
34+
[TestCase("api/orders/{value:required}", "string")]
35+
public void WithParameter(string parameter, string type)
36+
{
37+
var code = @"
38+
namespace ValidCode
39+
{
40+
using System.Threading.Tasks;
41+
using Microsoft.AspNetCore.Mvc;
42+
using Microsoft.EntityFrameworkCore;
43+
44+
[ApiController]
45+
public class OrdersController : Controller
46+
{
47+
[HttpGet(""api/{value}"")]
48+
public async Task<int> GetOrder(int value)
49+
{
50+
return value;
51+
}
52+
}
53+
}".AssertReplace("int", type)
54+
.AssertReplace("{value}", parameter);
55+
AnalyzerAssert.Valid(Analyzer, code);
56+
}
57+
}
58+
}

AspNetCoreAnalyzers.sln

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".docs", ".docs", "{1C271AF2
3232
documentation\ASP001.md = documentation\ASP001.md
3333
documentation\ASP002.md = documentation\ASP002.md
3434
documentation\ASP003.md = documentation\ASP003.md
35+
documentation\ASP004.md = documentation\ASP004.md
3536
README.md = README.md
3637
RELEASE_NOTES.md = RELEASE_NOTES.md
3738
EndProjectSection
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
namespace AspNetCoreAnalyzers
2+
{
3+
using Microsoft.CodeAnalysis;
4+
5+
internal static class ASP004ParameterSyntax
6+
{
7+
public const string DiagnosticId = "ASP004";
8+
9+
internal static readonly DiagnosticDescriptor Descriptor = new DiagnosticDescriptor(
10+
id: DiagnosticId,
11+
title: "Syntax error in parameter.",
12+
messageFormat: "Syntax error in parameter.",
13+
category: AnalyzerCategory.Routing,
14+
defaultSeverity: DiagnosticSeverity.Warning,
15+
isEnabledByDefault: true,
16+
description: "Syntax error in parameter.",
17+
helpLinkUri: HelpLink.ForId(DiagnosticId));
18+
}
19+
}

AspNetCoreAnalyzers/Analyzers/AttributeAnalyzer.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ public class AttributeAnalyzer : DiagnosticAnalyzer
1616
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(
1717
ASP001ParameterName.Descriptor,
1818
ASP002MissingParameter.Descriptor,
19-
ASP003ParameterType.Descriptor);
19+
ASP003ParameterType.Descriptor,
20+
ASP004ParameterSyntax.Descriptor);
2021

2122
public override void Initialize(AnalysisContext context)
2223
{
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
namespace AspNetCoreAnalyzers
2+
{
3+
using System.Collections.Immutable;
4+
using System.Threading.Tasks;
5+
using Gu.Roslyn.CodeFixExtensions;
6+
7+
public class ParameterSyntaxFix : DocumentEditorCodeFixProvider
8+
{
9+
public override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(
10+
ASP004ParameterSyntax.DiagnosticId);
11+
12+
protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context)
13+
{
14+
var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken)
15+
.ConfigureAwait(false);
16+
17+
foreach (var diagnostic in context.Diagnostics)
18+
{
19+
20+
}
21+
}
22+
}
23+
}

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ Roslyn analyzers for ASP.NET.Core.
2222
<td><a href="https://github.com/DotNetAnalyzers/AspNetCoreAnalyzers/tree/master/documentation/ASP003.md">ASP003</a></td>
2323
<td>Parameter type does not match template.</td>
2424
</tr>
25+
<tr>
26+
<td><a href="https://github.com/DotNetAnalyzers/AspNetCoreAnalyzers/tree/master/documentation/ASP004.md">ASP004</a></td>
27+
<td>Syntax error in parameter.</td>
28+
</tr>
2529
<table>
2630
<!-- end generated table -->
2731

documentation/ASP004.md

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# ASP004
2+
## Syntax error in parameter.
3+
4+
<!-- start generated table -->
5+
<table>
6+
<tr>
7+
<td>CheckId</td>
8+
<td>ASP004</td>
9+
</tr>
10+
<tr>
11+
<td>Severity</td>
12+
<td>Warning</td>
13+
</tr>
14+
<tr>
15+
<td>Enabled</td>
16+
<td>true</td>
17+
</tr>
18+
<tr>
19+
<td>Category</td>
20+
<td>AspNetCoreAnalyzers.Routing</td>
21+
</tr>
22+
<tr>
23+
<td>Code</td>
24+
<td><a href="https://github.com/DotNetAnalyzers/AspNetCoreAnalyzers/blob/master/AspNetCoreAnalyzers/Analyzers/AttributeAnalyzer.cs">AttributeAnalyzer</a></td>
25+
</tr>
26+
</table>
27+
<!-- end generated table -->
28+
29+
## Description
30+
31+
Syntax error in parameter.
32+
33+
## Motivation
34+
35+
```cs
36+
[HttpGet(""api/orders/id:int}"")]
37+
public IActionResult GetId(int id)
38+
{
39+
return this.Ok(id);
40+
}
41+
```
42+
43+
In the above code the opening curly brace for the parameter is missing.
44+
45+
## How to fix violations
46+
47+
Use the code fix of fix the syntax manually.
48+
The code in the example should be:
49+
50+
```cs
51+
[HttpGet(""api/orders/{id:int}"")]
52+
public IActionResult GetId(int id)
53+
{
54+
return this.Ok(id);
55+
}
56+
```
57+
58+
<!-- start generated config severity -->
59+
## Configure severity
60+
61+
### Via ruleset file.
62+
63+
Configure the severity per project, for more info see [MSDN](https://msdn.microsoft.com/en-us/library/dd264949.aspx).
64+
65+
### Via #pragma directive.
66+
```C#
67+
#pragma warning disable ASP004 // Syntax error in parameter.
68+
Code violating the rule here
69+
#pragma warning restore ASP004 // Syntax error in parameter.
70+
```
71+
72+
Or put this at the top of the file to disable all instances.
73+
```C#
74+
#pragma warning disable ASP004 // Syntax error in parameter.
75+
```
76+
77+
### Via attribute `[SuppressMessage]`.
78+
79+
```C#
80+
[System.Diagnostics.CodeAnalysis.SuppressMessage("AspNetCoreAnalyzers.Routing",
81+
"ASP004:Syntax error in parameter.",
82+
Justification = "Reason...")]
83+
```
84+
<!-- end generated config severity -->

0 commit comments

Comments
 (0)