Java: Highlight redundant 'break' and braces as unused symbols (IDEA-202623)

This commit is contained in:
Pavel Dolgov
2018-11-30 14:19:22 +03:00
parent a662a4d3f4
commit 958ab9bc29
15 changed files with 58 additions and 60 deletions
@@ -1,10 +1,7 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection.enhancedSwitch;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.*;
import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -33,33 +30,41 @@ public class RedundantLabeledSwitchRuleCodeBlockInspection extends LocalInspecti
public void visitSwitchLabeledRuleStatement(PsiSwitchLabeledRuleStatement statement) {
super.visitSwitchLabeledRuleStatement(statement);
PsiStatement bodyStatement = unwrapSingleStatementCodeBlock(statement.getBody());
if (bodyStatement instanceof PsiBreakStatement) {
if (((PsiBreakStatement)bodyStatement).getValueExpression() != null) {
registerProblem(statement);
PsiStatement body = statement.getBody();
if (body instanceof PsiBlockStatement) {
PsiCodeBlock codeBlock = ((PsiBlockStatement)body).getCodeBlock();
PsiStatement bodyStatement = unwrapSingleStatementCodeBlock(codeBlock);
if (bodyStatement instanceof PsiBreakStatement) {
PsiBreakStatement breakStatement = (PsiBreakStatement)bodyStatement;
if (breakStatement.getValueExpression() != null) {
PsiKeyword breakKeyword = ObjectUtils.tryCast(breakStatement.getFirstChild(), PsiKeyword.class);
registerProblem(breakKeyword);
}
}
else if (bodyStatement instanceof PsiThrowStatement || bodyStatement instanceof PsiExpressionStatement) {
registerProblem(codeBlock.getLBrace());
if (isOnTheFly) registerProblem(codeBlock.getRBrace());
}
}
else if (bodyStatement instanceof PsiThrowStatement || bodyStatement instanceof PsiExpressionStatement) {
registerProblem(statement);
}
}
public void registerProblem(PsiSwitchLabeledRuleStatement statement) {
holder.registerProblem(ObjectUtils.notNull(ObjectUtils.tryCast(statement.getFirstChild(), PsiKeyword.class), statement),
message("inspection.labeled.switch.rule.redundant.code.block.message"),
new UnwrapCodeBlockFix());
private void registerProblem(@Nullable PsiElement element) {
if (element != null) {
holder.registerProblem(element,
message("inspection.labeled.switch.rule.redundant.code.block.message"),
ProblemHighlightType.LIKE_UNUSED_SYMBOL,
new UnwrapCodeBlockFix());
}
}
};
}
@Nullable
private static PsiStatement unwrapSingleStatementCodeBlock(@Nullable PsiStatement statement) {
if (statement instanceof PsiBlockStatement) {
PsiCodeBlock block = ((PsiBlockStatement)statement).getCodeBlock();
PsiStatement firstStatement = PsiTreeUtil.getNextSiblingOfType(block.getLBrace(), PsiStatement.class);
if (firstStatement != null && PsiTreeUtil.getNextSiblingOfType(firstStatement, PsiStatement.class) == null) {
return firstStatement;
}
private static PsiStatement unwrapSingleStatementCodeBlock(PsiCodeBlock block) {
PsiStatement firstStatement = PsiTreeUtil.getNextSiblingOfType(block.getLBrace(), PsiStatement.class);
if (firstStatement != null && PsiTreeUtil.getNextSiblingOfType(firstStatement, PsiStatement.class) == null) {
return firstStatement;
}
return null;
}
@@ -74,14 +79,9 @@ public class RedundantLabeledSwitchRuleCodeBlockInspection extends LocalInspecti
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiElement element = descriptor.getStartElement();
if (element instanceof PsiKeyword) {
element = element.getParent();
}
if (element instanceof PsiSwitchLabeledRuleStatement) {
PsiStatement body = ((PsiSwitchLabeledRuleStatement)element).getBody();
PsiStatement bodyStatement = unwrapSingleStatementCodeBlock(body);
PsiBlockStatement body = PsiTreeUtil.getParentOfType(descriptor.getStartElement(), PsiBlockStatement.class);
if (body != null && body.getParent() instanceof PsiSwitchLabeledRuleStatement) {
PsiStatement bodyStatement = unwrapSingleStatementCodeBlock(body.getCodeBlock());
if (bodyStatement instanceof PsiBreakStatement) {
unwrapBreakValue(body, (PsiBreakStatement)bodyStatement);
}
@@ -95,14 +95,12 @@ public class RedundantLabeledSwitchRuleCodeBlockInspection extends LocalInspecti
PsiExpression valueExpression = breakStatement.getValueExpression();
if (valueExpression != null) {
CommentTracker tracker = new CommentTracker();
tracker.markUnchanged(valueExpression);
tracker.replaceAndRestoreComments(body, valueExpression.getText() + ';');
tracker.replaceAndRestoreComments(body, tracker.text(valueExpression) + ';');
}
}
private static void unwrap(PsiStatement body, PsiStatement bodyStatement) {
CommentTracker tracker = new CommentTracker();
tracker.markUnchanged(bodyStatement);
tracker.replaceAndRestoreComments(body, bodyStatement);
}
}
@@ -1,7 +1,7 @@
<html>
<body>
Reports rules of <code>switch</code> expression or enhanced <code>switch</code> statement which have redundant code block.<br>
Available if the language level is at least Java 12 Preview
Available if the language level is at least Java 12 Preview.
<!-- tooltip end -->
<p><small>New in 2019.1</small></p>
</body>
@@ -1,7 +1,7 @@
<html>
<body>
Reports rules of <code>switch</code> expression or enhanced <code>switch</code> statement which can be converted to a code block.<br>
Available if the language level is at least Java 12 Preview
Available if the language level is at least Java 12 Preview.
<!-- tooltip end -->
<p><small>New in 2019.1</small></p>
</body>
@@ -2,10 +2,10 @@ class C {
String foo(int n) {
return switch (n) {
case 1 -> Integer.toString(n);
<warning descr="Labeled rule's code block is redundant">case</warning> 2 -> { break Integer.toString(n); }
case 2 -> { <warning descr="Labeled rule's code block is redundant">break</warning> Integer.toString(n); }
case 3 -> throw new RuntimeException();
<warning descr="Labeled rule's code block is redundant">case</warning> 4 -> { throw new RuntimeException(); }
<warning descr="Labeled rule's code block is redundant">case</warning> 5 -> { break "a";}
case 4 -> <warning descr="Labeled rule's code block is redundant">{</warning> throw new RuntimeException(); <warning descr="Labeled rule's code block is redundant">}</warning>
case 5 -> { <warning descr="Labeled rule's code block is redundant">break</warning> "a";}
default -> "b";
};
}
@@ -3,10 +3,10 @@ class C {
String s;
switch (n) {
case 1 -> s = Integer.toString(n);
<warning descr="Labeled rule's code block is redundant">case</warning> 2 -> { s = Integer.toString(n); }
case 2 -> <warning descr="Labeled rule's code block is redundant">{</warning> s = Integer.toString(n); <warning descr="Labeled rule's code block is redundant">}</warning>
case 3 -> throw new RuntimeException();
<warning descr="Labeled rule's code block is redundant">case</warning> 4 -> { throw new RuntimeException(); }
<warning descr="Labeled rule's code block is redundant">case</warning> 5 -> { s = "a"; }
case 4 -> <warning descr="Labeled rule's code block is redundant">{</warning> throw new RuntimeException(); <warning descr="Labeled rule's code block is redundant">}</warning>
case 5 -> <warning descr="Labeled rule's code block is redundant">{</warning> s = "a"; <warning descr="Labeled rule's code block is redundant">}</warning>
default -> s = "b";
};
return s;
@@ -1,4 +1,4 @@
// "Unwrap code block of labeled rule" "GENERIC_ERROR_OR_WARNING"
// "Unwrap code block of labeled rule" "LIKE_UNUSED_SYMBOL"
class C {
String foo(int n) {
return switch (n) {
@@ -1,9 +1,9 @@
// "Unwrap code block of labeled rule" "GENERIC_ERROR_OR_WARNING"
// "Unwrap code block of labeled rule" "LIKE_UNUSED_SYMBOL"
class C {
void foo(int n) {
String s;
switch (n) {
<caret>case 1 -> System.out.println(n);
case 1 -> System.out.println(n);
default -> System.out.println();
};
}
@@ -1,8 +1,8 @@
// "Unwrap code block of labeled rule" "GENERIC_ERROR_OR_WARNING"
// "Unwrap code block of labeled rule" "LIKE_UNUSED_SYMBOL"
class C {
String foo(int n) {
return switch (n) {
case 1 -> /*1*/ /*2*/ /*3*/ "a"; /*4*/
case 1 -> /*1*/ /*2*/ /*3*/ /*4*/ /*5*/ "a"; /*6*/
default -> "b";
};
}
@@ -1,4 +1,4 @@
// "Unwrap code block of labeled rule" "GENERIC_ERROR_OR_WARNING"
// "Unwrap code block of labeled rule" "LIKE_UNUSED_SYMBOL"
class C {
String foo(int n) {
return switch (n) {
@@ -1,8 +1,8 @@
// "Unwrap code block of labeled rule" "GENERIC_ERROR_OR_WARNING"
// "Unwrap code block of labeled rule" "LIKE_UNUSED_SYMBOL"
class C {
String foo(int n) {
switch (n) {
case 1 -> /*1*//*2*/throw /*3*/new RuntimeException(/*4*/); /*5*//*6*/
case 1 -> /*1*//*2*/throw /*3*/new RuntimeException(/*4*/)/*5*/; /*6*//*7*/
default ->System.out.println();
};
}
@@ -1,8 +1,8 @@
// "Unwrap code block of labeled rule" "GENERIC_ERROR_OR_WARNING"
// "Unwrap code block of labeled rule" "LIKE_UNUSED_SYMBOL"
class C {
String foo(int n) {
return switch (n) {
<caret>case 1 -> { break Integer.toString(n); }
case 1 -> { break<caret> Integer.toString(n); }
default -> "b";
};
}
@@ -1,9 +1,9 @@
// "Unwrap code block of labeled rule" "GENERIC_ERROR_OR_WARNING"
// "Unwrap code block of labeled rule" "LIKE_UNUSED_SYMBOL"
class C {
void foo(int n) {
String s;
switch (n) {
<caret>case 1 -> { System.out.println(n); }
case 1 -> <caret>{ System.out.println(n); }
default -> System.out.println();
};
}
@@ -1,8 +1,8 @@
// "Unwrap code block of labeled rule" "GENERIC_ERROR_OR_WARNING"
// "Unwrap code block of labeled rule" "LIKE_UNUSED_SYMBOL"
class C {
String foo(int n) {
return switch (n) {
<caret>case 1 -> /*1*/ { break /*2*/"a"; /*3*/ } /*4*/
case 1 -> /*1*/ { /*2*/<caret>break /*3*/"a"/*4*/; /*5*/ } /*6*/
default -> "b";
};
}
@@ -1,10 +1,10 @@
// "Unwrap code block of labeled rule" "GENERIC_ERROR_OR_WARNING"
// "Unwrap code block of labeled rule" "LIKE_UNUSED_SYMBOL"
class C {
String foo(int n) {
return switch (n) {
<caret>case 1 -> {
case 1 -> {
throw new RuntimeException();
}
<caret>}
default -> "b";
};
}
@@ -1,8 +1,8 @@
// "Unwrap code block of labeled rule" "GENERIC_ERROR_OR_WARNING"
// "Unwrap code block of labeled rule" "LIKE_UNUSED_SYMBOL"
class C {
String foo(int n) {
switch (n) {
<caret>case 1 -> /*1*/{/*2*/throw /*3*/new RuntimeException(/*4*/); /*5*/}/*6*/
case 1 -> /*1*/<caret>{/*2*/throw /*3*/new RuntimeException(/*4*/)/*5*/; /*6*/}/*7*/
default ->System.out.println();
};
}