mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 09:19:13 +07:00
[java-inspections] IDEA-286507 Warn when colon-style expression switch uses yield or throw in every branch
GitOrigin-RevId: 2e79504ab44609427f51fe5652cb995ec72d17d6
This commit is contained in:
committed by
intellij-monorepo-bot
parent
74da8644f3
commit
7404f51dfc
+118
@@ -59,6 +59,49 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
|
||||
@Override
|
||||
public @NotNull PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
|
||||
return new JavaElementVisitor() {
|
||||
|
||||
@Override
|
||||
public void visitSwitchExpression(@NotNull PsiSwitchExpression expression) {
|
||||
PsiElement switchKeyword = expression.getFirstChild();
|
||||
if (switchKeyword == null) {
|
||||
return;
|
||||
}
|
||||
PsiCodeBlock body = expression.getBody();
|
||||
if (body == null) return;
|
||||
boolean onlyOneYieldAfterLabel = true;
|
||||
boolean isNotRule = true;
|
||||
int statementAfterLabelCount = 0;
|
||||
for (PsiStatement statement : body.getStatements()) {
|
||||
if (statement instanceof PsiSwitchLabeledRuleStatement) {
|
||||
isNotRule = false;
|
||||
break;
|
||||
}
|
||||
if (statement instanceof PsiSwitchLabelStatement) {
|
||||
statementAfterLabelCount = 0;
|
||||
}
|
||||
else {
|
||||
statementAfterLabelCount++;
|
||||
if (!(statement instanceof PsiYieldStatement || statement instanceof PsiThrowStatement)) {
|
||||
onlyOneYieldAfterLabel = false;
|
||||
}
|
||||
else {
|
||||
if (statementAfterLabelCount > 1) {
|
||||
onlyOneYieldAfterLabel = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isNotRule) {
|
||||
return;
|
||||
}
|
||||
ProblemHighlightType warningType = ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
|
||||
if (!onlyOneYieldAfterLabel) {
|
||||
warningType = ProblemHighlightType.INFORMATION;
|
||||
}
|
||||
holder.registerProblem(switchKeyword, JavaBundle.message("inspection.switch.expression.migration.inspection.switch.expression.description"),
|
||||
warningType, new ReplaceExpressionWithEnhancedSwitchExpressionFix());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSwitchStatement(@NotNull PsiSwitchStatement statement) {
|
||||
PsiElement switchKeyword = statement.getFirstChild();
|
||||
@@ -290,6 +333,81 @@ public final class EnhancedSwitchMigrationInspection extends AbstractBaseJavaLoc
|
||||
String generate(CommentTracker ct, SwitchBranch branch);
|
||||
}
|
||||
|
||||
private static class ReplaceExpressionWithEnhancedSwitchExpressionFix extends PsiUpdateModCommandQuickFix{
|
||||
|
||||
@Override
|
||||
protected void applyFix(@NotNull Project project, @NotNull PsiElement element, @NotNull ModPsiUpdater updater) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if(!(element.getParent() instanceof PsiSwitchExpression switchExpression)) return;
|
||||
for (@NotNull PsiElement switchExpressionChild : switchExpression.getChildren()) {
|
||||
if (switchExpressionChild instanceof PsiCodeBlock codeBlock) {
|
||||
for (@NotNull PsiElement codeBlockChildren : codeBlock.getChildren()) {
|
||||
if(codeBlockChildren instanceof PsiSwitchLabelStatement switchLabelStatement) {
|
||||
for (@NotNull PsiElement labelStatementChild : switchLabelStatement.getChildren()) {
|
||||
if (labelStatementChild instanceof PsiJavaToken javaToken && javaToken.textMatches(":")) {
|
||||
builder.append("->"); //replace ':' with '->'
|
||||
}else{
|
||||
builder.append(labelStatementChild.getText());
|
||||
}
|
||||
}
|
||||
PsiElement nextOfSwitchLabelStatement = PsiTreeUtil.skipWhitespacesAndCommentsForward(switchLabelStatement);
|
||||
if (!(nextOfSwitchLabelStatement instanceof PsiBlockStatement) &&
|
||||
findOneYieldOrThrowStatement(PsiTreeUtil.skipWhitespacesAndCommentsForward(codeBlockChildren)) == null) {
|
||||
builder.append("{"); //wrap multiline rule into '{}'
|
||||
}
|
||||
}
|
||||
else {
|
||||
PsiStatement yieldStatement = findOneYieldOrThrowStatement(codeBlockChildren);
|
||||
if (yieldStatement != null) {
|
||||
for (@NotNull PsiElement yieldStatementChild : yieldStatement.getChildren()) {
|
||||
if (!(yieldStatementChild instanceof PsiJavaToken javaToken && javaToken.textMatches("yield"))) {
|
||||
builder.append(yieldStatementChild.getText()); // skip 'yield' for one-line rule
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
builder.append(codeBlockChildren.getText());
|
||||
PsiElement nextOfCodeBlockChildren = PsiTreeUtil.skipWhitespacesAndCommentsForward(codeBlockChildren);
|
||||
if (!(codeBlockChildren instanceof PsiComment || codeBlockChildren instanceof PsiWhiteSpace) &&
|
||||
!(PsiTreeUtil.skipWhitespacesAndCommentsBackward(codeBlockChildren) instanceof PsiJavaToken) &&
|
||||
findOneYieldOrThrowStatement(PsiTreeUtil.skipWhitespacesAndCommentsBackward(codeBlockChildren)) == null &&
|
||||
!(codeBlockChildren instanceof PsiJavaToken) &&
|
||||
(nextOfCodeBlockChildren instanceof PsiSwitchLabelStatement ||
|
||||
nextOfCodeBlockChildren instanceof PsiJavaToken javaToken && javaToken.textMatches("}"))) {
|
||||
builder.append("\n}"); //wrap multiline rule into '{}'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
builder.append(switchExpressionChild.getText());
|
||||
}
|
||||
}
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(element.getProject());
|
||||
PsiExpression newSwitchExpression = factory.createExpressionFromText(builder.toString(), element);
|
||||
switchExpression.replace(newSwitchExpression);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiStatement findOneYieldOrThrowStatement(@Nullable PsiElement switchBlockChild) {
|
||||
if ((switchBlockChild instanceof PsiYieldStatement ||
|
||||
switchBlockChild instanceof PsiThrowStatement) &&
|
||||
PsiTreeUtil.skipWhitespacesAndCommentsBackward(switchBlockChild) instanceof PsiSwitchLabelStatement &&
|
||||
(PsiTreeUtil.skipWhitespacesAndCommentsForward(switchBlockChild) instanceof PsiSwitchLabelStatement ||
|
||||
PsiTreeUtil.skipWhitespacesAndCommentsForward(switchBlockChild) instanceof PsiJavaToken javaToken &&
|
||||
javaToken.textMatches("}"))) {
|
||||
return (PsiStatement)switchBlockChild;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getFamilyName() {
|
||||
return JavaBundle.message("inspection.replace.with.switch.rule.expression.fix.family.name");
|
||||
}
|
||||
}
|
||||
|
||||
private static class ReplaceWithSwitchExpressionFix extends PsiUpdateModCommandQuickFix {
|
||||
private final ReplacementType myReplacementType;
|
||||
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// "Migrate to enhanced switch with rules" "true-preview"
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class X {
|
||||
|
||||
int test(int y) {
|
||||
return switch (y) {
|
||||
case 1 -> {
|
||||
System.out.println("1");
|
||||
yield 1;
|
||||
}
|
||||
case 2 -> 3;
|
||||
case 3 -> throw new IllegalArgumentException();
|
||||
default -> {
|
||||
System.out.println();
|
||||
yield 5;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// "Migrate to enhanced switch with rules" "true-preview"
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class X {
|
||||
|
||||
int test(int y) {
|
||||
return switch (y) { //some comments3
|
||||
case 1 -> 1; //some comments2
|
||||
case 2 -> 3; /*some comments1*/
|
||||
default -> 5; //some comments
|
||||
};
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Migrate to enhanced switch with rules" "false"
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class X {
|
||||
|
||||
int test(int y) {
|
||||
return swi<caret>tch (y) { //some comments3
|
||||
case 1->
|
||||
yield 1; //some comments2
|
||||
case 2:
|
||||
yield 3; /*some comments1*/
|
||||
default:
|
||||
yield 5; //some comments
|
||||
};
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// "Migrate to enhanced switch with rules" "true-preview"
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class X {
|
||||
|
||||
int test(int y) {
|
||||
return swi<caret>tch (y) {
|
||||
case 1:
|
||||
System.out.println("1");
|
||||
yield 1;
|
||||
case 2:
|
||||
yield 3;
|
||||
case 3:
|
||||
throw new IllegalArgumentException();
|
||||
default:
|
||||
System.out.println();
|
||||
yield 5;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// "Migrate to enhanced switch with rules" "true-preview"
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class X {
|
||||
|
||||
int test(int y) {
|
||||
return swi<caret>tch (y) { //some comments3
|
||||
case 1:
|
||||
yield 1; //some comments2
|
||||
case 2:
|
||||
yield 3; /*some comments1*/
|
||||
default:
|
||||
yield 5; //some comments
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -703,6 +703,7 @@ inspection.replace.with.old.style.switch.statement.fix.name=Replace with old sty
|
||||
inspection.replace.with.regular.string.literal.fix=Replace with regular string literal
|
||||
inspection.replace.with.switch.expression.fix.name=Replace with 'switch' expression
|
||||
inspection.replace.with.switch.expression.fix.family.name=Migrate to enhanced switch
|
||||
inspection.replace.with.switch.rule.expression.fix.family.name=Migrate to enhanced switch with rules
|
||||
inspection.replace.with.text.block.fix=Replace with text block
|
||||
inspection.replace.with.string.template.fix=Replace with string template
|
||||
inspection.replace.with.string.concatenation.fix=Replace with string concatenation
|
||||
@@ -747,6 +748,7 @@ inspection.switch.expression.backward.migration.inspection.name=Enhanced 'switch
|
||||
inspection.switch.expression.backward.statement.migration.inspection.name='switch' statement can be replaced with old style 'switch' statement
|
||||
inspection.switch.expression.migration.inspection.name=Statement can be replaced with enhanced 'switch'
|
||||
inspection.switch.expression.migration.inspection.switch.description=Switch statement can be replaced with enhanced 'switch'
|
||||
inspection.switch.expression.migration.inspection.switch.expression.description=Switch expression can be replaced with enhanced 'switch' with rules
|
||||
inspection.switch.expression.migration.warn.only.on.expression=Show warning only if conversion to expression is possible
|
||||
inspection.switch.expression.migration.option.expression.max.statements=Do not report switches having more than {0} {0, choice, 1#statement|2#statements} in a single branch
|
||||
inspection.switch.expression.migration.expression.max.statements=Maximum number of statements in one branch to convert to switch expression
|
||||
|
||||
Reference in New Issue
Block a user