Skip to content

Commit

Permalink
Enhance SyntaxLogicalInverter to handle CoalesceExpressions and add c…
Browse files Browse the repository at this point in the history
…orresponding tests (#1069)
  • Loading branch information
jamesHargreaves12 authored Apr 15, 2023
1 parent faf227d commit e017499
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 0 deletions.
1 change: 1 addition & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Update processing of .globalconfig file to prioritize file-specific diagnostic severities over global diagnostic severities. [#1066](https://github.com/JosefPihrt/Roslynator/pull/1066/files)
- Fix RCS1009 to handles discard designations ([#1063](https://github.com/JosefPihrt/Roslynator/pull/1063/files)).
- [CLI] Fix number of formatted documents, file banners added ([#1072](https://github.com/JosefPihrt/Roslynator/pull/1072)).
- Improve support for coalesce expressions in code fixes that require computing the logical inversion of an expression, such as [RCS1208](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1208.md) ([#1069](https://github.com/JosefPihrt/Roslynator/pull/1069)).

## [4.2.0] - 2022-11-27

Expand Down
17 changes: 17 additions & 0 deletions src/CSharp.Workspaces/CSharp/SyntaxLogicalInverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,23 @@ private ExpressionSyntax LogicallyInvertImpl(
{
return DefaultInvert(expression);
}
case SyntaxKind.CoalesceExpression:
{
var binaryExpression = (BinaryExpressionSyntax)expression;
if (binaryExpression.Right.IsKind(SyntaxKind.FalseLiteralExpression))
{
// !(x ?? false) === (x != true)
return NotEqualsExpression(binaryExpression.Left, TrueLiteralExpression());
}

if (binaryExpression.Right.IsKind(SyntaxKind.TrueLiteralExpression))
{
// !(x ?? true) === (x == false)
return EqualsExpression(binaryExpression.Left, FalseLiteralExpression());
}

return DefaultInvert(expression);
}
}

Debug.Fail($"Logical inversion of unknown kind '{expression.Kind()}'");
Expand Down
120 changes: 120 additions & 0 deletions src/Tests/Analyzers.Tests/RCS1208ReduceIfNestingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,126 @@ void M2()
}
");
}


[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.ReduceIfNesting)]
public async Task Test_InvertingCoalesceToFalse()
{
await VerifyDiagnosticAndFixAsync(@"
class C
{
void M(bool? p)
{
[|if|] (p??false)
{
M2();
}
}
void M2()
{
}
}
", @"
class C
{
void M(bool? p)
{
if (p != true)
{
return;
}
M2();
}
void M2()
{
}
}
");
}


[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.ReduceIfNesting)]
public async Task Test_InvertingCoalesceToTrue()
{
await VerifyDiagnosticAndFixAsync(@"
class C
{
void M(bool? p)
{
[|if|] (p??true)
{
M2();
}
}
void M2()
{
}
}
", @"
class C
{
void M(bool? p)
{
if (p == false)
{
return;
}
M2();
}
void M2()
{
}
}
");
}

[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.ReduceIfNesting)]
public async Task Test_InvertingCoalesceToUnknown()
{
await VerifyDiagnosticAndFixAsync(@"
class C
{
bool b { get; set; }
void M(bool? p)
{
[|if|] (p??b)
{
M2();
}
}
void M2()
{
}
}
", @"
class C
{
bool b { get; set; }
void M(bool? p)
{
if (!(p ?? b))
{
return;
}
M2();
}
void M2()
{
}
}
");
}

[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.ReduceIfNesting)]
public async Task TestNoDiagnostic_OverlappingLocalVariables()
Expand Down

0 comments on commit e017499

Please sign in to comment.