Skip to content

Commit

Permalink
feat: Adds consider replacing switch statement with switch expression
Browse files Browse the repository at this point in the history
  • Loading branch information
ironcev committed May 11, 2019
1 parent 9f14c63 commit 040b347
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 15 deletions.
2 changes: 2 additions & 0 deletions src/Sharpen.Engine/Sharpen.Engine.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,9 @@
<Compile Include="SharpenSuggestions\CSharp80\NullableReferenceTypes\Suggestions\EnableNullableContextAndDeclareReferencePropertyAsNullable.cs" />
<Compile Include="SharpenSuggestions\CSharp80\NullableReferenceTypes\Suggestions\EnableNullableContextAndDeclareReferenceFieldAsNullable.cs" />
<Compile Include="SharpenSuggestions\CSharp80\SwitchExpressions\Analyzers\ReplaceSwitchStatementWithSwitchExpressionAnalyzer.cs" />
<Compile Include="SharpenSuggestions\CSharp80\SwitchExpressions\Suggestions\ConsiderReplacingSwitchStatementContainingOnlyAssignmentsWithSwitchExpression.cs" />
<Compile Include="SharpenSuggestions\CSharp80\SwitchExpressions\Suggestions\ReplaceSwitchStatementContainingOnlyAssignmentsWithSwitchExpression.cs" />
<Compile Include="SharpenSuggestions\CSharp80\SwitchExpressions\Suggestions\ConsiderReplacingSwitchStatementContainingOnlyReturnsWithSwitchExpression.cs" />
<Compile Include="SharpenSuggestions\CSharp80\SwitchExpressions\Suggestions\ReplaceSwitchStatementContainingOnlyReturnsWithSwitchExpression.cs" />
<Compile Include="SharpenSuggestions\CSharp80\UsingDeclarations\Analyzers\ReplaceUsingStatementWithUsingDeclarationAnalyzer.cs" />
<Compile Include="SharpenSuggestions\CSharp80\UsingDeclarations\Suggestions\ConsiderReplacingUsingStatementWithUsingDeclaration.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,35 +37,48 @@ public IEnumerable<AnalysisResult> Analyze(SyntaxTree syntaxTree, SemanticModel
.Where(replaceabilityInfo => replaceabilityInfo.switchStatement != null)
.Select(replaceabilityInfo => new AnalysisResult
(
replaceabilityInfo.category == SwitchStatementSectionsCategory.AllSwitchSectionsAreReturnStatements
? (ISharpenSuggestion)ReplaceSwitchStatementContainingOnlyReturnsWithSwitchExpression.Instance
: ReplaceSwitchStatementContainingOnlyAssignmentsWithSwitchExpression.Instance,
GetSuggestion(replaceabilityInfo.category, replaceabilityInfo.isSurelyExhaustive),
analysisContext,
syntaxTree.FilePath,
replaceabilityInfo.switchStatement.SwitchKeyword,
replaceabilityInfo.switchStatement
));

(SwitchStatementSyntax switchStatement, SwitchStatementSectionsCategory category) GetSwitchStatementPotentialReplaceabilityInfo(SwitchStatementSyntax switchStatement)
ISharpenSuggestion GetSuggestion(SwitchStatementSectionsCategory category, bool isSurelyExhaustive)
{
// TODO-IG: It will be so nice to switch to switch statement one day we move Sharpen to C# 8.0 :-)
if (category == SwitchStatementSectionsCategory.AllSwitchSectionsAreAssignmentsToTheSameIdentifier)
{
return isSurelyExhaustive
? (ISharpenSuggestion)ReplaceSwitchStatementContainingOnlyAssignmentsWithSwitchExpression.Instance
: ConsiderReplacingSwitchStatementContainingOnlyAssignmentsWithSwitchExpression.Instance;
}
else
{
return isSurelyExhaustive
? (ISharpenSuggestion)ReplaceSwitchStatementContainingOnlyReturnsWithSwitchExpression.Instance
: ConsiderReplacingSwitchStatementContainingOnlyReturnsWithSwitchExpression.Instance;
}
}

