Skip to content

Commit

Permalink
Add more test cases
Browse files Browse the repository at this point in the history
  • Loading branch information
costin-zaharia-sonarsource committed Mar 21, 2024
1 parent ce45574 commit 1951a32
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace SonarAnalyzer.Rules.CSharp;
public sealed class SpecifyRouteAttribute : SonarDiagnosticAnalyzer
{
private const string DiagnosticId = "S6934";
private const string MessageFormat = "Specify the RouteAttribute when an HttpMethodAttribute is specified at an action level";
private const string MessageFormat = "Specify the RouteAttribute when an HttpMethodAttribute is specified at an action level.";

private static readonly DiagnosticDescriptor Rule = DescriptorFactory.Create(DiagnosticId, MessageFormat);

Expand All @@ -49,7 +49,7 @@ protected override void Initialize(SonarAnalysisContext context) =>
symbolStart.RegisterSyntaxNodeAction(nodeContext =>
{
var node = (MethodDeclarationSyntax)nodeContext.Node;
if (nodeContext.SemanticModel.GetDeclaredSymbol(node, nodeContext.Cancel) is IMethodSymbol method
if (nodeContext.SemanticModel.GetDeclaredSymbol(node, nodeContext.Cancel) is { } method
&& method.IsControllerMethod()
&& method.GetAttributes().Any(x =>
x.AttributeClass.IsAny(KnownType.Microsoft_AspNetCore_Mvc_Routing_HttpMethodAttributes)
Expand All @@ -67,9 +67,12 @@ private static void ReportIssues(SonarSymbolReportingContext context, ISymbol sy
{
if (!secondaryLocations.IsEmpty)
{
foreach (var declaration in symbol.DeclaringSyntaxReferences.Select(r => r.GetSyntax()))
foreach (var declaration in symbol.DeclaringSyntaxReferences.Select(x => x.GetSyntax()))
{
context.ReportIssue(CSharpGeneratedCodeRecognizer.Instance, Diagnostic.Create(Rule, declaration.GetLocation(), secondaryLocations));
if (declaration.GetIdentifier() is { } identifier)
{
context.ReportIssue(CSharpGeneratedCodeRecognizer.Instance, Diagnostic.Create(Rule, identifier.GetLocation(), secondaryLocations));
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,38 +1,95 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Routing;

public class NoActionHasHttpAttributeWithRouteController : Controller
using MA = Microsoft.AspNetCore;

public class RouteTemplateIsNotSpecified : Controller
{
public IActionResult Index() => View(); // Compliant
public IActionResult Index() => View(); // Compliant

[HttpGet]
public IActionResult Index2() => View(); // Compliant, default behavior if not route template is defined
public IActionResult Index2() => View(); // Compliant

[HttpGet()]
public IActionResult Index3() => View(); // Compliant

[HttpGetAttribute]
public IActionResult Index4() => View(); // Compliant

[Microsoft.AspNetCore.Mvc.HttpGet]
public IActionResult Index5() => View(); // Compliant

[MA.Mvc.HttpGet]
public IActionResult Index6() => View(); // Compliant

public IActionResult Error() => View(); // Compliant
[method: HttpGet]
public IActionResult Index7() => View(); // Compliant

public IActionResult Error() => View(); // Compliant
}

public class ActionHasHttpAttributeWithRouteController : Controller // Noncompliant [controller]
public class RouteTemplatesAreSpecified : Controller // Noncompliant [controller] {{Specify the RouteAttribute when an HttpMethodAttribute is specified at an action level.}}
// ^^^^^^^^^^^^^^^^^^^^^^^^^^
{
[HttpGet("GetObject")]
public IActionResult Get() => View(); // Secondary [controller]
private const string ConstantRoute = "ConstantRoute";

[HttpGet("GetObject")]
public IActionResult Get() => View();
// ^^^ Secondary [controller]

[HttpGet("GetFirst")]
[HttpGet("GetSecond")]
public IActionResult GetMultipleTemplates() => View(); // Secondary [controller]

[HttpGet("GetFirst")]
[HttpPut("GetSecond")]
public IActionResult Mix() => View(); // Secondary [controller]

[HttpPost("CreateObject")]
public IActionResult Post() => View(); // Secondary [controller]

[HttpPut("UpdateObject")]
public IActionResult Put() => View(); // Secondary [controller]

[HttpDelete("DeleteObject")]
public IActionResult Delete() => View(); // Secondary [controller]

[HttpPatch("PatchObject")]
public IActionResult Patch() => View(); // Secondary [controller]

[HttpHead("Head")]
public IActionResult HttpHead() => View(); // Secondary [controller]

[HttpOptions("Options")]
public IActionResult HttpOptions() => View(); // Secondary [controller]

[Route("details")]
public IActionResult GetDetails() => View(); // FN

[HttpGet("details", Order = 1)]
public IActionResult GetDetails2() => View(); // Secondary [controller]

[HttpPost("CreateObject")]
public IActionResult Post() => View(); // Secondary [controller]
[HttpGet("details", Order = 1, Name = "Details")]
public IActionResult GetDetails3() => View(); // Secondary [controller]

[HttpPut("UpdateObject")]
public IActionResult Put() => View(); // Secondary [controller]
[HttpGet(ConstantRoute)]
public IActionResult GetDetails4() => View(); // Secondary [controller]

[HttpDelete("DeleteObject")]
public IActionResult Delete() => View(); // Secondary [controller]
[HttpGet("""
ConstantRoute
""")]
public IActionResult GetDetails5() => View(); // Secondary [controller]

[HttpPatch("PatchObject")]
public IActionResult Patch() => View(); // Secondary [controller]
[HttpGet($"Route {ConstantRoute}")]
public IActionResult GetDetails6() => View(); // Secondary [controller]

[HttpHead("Head")]
public IActionResult HttpHead() => View(); // Secondary [controller]
[HttpGet($"""
{ConstantRoute}
""")]
public IActionResult GetDetails7() => View(); // Secondary [controller]

[HttpOptions("Options")]
public IActionResult HttpOptions() => View(); // Secondary [controller]
// [HttpPost("Comment")]
public IActionResult Comment() => View();
}

public class WithUserDefinedAttribute : Controller
Expand Down

0 comments on commit 1951a32

Please sign in to comment.