From e6d2a745265617f52e80420b1c0823c8c45e512c Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Wed, 23 Nov 2022 02:44:51 +0100 Subject: [PATCH 1/4] Use pattern matching --- .../UseConditionalAccessCodeFixProvider.cs | 4 +-- .../Analysis/UseConditionalAccessAnalyzer.cs | 8 +++--- .../RCS1146UseConditionalAccessTests.cs | 26 +++++++++++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/src/Analyzers.CodeFixes/CSharp/CodeFixes/UseConditionalAccessCodeFixProvider.cs b/src/Analyzers.CodeFixes/CSharp/CodeFixes/UseConditionalAccessCodeFixProvider.cs index ebd5fa4ba3..3a540ffdd4 100644 --- a/src/Analyzers.CodeFixes/CSharp/CodeFixes/UseConditionalAccessCodeFixProvider.cs +++ b/src/Analyzers.CodeFixes/CSharp/CodeFixes/UseConditionalAccessCodeFixProvider.cs @@ -84,8 +84,8 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) (ExpressionSyntax left, ExpressionSyntax right) = UseConditionalAccessAnalyzer.GetFixableExpressions(binaryExpression, kind, semanticModel, cancellationToken); NullCheckStyles allowedStyles = (kind == SyntaxKind.LogicalAndExpression) - ? NullCheckStyles.NotEqualsToNull - : NullCheckStyles.EqualsToNull; + ? (NullCheckStyles.NotEqualsToNull | NullCheckStyles.IsNotNull) + : (NullCheckStyles.EqualsToNull | NullCheckStyles.IsNull); NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(left, semanticModel, allowedStyles: allowedStyles, cancellationToken: cancellationToken); diff --git a/src/Analyzers/CSharp/Analysis/UseConditionalAccessAnalyzer.cs b/src/Analyzers/CSharp/Analysis/UseConditionalAccessAnalyzer.cs index 93cdb2a9d3..2959fdd407 100644 --- a/src/Analyzers/CSharp/Analysis/UseConditionalAccessAnalyzer.cs +++ b/src/Analyzers/CSharp/Analysis/UseConditionalAccessAnalyzer.cs @@ -58,7 +58,9 @@ private static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context) if (ifStatement.SpanContainsDirectives()) return; - NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, allowedStyles: NullCheckStyles.NotEqualsToNull); + NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo( + ifStatement.Condition, + allowedStyles: NullCheckStyles.NotEqualsToNull | NullCheckStyles.IsNotNull); ExpressionSyntax expression = nullCheck.Expression; @@ -165,8 +167,8 @@ static bool ExistsImplicitConversionToBoolean(INamedTypeSymbol typeSymbol) CancellationToken cancellationToken) { NullCheckStyles allowedStyles = (binaryExpressionKind == SyntaxKind.LogicalAndExpression) - ? NullCheckStyles.NotEqualsToNull - : NullCheckStyles.EqualsToNull; + ? (NullCheckStyles.NotEqualsToNull | NullCheckStyles.IsNotNull) + : (NullCheckStyles.EqualsToNull | NullCheckStyles.IsNull); NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(left, semanticModel, allowedStyles: allowedStyles, cancellationToken: cancellationToken); diff --git a/src/Tests/Analyzers.Tests/RCS1146UseConditionalAccessTests.cs b/src/Tests/Analyzers.Tests/RCS1146UseConditionalAccessTests.cs index 0289069218..51b0be2c2f 100644 --- a/src/Tests/Analyzers.Tests/RCS1146UseConditionalAccessTests.cs +++ b/src/Tests/Analyzers.Tests/RCS1146UseConditionalAccessTests.cs @@ -183,6 +183,32 @@ void M() "); } + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseConditionalAccess)] + public async Task Test_LogicalAnd_ReferenceType_PatternMatching() + { + await VerifyDiagnosticAndFixAsync(@" +class Foo +{ + void M() + { + Foo x = null; + + if ([|x is not null && !x.Equals(x)|]) { } + } +} +", @" +class Foo +{ + void M() + { + Foo x = null; + + if (x?.Equals(x) == false) { } + } +} +"); + } + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseConditionalAccess)] public async Task Test_LogicalOr_ReferenceType() { From a490685946695a6c06dc2baea7fc2c3e596f0bff Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Wed, 23 Nov 2022 02:50:06 +0100 Subject: [PATCH 2/4] update --- ChangeLog.md | 1 + .../UseConditionalAccessCodeFixProvider.cs | 2 +- .../RCS1146UseConditionalAccessTests.cs | 29 +++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 3aa4337353..2364d4d030 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix refactoring ([RR0014](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RR0014.md)) ([#988](https://github.com/josefpihrt/roslynator/pull/988)). - Fix refactoring ([RR0180](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RR0180.md)) ([#988](https://github.com/josefpihrt/roslynator/pull/988)). - Recognize `ArgumentNullException.ThrowIfNull` ([RCS1227](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1227.md)) ([#992](https://github.com/josefpihrt/roslynator/pull/992)). +- Handle pattern matching in [RCS1146](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1146.md) ([#999](https://github.com/josefpihrt/roslynator/pull/999)). ## [4.1.2] - 2022-10-31 diff --git a/src/Analyzers.CodeFixes/CSharp/CodeFixes/UseConditionalAccessCodeFixProvider.cs b/src/Analyzers.CodeFixes/CSharp/CodeFixes/UseConditionalAccessCodeFixProvider.cs index 3a540ffdd4..35bf316784 100644 --- a/src/Analyzers.CodeFixes/CSharp/CodeFixes/UseConditionalAccessCodeFixProvider.cs +++ b/src/Analyzers.CodeFixes/CSharp/CodeFixes/UseConditionalAccessCodeFixProvider.cs @@ -190,7 +190,7 @@ int GetParenTokenDiff() StatementSyntax newStatement = statement; - NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, NullCheckStyles.NotEqualsToNull); + NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, NullCheckStyles.NotEqualsToNull | NullCheckStyles.IsNotNull); SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo(statement); diff --git a/src/Tests/Analyzers.Tests/RCS1146UseConditionalAccessTests.cs b/src/Tests/Analyzers.Tests/RCS1146UseConditionalAccessTests.cs index 51b0be2c2f..e523fc427e 100644 --- a/src/Tests/Analyzers.Tests/RCS1146UseConditionalAccessTests.cs +++ b/src/Tests/Analyzers.Tests/RCS1146UseConditionalAccessTests.cs @@ -80,6 +80,35 @@ void M() "); } + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseConditionalAccess)] + public async Task Test_IfStatement_PatternMatching() + { + await VerifyDiagnosticAndFixAsync(@" +class C +{ + void M() + { + C x = null; + + [|if (x is not null) + { + x.M(); + }|] + } +} +", @" +class C +{ + void M() + { + C x = null; + + x?.M(); + } +} +"); + } + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseConditionalAccess)] public async Task Test_LogicalAnd_ReferenceType() { From 86b8afa407b8bc17a2e24e2374b6afd544208dcf Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Wed, 23 Nov 2022 02:51:13 +0100 Subject: [PATCH 3/4] changelog --- ChangeLog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 2364d4d030..76f2194d13 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -34,7 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix refactoring ([RR0014](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RR0014.md)) ([#988](https://github.com/josefpihrt/roslynator/pull/988)). - Fix refactoring ([RR0180](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RR0180.md)) ([#988](https://github.com/josefpihrt/roslynator/pull/988)). - Recognize `ArgumentNullException.ThrowIfNull` ([RCS1227](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1227.md)) ([#992](https://github.com/josefpihrt/roslynator/pull/992)). -- Handle pattern matching in [RCS1146](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1146.md) ([#999](https://github.com/josefpihrt/roslynator/pull/999)). +- Use pattern matching in [RCS1146](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1146.md) ([#999](https://github.com/josefpihrt/roslynator/pull/999)). ## [4.1.2] - 2022-10-31 From 617b909acfb5f691bd00be9e738a71e110d9a2d7 Mon Sep 17 00:00:00 2001 From: Josef Pihrt Date: Wed, 23 Nov 2022 02:51:52 +0100 Subject: [PATCH 4/4] changelog --- ChangeLog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 76f2194d13..495eca5531 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -34,7 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix refactoring ([RR0014](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RR0014.md)) ([#988](https://github.com/josefpihrt/roslynator/pull/988)). - Fix refactoring ([RR0180](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RR0180.md)) ([#988](https://github.com/josefpihrt/roslynator/pull/988)). - Recognize `ArgumentNullException.ThrowIfNull` ([RCS1227](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1227.md)) ([#992](https://github.com/josefpihrt/roslynator/pull/992)). -- Use pattern matching in [RCS1146](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1146.md) ([#999](https://github.com/josefpihrt/roslynator/pull/999)). +- Detect pattern matching in [RCS1146](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1146.md) ([#999](https://github.com/josefpihrt/roslynator/pull/999)). ## [4.1.2] - 2022-10-31