Skip to content
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

Suppress CA1862 for string.Contains on netfx #7083

Merged
merged 2 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ public sealed class RecommendCaseInsensitiveStringComparisonAnalyzer : Diagnosti
internal const string StringIndexOfMethodName = "IndexOf";
internal const string StringStartsWithMethodName = "StartsWith";
internal const string StringCompareToMethodName = "CompareTo";
internal const string StringComparerCompareMethodName = "Compare";
internal const string StringEqualsMethodName = "Equals";
internal const string StringParameterName = "value";
internal const string StringComparisonParameterName = "comparisonType";
Expand Down Expand Up @@ -211,12 +210,19 @@ private void AnalyzeCompilationStart(CompilationStartAnalysisContext context)
return;
}

ParameterInfo[] stringStringComparisonParameters = {
ParameterInfo.GetParameterInfo(stringType),
ParameterInfo.GetParameterInfo(stringComparisonType)
};
IMethodSymbol? containsStringWithStringComparisonMethod
= stringType.GetMembers(StringContainsMethodName).OfType<IMethodSymbol>().GetFirstOrDefaultMemberWithParameterInfos(stringStringComparisonParameters);

// a.ToLower().Method(b.ToLower())
context.RegisterOperationAction(context =>
{
IInvocationOperation invocation = (IInvocationOperation)context.Operation;
AnalyzeInvocation(context, invocation, stringType,
containsStringMethod, startsWithStringMethod, compareToStringMethod,
containsStringMethod, containsStringWithStringComparisonMethod, startsWithStringMethod, compareToStringMethod,
indexOfStringMethod, indexOfStringInt32Method, indexOfStringInt32Int32Method);
}, OperationKind.Invocation);

Expand All @@ -230,13 +236,13 @@ private void AnalyzeCompilationStart(CompilationStartAnalysisContext context)
}

private static void AnalyzeInvocation(OperationAnalysisContext context, IInvocationOperation invocation, INamedTypeSymbol stringType,
IMethodSymbol containsStringMethod, IMethodSymbol startsWithStringMethod, IMethodSymbol compareToStringMethod,
IMethodSymbol containsStringMethod, IMethodSymbol? containsStringWithStringComparisonMethod, IMethodSymbol startsWithStringMethod, IMethodSymbol compareToStringMethod,
IMethodSymbol indexOfStringMethod, IMethodSymbol indexOfStringInt32Method, IMethodSymbol indexOfStringInt32Int32Method)
{
IMethodSymbol diagnosableMethod = invocation.TargetMethod;

DiagnosticDescriptor? chosenRule;
if (diagnosableMethod.Equals(containsStringMethod) ||
if (diagnosableMethod.Equals(containsStringMethod) && containsStringWithStringComparisonMethod is not null ||
diagnosableMethod.Equals(startsWithStringMethod) ||
diagnosableMethod.Equals(indexOfStringMethod) ||
diagnosableMethod.Equals(indexOfStringInt32Method) ||
Expand Down
1 change: 0 additions & 1 deletion src/NetAnalyzers/RulesMissingDocumentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@

Rule ID | Missing Help Link | Title |
--------|-------------------|-------|
CA1515 | <https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1515> | Consider making public types internal |
CA2262 | <https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2262> | Set 'MaxResponseHeadersLength' properly |
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Testing;
using Test.Utilities;
using Xunit;
using VerifyCS = Test.Utilities.CSharpCodeFixVerifier<
Microsoft.NetCore.Analyzers.Performance.RecommendCaseInsensitiveStringComparisonAnalyzer,
Expand Down Expand Up @@ -370,6 +371,66 @@ bool M()
await VerifyFixCSharpAsync(originalCode, originalCode);
}

[Fact, WorkItem(7053, "https://github.com/dotnet/roslyn-analyzers/issues/7053")]
public Task Net48_Contains_NoDiagnostic()
{
const string code = """
using System;

class C
{
void M(string s)
{
s.ToUpperInvariant().Contains("ABC");
}
}
""";

return new VerifyCS.Test
{
TestCode = code,
ReferenceAssemblies = ReferenceAssemblies.NetFramework.Net48.Default,
MarkupOptions = MarkupOptions.UseFirstDescriptor
}.RunAsync();
}

[Theory, WorkItem(7053, "https://github.com/dotnet/roslyn-analyzers/issues/7053")]
[InlineData("StartsWith")]
[InlineData("IndexOf")]
public Task Net48_Diagnostic(string method)
{
var code = $$"""
using System;

class C
{
void M(string s)
{
[|s.ToUpperInvariant().{{method}}("ABC")|];
}
}
""";
var fixedCode = $$"""
using System;

class C
{
void M(string s)
{
s.{{method}}("ABC", StringComparison.InvariantCultureIgnoreCase);
}
}
""";

return new VerifyCS.Test
{
TestCode = code,
FixedCode = fixedCode,
ReferenceAssemblies = ReferenceAssemblies.NetFramework.Net48.Default,
MarkupOptions = MarkupOptions.UseFirstDescriptor
}.RunAsync();
}

private async Task VerifyNoDiagnosticCSharpAsync(string originalSource)
{
VerifyCS.Test test = new()
Expand Down