(SwitchStatementSyntax switchStatement, SwitchStatementSectionsCategory category, bool isSurelyExhaustive) GetSwitchStatementPotentialReplaceabilityInfo(SwitchStatementSyntax switchStatement)
{
// We have to have at least one switch section (case or default).
if (switchStatement.Sections.Count <= 0) return (null, SwitchStatementSectionsCategory.None);
if (switchStatement.Sections.Count <= 0) return (null, SwitchStatementSectionsCategory.None, false);

// We have to have the default section, otherwise we cannot replace the switch
// statement with a switch expressions.
// TODO-IG: Provide additional "consider" suggestion in case of missing the return.
// Something like "Consider adding the default case and replacing switch statement with switch expression".
if (!switchStatement.Sections.Any(switchSection =>
switchSection.Labels.Any(label => label.IsKind(SyntaxKind.DefaultSwitchLabel))))
return (null, SwitchStatementSectionsCategory.None);
// If we have the default section it is surely exhaustive.
// Otherwise we cannot be sure. We will of course not do any
// proper check that the compiler does.
bool isSurelyExhaustive = switchStatement.Sections.Any(switchSection =>
switchSection.Labels.Any(label => label.IsKind(SyntaxKind.DefaultSwitchLabel)));

if (AllSwitchSectionsAreAssignmentsToTheSameIdentifier(switchStatement.Sections))
return (switchStatement, SwitchStatementSectionsCategory.AllSwitchSectionsAreAssignmentsToTheSameIdentifier);
return (switchStatement, SwitchStatementSectionsCategory.AllSwitchSectionsAreAssignmentsToTheSameIdentifier, isSurelyExhaustive);

if (AllSwitchSectionsAreReturnStatements(switchStatement.Sections))
return (switchStatement, SwitchStatementSectionsCategory.AllSwitchSectionsAreReturnStatements);
return (switchStatement, SwitchStatementSectionsCategory.AllSwitchSectionsAreReturnStatements, isSurelyExhaustive);

return (null, SwitchStatementSectionsCategory.None);
return (null, SwitchStatementSectionsCategory.None, false);

bool AllSwitchSectionsAreAssignmentsToTheSameIdentifier(SyntaxList<SwitchSectionSyntax> switchSections)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Sharpen.Engine.SharpenSuggestions.CSharp80.SwitchExpressions.Suggestions
{
internal sealed class ConsiderReplacingSwitchStatementContainingOnlyAssignmentsWithSwitchExpression : ISharpenSuggestion
{
private ConsiderReplacingSwitchStatementContainingOnlyAssignmentsWithSwitchExpression() { }

public string MinimumLanguageVersion { get; } = CSharpLanguageVersions.CSharp80;

public ICSharpFeature LanguageFeature { get; } = CSharpFeatures.SwitchExpressions.Instance;

public string FriendlyName { get; } = "Consider replacing switch statement containing only assignments with switch expression";

public static readonly ConsiderReplacingSwitchStatementContainingOnlyAssignmentsWithSwitchExpression Instance = new ConsiderReplacingSwitchStatementContainingOnlyAssignmentsWithSwitchExpression();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Sharpen.Engine.SharpenSuggestions.CSharp80.SwitchExpressions.Suggestions
{
internal sealed class ConsiderReplacingSwitchStatementContainingOnlyReturnsWithSwitchExpression : ISharpenSuggestion
{
private ConsiderReplacingSwitchStatementContainingOnlyReturnsWithSwitchExpression() { }

public string MinimumLanguageVersion { get; } = CSharpLanguageVersions.CSharp80;

public ICSharpFeature LanguageFeature { get; } = CSharpFeatures.SwitchExpressions.Instance;

public string FriendlyName { get; } = "Consider replacing switch statement containing only returns with switch expression";

public static readonly ConsiderReplacingSwitchStatementContainingOnlyReturnsWithSwitchExpression Instance = new ConsiderReplacingSwitchStatementContainingOnlyReturnsWithSwitchExpression();
}
}

0 comments on commit 040b347

Please sign in to comment.