Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add else if support to RCS1211 #1155

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions ChangeLog.md
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Add SECURITY.md ([#1147](https://github.com/josefpihrt/roslynator/pull/1147))
- [RCS1211](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1211) will suggest removing unecessary 'else if' clauses ([#1155](https://github.com/josefpihrt/roslynator/pull/1155))

### Fixed

Expand Down
28 changes: 11 additions & 17 deletions src/Analyzers/CSharp/Analysis/RemoveUnnecessaryElseAnalyzer.cs
Expand Up @@ -47,9 +47,6 @@ public static void Analyze(SyntaxNodeAnalysisContext context)

private static bool IsFixable(ElseClauseSyntax elseClause, SemanticModel semanticModel)
{
if (elseClause.Statement?.IsKind(SyntaxKind.IfStatement) != false)
return false;

if (elseClause.Parent is not IfStatementSyntax ifStatement)
return false;

Expand All @@ -61,22 +58,19 @@ private static bool IsFixable(ElseClauseSyntax elseClause, SemanticModel semanti
if (ifStatementStatement is not BlockSyntax ifBlock)
return CSharpFacts.IsJumpStatement(ifStatementStatement.Kind());

if (elseClause.Statement is BlockSyntax elseBlock)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The diffs from L64 onwards do not change behaviour. They are just reducing nesting / Moving the checks that require a semantic model later.

{
if (LocalDeclaredVariablesOverlap(elseBlock, ifBlock, semanticModel))
return false;

if (ifStatement.Parent is SwitchSectionSyntax { Parent: SwitchStatementSyntax switchStatement }
&& SwitchLocallyDeclaredVariablesHelper.BlockDeclaredVariablesOverlapWithOtherSwitchSections(elseBlock, switchStatement, semanticModel))
{
return false;
}
}

StatementSyntax lastStatementInIf = ifBlock.Statements.LastOrDefault();

return lastStatementInIf is not null
&& CSharpFacts.IsJumpStatement(lastStatementInIf.Kind());
if (lastStatementInIf is null || !CSharpFacts.IsJumpStatement(lastStatementInIf.Kind()))
return false;

if (elseClause.Statement is not BlockSyntax elseBlock)
return true;

if (LocalDeclaredVariablesOverlap(elseBlock, ifBlock, semanticModel))
return false;

return ifStatement.Parent is not SwitchSectionSyntax { Parent: SwitchStatementSyntax switchStatement }
|| !SwitchLocallyDeclaredVariablesHelper.BlockDeclaredVariablesOverlapWithOtherSwitchSections(elseBlock, switchStatement, semanticModel);
}

private static bool LocalDeclaredVariablesOverlap(BlockSyntax elseBlock, BlockSyntax ifBlock, SemanticModel semanticModel)
Expand Down
41 changes: 41 additions & 0 deletions src/Tests/Analyzers.Tests/RCS1211RemoveUnnecessaryElseTests.cs
Expand Up @@ -46,6 +46,47 @@ int M(bool flag)
");
}

[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.RemoveUnnecessaryElse)]
public async Task Test_UnnecessaryElseIf_Removed()
{
await VerifyDiagnosticAndFixAsync(@"
class C
{
int M(bool flag, bool flag2)
{
if (flag)
{
return 1;
}
[|else|] if (flag2)
{
return 0;
}

return 2;
}
}
", @"
class C
{
int M(bool flag, bool flag2)
{
if (flag)
{
return 1;
}

if (flag2)
{
return 0;
}

return 2;
}
}
");
}

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