-
Notifications
You must be signed in to change notification settings - Fork 231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix S4529: Should not highlight constructors, properties and methods with NonActionAttribute #2109
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,8 +29,13 @@ public static class AspNetMvcHelper | |
private static readonly ImmutableArray<KnownType> controllerTypes = | ||
ImmutableArray.Create( | ||
KnownType.Microsoft_AspNetCore_Mvc_ControllerBase, | ||
KnownType.System_Web_Mvc_Controller | ||
); | ||
KnownType.System_Web_Mvc_Controller); | ||
|
||
private static readonly ImmutableArray<KnownType> nonactionTypes = | ||
ImmutableArray.Create( | ||
KnownType.Microsoft_AspNetCore_Mvc_NonActionAttribute, | ||
KnownType.System_Web_Mvc_NonActionAttribute); | ||
|
||
|
||
private static readonly ImmutableArray<KnownType> nonControllerAttributeTypes = | ||
ImmutableArray.Create(KnownType.Microsoft_AspNetCore_Mvc_NonControllerAttribute); | ||
|
@@ -44,6 +49,8 @@ public static class AspNetMvcHelper | |
/// </summary> | ||
public static bool IsControllerMethod(this IMethodSymbol methodSymbol) => | ||
methodSymbol.GetEffectiveAccessibility() == Accessibility.Public && | ||
methodSymbol.MethodKind == MethodKind.Ordinary && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would put this line before the effective accessibility check as it is simpler (faster). |
||
!methodSymbol.GetAttributes().Any(d => d.AttributeClass.IsAny(nonactionTypes)) && | ||
IsControllerType(methodSymbol?.ContainingType); | ||
|
||
/// <summary> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,10 +40,12 @@ public void PublicFoo() { } | |
protected void ProtectedFoo() { } | ||
internal void InternalFoo() { } | ||
private void PrivateFoo() { } | ||
private class Bar : System.Web.Mvb.Controller | ||
private class Bar : System.Web.Mvc.Controller | ||
{ | ||
public void InnerFoo() { } | ||
} | ||
[System.Web.Mvc.NonActionAttribute] | ||
public void PublicNonAction() { } | ||
} | ||
"; | ||
var compilation = TestHelper.Compile(code, | ||
|
@@ -54,12 +56,14 @@ public void InnerFoo() { } | |
var internalFoo = compilation.GetMethodSymbol("InternalFoo"); | ||
var privateFoo = compilation.GetMethodSymbol("PrivateFoo"); | ||
var innerFoo = compilation.GetMethodSymbol("InnerFoo"); | ||
var publicNonAction = compilation.GetMethodSymbol("PublicNonAction"); | ||
|
||
AspNetMvcHelper.IsControllerMethod(publicFoo).Should().Be(true); | ||
AspNetMvcHelper.IsControllerMethod(protectedFoo).Should().Be(false); | ||
AspNetMvcHelper.IsControllerMethod(internalFoo).Should().Be(false); | ||
AspNetMvcHelper.IsControllerMethod(privateFoo).Should().Be(false); | ||
AspNetMvcHelper.IsControllerMethod(innerFoo).Should().Be(false); | ||
AspNetMvcHelper.IsControllerMethod(publicNonAction).Should().Be(false); | ||
} | ||
|
||
[DataTestMethod] | ||
|
@@ -71,6 +75,8 @@ public void Controller_Methods_Are_EntryPoints(string aspNetMvcVersion) | |
public class Foo : System.Web.Mvc.Controller | ||
{ | ||
public void PublicFoo() { } | ||
[System.Web.Mvc.NonActionAttribute] | ||
public void PublicNonAction() { } | ||
} | ||
public class Controller | ||
{ | ||
|
@@ -87,52 +93,58 @@ public void PublicDiz() { } | |
var publicFoo = compilation.GetMethodSymbol("PublicFoo"); | ||
var publicBar = compilation.GetMethodSymbol("PublicBar"); | ||
var publicDiz = compilation.GetMethodSymbol("PublicDiz"); | ||
var publicNonAction = compilation.GetMethodSymbol("PublicNonAction"); | ||
|
||
AspNetMvcHelper.IsControllerMethod(publicFoo).Should().Be(true); | ||
AspNetMvcHelper.IsControllerMethod(publicBar).Should().Be(false); | ||
AspNetMvcHelper.IsControllerMethod(publicDiz).Should().Be(false); | ||
AspNetMvcHelper.IsControllerMethod(publicNonAction).Should().Be(false); | ||
} | ||
|
||
[DataTestMethod] | ||
[DataRow("3.0.20105.1")] | ||
[DataRow("2.1.3")] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please explain why you did this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The test is for ASP.NET MVC Core (the attributes are not present in the desktop version of ASP.NET MVC) |
||
[DataRow(Constants.NuGetLatestVersion)] | ||
public void Methods_In_Classes_With_ControllerAttribute_Are_EntryPoints(string aspNetMvcVersion) | ||
{ | ||
const string code = @" | ||
// The Attribute suffix is required because we don't have a reference | ||
// to ASP.NET Core and we cannot do type checking in the test project. | ||
// We will need to convert this test project to .NET Core to do that. | ||
[Microsoft.AspNetCore.Mvc.ControllerAttribute] | ||
public class Foo | ||
{ | ||
public void PublicFoo() { } | ||
[Microsoft.AspNetCore.Mvc.NonActionAttribute] | ||
public void PublicNonAction() { } | ||
} | ||
"; | ||
var compilation = TestHelper.Compile(code, | ||
additionalReferences: NuGetMetadataReference.MicrosoftAspNetMvc(aspNetMvcVersion).ToArray()); | ||
additionalReferences: | ||
FrameworkMetadataReference.Netstandard | ||
.Union(NuGetMetadataReference.MicrosoftAspNetCoreMvcCore(aspNetMvcVersion)) | ||
.ToArray()); | ||
|
||
var publicFoo = compilation.GetMethodSymbol("PublicFoo"); | ||
var publicNonAction = compilation.GetMethodSymbol("PublicNonAction"); | ||
|
||
AspNetMvcHelper.IsControllerMethod(publicFoo).Should().Be(true); | ||
AspNetMvcHelper.IsControllerMethod(publicNonAction).Should().Be(false); | ||
} | ||
|
||
[DataTestMethod] | ||
[DataRow("3.0.20105.1")] | ||
[DataRow("2.1.3")] | ||
[DataRow(Constants.NuGetLatestVersion)] | ||
public void Methods_In_Classes_With_NonControllerAttribute_Are_Not_EntryPoints(string aspNetMvcVersion) | ||
{ | ||
const string code = @" | ||
// The Attribute suffix is required because we don't have a reference | ||
// to ASP.NET Core and we cannot do type checking in the test project. | ||
// We will need to convert this test project to .NET Core to do that. | ||
[Microsoft.AspNetCore.Mvc.NonControllerAttribute] | ||
public class Foo : Microsoft.AspNetCore.Mvc.ControllerBase | ||
{ | ||
public void PublicFoo() { } | ||
} | ||
"; | ||
var compilation = TestHelper.Compile(code, | ||
additionalReferences: NuGetMetadataReference.MicrosoftAspNetMvc(aspNetMvcVersion).ToArray()); | ||
additionalReferences: | ||
FrameworkMetadataReference.Netstandard | ||
.Union(NuGetMetadataReference.MicrosoftAspNetCoreMvcCore(aspNetMvcVersion)) | ||
.ToArray()); | ||
|
||
var publicFoo = compilation.GetMethodSymbol("PublicFoo"); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,14 @@ | |
|
||
public class Foo : Controller | ||
{ | ||
public Foo() { } // Compliant, ctors should not be highlighted | ||
|
||
public int MyProperty // Compliant, properties should not be highlighted | ||
{ | ||
get { return 0; } | ||
set { } | ||
} | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add a test with an event, an operator and a destructor. |
||
public void PublicFoo() { } // Noncompliant {{Make sure that exposing this HTTP endpoint is safe here.}} | ||
// ^^^^^^^^^ | ||
|
||
|
@@ -11,6 +19,9 @@ internal void InternalFoo() { } | |
|
||
private void PrivateFoo() { } | ||
|
||
[NonAction] | ||
public void PublicNonAction() { } // Compliant, methods decorated with NonAction are not entrypoints | ||
|
||
private class Bar : Controller | ||
{ | ||
public void InnerFoo() { } | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,17 @@ | |
Public Class Foo | ||
Inherits Controller | ||
|
||
Public sub New () ' Compliant, ctors should not be highlighted | ||
End sub | ||
|
||
Public Property MyProperty As Integer ' Compliant, properties should not be highlighted | ||
Get | ||
Return 0 | ||
End Get | ||
Set(ByVal value As Integer) | ||
End Set | ||
End Property | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as for C#. |
||
Public Sub PublicFoo() ' Noncompliant {{Make sure that exposing this HTTP endpoint is safe here.}} | ||
' ^^^^^^^^^ | ||
End Sub | ||
|
@@ -16,6 +27,10 @@ Public Class Foo | |
Private Sub PrivateFoo() | ||
End Sub | ||
|
||
<NonAction> | ||
Public Sub PublicNonAction() ' Compliant, methods decorated with NonAction are not entrypoints | ||
End Sub | ||
|
||
Private Class Bar | ||
Inherits Controller | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[minor] The
a
should be uppercase (i.e.nonActionTypes
)