Skip to content

Commit 66532eb

Browse files
committed
Rename parameter in attribute text fix.
1 parent 1fa5a85 commit 66532eb

8 files changed

Lines changed: 139 additions & 59 deletions

File tree

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
namespace AspNetCoreAnalyzers.Tests.ASP002MissingParameterTests
2+
{
3+
using Gu.Roslyn.Asserts;
4+
using Microsoft.CodeAnalysis.CodeFixes;
5+
using Microsoft.CodeAnalysis.Diagnostics;
6+
using NUnit.Framework;
7+
8+
public class CodeFix
9+
{
10+
private static readonly DiagnosticAnalyzer Analyzer = new AttributeAnalyzer();
11+
private static readonly ExpectedDiagnostic ExpectedDiagnostic = ExpectedDiagnostic.Create(ASP002MissingParameter.Descriptor);
12+
private static readonly CodeFixProvider Fix = new TemplateTextFix();
13+
14+
[TestCase("api/{↓value}", "api/{text}")]
15+
[TestCase("api/{↓value:alpha}", "api/{text:alpha}")]
16+
public void WhenWrongName(string before, string after)
17+
{
18+
var code = @"
19+
namespace ValidCode
20+
{
21+
using System.Threading.Tasks;
22+
using Microsoft.AspNetCore.Mvc;
23+
using Microsoft.EntityFrameworkCore;
24+
25+
[ApiController]
26+
public class OrdersController : Controller
27+
{
28+
[HttpGet(""api/{↓value}"")]
29+
public IActionResult GetValue(string text)
30+
{
31+
return this.Ok(text);
32+
}
33+
}
34+
}".AssertReplace("api/{↓value}", before);
35+
36+
var fixedCode = @"
37+
namespace ValidCode
38+
{
39+
using System.Threading.Tasks;
40+
using Microsoft.AspNetCore.Mvc;
41+
using Microsoft.EntityFrameworkCore;
42+
43+
[ApiController]
44+
public class OrdersController : Controller
45+
{
46+
[HttpGet(""api/{text}"")]
47+
public IActionResult GetValue(string text)
48+
{
49+
return this.Ok(text);
50+
}
51+
}
52+
}".AssertReplace("api/{text}", after);
53+
54+
AnalyzerAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, code, fixedCode);
55+
}
56+
}
57+
}

AspNetCoreAnalyzers.Tests/ASP002MissingParameterTests/ValidCode.cs

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -172,28 +172,5 @@ public async Task<IActionResult> GetOrder([FromHeader]int id)
172172
}";
173173
AnalyzerAssert.Valid(Analyzer, order, db, code);
174174
}
175-
176-
[Test]
177-
public void WhenWrongName()
178-
{
179-
var code = @"
180-
namespace ValidCode
181-
{
182-
using System.Threading.Tasks;
183-
using Microsoft.AspNetCore.Mvc;
184-
using Microsoft.EntityFrameworkCore;
185-
186-
[ApiController]
187-
public class OrdersController : Controller
188-
{
189-
[HttpGet(""api/{value}"")]
190-
public IActionResult GetValue(string wrongName)
191-
{
192-
return this.Ok(wrongName);
193-
}
194-
}
195-
}";
196-
AnalyzerAssert.Valid(Analyzer, ASP002MissingParameter.Descriptor, code);
197-
}
198175
}
199176
}

