Skip to content

Commit c3dc3e2

Browse files
authored
Use pattern matching (RCS1146) (#999)
1 parent 2fa20b1 commit c3dc3e2

File tree

4 files changed

+64
-6
lines changed

4 files changed

+64
-6
lines changed

ChangeLog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3434
- Fix refactoring ([RR0014](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RR0014.md)) ([#988](https://github.com/josefpihrt/roslynator/pull/988)).
3535
- Fix refactoring ([RR0180](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RR0180.md)) ([#988](https://github.com/josefpihrt/roslynator/pull/988)).
3636
- Recognize `ArgumentNullException.ThrowIfNull` ([RCS1227](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1227.md)) ([#992](https://github.com/josefpihrt/roslynator/pull/992)).
37+
- Detect pattern matching in [RCS1146](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1146.md) ([#999](https://github.com/josefpihrt/roslynator/pull/999)).
3738

3839
## [4.1.2] - 2022-10-31
3940

src/Analyzers.CodeFixes/CSharp/CodeFixes/UseConditionalAccessCodeFixProvider.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ private static async Task<Document> UseConditionalAccessAsync(
8484
(ExpressionSyntax left, ExpressionSyntax right) = UseConditionalAccessAnalyzer.GetFixableExpressions(binaryExpression, kind, semanticModel, cancellationToken);
8585

8686
NullCheckStyles allowedStyles = (kind == SyntaxKind.LogicalAndExpression)
87-
? NullCheckStyles.NotEqualsToNull
88-
: NullCheckStyles.EqualsToNull;
87+
? (NullCheckStyles.NotEqualsToNull | NullCheckStyles.IsNotNull)
88+
: (NullCheckStyles.EqualsToNull | NullCheckStyles.IsNull);
8989

9090
NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(left, semanticModel, allowedStyles: allowedStyles, cancellationToken: cancellationToken);
9191

@@ -190,7 +190,7 @@ private static async Task<Document> UseConditionalAccessAsync(
190190

191191
StatementSyntax newStatement = statement;
192192

193-
NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, NullCheckStyles.NotEqualsToNull);
193+
NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, NullCheckStyles.NotEqualsToNull | NullCheckStyles.IsNotNull);
194194

195195
SimpleMemberInvocationStatementInfo invocationInfo = SyntaxInfo.SimpleMemberInvocationStatementInfo(statement);
196196

src/Analyzers/CSharp/Analysis/UseConditionalAccessAnalyzer.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ private static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context)
5858
if (ifStatement.SpanContainsDirectives())
5959
return;
6060

61-
NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(ifStatement.Condition, allowedStyles: NullCheckStyles.NotEqualsToNull);
61+
NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(
62+
ifStatement.Condition,
63+
allowedStyles: NullCheckStyles.NotEqualsToNull | NullCheckStyles.IsNotNull);
6264

6365
ExpressionSyntax expression = nullCheck.Expression;
6466

@@ -165,8 +167,8 @@ private static bool IsFixable(
165167
CancellationToken cancellationToken)
166168
{
167169
NullCheckStyles allowedStyles = (binaryExpressionKind == SyntaxKind.LogicalAndExpression)
168-
? NullCheckStyles.NotEqualsToNull
169-
: NullCheckStyles.EqualsToNull;
170+
? (NullCheckStyles.NotEqualsToNull | NullCheckStyles.IsNotNull)
171+
: (NullCheckStyles.EqualsToNull | NullCheckStyles.IsNull);
170172

171173
NullCheckExpressionInfo nullCheck = SyntaxInfo.NullCheckExpressionInfo(left, semanticModel, allowedStyles: allowedStyles, cancellationToken: cancellationToken);
172174

src/Tests/Analyzers.Tests/RCS1146UseConditionalAccessTests.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,35 @@ void M()
8080
");
8181
}
8282

83+
[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseConditionalAccess)]
84+
public async Task Test_IfStatement_PatternMatching()
85+
{
86+
await VerifyDiagnosticAndFixAsync(@"
87+
class C
88+
{
89+
void M()
90+
{
91+
C x = null;
92+
93+
[|if (x is not null)
94+
{
95+
x.M();
96+
}|]
97+
}
98+
}
99+
", @"
100+
class C
101+
{
102+
void M()
103+
{
104+
C x = null;
105+
106+
x?.M();
107+
}
108+
}
109+
");
110+
}
111+
83112
[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseConditionalAccess)]
84113
public async Task Test_LogicalAnd_ReferenceType()
85114
{
@@ -183,6 +212,32 @@ void M()
183212
");
184213
}
185214

215+
[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseConditionalAccess)]
216+
public async Task Test_LogicalAnd_ReferenceType_PatternMatching()
217+
{
218+
await VerifyDiagnosticAndFixAsync(@"
219+
class Foo
220+
{
221+
void M()
222+
{
223+
Foo x = null;
224+
225+
if ([|x is not null && !x.Equals(x)|]) { }
226+
}
227+
}
228+
", @"
229+
class Foo
230+
{
231+
void M()
232+
{
233+
Foo x = null;
234+
235+
if (x?.Equals(x) == false) { }
236+
}
237+
}
238+
");
239+
}
240+
186241
[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.UseConditionalAccess)]
187242
public async Task Test_LogicalOr_ReferenceType()
188243
{

0 commit comments

Comments
 (0)