Skip to content

Commit

Permalink
Merge pull request #6998 from david-acker/bug/CA1307-overload-accessi…
Browse files Browse the repository at this point in the history
…bility

CA1307: Only consider equal or more accessible overloads
  • Loading branch information
mavasani authored Dec 1, 2023
2 parents 793f8f2 + 7c1edb4 commit d8623b0
Show file tree
Hide file tree
Showing 2 changed files with 264 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ protected override void InitializeWorker(CompilationStartAnalysisContext context
// plus as additional StringComparison parameter. Default StringComparison may or may not match user's intent,
// but it is recommended to explicitly specify it for clarity and readability:
// https://learn.microsoft.com/dotnet/standard/base-types/best-practices-strings#recommendations-for-string-usage
IEnumerable<IMethodSymbol> methodsWithSameNameAsTargetMethod = targetMethod.ContainingType.GetMembers(targetMethod.Name).OfType<IMethodSymbol>();
var methodsWithSameNameAsTargetMethod =
GetAccessibleMethodsWithSameNameAsTargetMethod(invocationExpression, targetMethod);

if (methodsWithSameNameAsTargetMethod.HasMoreThan(1))
{
var correctOverload = methodsWithSameNameAsTargetMethod
Expand Down Expand Up @@ -208,5 +210,18 @@ private static ParameterInfo GetParameterInfo(INamedTypeSymbol type, bool isArra
{
return ParameterInfo.GetParameterInfo(type, isArray, arrayRank, isParams);
}

private static IEnumerable<IMethodSymbol> GetAccessibleMethodsWithSameNameAsTargetMethod(
IInvocationOperation invocationExpression,
IMethodSymbol targetMethod)
{
var invocationStart = invocationExpression.Syntax.GetLocation().SourceSpan.Start;

return targetMethod.ContainingType
.GetMembers(targetMethod.Name)
.OfType<IMethodSymbol>()
.Where(method => method.IsStatic == targetMethod.IsStatic &&
invocationExpression.SemanticModel!.IsAccessible(invocationStart, method));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,254 @@ private void F(Expression<Func<C, bool>> e) {}
}");
}

[Fact, WorkItem(6943, "https://github.com/dotnet/roslyn-analyzers/issues/6943")]
public async Task CA1307_StaticMethodWithPrivateOverload_NoDiagnosticAsync()
{
await VerifyCS.VerifyAnalyzerAsync(@"
using System;
public class G
{
public static void DoSomething()
{
F.M("""");
}
}
public class F
{
private static void M(string s, StringComparison c) { }
public static void M(string s) { }
}");

await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
Public Class G
Public Shared Sub DoSomething()
F.M("""")
End Sub
End Class
Public Class F
Private Shared Sub M(s As String, c As StringComparison)
End Sub
Public Shared Sub M(s As String)
End Sub
End Class");
}

[Fact, WorkItem(6943, "https://github.com/dotnet/roslyn-analyzers/issues/6943")]
public async Task CA1307_StaticMethodWithAccessibleInstanceOverload_NoDiagnosticAsync()
{
await VerifyCS.VerifyAnalyzerAsync(@"
using System;
public class G
{
public static void DoSomething()
{
F.M("""");
}
}
public class F
{
public void M(string s, StringComparison c) { }
public static void M(string s) { }
}");

await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
Public Class G
Public Shared Sub DoSomething()
F.M("""")
End Sub
End Class
Public Class F
Public Sub M(s As String, c As StringComparison)
End Sub
Public Shared Sub M(s As String)
End Sub
End Class");
}

[Fact, WorkItem(6943, "https://github.com/dotnet/roslyn-analyzers/issues/6943")]
public async Task CA1307_StaticMethodWithProtectedStaticOverloadOnBaseClass_DiagnosticAsync()
{
await VerifyCS.VerifyAnalyzerAsync(@"
using System;
public class G : F
{
public static void DoSomething()
{
F.M("""");
}
}
public class F
{
protected static void M(string s, StringComparison c) { }
public static void M(string s) { }
}",
GetCA1307CSharpResultsAt(8, 9, "F.M(string)",
"G.DoSomething()",
"F.M(string, System.StringComparison)"));

await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
Public Class G
Inherits F
Public Shared Sub DoSomething()
F.M("""")
End Sub
End Class
Public Class F
Protected Shared Sub M(s As String, c As StringComparison)
End Sub
Public Shared Sub M(s As String)
End Sub
End Class",
GetCA1307BasicResultsAt(8, 9, "F.M(String)",
"G.DoSomething()",
"F.M(String, System.StringComparison)"));
}

[Fact, WorkItem(6943, "https://github.com/dotnet/roslyn-analyzers/issues/6943")]
public async Task CA1307_PrivateOverloadOnBaseClass_NoDiagnosticAsync()
{
await VerifyCS.VerifyAnalyzerAsync(@"
using System;
public class G : F
{
public void DoSomething()
{
M("""");
}
}
public class F
{
private void M(string s, StringComparison c) { }
public void M(string s) { }
}");

await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
Public Class G
Inherits F
Public Sub DoSomething()
M("""")
End Sub
End Class
Public Class F
Private Sub M(s As String, c As StringComparison)
End Sub
Public Sub M(s As String)
End Sub
End Class");
}

[Fact, WorkItem(6943, "https://github.com/dotnet/roslyn-analyzers/issues/6943")]
public async Task CA1307_ProtectedOverloadOnBaseClass_DiagnosticAsync()
{
await VerifyCS.VerifyAnalyzerAsync(@"
using System;
public class G : F
{
public void DoSomething()
{
M("""");
}
}
public class F
{
protected void M(string s, StringComparison c) { }
public void M(string s) { }
}",
GetCA1307CSharpResultsAt(8, 9, "F.M(string)",
"G.DoSomething()",
"F.M(string, System.StringComparison)"));

await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
Public Class G
Inherits F
Public Sub DoSomething()
M("""")
End Sub
End Class
Public Class F
Protected Sub M(s As String, c As StringComparison)
End Sub
Public Sub M(s As String)
End Sub
End Class",
GetCA1307BasicResultsAt(8, 9, "F.M(String)",
"G.DoSomething()",
"F.M(String, System.StringComparison)"));
}

[Fact, WorkItem(6943, "https://github.com/dotnet/roslyn-analyzers/issues/6943")]
public async Task CA1307_StaticOverloadOnBaseClass_NoDiagnosticAsync()
{
await VerifyCS.VerifyAnalyzerAsync(@"
using System;
public class G : F
{
public void DoSomething()
{
M("""");
}
}
public class F
{
public static void M(string s, StringComparison c) { }
public void M(string s) { }
}");

await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
Public Class G
Inherits F
Public Sub DoSomething()
M("""")
End Sub
End Class
Public Class F
Public Shared Sub M(s As String, c As StringComparison)
End Sub
Public Sub M(s As String)
End Sub
End Class");
}

private static DiagnosticResult GetCA1307CSharpResultsAt(int line, int column, string arg1, string arg2, string arg3) =>
#pragma warning disable RS0030 // Do not use banned APIs
VerifyCS.Diagnostic(SpecifyStringComparisonAnalyzer.Rule_CA1307)
Expand Down

0 comments on commit d8623b0

Please sign in to comment.