AspNetCoreAnalyzers.Tests/ASP004ParameterSyntaxTests/CodeFix.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public class CodeFix
99
{
1010
private static readonly DiagnosticAnalyzer Analyzer = new AttributeAnalyzer();
1111
private static readonly ExpectedDiagnostic ExpectedDiagnostic = ExpectedDiagnostic.Create(ASP004ParameterSyntax.Descriptor);
12-
private static readonly CodeFixProvider Fix = new ParameterSyntaxFix();
12+
private static readonly CodeFixProvider Fix = new TemplateTextFix();
1313

1414
[TestCase("api/orders/↓id:long}", "api/orders/{id:long}")]
1515
[TestCase("api/orders/↓{id:long", "api/orders/{id:long}")]

AspNetCoreAnalyzers.Tests/ASP004ParameterSyntaxTests/Diagnostics.cs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,33 @@ public class Diagnostics
1414
[TestCase("api/orders/{id:max1)}")]
1515
[TestCase("api/orders/{id:min(↓wrong))}")]
1616
[TestCase("api/orders/{id:max(↓wrong))}")]
17+
[TestCase("api/orders/{id:↓:long)}")]
18+
[TestCase("api/orders/{id:long:↓)}")]
19+
[TestCase("api/orders/{id:long:↓:)}")]
20+
public void WhenLong(string before)
21+
{
22+
var code = @"
23+
namespace ValidCode
24+
{
25+
using Microsoft.AspNetCore.Mvc;
26+
27+
[ApiController]
28+
public class OrdersController : Controller
29+
{
30+
[HttpGet(""api/orders/↓{id:wrong}"")]
31+
public IActionResult GetId(long id)
32+
{
33+
return this.Ok(id);
34+
}
35+
}
36+
}".AssertReplace("api/orders/↓{id:wrong}", before);
37+
38+
AnalyzerAssert.Diagnostics(Analyzer, ExpectedDiagnostic, code);
39+
}
40+
1741
[TestCase("api/orders/{id:minlength(↓wrong))}")]
1842
[TestCase("api/orders/{id:maxlength(↓wrong))}")]
19-
[TestCase("api/orders/{id:↓:int)}")]
20-
[TestCase("api/orders/{id:int:↓)}")]
21-
[TestCase("api/orders/{id:int:↓:)}")]
22-
public void When(string before)
43+
public void WhenString(string before)
2344
{
2445
var code = @"
2546
namespace ValidCode
@@ -30,7 +51,7 @@ namespace ValidCode
3051
public class OrdersController : Controller
3152
{
3253
[HttpGet(""api/orders/↓{id:wrong}"")]
33-
public IActionResult GetId(long id)
54+
public IActionResult GetId(string id)
3455
{
3556
return this.Ok(id);
3657
}

AspNetCoreAnalyzers.Tests/ASP005ParameterRegexTests/CodeFix.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public class CodeFix
99
{
1010
private static readonly DiagnosticAnalyzer Analyzer = new AttributeAnalyzer();
1111
private static readonly ExpectedDiagnostic ExpectedDiagnostic = ExpectedDiagnostic.Create(ASP005ParameterRegex.Descriptor);
12-
private static readonly CodeFixProvider Fix = new ParameterSyntaxFix();
12+
private static readonly CodeFixProvider Fix = new TemplateTextFix();
1313

1414
[TestCase("api/orders/{id:regex(↓a{1})}", "api/orders/{id:regex(a{{1}})}")]
1515
[TestCase("api/orders/{id:regex(↓^[a-z]{2}$)}", "api/orders/{id:regex(^[[a-z]]{{2}}$)}")]

AspNetCoreAnalyzers.Tests/ASP005ParameterRegexTests/ValidCode.cs

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,32 @@ public class ValidCode
88
{
99
private static readonly DiagnosticAnalyzer Analyzer = new AttributeAnalyzer();
1010

11-
[TestCase("{value}", "string")]
12-
[TestCase("{value?}", "string")]
13-
[TestCase("{value:bool}", "bool")]
14-
[TestCase("{value:datetime}", "System.DateTime")]
15-
[TestCase("{value:decimal}", "decimal")]
16-
[TestCase("{value:double}", "double")]
17-
[TestCase("{value:float}", "float")]
18-
[TestCase("{value:int}", "int")]
19-
[TestCase("api/orders/{value:int:min(1)}", "int")]
20-
[TestCase("api/orders/{value:int:max(1)}", "int")]
21-
[TestCase("api/orders/{value:int:range(1,10)}", "int")]
22-
[TestCase("api/orders/{value:int:required}", "int")]
23-
[TestCase("{value:long}", "long")]
24-
[TestCase("api/orders/{value:min(1)}", "long")]
25-
[TestCase("api/orders/{value:max(1)}", "long")]
26-
[TestCase("api/orders/{value:range(1,10)}", "long")]
27-
[TestCase("api/orders/{value:required}", "long")]
28-
[TestCase("{value:guid}", "System.Guid")]
29-
[TestCase("api/orders/{value:minlength(1)}", "string")]
30-
[TestCase("api/orders/{value:maxlength(1)}", "string")]
31-
[TestCase("api/orders/{value:length(1)}", "string")]
32-
[TestCase("api/orders/{value:length(1,3)}", "string")]
33-
[TestCase("api/orders/{value:alpha}", "string")]
34-
[TestCase("api/orders/{value:regex(a-(0|1))}", "string")]
35-
[TestCase("api/orders/{value:regex(^\\\\d{{3}}-\\\\d{{2}}-\\\\d{{4}}$)}", "string")]
36-
[TestCase("api/orders/{value:required}", "string")]
11+
[TestCase("{value}", "string")]
12+
[TestCase("{value?}", "string")]
13+
[TestCase("{value:bool}", "bool")]
14+
[TestCase("{value:datetime}", "System.DateTime")]
15+
[TestCase("{value:decimal}", "decimal")]
16+
[TestCase("{value:double}", "double")]
17+
[TestCase("{value:float}", "float")]
18+
[TestCase("{value:int}", "int")]
19+
[TestCase("api/orders/{value:int:min(1)}", "int")]
20+
[TestCase("api/orders/{value:int:max(1)}", "int")]
21+
[TestCase("api/orders/{value:int:range(1,10)}", "int")]
22+
[TestCase("api/orders/{value:int:required}", "int")]
23+
[TestCase("{value:long}", "long")]
24+
[TestCase("api/orders/{value:min(1)}", "long")]
25+
[TestCase("api/orders/{value:max(1)}", "long")]
26+
[TestCase("api/orders/{value:range(1,10)}", "long")]
27+
[TestCase("api/orders/{value:required}", "long")]
28+
[TestCase("{value:guid}", "System.Guid")]
29+
[TestCase("api/orders/{value:minlength(1)}", "string")]
30+
[TestCase("api/orders/{value:maxlength(1)}", "string")]
31+
[TestCase("api/orders/{value:length(1)}", "string")]
32+
[TestCase("api/orders/{value:length(1,3)}", "string")]
33+
[TestCase("api/orders/{value:alpha}", "string")]
34+
[TestCase("api/orders/{value:regex(a-(0|1))}", "string")]
35+
[TestCase("api/orders/{value:regex(^\\\\\\\\d{{3}}-\\\\\\\\d{{2}}-\\\\\\\\d{{4}}$)}", "string")]
36+
[TestCase("api/orders/{value:required}", "string")]
3737
public void WithParameter(string parameter, string type)
3838
{
3939
var code = @"

AspNetCoreAnalyzers/Analyzers/AttributeAnalyzer.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ context.ContainingSymbol is IMethodSymbol method &&
4848
ImmutableDictionary<string, string>.Empty.Add(
4949
nameof(NameSyntax),
5050
templateParameter.Name.Text)));
51+
52+
context.ReportDiagnostic(
53+
Diagnostic.Create(
54+
ASP002MissingParameter.Descriptor,
55+
templateParameter.Name.GetLocation(),
56+
ImmutableDictionary<string, string>.Empty.Add(
57+
nameof(Text),
58+
withMethodParameter.Method.Name)));
5159
}
5260
else if (pairs.Count(x => x.Template == null) > 1 &&
5361
pairs.Count(x => x.Method == null) > 1)

AspNetCoreAnalyzers/CodeFixes/ParameterSyntaxFix.cs renamed to AspNetCoreAnalyzers/CodeFixes/TemplateTextFix.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace AspNetCoreAnalyzers
22
{
3+
using System;
34
using System.Collections.Immutable;
45
using System.Composition;
56
using System.Threading;
@@ -10,11 +11,12 @@ namespace AspNetCoreAnalyzers
1011
using Microsoft.CodeAnalysis.CodeFixes;
1112
using Microsoft.CodeAnalysis.CSharp.Syntax;
1213

13-
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(ParameterSyntaxFix))]
14+
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(TemplateTextFix))]
1415
[Shared]
15-
public class ParameterSyntaxFix : CodeFixProvider
16+
public class TemplateTextFix : CodeFixProvider
1617
{
1718
public override ImmutableArray<string> FixableDiagnosticIds { get; } = ImmutableArray.Create(
19+
ASP002MissingParameter.DiagnosticId,
1820
ASP004ParameterSyntax.DiagnosticId,
1921
ASP005ParameterRegex.DiagnosticId);
2022

@@ -32,7 +34,7 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
3234
{
3335
context.RegisterCodeFix(
3436
CodeAction.Create(
35-
diagnostic.Id == ASP004ParameterSyntax.DiagnosticId ? "Fix syntax error." : "Escape regex",
37+
GetTitle(diagnostic),
3638
_ => Fix(_)),
3739
diagnostic);
3840

@@ -45,5 +47,20 @@ async Task<Document> Fix(CancellationToken cancellationToken)
4547
}
4648
}
4749
}
50+
51+
private static string GetTitle(Diagnostic diagnostic)
52+
{
53+
switch (diagnostic.Id)
54+
{
55+
case ASP002MissingParameter.DiagnosticId:
56+
return "Rename parameter";
57+
case ASP004ParameterSyntax.DiagnosticId:
58+
return "Fix syntax error.";
59+
case ASP005ParameterRegex.DiagnosticId:
60+
return "Escape regex.";
61+
default:
62+
throw new InvalidOperationException("Should never get here.");
63+
}
64+
}
4865
}
4966
}

0 commit comments

Comments
 (0)