diff --git a/ChangeLog.md b/ChangeLog.md index 1267b618e9..bef300d235 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix [RCS1187](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1187.md) ([#1150](https://github.com/JosefPihrt/Roslynator/pull/1150)). - Fix [RCS1056](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1056.md) ([#1154](https://github.com/JosefPihrt/Roslynator/pull/1154)). +- Fix [RCS1208](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1208.md) ([#1153](https://github.com/JosefPihrt/Roslynator/pull/1153)) ## [4.4.0] - 2023-08-01 diff --git a/src/CSharp.Workspaces/CSharp/SyntaxLogicalInverter.cs b/src/CSharp.Workspaces/CSharp/SyntaxLogicalInverter.cs index e67258375b..e46506796d 100644 --- a/src/CSharp.Workspaces/CSharp/SyntaxLogicalInverter.cs +++ b/src/CSharp.Workspaces/CSharp/SyntaxLogicalInverter.cs @@ -128,13 +128,26 @@ private ExpressionSyntax LogicallyInvertImpl( case SyntaxKind.IsExpression: { var isExpression = (BinaryExpressionSyntax)expression; + var rightTypeSymbol = (ITypeSymbol)semanticModel.GetSymbol(isExpression.Right, cancellationToken)!; - return IsPatternExpression( - isExpression.Left, - isExpression.OperatorToken.WithTrailingTrivia(Space), - UnaryPattern( - Token(SyntaxKind.NotKeyword).WithTrailingTrivia(isExpression.OperatorToken.TrailingTrivia), - TypePattern((TypeSyntax)isExpression.Right))); + TypeSyntax type = rightTypeSymbol.ToTypeSyntax(); + + if (SymbolEqualityComparer.Default.Equals( + semanticModel.GetSpeculativeSymbolInfo(isExpression.SpanStart, isExpression.Right, SpeculativeBindingOption.BindAsExpression).Symbol, + semanticModel.GetSpeculativeSymbolInfo(isExpression.SpanStart, isExpression.Right, SpeculativeBindingOption.BindAsTypeOrNamespace).Symbol)) + { + type = type.WithSimplifierAnnotation(); + } + + return (Options.UseNotPattern) + ? IsPatternExpression( + isExpression.Left, + isExpression.OperatorToken.WithTrailingTrivia(Space), + UnaryPattern( + Token(SyntaxKind.NotKeyword) + .WithTrailingTrivia(isExpression.OperatorToken.TrailingTrivia), + TypePattern(type))) + : DefaultInvert(expression); } case SyntaxKind.AsExpression: { diff --git a/src/Tests/Analyzers.Tests/RCS1208ReduceIfNestingTests.cs b/src/Tests/Analyzers.Tests/RCS1208ReduceIfNestingTests.cs index 54a9e8298e..a6c5a1d3bd 100644 --- a/src/Tests/Analyzers.Tests/RCS1208ReduceIfNestingTests.cs +++ b/src/Tests/Analyzers.Tests/RCS1208ReduceIfNestingTests.cs @@ -50,6 +50,56 @@ void M2() "); } + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.ReduceIfNesting)] + public async Task Test_IsWhenIsNotIsInvalid() + { + await VerifyDiagnosticAndFixAsync(@" +class X +{ +} + +class C +{ + public X X { get; set; } + + C(object o) + { + [|if|] (o is X) + { + M2(); + } + } + + void M2() + { + } +} +", @" +class X +{ +} + +class C +{ + public X X { get; set; } + + C(object o) + { + if (o is not global::X) + { + return; + } + + M2(); + } + + void M2() + { + } +} +"); + } + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.ReduceIfNesting)] public async Task Test_WhenParentIsConversionOperator() { @@ -614,6 +664,82 @@ void M2() { } } +"); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.ReduceIfNesting)] + public async Task Test_WhenIsExpressionCsharp8() + { + await VerifyDiagnosticAndFixAsync(@" +class C +{ + void M(object o) + { + [|if|] (o is string) + { + M2(); + } + } + + void M2() + { + } +} +", @" +class C +{ + void M(object o) + { + if (!(o is string)) + { + return; + } + + M2(); + } + + void M2() + { + } +} +", options: WellKnownCSharpTestOptions.Default_CSharp8); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.ReduceIfNesting)] + public async Task Test_WhenIsExpression() + { + await VerifyDiagnosticAndFixAsync(@" +class C +{ + void M(object o) + { + [|if|] (o is string) + { + M2(); + } + } + + void M2() + { + } +} +", @" +class C +{ + void M(object o) + { + if (o is not string) + { + return; + } + + M2(); + } + + void M2() + { + } +} "); } }