Skip to content

Commit

Permalink
Fix false positive for CA1854 across instances (#7309)
Browse files Browse the repository at this point in the history
* Fix false positive for CA1854 across instances

* Apply PR feedback
  • Loading branch information
CollinAlpert authored Oct 16, 2024
1 parent 8c173ce commit 82cdc84
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -556,9 +556,9 @@ private static bool IsSameReferenceOperation(IOperation? sourceReference, IOpera
case IParameterReferenceOperation source when targetReference is IParameterReferenceOperation target:
return target.Parameter.Equals(source.Parameter, SymbolEqualityComparer.Default);
case IFieldReferenceOperation source when targetReference is IFieldReferenceOperation target:
return target.Field.Equals(source.Field, SymbolEqualityComparer.Default);
return target.Field.Equals(source.Field, SymbolEqualityComparer.Default) && AreInstancesEqual(source, target);
case IPropertyReferenceOperation source when targetReference is IPropertyReferenceOperation target:
return target.Property.Equals(source.Property, SymbolEqualityComparer.Default);
return target.Property.Equals(source.Property, SymbolEqualityComparer.Default) && AreInstancesEqual(source, target);
case IMemberReferenceOperation source when targetReference is IMemberReferenceOperation target:
return target.Member.Equals(source.Member, SymbolEqualityComparer.Default);
case IArrayElementReferenceOperation source when targetReference is IArrayElementReferenceOperation target:
Expand Down Expand Up @@ -607,6 +607,20 @@ private static IEnumerable<IOperation> GetNonConditionalDescendantsAndSelf(IOper
return[operation, .. childOperations];
}

private static bool AreInstancesEqual(IOperation instance1, IOperation instance2)
{
string syntax1 = instance1.Syntax
.ToString()
.Replace("this.", string.Empty)
.Replace("Me.", string.Empty);
string syntax2 = instance2.Syntax
.ToString()
.Replace("this.", string.Empty)
.Replace("Me.", string.Empty);

return syntax1 == syntax2;
}

private enum SearchContext
{
None = 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1821,6 +1821,123 @@ public class DbContext
return VerifyCS.VerifyAnalyzerAsync(code);
}

[Fact, WorkItem(7295, "https://github.com/dotnet/roslyn-analyzers/issues/7295")]
public Task WhenDifferentPropertyInstanceContainingDictionary_NoDiagnostic()
{
const string code = """
using System;
using System.Collections.Generic;
class Test
{
private Dictionary<int, int> PermissionsData => throw null;
void M(int objId) {
Test otherTest = new Test();
if (PermissionsData.ContainsKey(objId))
{
Console.WriteLine(otherTest.PermissionsData[objId]);
}
}
}
""";

return VerifyCS.VerifyAnalyzerAsync(code);
}

[Fact, WorkItem(7295, "https://github.com/dotnet/roslyn-analyzers/issues/7295")]
public Task WhenDifferentFieldInstanceContainingDictionary_NoDiagnostic()
{
const string code = """
using System;
using System.Collections.Generic;
class Test
{
private Dictionary<int, int> permissionsData;
void M(int objId) {
Test otherTest = new Test();
if (permissionsData.ContainsKey(objId))
{
Console.WriteLine(otherTest.permissionsData[objId]);
}
}
}
""";

return VerifyCS.VerifyAnalyzerAsync(code);
}

[Fact, WorkItem(7295, "https://github.com/dotnet/roslyn-analyzers/issues/7295")]
public Task WhenDifferentLocalInstancesContainingDictionary_NoDiagnostic()
{
const string code = """
using System;
using System.Collections.Generic;
class Test
{
private Dictionary<int, int> permissionsData;
void M(int objId) {
Test test1 = new Test();
Test test2 = new Test();
if (test1.permissionsData.ContainsKey(objId))
{
Console.WriteLine(test2.permissionsData[objId]);
}
}
}
""";

return VerifyCS.VerifyAnalyzerAsync(code);
}

[Fact, WorkItem(7295, "https://github.com/dotnet/roslyn-analyzers/issues/7295")]
public Task WhenReferencingSameInstanceWithThisQualifier_Diagnostic()
{
const string code = """
using System;
using System.Collections.Generic;
class Test
{
private Dictionary<int, int> permissionsData;
void M(int objId) {
if ({|#0:permissionsData.ContainsKey(objId)|})
{
Console.WriteLine({|#1:this.permissionsData[objId]|});
}
}
}
""";

const string fixedCode = """
using System;
using System.Collections.Generic;
class Test
{
private Dictionary<int, int> permissionsData;
void M(int objId) {
if (permissionsData.TryGetValue(objId, out int value))
{
Console.WriteLine(value);
}
}
}
""";

var result = new DiagnosticResult(PreferDictionaryTryMethodsOverContainsKeyGuardAnalyzer.PreferTryGetValueDiagnostic)
.WithLocation(0)
.WithLocation(1);

return VerifyCS.VerifyCodeFixAsync(code, result, fixedCode);
}

private static string CreateCSharpCode(string content)
{
return string.Format(CultureInfo.InvariantCulture, CSharpTemplate, content);
Expand Down

0 comments on commit 82cdc84

Please sign in to comment.