[java-highlighting] IDEA-324652 Unreachable branch quickfix produces incorrect code

GitOrigin-RevId: 3c00dae40f890c0a5bfda425f9c30d479f4d40b3
This commit is contained in:
Mikhail Pyltsin
2023-07-14 19:30:27 +02:00
committed by intellij-monorepo-bot
parent 9081464e94
commit 830275db3c
42 changed files with 233 additions and 514 deletions

View File

@@ -862,33 +862,44 @@ public class SwitchBlockHighlightingModel {
for (int j = i + 1; j < switchLabels.size(); j++) {
PsiElement next = switchLabels.get(j);
if (!(next instanceof PsiCaseLabelElement nextElement)) continue;
if (!JavaPsiPatternUtil.isUnconditionalForType(nextElement, mySelectorType) &&
((!(next instanceof PsiExpression expression) || ExpressionUtils.isNullLiteral(expression)) &&
current instanceof PsiKeyword &&
PsiKeyword.DEFAULT.equals(current.getText()) || isInCaseNullDefaultLabel(current))) {
// JEP 440-441
// A 'default' label dominates a case label with a case pattern,
// and it also dominates a case label with a null case constant.
// A 'case null, default' label dominates all other switch labels.
boolean dominated = isDominated(nextElement, current, mySelectorType);
if (dominated) {
result.put(nextElement, current);
}
else if (current instanceof PsiCaseLabelElement currentElement) {
if (isConstantLabelElement(nextElement)) {
PsiExpression constExpr = ObjectUtils.tryCast(nextElement, PsiExpression.class);
assert constExpr != null;
if (JavaPsiPatternUtil.dominatesOverConstant(currentElement, constExpr.getType())) {
result.put(nextElement, current);
}
}
else if (JavaPsiPatternUtil.dominates(currentElement, nextElement)) {
result.put(nextElement, current);
}
}
}
}
return result;
}
public static boolean isDominated(@NotNull PsiCaseLabelElement overWhom,
@NotNull PsiElement who,
@NotNull PsiType selectorType) {
boolean dominated = false;
if (!JavaPsiPatternUtil.isUnconditionalForType(overWhom, selectorType) &&
((!(overWhom instanceof PsiExpression expression) || ExpressionUtils.isNullLiteral(expression)) &&
who instanceof PsiKeyword &&
PsiKeyword.DEFAULT.equals(who.getText()) || isInCaseNullDefaultLabel(who))) {
// JEP 440-441
// A 'default' label dominates a case label with a case pattern,
// and it also dominates a case label with a null case constant.
// A 'case null, default' label dominates all other switch labels.
dominated =true;
}
else if (who instanceof PsiCaseLabelElement currentElement) {
if (isConstantLabelElement(overWhom)) {
PsiExpression constExpr = ObjectUtils.tryCast(overWhom, PsiExpression.class);
assert constExpr != null;
if (JavaPsiPatternUtil.dominatesOverConstant(currentElement, constExpr.getType())) {
dominated =true;
}
}
else if (JavaPsiPatternUtil.dominates(currentElement, overWhom)) {
dominated =true;
}
}
return dominated;
}
private static boolean isInCaseNullDefaultLabel(@NotNull PsiElement element) {
PsiCaseLabelElementList list = ObjectUtils.tryCast(element.getParent(), PsiCaseLabelElementList.class);
if (list == null || list.getElementCount() != 2) return false;

View File

@@ -45,6 +45,7 @@ import org.jetbrains.annotations.PropertyKey;
import java.util.*;
import java.util.function.Consumer;
import static com.intellij.codeInsight.daemon.impl.analysis.SwitchBlockHighlightingModel.PatternsInSwitchBlockHighlightingModel;
import static com.intellij.util.ObjectUtils.tryCast;
public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspectionTool {
@@ -58,7 +59,8 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
@Override
public void writeSettings(@NotNull Element node) throws WriteExternalException {
node.addContent(new Element("option").setAttribute("name", "SUGGEST_NULLABLE_ANNOTATIONS").setAttribute("value", String.valueOf(SUGGEST_NULLABLE_ANNOTATIONS)));
node.addContent(new Element("option").setAttribute("name", "SUGGEST_NULLABLE_ANNOTATIONS")
.setAttribute("value", String.valueOf(SUGGEST_NULLABLE_ANNOTATIONS)));
// Preserved for serialization compatibility
node.addContent(new Element("option").setAttribute("name", "DONT_REPORT_TRUE_ASSERT_STATEMENTS").setAttribute("value", "false"));
if (IGNORE_ASSERT_STATEMENTS) {
@@ -68,10 +70,12 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
node.addContent(new Element("option").setAttribute("name", "TREAT_UNKNOWN_MEMBERS_AS_NULLABLE").setAttribute("value", "true"));
}
if (!REPORT_NULLS_PASSED_TO_NOT_NULL_PARAMETER) {
node.addContent(new Element("option").setAttribute("name", "REPORT_NULLS_PASSED_TO_NOT_NULL_PARAMETER").setAttribute("value", "false"));
node.addContent(
new Element("option").setAttribute("name", "REPORT_NULLS_PASSED_TO_NOT_NULL_PARAMETER").setAttribute("value", "false"));
}
if (!REPORT_NULLABLE_METHODS_RETURNING_NOT_NULL) {
node.addContent(new Element("option").setAttribute("name", "REPORT_NULLABLE_METHODS_RETURNING_NOT_NULL").setAttribute("value", "false"));
node.addContent(
new Element("option").setAttribute("name", "REPORT_NULLABLE_METHODS_RETURNING_NOT_NULL").setAttribute("value", "false"));
}
if (!REPORT_UNSOUND_WARNINGS) {
node.addContent(new Element("option").setAttribute("name", "REPORT_UNSOUND_WARNINGS").setAttribute("value", "false"));
@@ -98,9 +102,11 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
}
List<DfaMemoryState> initialStates;
PsiMethodCallExpression call = JavaPsiConstructorUtil.findThisOrSuperCallInConstructor(method);
if (JavaPsiConstructorUtil.isChainedConstructorCall(call) || (call == null && DfaUtil.hasImplicitImpureSuperCall(aClass, method))) {
if (JavaPsiConstructorUtil.isChainedConstructorCall(call) ||
(call == null && DfaUtil.hasImplicitImpureSuperCall(aClass, method))) {
initialStates = Collections.singletonList(runner.createMemoryState());
} else {
}
else {
initialStates = ContainerUtil.map(states, DfaMemoryState::createCopy);
}
analyzeMethod(method, runner, initialStates);
@@ -118,7 +124,11 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
PsiCodeBlock scope = method.getBody();
if (scope == null) return;
PsiClass containingClass = PsiTreeUtil.getParentOfType(method, PsiClass.class);
if (containingClass != null && PsiUtil.isLocalOrAnonymousClass(containingClass) && !(containingClass instanceof PsiEnumConstantInitializer)) return;
if (containingClass != null &&
PsiUtil.isLocalOrAnonymousClass(containingClass) &&
!(containingClass instanceof PsiEnumConstantInitializer)) {
return;
}
analyzeDfaWithNestedClosures(scope, holder, runner, initialStates);
analyzeNullLiteralMethodArguments(method, holder);
@@ -181,13 +191,16 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
return visitor;
}
private static void reportAnalysisQualityProblem(ProblemsHolder holder, PsiElement scope, @PropertyKey(resourceBundle = JavaAnalysisBundle.BUNDLE) String problemKey) {
private static void reportAnalysisQualityProblem(ProblemsHolder holder,
PsiElement scope,
@PropertyKey(resourceBundle = JavaAnalysisBundle.BUNDLE) String problemKey) {
PsiIdentifier name = null;
String message = null;
if(scope.getParent() instanceof PsiMethod) {
if (scope.getParent() instanceof PsiMethod) {
name = ((PsiMethod)scope.getParent()).getNameIdentifier();
message = JavaAnalysisBundle.message(problemKey, "Method <code>#ref</code>");
} else if(scope instanceof PsiClass) {
}
else if (scope instanceof PsiClass) {
name = ((PsiClass)scope).getNameIdentifier();
message = JavaAnalysisBundle.message(problemKey, "Class initializer");
}
@@ -210,7 +223,9 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
return Collections.emptyList();
}
protected @NotNull List<@NotNull LocalQuickFix> createUnboxingNullableFixes(@NotNull PsiExpression qualifier, PsiElement anchor, boolean onTheFly) {
protected @NotNull List<@NotNull LocalQuickFix> createUnboxingNullableFixes(@NotNull PsiExpression qualifier,
PsiElement anchor,
boolean onTheFly) {
return Collections.emptyList();
}
@@ -292,7 +307,8 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
PsiCaseLabelElement label = entry.getKey();
PsiSwitchLabelStatementBase labelStatement = Objects.requireNonNull(PsiImplUtil.getSwitchLabel(label));
PsiSwitchBlock switchBlock = labelStatement.getEnclosingSwitchBlock();
if (switchBlock == null || !canRemoveUnreachableBranches(labelStatement, label, switchBlock)) continue;
if (switchBlock == null) continue;
if (findRemovableUnreachableBranches(label, switchBlock).isEmpty()) continue;
if (!canRemoveTheOnlyReachableLabel(label, switchBlock)) continue;
if (!StreamEx.iterate(labelStatement, Objects::nonNull, l -> PsiTreeUtil.getPrevSiblingOfType(l, PsiSwitchLabelStatementBase.class))
.skip(1).map(PsiSwitchLabelStatementBase::getCaseLabelElementList)
@@ -355,7 +371,7 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
}
if (labelStatement instanceof PsiSwitchLabelStatement) {
PsiElement cur = labelStatement;
while(true) {
while (true) {
PsiElement next = cur.getNextSibling();
if (!(next instanceof PsiComment) && !(next instanceof PsiWhiteSpace) && !(next instanceof PsiSwitchLabelStatement)) {
return next instanceof PsiThrowStatement;
@@ -366,24 +382,74 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
return false;
}
private static boolean canRemoveUnreachableBranches(PsiSwitchLabelStatementBase labelStatement,
PsiCaseLabelElement label,
PsiSwitchBlock statement) {
PsiCaseLabelElementList labelElementList = Objects.requireNonNull(labelStatement.getCaseLabelElementList());
if (labelElementList.getElementCount() != 1 &&
!ContainerUtil.and(labelElementList.getElements(), element -> element == label || element instanceof PsiDefaultCaseLabelElement)) {
return true;
}
/**
* Finds the removable unreachable branches in a switch statement.
* Default case is not included in this list and should be checked separately
*
* @param reachableLabel The label that is reachable.
* @param statement The switch statement to analyze.
* @return A list of unreachable branches that can be safely removed.
*/
public static List<PsiCaseLabelElement> findRemovableUnreachableBranches(PsiCaseLabelElement reachableLabel,
PsiSwitchBlock statement) {
PsiSwitchLabelStatementBase labelStatement = PsiTreeUtil.getParentOfType(reachableLabel, PsiSwitchLabelStatementBase.class);
List<PsiSwitchLabelStatementBase> allBranches =
PsiTreeUtil.getChildrenOfTypeAsList(statement.getBody(), PsiSwitchLabelStatementBase.class);
if (statement instanceof PsiSwitchStatement) {
// Cannot do anything if we have already single branch, and we cannot restore flow due to non-terminal breaks
return allBranches.size() != 1 || BreakConverter.from(statement) != null;
boolean hasDefault = false;
List<PsiCaseLabelElement> unreachableElements = new ArrayList<>();
for (PsiSwitchLabelStatementBase branch : allBranches) {
if (branch.isDefaultCase()) {
hasDefault = true;
continue;
}
PsiCaseLabelElementList elementList = branch.getCaseLabelElementList();
if (elementList == null) {
continue;
}
PsiCaseLabelElement[] elements = elementList.getElements();
unreachableElements.addAll(Arrays.asList(elements));
}
// Expression switch: if we cannot unwrap existing branch and the other one is default case, we cannot kill it either
return !ContainerUtil.and(allBranches, branch -> branch == labelStatement || SwitchUtils.hasOnlyDefaultCase(branch)) ||
(labelStatement instanceof PsiSwitchLabeledRuleStatement &&
((PsiSwitchLabeledRuleStatement)labelStatement).getBody() instanceof PsiExpressionStatement);
unreachableElements.remove(reachableLabel);
boolean canUnwrap = (statement instanceof PsiSwitchStatement && BreakConverter.from(statement) != null) ||
(!(statement instanceof PsiSwitchStatement) &&
labelStatement instanceof PsiSwitchLabeledRuleStatement ruleStatement &&
ruleStatement.getBody() instanceof PsiExpressionStatement);
if (canUnwrap) {
return unreachableElements;
}
if (unreachableElements.isEmpty() || hasDefault) {
return unreachableElements;
}
boolean isEnhancedSwitch = JavaPsiSwitchUtil.isEnhancedSwitchStatement(statement) || statement instanceof PsiSwitchExpression;
if (isEnhancedSwitch) {
PsiExpression expression = statement.getExpression();
if (expression == null) {
return List.of();
}
PsiType selectorType = expression.getType();
if (selectorType == null) {
return List.of();
}
List<PsiCaseLabelElement> toDelete = new ArrayList<>();
for (int i = 0; i < unreachableElements.size(); i++) {
PsiCaseLabelElement currentElement = unreachableElements.get(i);
boolean isDominated = false;
for (int j = i + 1; j < unreachableElements.size(); j++) {
PsiCaseLabelElement nextElement = unreachableElements.get(j);
isDominated = PatternsInSwitchBlockHighlightingModel.isDominated(currentElement, nextElement, selectorType);
if (!isDominated) {
break;
}
}
if (!isDominated) {
toDelete.add(currentElement);
}
}
unreachableElements.removeAll(toDelete);
}
return unreachableElements;
}
private static boolean canRemoveTheOnlyReachableLabel(@NotNull PsiCaseLabelElement label, @NotNull PsiSwitchBlock switchBlock) {
@@ -654,7 +720,8 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
PsiParameter parameter = parameters[0];
if (!BaseIntentionAction.canModify(parameter) || !AnnotationUtil.isAnnotatingApplicable(parameter)) return;
reporter.registerProblem(methodRef, problem.getMessage(IGNORE_ASSERT_STATEMENTS),
LocalQuickFix.notNullElements(parameters.length == 1 ? AddAnnotationPsiFix.createAddNullableFix(parameter) : null));
LocalQuickFix.notNullElements(
parameters.length == 1 ? AddAnnotationPsiFix.createAddNullableFix(parameter) : null));
}
private void reportNullableArgumentsPassedToNonAnnotated(ProblemReporter reporter,
@@ -695,7 +762,8 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
private void reportCallMayProduceNpe(ProblemReporter reporter, @InspectionMessage String message, PsiMethodCallExpression callExpression,
boolean alwaysNull) {
PsiReferenceExpression methodExpression = callExpression.getMethodExpression();
List<LocalQuickFix> fixes = createNPEFixes(methodExpression.getQualifierExpression(), callExpression, reporter.isOnTheFly(), alwaysNull);
List<LocalQuickFix> fixes =
createNPEFixes(methodExpression.getQualifierExpression(), callExpression, reporter.isOnTheFly(), alwaysNull);
if (!alwaysNull) {
ContainerUtil.addIfNotNull(fixes, ReplaceWithObjectsEqualsFix.createFix(callExpression, methodExpression));
}
@@ -750,7 +818,9 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
private static @Nullable PsiMethod getScopeMethod(PsiElement block) {
PsiElement parent = block.getParent();
if (parent instanceof PsiMethod) return (PsiMethod)parent;
if (parent instanceof PsiLambdaExpression) return LambdaUtil.getFunctionalInterfaceMethod(((PsiLambdaExpression)parent).getFunctionalInterfaceType());
if (parent instanceof PsiLambdaExpression) {
return LambdaUtil.getFunctionalInterfaceMethod(((PsiLambdaExpression)parent).getFunctionalInterfaceType());
}
return null;
}
@@ -774,12 +844,15 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
if (nullability != Nullability.NOT_NULL && (!SUGGEST_NULLABLE_ANNOTATIONS || block.getParent() instanceof PsiLambdaExpression)) return;
// no warnings in void lambdas, where the expression is not returned anyway
if (block instanceof PsiExpression && block.getParent() instanceof PsiLambdaExpression && PsiTypes.voidType().equals(returnType)) return;
if (block instanceof PsiExpression && block.getParent() instanceof PsiLambdaExpression && PsiTypes.voidType().equals(returnType)) {
return;
}
// no warnings for Void methods, where only null can be possibly returned
if (returnType == null || returnType.equalsToText(CommonClassNames.JAVA_LANG_VOID)) return;
for (NullabilityProblem<PsiExpression> problem : StreamEx.of(problems).map(NullabilityProblemKind.nullableReturn::asMyProblem).nonNull()) {
for (NullabilityProblem<PsiExpression> problem : StreamEx.of(problems).map(NullabilityProblemKind.nullableReturn::asMyProblem)
.nonNull()) {
final PsiExpression anchor = problem.getAnchor();
PsiExpression expr = problem.getDereferencedExpression();
@@ -790,7 +863,8 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
final String text = exactlyNull
? JavaAnalysisBundle.message("dataflow.message.return.null.from.notnull", presentable)
: JavaAnalysisBundle.message("dataflow.message.return.nullable.from.notnull", presentable);
reporter.registerProblem(expr, text, createNPEFixes(expr, expr, reporter.isOnTheFly(), exactlyNull).toArray(LocalQuickFix.EMPTY_ARRAY));
reporter.registerProblem(expr, text,
createNPEFixes(expr, expr, reporter.isOnTheFly(), exactlyNull).toArray(LocalQuickFix.EMPTY_ARRAY));
}
else if (AnnotationUtil.isAnnotatingApplicable(anchor)) {
final String defaultNullable = manager.getDefaultNullable();

View File

@@ -4,6 +4,7 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.BlockUtils;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInspection.PsiUpdateModCommandQuickFix;
import com.intellij.codeInspection.dataFlow.DataFlowInspectionBase;
import com.intellij.codeInspection.dataFlow.fix.DeleteSwitchLabelFix;
import com.intellij.modcommand.ModPsiUpdater;
import com.intellij.openapi.project.Project;
@@ -44,9 +45,16 @@ public class UnwrapSwitchLabelFix extends PsiUpdateModCommandQuickFix {
boolean shouldKeepDefault = block instanceof PsiSwitchExpression &&
!(labelStatement instanceof PsiSwitchLabeledRuleStatement ruleStatement &&
ruleStatement.getBody() instanceof PsiExpressionStatement);
Set<PsiCaseLabelElement> removableUnreachableBranches = new HashSet<>(DataFlowInspectionBase.findRemovableUnreachableBranches(label, block));
for (PsiSwitchLabelStatementBase otherLabel : labels) {
if (otherLabel == labelStatement) continue;
if (!shouldKeepDefault || !SwitchUtils.isDefaultLabel(otherLabel)) {
boolean isDefault = SwitchUtils.isDefaultLabel(otherLabel);
PsiCaseLabelElementList otherElementList = otherLabel.getCaseLabelElementList();
if (otherElementList != null) {
PsiCaseLabelElement[] otherElements = otherElementList.getElements();
if(!removableUnreachableBranches.containsAll(Set.of(otherElements)) && !isDefault) continue;
}
if (!shouldKeepDefault || !isDefault) {
DeleteSwitchLabelFix.deleteLabel(otherLabel);
}
else {
@@ -54,7 +62,9 @@ public class UnwrapSwitchLabelFix extends PsiUpdateModCommandQuickFix {
}
}
for (PsiCaseLabelElement labelElement : Objects.requireNonNull(labelStatement.getCaseLabelElementList()).getElements()) {
if (labelElement != label && !(shouldKeepDefault && labelElement instanceof PsiDefaultCaseLabelElement)) {
boolean isDefault = labelElement instanceof PsiDefaultCaseLabelElement;
if(!removableUnreachableBranches.contains(labelElement) && !isDefault) continue;
if (labelElement != label && !(shouldKeepDefault && isDefault)) {
new CommentTracker().deleteAndRestoreComments(labelElement);
}
}

View File

@@ -10,10 +10,14 @@ class Main {
// 5
// 6
// 7
case 42, default -> {
case 42 -> {
System.out.println("something");
yield "Six by nine"; // 42
}
default -> {
System.out.println("something");
yield "many";
}
});
}
}

View File

@@ -0,0 +1,19 @@
// "Remove unreachable branches" "false"
public class Switches {
sealed interface I2{}
enum En implements I2{A, B,}
void foo(I2 x) {
if (x == En.A) {
System.out.println(switch (x) {
case En.A<caret> -> {
System.out.println("something");
yield "1";
}
case En.B ->{
yield "2";
}
});
}
}
}

View File

@@ -0,0 +1,22 @@
// "Remove unreachable branches" "false"
public class Switches {
sealed interface I2{}
record A() implements I2{}
record B() implements I2{}
void foo(I2 x) {
if (x instanceof A) {
System.out.println(switch (x) {
case A <caret>a -> {
System.out.println("something");
yield "1";
}
case B b -> {
System.out.println("something");
yield "2";
}
});
}
}
}

View File

@@ -0,0 +1,26 @@
// "Remove unreachable branches" "false"
public class Switches {
sealed interface I2{}
record A(I2 x) implements I2{}
record B() implements I2{}
void foo(I2 x) {
if (x instanceof B) {
System.out.println(switch (x) {
case A(A a) -> {
System.out.println("something");
yield "1";
}
case A(B a) -> {
System.out.println("something");
yield "1";
}
case B <caret>b -> {
System.out.println("something");
yield "1";
}
});
}
}
}

View File

@@ -10,10 +10,14 @@ class Main {
case 5 -> "five"; // 5
case 6 -> "six"; // 6
case 7 -> "seven"; // 7
case 42<caret>, default -> {
case 42<caret> -> {
System.out.println("something");
yield "Six by nine"; // 42
}
default -> {
System.out.println("something");
yield "many";
}
});
}
}

View File

@@ -1,12 +0,0 @@
// "Remove unreachable branches" "true"
import org.jetbrains.annotations.*;
class Test {
void test(Object obj) {
if (!(obj instanceof Rect)) return;
System.out.println(42);
}
record Point(double x, double y) {}
record Rect(@NotNull Point point1, @NotNull Point point2) {}
}

View File

@@ -1,12 +0,0 @@
// "Remove unreachable branches" "true"
import org.jetbrains.annotations.*;
class Test {
void test(Object obj) {
if (!(obj instanceof Rect)) return;
System.out.println(42);
}
record Point(double x, double y) {}
record Rect(@NotNull Point point1, @NotNull Point point2) {}
}

View File

@@ -1,16 +0,0 @@
// "Remove unreachable branches" "true"
import org.jetbrains.annotations.*;
class Test {
void foo(Object obj) {
switch (obj) {
case X x -> { }
default -> { return; }
}
X x1 = (X) obj;
System.out.println(x1.x().x().x().x());
}
}
record X(@NotNull X x) { }

View File

@@ -1,18 +0,0 @@
// "Remove unreachable branches" "true"
import org.jetbrains.annotations.*;
class Test {
void foo(Object obj) {
switch (obj) {
case X x -> { }
default -> { return; }
}
X x1 = (X) obj;
System.out.println(x1);
System.out.println(x1.x().x());
System.out.println(x1.x().x().x().x());
}
}
record X(@NotNull X x) { }

View File

@@ -1,8 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(EmptyBox box) {
System.out.println("Fill it up and send it back");
}
record EmptyBox() {}
}

View File

@@ -1,8 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(EmptyBox box) {
System.out.println(box);
}
record EmptyBox() {}
}

View File

@@ -1,8 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(EmptyBox box) {
System.out.println("Fill it up and send it back");
}
record EmptyBox() {}
}

View File

@@ -1,23 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void foo(Rec rec) {
switch (rec) {
case Rec(A a) -> a.doA();
default -> { return; }
}
((A) rec.i()).doA();
}
}
record Rec(I i) {}
interface I {}
class A implements I {
void doA() {}
}
class B implements I {
void doB() {}
}

View File

@@ -1,9 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(R r) {
System.out.println(r.s() + r.i());
System.out.println(r);
}
record R(int i, String s) {}
}

View File

@@ -1,10 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(Object obj) {
if (!(obj instanceof R)) return;
R rec = (R) obj;
System.out.println(rec.s() + rec.i());
}
record R(int i, String s) {}
}

View File

@@ -1,11 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(Object obj) {
if (!(obj instanceof R)) return;
R rec = (R) obj;
rec = new R(42, "hello");
System.out.println(rec.s() + rec.i());
}
record R(int i, String s) {}
}

View File

@@ -1,11 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(R r) {
R rec = r;
rec = new R(42, "hello");
System.out.println(rec.s() + rec.i());
System.out.println(rec);
}
record R(int i, String s) {}
}

View File

@@ -1,8 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(R r) {
System.out.println(r.s() + r.i());
}
record R(int i, String s) {}
}

View File

@@ -1,10 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(Object obj) {
if (!(obj instanceof R)) return;
R rec = (R) obj;
System.out.println(rec.s() + rec.i());
}
record R(int i, String s) {}
}

View File

@@ -1,8 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(R r) {
System.out.println(r.s());
}
record R(int i, String s) {}
}

View File

@@ -1,10 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(Object obj) {
if (!(obj instanceof R)) return;
R r = (R) obj;
System.out.println(r.i() + r.s());
}
record R(int i, String s) {}
}

View File

@@ -1,18 +0,0 @@
// "Remove unreachable branches" "true"
import org.jetbrains.annotations.*;
class Test {
void test(Object obj) {
if (!(obj instanceof Rect)) return;
switch (obj) {
case Rect(Point(double x1, double y1), Point(double x2, double y2)) rec<caret>:
System.out.println(42);
break;
default:
break;
}
}
record Point(double x, double y) {}
record Rect(@NotNull Point point1, @NotNull Point point2) {}
}

View File

@@ -1,18 +0,0 @@
// "Remove unreachable branches" "true"
import org.jetbrains.annotations.*;
class Test {
void test(Object obj) {
if (!(obj instanceof Rect)) return;
switch (obj) {
case Rect(Point(double x1, double y1) point1, Point(double x2, double y2))<caret>:
System.out.println(42);
break;
default:
break;
}
}
record Point(double x, double y) {}
record Rect(@NotNull Point point1, @NotNull Point point2) {}
}

View File

@@ -1,18 +0,0 @@
// "Remove unreachable branches" "true"
import org.jetbrains.annotations.*;
class Test {
void foo(Object obj) {
switch (obj) {
case X x -> { }
default -> { return; }
}
switch (obj) {
case X(X(X(X(X x)<caret>))) -> System.out.println(x);
default -> { }
}
}
}
record X(@NotNull X x) { }

View File

@@ -1,22 +0,0 @@
// "Remove unreachable branches" "true"
import org.jetbrains.annotations.*;
class Test {
void foo(Object obj) {
switch (obj) {
case X x -> { }
default -> { return; }
}
switch (obj) {
case X<caret>(X(X(X(X x5)) x3)) x1 -> {
System.out.println(x1);
System.out.println(x3);
System.out.println(x5);
}
default -> { }
}
}
}
record X(@NotNull X x) { }

View File

@@ -1,12 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(EmptyBox box) {
switch (box) {
case Empty<caret>Box() when true -> {
System.out.println("Fill it up and send it back");
}
}
}
record EmptyBox() {}
}

View File

@@ -1,12 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(EmptyBox box) {
switch (box) {
case Empt<caret>yBox() emptyBox when true -> {
System.out.println(emptyBox);
}
}
}
record EmptyBox() {}
}

