Skip to content

Commit c2f523c

Browse files
authored
Merge pull request #31 from DotNetAnalyzers/handle_backslash
Handle backslash
2 parents 47730f9 + deaee44 commit c2f523c

9 files changed

Lines changed: 307 additions & 83 deletions

File tree

.paket/Paket.Restore.targets

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,43 @@
1717
<PaketExeImage Condition=" '$(PaketBootstrapperStyle)' == 'proj' ">native</PaketExeImage>
1818
<MonoPath Condition="'$(MonoPath)' == '' And Exists('/Library/Frameworks/Mono.framework/Commands/mono')">/Library/Frameworks/Mono.framework/Commands/mono</MonoPath>
1919
<MonoPath Condition="'$(MonoPath)' == ''">mono</MonoPath>
20-
<!-- Paket command -->
21-
<PaketExePath Condition=" '$(PaketExePath)' == '' AND Exists('$(PaketToolsPath)paket')">$(PaketToolsPath)paket</PaketExePath>
22-
<PaketExePath Condition=" '$(PaketExePath)' == '' AND Exists('$(PaketRootPath)paket.exe')">$(PaketRootPath)paket.exe</PaketExePath>
2320

24-
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' ">$(PaketToolsPath)paket.exe</PaketExePath>
25-
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND '$(PaketExeImage)' == 'assembly' ">$(PaketToolsPath)paket.exe</PaketExePath>
26-
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND '$(PaketExeImage)' == 'native' ">$(PaketToolsPath)paket</PaketExePath>
21+
<!-- PaketBootStrapper -->
22+
<PaketBootStrapperExePath Condition=" '$(PaketBootStrapperExePath)' == '' AND Exists('$(PaketRootPath)paket.bootstrapper.exe')">$(PaketRootPath)paket.bootstrapper.exe</PaketBootStrapperExePath>
23+
<PaketBootStrapperExePath Condition=" '$(PaketBootStrapperExePath)' == '' ">$(PaketToolsPath)paket.bootstrapper.exe</PaketBootStrapperExePath>
24+
<PaketBootStrapperExeDir Condition=" Exists('$(PaketBootStrapperExePath)') " >$([System.IO.Path]::GetDirectoryName("$(PaketBootStrapperExePath)"))\</PaketBootStrapperExeDir>
25+
26+
<!-- Paket -->
27+
28+
<!-- windows, root => tool => proj style => bootstrapper => global -->
29+
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' AND Exists('$(PaketRootPath)paket.exe') ">$(PaketRootPath)paket.exe</PaketExePath>
30+
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' AND Exists('$(PaketToolsPath)paket.exe') ">$(PaketToolsPath)paket.exe</PaketExePath>
31+
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' AND '$(PaketBootstrapperStyle)' == 'proj' ">$(PaketToolsPath)paket.exe</PaketExePath>
32+
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' AND Exists('$(PaketBootStrapperExeDir)') ">$(_PaketBootStrapperExeDir)paket.exe</PaketExePath>
33+
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' == 'Windows_NT' ">paket.exe</PaketExePath>
34+
35+
<!-- no windows, try native paket as default, root => tool => proj style => mono paket => bootstrpper => global -->
36+
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND Exists('$(PaketRootPath)paket') ">$(PaketRootPath)paket</PaketExePath>
37+
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND Exists('$(PaketToolsPath)paket') ">$(PaketToolsPath)paket</PaketExePath>
38+
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND '$(PaketBootstrapperStyle)' == 'proj' ">$(PaketToolsPath)paket</PaketExePath>
39+
40+
<!-- no windows, try mono paket -->
41+
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND Exists('$(PaketRootPath)paket.exe') ">$(PaketRootPath)paket.exe</PaketExePath>
42+
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND Exists('$(PaketToolsPath)paket.exe') ">$(PaketToolsPath)paket.exe</PaketExePath>
43+
44+
<!-- no windows, try bootstrapper -->
45+
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' AND Exists('$(PaketBootStrapperExeDir)') ">$(PaketBootStrapperExeDir)paket.exe</PaketExePath>
46+
47+
<!-- no windows, try global native paket -->
48+
<PaketExePath Condition=" '$(PaketExePath)' == '' AND '$(OS)' != 'Windows_NT' ">paket</PaketExePath>
2749

