10
10
11
11
namespace Microsoft . CodeAnalysis . RemoveRedundantEquality ;
12
12
13
- internal abstract class AbstractRemoveRedundantEqualityDiagnosticAnalyzer
14
- : AbstractBuiltInCodeStyleDiagnosticAnalyzer
13
+ internal abstract class AbstractRemoveRedundantEqualityDiagnosticAnalyzer ( ISyntaxFacts syntaxFacts )
14
+ : AbstractBuiltInCodeStyleDiagnosticAnalyzer (
15
+ IDEDiagnosticIds . RemoveRedundantEqualityDiagnosticId ,
16
+ EnforceOnBuildValues . RemoveRedundantEquality ,
17
+ option : null ,
18
+ new LocalizableResourceString ( nameof ( AnalyzersResources . Remove_redundant_equality ) , AnalyzersResources . ResourceManager , typeof ( AnalyzersResources ) ) )
15
19
{
16
- private readonly ISyntaxFacts _syntaxFacts ;
17
-
18
- protected AbstractRemoveRedundantEqualityDiagnosticAnalyzer ( ISyntaxFacts syntaxFacts )
19
- : base ( IDEDiagnosticIds . RemoveRedundantEqualityDiagnosticId ,
20
- EnforceOnBuildValues . RemoveRedundantEquality ,
21
- option : null ,
22
- new LocalizableResourceString ( nameof ( AnalyzersResources . Remove_redundant_equality ) , AnalyzersResources . ResourceManager , typeof ( AnalyzersResources ) ) )
23
- {
24
- _syntaxFacts = syntaxFacts ;
25
- }
26
-
27
20
public override DiagnosticAnalyzerCategory GetAnalyzerCategory ( )
28
21
=> DiagnosticAnalyzerCategory . SemanticSpanAnalysis ;
29
22
@@ -35,19 +28,15 @@ private void AnalyzeBinaryOperator(OperationAnalysisContext context)
35
28
if ( ShouldSkipAnalysis ( context , notification : null ) )
36
29
return ;
37
30
31
+ // We shouldn't report diagnostic on overloaded operator as the behavior can change.
38
32
var operation = ( IBinaryOperation ) context . Operation ;
39
33
if ( operation . OperatorMethod is not null )
40
- {
41
- // We shouldn't report diagnostic on overloaded operator as the behavior can change.
42
34
return ;
43
- }
44
35
45
36
if ( operation . OperatorKind is not ( BinaryOperatorKind . Equals or BinaryOperatorKind . NotEquals ) )
46
- {
47
37
return ;
48
- }
49
38
50
- if ( ! _syntaxFacts . IsBinaryExpression ( operation . Syntax ) )
39
+ if ( ! syntaxFacts . IsBinaryExpression ( operation . Syntax ) )
51
40
{
52
41
return ;
53
42
}
@@ -56,9 +45,7 @@ private void AnalyzeBinaryOperator(OperationAnalysisContext context)
56
45
var leftOperand = operation . LeftOperand ;
57
46
58
47
if ( rightOperand . Type is null || leftOperand . Type is null )
59
- {
60
48
return ;
61
- }
62
49
63
50
if ( rightOperand . Type . SpecialType != SpecialType . System_Boolean ||
64
51
leftOperand . Type . SpecialType != SpecialType . System_Boolean )
@@ -67,34 +54,43 @@ private void AnalyzeBinaryOperator(OperationAnalysisContext context)
67
54
}
68
55
69
56
var isOperatorEquals = operation . OperatorKind == BinaryOperatorKind . Equals ;
70
- _syntaxFacts . GetPartsOfBinaryExpression ( operation . Syntax , out _ , out var operatorToken , out _ ) ;
57
+ syntaxFacts . GetPartsOfBinaryExpression ( operation . Syntax , out _ , out var operatorToken , out _ ) ;
58
+
71
59
var properties = ImmutableDictionary . CreateBuilder < string , string ? > ( ) ;
72
- if ( TryGetLiteralValue ( rightOperand ) == isOperatorEquals )
60
+ if ( TryGetLiteralValue ( rightOperand ) is bool rightBool )
73
61
{
74
62
properties . Add ( RedundantEqualityConstants . RedundantSide , RedundantEqualityConstants . Right ) ;
63
+ if ( rightBool != isOperatorEquals )
64
+ properties . Add ( RedundantEqualityConstants . Negate , RedundantEqualityConstants . Negate ) ;
75
65
}
76
- else if ( TryGetLiteralValue ( leftOperand ) == isOperatorEquals )
66
+ else if ( TryGetLiteralValue ( leftOperand ) is bool leftBool )
77
67
{
78
68
properties . Add ( RedundantEqualityConstants . RedundantSide , RedundantEqualityConstants . Left ) ;
69
+ if ( leftBool != isOperatorEquals )
70
+ properties . Add ( RedundantEqualityConstants . Negate , RedundantEqualityConstants . Negate ) ;
79
71
}
80
-
81
- if ( properties . Count == 1 )
72
+ else
82
73
{
83
- context . ReportDiagnostic ( Diagnostic . Create ( Descriptor ,
84
- operatorToken . GetLocation ( ) ,
85
- additionalLocations : [ operation . Syntax . GetLocation ( ) ] ,
86
- properties : properties . ToImmutable ( ) ) ) ;
74
+ return ;
87
75
}
88
76
77
+ context . ReportDiagnostic ( Diagnostic . Create ( Descriptor ,
78
+ operatorToken . GetLocation ( ) ,
79
+ additionalLocations : [ operation . Syntax . GetLocation ( ) ] ,
80
+ properties : properties . ToImmutable ( ) ) ) ;
81
+
89
82
return ;
90
83
91
84
static bool ? TryGetLiteralValue ( IOperation operand )
92
85
{
93
86
// Make sure we only simplify literals to avoid changing
94
87
// something like the following example:
95
88
// const bool Activated = true; ... if (state == Activated)
96
- if ( operand . ConstantValue . HasValue && operand . Kind == OperationKind . Literal &&
97
- operand . ConstantValue . Value is bool constValue )
89
+ if ( operand is
90
+ {
91
+ Kind : OperationKind . Literal ,
92
+ ConstantValue : { HasValue : true , Value : bool constValue }
93
+ } )
98
94
{
99
95
return constValue ;
100
96
}
0 commit comments