View File

@@ -1,12 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(EmptyBox box) {
switch (box) {
case Empty<caret>Box() emptyBox when true -> {
System.out.println("Fill it up and send it back");
}
}
}
record EmptyBox() {}
}

View File

@@ -1,26 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void foo(Rec rec) {
switch (rec) {
case Rec(A a) -> a.doA();
default -> { return; }
}
switch (rec) {
case R<caret>ec(A a) when true -> a.doA();
default -> {}
}
}
}
record Rec(I i) {}
interface I {}
class A implements I {
void doA() {}
}
class B implements I {
void doB() {}
}

View File

@@ -1,13 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(R r) {
switch (r) {
case R(int i, String s)<caret> rec when true:
System.out.println(s + i);
System.out.println(rec);
break;
}
}
record R(int i, String s) {}
}

View File

@@ -1,15 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(Object obj) {
if (!(obj instanceof R)) return;
switch (obj) {
case R(int i, String s)<caret> rec when true:
System.out.println(s + i);
break;
default:
break;
}
}
record R(int i, String s) {}
}

View File

@@ -1,16 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(Object obj) {
if (!(obj instanceof R)) return;
switch (obj) {
case R(int i, String s)<caret> rec when true:
rec = new R(42, "hello");
System.out.println(s + i);
break;
default:
break;
}
}
record R(int i, String s) {}
}