2850
<!-- Paket command -->
2951
<_PaketExeExtension>$([System.IO.Path]::GetExtension("$(PaketExePath)"))</_PaketExeExtension>
3052
<PaketCommand Condition=" '$(PaketCommand)' == '' AND '$(_PaketExeExtension)' == '.dll' ">dotnet "$(PaketExePath)"</PaketCommand>
31-
<PaketCommand Condition=" '$(PaketCommand)' == '' AND '$(OS)' == 'Windows_NT'">"$(PaketExePath)"</PaketCommand>
3253
<PaketCommand Condition=" '$(PaketCommand)' == '' AND '$(OS)' != 'Windows_NT' AND '$(_PaketExeExtension)' == '.exe' ">$(MonoPath) --runtime=v4.0.30319 "$(PaketExePath)"</PaketCommand>
33-
<PaketCommand Condition=" '$(PaketCommand)' == '' AND '$(OS)' != 'Windows_NT'">"$(PaketExePath)"</PaketCommand>
54+
<PaketCommand Condition=" '$(PaketCommand)' == '' ">"$(PaketExePath)"</PaketCommand>
55+
3456

35-
<PaketBootStrapperExePath Condition=" '$(PaketBootStrapperExePath)' == '' AND Exists('$(PaketRootPath)paket.bootstrapper.exe')">$(PaketRootPath)paket.bootstrapper.exe</PaketBootStrapperExePath>
36-
<PaketBootStrapperExePath Condition=" '$(PaketBootStrapperExePath)' == '' ">$(PaketToolsPath)paket.bootstrapper.exe</PaketBootStrapperExePath>
3757
<PaketBootStrapperCommand Condition=" '$(OS)' == 'Windows_NT'">"$(PaketBootStrapperExePath)"</PaketBootStrapperCommand>
3858
<PaketBootStrapperCommand Condition=" '$(OS)' != 'Windows_NT' ">$(MonoPath) --runtime=v4.0.30319 "$(PaketBootStrapperExePath)"</PaketBootStrapperCommand>
3959

AspNetCoreAnalyzers.Tests/ASP002MissingParameterTests/CodeFix.cs

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ public class CodeFix
1111
private static readonly ExpectedDiagnostic ExpectedDiagnostic = ExpectedDiagnostic.Create(ASP002MissingParameter.Descriptor);
1212
private static readonly CodeFixProvider Fix = new TemplateTextFix();
1313

14-
[TestCase("api/{↓value}", "api/{text}")]
15-
[TestCase("api/{↓value:alpha}", "api/{text:alpha}")]
14+
[TestCase("\"api/{↓value}\"", "\"api/{text}\"")]
15+
[TestCase("\"api/{↓value:alpha}\"", "\"api/{text:alpha}\"")]
1616
public void WhenWrongName(string before, string after)
1717
{
1818
var code = @"
@@ -31,7 +31,7 @@ public IActionResult GetValue(string text)
3131
return this.Ok(text);
3232
}
3333
}
34-
}".AssertReplace("api/{↓value}", before);
34+
}".AssertReplace("\"api/{↓value}\"", before);
3535

