Skip to content

Commit

Permalink
Merge pull request #7296 from DoctorKrolic/fix-rs1024-codefix
Browse files Browse the repository at this point in the history
Avoid direct descriptor comparison, so the fix can be shown
  • Loading branch information
sharwell committed Apr 29, 2024
2 parents 8dcccce + 37a5a32 commit bc8aca0
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 26 deletions.
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the MIT license. See License.txt in the project root for license information.

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
Expand All @@ -26,9 +27,15 @@ public class CompareSymbolsCorrectlyAnalyzer : DiagnosticAnalyzer
private static readonly string s_symbolTypeFullName = typeof(ISymbol).FullName;
private const string s_symbolEqualsName = nameof(ISymbol.Equals);
private const string s_HashCodeCombineName = "Combine";

public const string SymbolEqualityComparerName = "Microsoft.CodeAnalysis.SymbolEqualityComparer";
public const string RulePropertyName = "Rule";

public const string EqualityRuleName = "EqualityRule";
public const string GetHashCodeRuleName = "GetHashCodeRule";
public const string CollectionRuleName = "CollectionRule";

public static readonly DiagnosticDescriptor EqualityRule = new(
private static readonly DiagnosticDescriptor s_equalityRule = new(
DiagnosticIds.CompareSymbolsCorrectlyRuleId,
s_localizableTitle,
s_localizableMessage,
Expand All @@ -38,7 +45,7 @@ public class CompareSymbolsCorrectlyAnalyzer : DiagnosticAnalyzer
description: s_localizableDescription,
customTags: WellKnownDiagnosticTagsExtensions.Telemetry);

public static readonly DiagnosticDescriptor GetHashCodeRule = new(
private static readonly DiagnosticDescriptor s_getHashCodeRule = new(
DiagnosticIds.CompareSymbolsCorrectlyRuleId,
s_localizableTitle,
s_localizableMessage,
Expand All @@ -48,7 +55,7 @@ public class CompareSymbolsCorrectlyAnalyzer : DiagnosticAnalyzer
description: CreateLocalizableResourceString(nameof(CompareSymbolsCorrectlyDescriptionGetHashCode)),
customTags: WellKnownDiagnosticTagsExtensions.Telemetry);

public static readonly DiagnosticDescriptor CollectionRule = new(
private static readonly DiagnosticDescriptor s_collectionRule = new(
DiagnosticIds.CompareSymbolsCorrectlyRuleId,
s_localizableTitle,
s_localizableMessage,
Expand All @@ -58,7 +65,16 @@ public class CompareSymbolsCorrectlyAnalyzer : DiagnosticAnalyzer
description: s_localizableDescription,
customTags: WellKnownDiagnosticTagsExtensions.Telemetry);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(EqualityRule);
private static readonly ImmutableDictionary<string, string?> s_EqualityRuleProperties =
ImmutableDictionary.CreateRange([new KeyValuePair<string, string?>(RulePropertyName, EqualityRuleName)]);

private static readonly ImmutableDictionary<string, string?> s_GetHashCodeRuleProperties =
ImmutableDictionary.CreateRange([new KeyValuePair<string, string?>(RulePropertyName, GetHashCodeRuleName)]);

private static readonly ImmutableDictionary<string, string?> s_CollectionRuleProperties =
ImmutableDictionary.CreateRange([new KeyValuePair<string, string?>(RulePropertyName, CollectionRuleName)]);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(s_equalityRule);

public override void Initialize(AnalysisContext context)
{
Expand Down Expand Up @@ -142,7 +158,7 @@ private static void HandleBinaryOperator(in OperationAnalysisContext context, IN
return;
}

context.ReportDiagnostic(binary.Syntax.GetLocation().CreateDiagnostic(EqualityRule));
context.ReportDiagnostic(binary.Syntax.GetLocation().CreateDiagnostic(s_equalityRule, s_EqualityRuleProperties));
}

private static void HandleInvocationOperation(
Expand All @@ -163,7 +179,7 @@ private static void HandleBinaryOperator(in OperationAnalysisContext context, IN
// without the correct arguments
if (IsSymbolType(invocationOperation.Instance, symbolType))
{
context.ReportDiagnostic(invocationOperation.CreateDiagnostic(GetHashCodeRule));
context.ReportDiagnostic(invocationOperation.CreateDiagnostic(s_getHashCodeRule, s_GetHashCodeRuleProperties));
}

break;
Expand All @@ -174,7 +190,7 @@ private static void HandleBinaryOperator(in OperationAnalysisContext context, IN
var parameters = invocationOperation.Arguments;
if (parameters.All(p => IsSymbolType(p.Value, symbolType)))
{
context.ReportDiagnostic(invocationOperation.Syntax.GetLocation().CreateDiagnostic(EqualityRule));
context.ReportDiagnostic(invocationOperation.Syntax.GetLocation().CreateDiagnostic(s_equalityRule, s_EqualityRuleProperties));
}
}

Expand All @@ -187,7 +203,7 @@ private static void HandleBinaryOperator(in OperationAnalysisContext context, IN
systemHashCodeType.Equals(method.ContainingType, SymbolEqualityComparer.Default) &&
invocationOperation.Arguments.Any(arg => IsSymbolType(arg.Value, symbolType)))
{
context.ReportDiagnostic(invocationOperation.CreateDiagnostic(GetHashCodeRule));
context.ReportDiagnostic(invocationOperation.CreateDiagnostic(s_getHashCodeRule, s_GetHashCodeRuleProperties));
}

break;
Expand All @@ -199,7 +215,7 @@ private static void HandleBinaryOperator(in OperationAnalysisContext context, IN
IsBehavingOnSymbolType(method, symbolType) &&
!invocationOperation.Arguments.Any(arg => IsSymbolType(arg.Value, iEqualityComparer)))
{
context.ReportDiagnostic(invocationOperation.CreateDiagnostic(CollectionRule));
context.ReportDiagnostic(invocationOperation.CreateDiagnostic(s_collectionRule, s_CollectionRuleProperties));
}

break;
Expand Down Expand Up @@ -249,7 +265,7 @@ static bool IsBehavingOnSymbolType(IMethodSymbol? method, INamedTypeSymbol symbo
IsSymbolType(createdType.TypeArguments[0], symbolType) &&
!objectCreation.Arguments.Any(arg => IsSymbolType(arg.Value, iEqualityComparerType)))
{
context.ReportDiagnostic(objectCreation.CreateDiagnostic(CollectionRule));
context.ReportDiagnostic(objectCreation.CreateDiagnostic(s_collectionRule, s_CollectionRuleProperties));
}
}

Expand Down
Expand Up @@ -32,23 +32,27 @@ public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
{
foreach (var diagnostic in context.Diagnostics)
{
if (diagnostic.Descriptor == CompareSymbolsCorrectlyAnalyzer.EqualityRule)
if (diagnostic.Properties.TryGetValue(CompareSymbolsCorrectlyAnalyzer.RulePropertyName, out var rule))
{
context.RegisterCodeFix(
CodeAction.Create(
CodeAnalysisDiagnosticsResources.CompareSymbolsCorrectlyCodeFix,
cancellationToken => ConvertToEqualsAsync(context.Document, diagnostic.Location.SourceSpan, cancellationToken),
equivalenceKey: nameof(CompareSymbolsCorrectlyFix)),
diagnostic);
}
else if (diagnostic.Descriptor == CompareSymbolsCorrectlyAnalyzer.CollectionRule)
{
context.RegisterCodeFix(
CodeAction.Create(
CodeAnalysisDiagnosticsResources.CompareSymbolsCorrectlyCodeFix,
cancellationToken => CallOverloadWithEqualityComparerAsync(context.Document, diagnostic.Location.SourceSpan, cancellationToken),
equivalenceKey: nameof(CompareSymbolsCorrectlyFix)),
diagnostic);
switch (rule)
{
case CompareSymbolsCorrectlyAnalyzer.EqualityRuleName:
context.RegisterCodeFix(
CodeAction.Create(
CodeAnalysisDiagnosticsResources.CompareSymbolsCorrectlyCodeFix,
cancellationToken => ConvertToEqualsAsync(context.Document, diagnostic.Location.SourceSpan, cancellationToken),
equivalenceKey: nameof(CompareSymbolsCorrectlyFix)),
diagnostic);
break;
case CompareSymbolsCorrectlyAnalyzer.CollectionRuleName:
context.RegisterCodeFix(
CodeAction.Create(
CodeAnalysisDiagnosticsResources.CompareSymbolsCorrectlyCodeFix,
cancellationToken => CallOverloadWithEqualityComparerAsync(context.Document, diagnostic.Location.SourceSpan, cancellationToken),
equivalenceKey: nameof(CompareSymbolsCorrectlyFix)),
diagnostic);
break;
}
}
}

Expand Down

0 comments on commit bc8aca0

Please sign in to comment.