Skip to content
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
12 changes: 12 additions & 0 deletions docs/Rules/MA0148.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,15 @@ value == 0 || value == 1; // not compliant

value is 0 or 1; // ok
````

Cases that rely on implicit user-defined conversions are ignored because replacing `==` with `is` would be invalid:

````c#
class Sample
{
public static implicit operator int(Sample value) => 0;
}

Sample value = null;
_ = value == 0; // ok
````
12 changes: 12 additions & 0 deletions docs/Rules/MA0149.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,15 @@ value != 0 && value != 1; // not compliant

value is not (0 or 1); // ok
````

Cases that rely on implicit user-defined conversions are ignored because replacing `!=` with `is not` would be invalid:

````c#
class Sample
{
public static implicit operator int(Sample value) => 0;
}

Sample value = null;
_ = value != 0; // ok
````
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ private static bool TryCreateDiscreteComparisonCandidate(ExpressionSyntax expres
return false;

var expressionOperation = leftIsConstant ? operation.RightOperand : operation.LeftOperand;
if (UsePatternMatchingForEqualityComparisonsCommon.HasImplicitUserDefinedConversion(expressionOperation))
return false;

if (expressionOperation.Syntax is not ExpressionSyntax valueExpression || constantOperation.Syntax is not ExpressionSyntax constantExpression)
return false;

Expand Down Expand Up @@ -255,6 +258,8 @@ private static bool TryCreatePatternExpression(BinaryExpressionSyntax binaryExpr

var constantOperation = leftIsConstant ? operation.LeftOperand : operation.RightOperand;
var expressionOperation = leftIsConstant ? operation.RightOperand : operation.LeftOperand;
if (UsePatternMatchingForEqualityComparisonsCommon.HasImplicitUserDefinedConversion(expressionOperation))
return false;

if (constantOperation.Syntax is not ExpressionSyntax constantExpression || expressionOperation.Syntax is not ExpressionSyntax valueExpression)
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ public void AnalyzeBinary(OperationAnalysisContext context)
var rightIsConstant = UsePatternMatchingForEqualityComparisonsCommon.IsConstantLiteral(operation.RightOperand);
if (leftIsConstant ^ rightIsConstant)
{
var expressionOperation = leftIsConstant ? operation.RightOperand : operation.LeftOperand;
if (UsePatternMatchingForEqualityComparisonsCommon.HasImplicitUserDefinedConversion(expressionOperation))
return;

if (_operationUtilities.IsInExpressionContext(operation))
return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,17 @@ public static bool IsConstantLiteral(IOperation operation)

return false;
}

public static bool HasImplicitUserDefinedConversion(IOperation operation)
{
while (operation is IConversionOperation { IsImplicit: true } conversionOperation)
{
if (conversionOperation.Conversion.IsUserDefined)
return true;

operation = conversionOperation.Operand;
}

return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -260,4 +260,63 @@ class Sample
""")
.ValidateAsync();
}

[Fact]
public async Task EqualityComparison_ImplicitConversion_NoDiagnostic()
{
await CreateProjectBuilder()
.WithSourceCode("""
Sample value = null;
_ = value == 0;

class Sample
{
public static implicit operator int(Sample value) => 0;
}
""")
.ValidateAsync();
}

[Fact]
public async Task InequalityComparison_ImplicitConversion_NoDiagnostic()
{
await CreateProjectBuilder()
.WithSourceCode("""
Sample value = null;
_ = value != 0;

class Sample
{
public static implicit operator int(Sample value) => 0;
}
""")
.ValidateAsync();
}

[Fact]
public async Task EqualityComparison_MixedWithImplicitConversion_OnlyFixValidExpression()
{
await CreateProjectBuilder()
.WithSourceCode("""
var number = 0;
Sample value = null;
_ = [|number == 0|] || value == 0;

class Sample
{
public static implicit operator int(Sample value) => 0;
}
""")
.ShouldFixCodeWith("""
var number = 0;
Sample value = null;
_ = number is 0 || value == 0;

class Sample
{
public static implicit operator int(Sample value) => 0;
}
""")
.ValidateAsync();
}
}
Loading