3636
var fixedCode = @"
3737
namespace ValidCode
@@ -49,7 +49,54 @@ public IActionResult GetValue(string text)
4949
return this.Ok(text);
5050
}
5151
}
52-
}".AssertReplace("api/{text}", after);
52+
}".AssertReplace("\"api/{text}\"", after);
53+
54+
AnalyzerAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, code, fixedCode);
55+
}
56+
57+
[TestCase("\"api/{text1}/{↓value}\"", "\"api/{text1}/{text2}\"")]
58+
[TestCase("\"api/{↓value}/{text2}\"", "\"api/{text1}/{text2}\"")]
59+
[TestCase("\"api/{text1:regex(\\\\d+)}/{↓value}\"", "\"api/{text1:regex(\\\\d+)}/{text2}\"")]
60+
[TestCase("\"api/{text1:regex(\\\\\\\\d+)}/{↓value}\"", "\"api/{text1:regex(\\\\\\\\d+)}/{text2}\"")]
61+
[TestCase("@\"api/{text1:regex(\\d+)}/{↓value}\"", "@\"api/{text1:regex(\\d+)}/{text2}\"")]
62+
[TestCase("\"api/{text1::regex(^\\\\\\\\d{{3}}-\\\\\\\\d{{2}}-\\\\\\\\d{{4}}$)}/{↓value}\"", "\"api/{text1::regex(^\\\\\\\\d{{3}}-\\\\\\\\d{{2}}-\\\\\\\\d{{4}}$)}/{text2}\"")]
63+
public void WhenWrongNameSecondParameter(string before, string after)
64+
{
65+
var code = @"
66+
namespace ValidCode
67+
{
68+
using System.Threading.Tasks;
69+
using Microsoft.AspNetCore.Mvc;
70+
using Microsoft.EntityFrameworkCore;
71+
72+
[ApiController]
73+
public class OrdersController : Controller
74+
{
75+
[HttpGet(""api/{text1}/{↓value}"")]
76+
public IActionResult GetValue(string text1, string text2)
77+
{
78+
return this.Ok(text1 + text2);
79+
}
80+
}
81+
}".AssertReplace("\"api/{text1}/{↓value}\"", before);
82+
83+
var fixedCode = @"
84+
namespace ValidCode
85+
{
86+
using System.Threading.Tasks;
87+
using Microsoft.AspNetCore.Mvc;
88+
using Microsoft.EntityFrameworkCore;
89+
90+
[ApiController]
91+
public class OrdersController : Controller
92+
{
93+
[HttpGet(""api/{text1}/{text2}"")]
94+
public IActionResult GetValue(string text1, string text2)
95+
{
96+
return this.Ok(text1 + text2);
97+
}
98+
}
99+
}".AssertReplace("\"api/{text1}/{text2}\"", after);
53100

54101
AnalyzerAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, code, fixedCode);
55102
}

AspNetCoreAnalyzers.Tests/ASP004ParameterSyntaxTests/CodeFix.cs

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,12 @@ public class CodeFix
1111
private static readonly ExpectedDiagnostic ExpectedDiagnostic = ExpectedDiagnostic.Create(ASP004ParameterSyntax.Descriptor);
1212
private static readonly CodeFixProvider Fix = new TemplateTextFix();
1313

14-
[TestCase("api/orders/↓id:long}", "api/orders/{id:long}")]
15-
[TestCase("api/orders/↓{id:long", "api/orders/{id:long}")]
16-
[TestCase("api/orders/{id:min(1}", "api/orders/{id:min(1)}")]
17-
[TestCase("api/orders/{id:max(1}", "api/orders/{id:max(1)}")]
18-
[TestCase("api/orders/{id:minlength(1}", "api/orders/{id:minlength(1)}")]
19-
[TestCase("api/orders/{id:maxlength(1}", "api/orders/{id:maxlength(1)}")]
20-
[TestCase("api/orders/{id:length(1}", "api/orders/{id:length(1)}")]
21-
[TestCase("api/orders/{id:length(1,2}", "api/orders/{id:length(1,2)}")]
22-
[TestCase("api/orders/{id:range(1,2}", "api/orders/{id:range(1,2)}")]
23-
[TestCase("api/orders/{id:regex((a|b)-c}", "api/orders/{id:regex((a|b)-c)}")]
24-
public void When(string before, string after)
14+
[TestCase("api/orders/↓id:long}", "api/orders/{id:long}")]
15+
[TestCase("api/orders/↓{id:long", "api/orders/{id:long}")]
16+
[TestCase("api/orders/{id:min(1}", "api/orders/{id:min(1)}")]
17+
[TestCase("api/orders/{id:max(1}", "api/orders/{id:max(1)}")]
18+
[TestCase("api/orders/{id:range(1,2}", "api/orders/{id:range(1,2)}")]
19+
public void WhenLong(string before, string after)
2520
{
2621
var code = @"
2722
namespace ValidCode
@@ -56,5 +51,48 @@ public IActionResult GetId(long id)
5651
}".AssertReplace("api/orders/{id:long}", after);
5752
AnalyzerAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, code, fixedCode);
5853
}
54+
55+
[TestCase("\"api/orders/{id:↓minlength(1}\"", "\"api/orders/{id:minlength(1)}\"")]
56+
[TestCase("\"api/orders/{id:↓maxlength(1}\"", "\"api/orders/{id:maxlength(1)}\"")]
57+
[TestCase("\"api/orders/{id:↓length(1}\"", "\"api/orders/{id:length(1)}\"")]
58+
[TestCase("\"api/orders/{id:↓length(1,2}\"", "\"api/orders/{id:length(1,2)}\"")]
59+
[TestCase("\"api/orders/{id:↓regex((a|b)-c}\"", "\"api/orders/{id:regex((a|b)-c)}\"")]
60+
[TestCase("\"api/orders/{id:regex(\\\\d+):↓length(1}\"", "\"api/orders/{id:regex(\\\\d+):length(1)}\"")]
61+
public void WhenString(string before, string after)
62+
{
63+
var code = @"
64+
namespace ValidCode
65+
{
66+
using Microsoft.AspNetCore.Mvc;
67+
68+
[ApiController]
69+
public class OrdersController : Controller
70+
{
71+
[HttpGet(""api/orders/{id}"")]
72+
public IActionResult GetId(string id)
73+
{
74+
return this.Ok(id);
75+
}
76+
}
77+
}".AssertReplace("\"api/orders/{id}\"", before);
78+
79+
var fixedCode = @"
80+
namespace ValidCode
81+
{
82+
using Microsoft.AspNetCore.Mvc;
83+
84+
[ApiController]
85+
public class OrdersController : Controller
86+
{
87+
[HttpGet(""api/orders/{id}"")]
88+
public IActionResult GetId(string id)
89+
{
90+
return this.Ok(id);
91+
}
92+
}
93+
}".AssertReplace("\"api/orders/{id}\"", after);
94+
95+
AnalyzerAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, code, fixedCode);
96+
}
5997
}
6098
}