View File

@@ -1,14 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(R r) {
switch (r) {
case R(int i, String s)<caret> rec when true:
rec = new R(42, "hello");
System.out.println(s + i);
System.out.println(rec);
break;
}
}
record R(int i, String s) {}
}

View File

@@ -1,12 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(R r) {
switch (r) {
case R(int i, String s)<caret> rec when true:
System.out.println(s + i);
break;
}
}
record R(int i, String s) {}
}

View File

@@ -1,15 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(Object obj) {
if (!(obj instanceof R)) return;
switch (obj) {
case R(int i, String s)<caret> rec when true:
System.out.println(s + i);
break;
default:
break;
}
}
record R(int i, String s) {}
}

View File

@@ -1,12 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(R r) {
switch (r) {
case R(int i, String s)<caret> when true:
System.out.println(s);
break;
}
}
record R(int i, String s) {}
}

View File

@@ -1,13 +0,0 @@
// "Remove unreachable branches" "true"
class Test {
void test(Object obj) {
if (!(obj instanceof R)) return;
switch (obj) {
case R(int i, String s)<caret> when true:
System.out.println(i + s);
break;
}
}
record R(int i, String s) {}
}

View File

@@ -1,27 +0,0 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.dataFlow.DataFlowInspection;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
public class DeleteSwitchLabelFix19Test extends LightQuickFixParameterizedTestCase {
@Override
protected LocalInspectionTool @NotNull [] configureLocalInspectionTools() {
return new LocalInspectionTool[]{new DataFlowInspection()};
}
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return LightJavaCodeInsightFixtureTestCase.JAVA_19;
}
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/deleteSwitchLabel19";
}
}

View File

@@ -4,6 +4,7 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.dataFlow.DataFlowInspection;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
@@ -14,6 +15,11 @@ public class DeleteSwitchLabelFixTest extends LightQuickFixParameterizedTestCase
return new LocalInspectionTool[]{new DataFlowInspection()};
}
@Override
protected LanguageLevel getLanguageLevel() {
return LanguageLevel.JDK_21;
}
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {