Skip to content

Commit

Permalink
Add more cases to analyzer SimplifyCodeBranching (RCS1218)
Browse files Browse the repository at this point in the history
  • Loading branch information
josefpihrt committed Apr 9, 2021
1 parent 6b4a415 commit 37e8edb
Show file tree
Hide file tree
Showing 4 changed files with 404 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
return;

Diagnostic diagnostic = context.Diagnostics[0];

Document document = context.Document;

CodeAction codeAction = CodeAction.Create(
Expand Down Expand Up @@ -224,6 +223,19 @@ private static async Task<Document> RefactorAsync(

return await document.ReplaceNodeAsync(ifStatement, whileStatement, cancellationToken).ConfigureAwait(false);
}
else if (kind == SimplifyCodeBranchingKind.LastIfElseWithReturnOrContinueInsideIf)
{
IfStatementSyntax newIfStatement = ifStatement.Update(
ifStatement.IfKeyword,
ifStatement.OpenParenToken,
SyntaxInverter.LogicallyInvert(condition, semanticModel, cancellationToken),
ifStatement.CloseParenToken,
elseClause.Statement,
default(ElseClauseSyntax))
.WithFormatterAnnotation();

return await document.ReplaceNodeAsync(ifStatement, newIfStatement, cancellationToken).ConfigureAwait(false);
}
else
{
throw new InvalidOperationException();
Expand Down
147 changes: 137 additions & 10 deletions src/Analyzers/CSharp/Analysis/SimplifyCodeBranchingAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright (c) Josef Pihrt. All rights reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis;
Expand Down Expand Up @@ -45,13 +44,11 @@ private static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context)
if (condition?.IsMissing != false)
return null;

StatementSyntax statement = ifStatement.Statement;
StatementSyntax ifStatementStatement = ifStatement.Statement;

if (statement == null)
if (ifStatementStatement == null)
return null;

var block = statement as BlockSyntax;

ElseClauseSyntax elseClause = ifStatement.Else;

if (elseClause != null)
Expand All @@ -60,12 +57,21 @@ private static void AnalyzeIfStatement(SyntaxNodeAnalysisContext context)
{
return SimplifyCodeBranchingKind.IfElseInsideWhile;
}
else if (block?.Statements.Any() == false
&& block.OpenBraceToken.TrailingTrivia.IsEmptyOrWhitespace()
&& block.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace()
&& IsFixableIfElseWithEmptyIf(ifStatement, elseClause))
else
{
return SimplifyCodeBranchingKind.IfElseWithEmptyIf;
var ifStatementBlock = ifStatementStatement as BlockSyntax;

if (ifStatementBlock?.Statements.Any() == false
&& ifStatementBlock.OpenBraceToken.TrailingTrivia.IsEmptyOrWhitespace()
&& ifStatementBlock.CloseBraceToken.LeadingTrivia.IsEmptyOrWhitespace()
&& IsFixableIfElseWithEmptyIf(ifStatement, elseClause))
{
return SimplifyCodeBranchingKind.IfElseWithEmptyIf;
}
else if (IsFixableIfElseWithReturnOrContinueInsideIf(ifStatement, elseClause))
{
return SimplifyCodeBranchingKind.LastIfElseWithReturnOrContinueInsideIf;
}
}
}
else if (IsFixableSimpleIfInsideWhileOrDo(ifStatement, semanticModel, cancellationToken))
Expand Down Expand Up @@ -111,16 +117,104 @@ private static bool IsFixableIfElseWithEmptyIf(IfStatementSyntax ifStatement, El

if ((statement as BlockSyntax)?.Statements.Any() == false)
return false;

//if (x)
//{
//}
//else if (y)
//{
// M();
//}
}
else if (kind == SyntaxKind.Block)
{
if (!((BlockSyntax)whenFalse).Statements.Any())
return false;

//if (x)
//{
//}
//else
//{
// M();
//}
}

//void M()
//{
// if (x)
// {
// }
// else
// {
// M();
// }
//}

return true;
}

private static bool IsFixableIfElseWithReturnOrContinueInsideIf(IfStatementSyntax ifStatement, ElseClauseSyntax elseClause)
{
if (elseClause.Statement?.IsKind(SyntaxKind.IfStatement) != false)
return false;

IfStatementSyntax topmostIf = ifStatement.GetTopmostIf();

if (!(topmostIf.Parent is BlockSyntax block))
return false;

if (!block.Statements.IsLast(topmostIf, ignoreLocalFunctions: true))
return false;

switch (block.Parent.Kind())
{
case SyntaxKind.MethodDeclaration:
case SyntaxKind.LocalFunctionStatement:
case SyntaxKind.ConstructorDeclaration:
case SyntaxKind.DestructorDeclaration:
case SyntaxKind.AddAccessorDeclaration:
case SyntaxKind.RemoveAccessorDeclaration:
case SyntaxKind.SetAccessorDeclaration:
{
//void M()
//{
// if (x)
// {
// return;
// }
// else
// {
// M();
// }

return ifStatement.SingleNonBlockStatementOrDefault() is ReturnStatementSyntax returnStatement
&& returnStatement.Expression == null;
}
case SyntaxKind.ForEachStatement:
case SyntaxKind.ForEachVariableStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.WhileStatement:
{
//while (x)
//{
// if (y)
// {
// continue;
// }
// else
// {
// M();
// }
//}

return ifStatement.SingleNonBlockStatementOrDefault().IsKind(SyntaxKind.ContinueStatement);
}
}

return false;
}

private static bool IsFixableIfElseInsideWhile(
IfStatementSyntax ifStatement,
ElseClauseSyntax elseClause)
Expand Down Expand Up @@ -160,6 +254,19 @@ private static bool IsFixableIfElseInsideWhile(
if (whileStatement.Condition?.WalkDownParentheses().Kind() != SyntaxKind.TrueLiteralExpression)
return false;

//while (x)
//{
// if (y)
// {
// break;
// }
// else
// {
// }
//
// M();
//}

return true;
}

Expand Down Expand Up @@ -217,6 +324,16 @@ private static bool IsFixableSimpleIfInsideWhileOrDo(
return false;
}

//while (x)
//{
// M();
//
// if (y)
// {
// break;
// }
//}

return true;
}
else if (kind == SyntaxKind.DoStatement)
Expand All @@ -239,6 +356,16 @@ private static bool IsFixableSimpleIfInsideWhileOrDo(
return false;
}

//do
//{
// if (x)
// {
// break;
// }
//
// M();
//}
//while (y);
return true;
}

Expand Down
3 changes: 2 additions & 1 deletion src/Analyzers/CSharp/Analysis/SimplifyCodeBranchingKind.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ internal enum SimplifyCodeBranchingKind
IfElseWithEmptyIf,
IfElseInsideWhile,
SimplifyIfInsideWhileOrDo,
SimpleIfContainingOnlyDo
SimpleIfContainingOnlyDo,
LastIfElseWithReturnOrContinueInsideIf,
}
}
Loading

0 comments on commit 37e8edb

Please sign in to comment.