AspNetCoreAnalyzers.Tests/ASP004ParameterSyntaxTests/Diagnostics.cs

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
namespace AspNetCoreAnalyzers.Tests.ASP004ParameterSyntaxTests
22
{
3+
using System.Globalization;
34
using Gu.Roslyn.Asserts;
5+
using Microsoft.CodeAnalysis;
46
using Microsoft.CodeAnalysis.Diagnostics;
7+
using Microsoft.CodeAnalysis.Text;
58
using NUnit.Framework;
69

710
public class Diagnostics
@@ -10,6 +13,7 @@ public class Diagnostics
1013
private static readonly ExpectedDiagnostic ExpectedDiagnostic = ExpectedDiagnostic.Create(ASP004ParameterSyntax.Descriptor);
1114

1215
[TestCase("\"api/orders/{id:↓wrong}\"")]
16+
[TestCase("@\"api/orders/{id:↓wrong}\"")]
1317
[TestCase("\"api/orders/{id:min1)}\"")]
1418
[TestCase("\"api/orders/{id:max1)}\"")]
1519
[TestCase("\"api/orders/{id:min(↓wrong))}\"")]
@@ -38,8 +42,12 @@ public IActionResult GetId(long id)
3842
AnalyzerAssert.Diagnostics(Analyzer, ExpectedDiagnostic, code);
3943
}
4044

41-
[TestCase("api/orders/{id:minlength(↓wrong))}")]
42-
[TestCase("api/orders/{id:maxlength(↓wrong))}")]
45+
[TestCase("\"api/orders/{id:minlength(↓wrong))}\"")]
46+
[TestCase("\"api/orders/{id:minlength(↓1a))}\"")]
47+
[TestCase("\"api/orders/{id:minlength(↓a1))}\"")]
48+
[TestCase("\"api/orders/{id:maxlength(↓wrong))}\"")]
49+
[TestCase("\"api/orders/{id:regex(\\\\d):minlength(↓wrong))}\"")]
50+
[TestCase("@\"api/orders/{id:regex(\\d):minlength(↓wrong))}\"")]
4351
public void WhenString(string before)
4452
{
4553
var code = @"
@@ -56,9 +64,36 @@ public IActionResult GetId(string id)
5664
return this.Ok(id);
5765
}
5866
}
59-
}".AssertReplace("api/orders/↓{id:wrong}", before);
67+
}".AssertReplace("\"api/orders/↓{id:wrong}\"", before);
6068

6169
AnalyzerAssert.Diagnostics(Analyzer, ExpectedDiagnostic, code);
6270
}
71+
72+
[TestCase("\"api/orders/{id:regex(\\\\d):minlength(wrong)}\"", 54, 59)]
73+
[TestCase("@\"api/orders/{id:regex(\\d):minlength(wrong)}\"", 54, 59)]
74+
public void WhenStringExplicitSpan(string before, int start, int end)
75+
{
76+
var code = @"
77+
namespace ValidCode
78+
{
79+
using Microsoft.AspNetCore.Mvc;
80+
81+
[ApiController]
82+
public class OrdersController : Controller
83+
{
84+
[HttpGet(""api/orders/{id:wrong}"")]
85+
public IActionResult GetId(string id)
86+
{
87+
return this.Ok(id);
88+
}
89+
}
90+
}".AssertReplace("\"api/orders/{id:wrong}\"", before);
91+
92+
var expectedDiagnostic = new ExpectedDiagnostic(
93+
ASP004ParameterSyntax.DiagnosticId,
94+
ASP004ParameterSyntax.Descriptor.MessageFormat.ToString(CultureInfo.InvariantCulture),
95+
new FileLinePositionSpan("OrdersController.cs", new LinePosition(8, start), new LinePosition(8, end)));
96+
AnalyzerAssert.Diagnostics(Analyzer, expectedDiagnostic, code);
97+
}
6398
}
6499
}

AspNetCoreAnalyzers.Tests/ASP005ParameterRegexTests/CodeFix.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@ public class CodeFix
1111
private static readonly ExpectedDiagnostic ExpectedDiagnostic = ExpectedDiagnostic.Create(ASP005ParameterRegex.Descriptor);
1212
private static readonly CodeFixProvider Fix = new TemplateTextFix();
1313

14-
[TestCase("api/orders/{id:regex(↓a{1})}", "api/orders/{id:regex(a{{1}})}")]
15-
[TestCase("api/orders/{id:regex(↓^[a-z]{2}$)}", "api/orders/{id:regex(^[[a-z]]{{2}}$)}")]
14+
[TestCase("\"api/orders/{id:regex(↓a{1})}\"", "\"api/orders/{id:regex(a{{1}})}\"")]
15+
[TestCase("\"api/orders/{id:regex(↓^[a-z]{2}$)}\"", "\"api/orders/{id:regex(^[[a-z]]{{2}}$)}\"")]
16+
[TestCase("\"api/orders/{id:regex(↓\\\\d+)}\"", "\"api/orders/{id:regex(\\\\\\\\d+)}\"")]
17+
[TestCase("@\"api/orders/{id:regex(↓\\d+)}\"", "@\"api/orders/{id:regex(\\\\d+)}\"")]
18+
[TestCase("\"api/orders/{id:regex(↓^\\\\d{3}-\\\\d{2}-\\\\d{4}$)}\"", "\"api/orders/{id:regex(^\\\\\\\\d{{3}}-\\\\\\\\d{{2}}-\\\\\\\\d{{4}}$)}\"")]
19+
[TestCase("@\"api/orders/{id:regex(↓^\\d{3}-\\d{2}-\\d{4}$)}\"", "@\"api/orders/{id:regex(^\\\\d{{3}}-\\\\d{{2}}-\\\\d{{4}}$)}\"")]
1620
public void When(string before, string after)
1721
{
1822
var code = @"
@@ -29,7 +33,7 @@ public IActionResult GetId(string id)
2933
return this.Ok(id);
3034
}
3135
}
32-
}".AssertReplace("api/orders/{id}", before);
36+
}".AssertReplace("\"api/orders/{id}\"", before);
3337

3438
var fixedCode = @"
3539
namespace ValidCode
@@ -45,7 +49,7 @@ public IActionResult GetId(string id)
4549
return this.Ok(id);
4650
}
4751
}
48-
}".AssertReplace("api/orders/{id}", after);
52+
}".AssertReplace("\"api/orders/{id}\"", after);
4953
AnalyzerAssert.CodeFix(Analyzer, Fix, ExpectedDiagnostic, code, fixedCode);
5054
}
5155
}

0 commit comments

Comments
 (0)