mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java switch resolve] IDEA-277110 Compilation error not highlighted when using Pattern Matching for switch
Fallthrough to default is not acceptable according to JEP 406. This patch eliminates the default cases from a special case rules and leaves only `case null` as the only special case rule. GitOrigin-RevId: 06c865f92fed01a41c5c87e1aa0a852acb3e7ee0
This commit is contained in:
committed by
intellij-monorepo-bot
parent
d280ec0766
commit
ee954bc169
+5
-11
@@ -107,7 +107,7 @@ public class PsiSwitchLabelStatementImpl extends PsiSwitchLabelStatementBaseImpl
|
||||
immediateSwitchLabel = PsiTreeUtil.getPrevSiblingOfType(currentScope, PsiSwitchLabelStatementBase.class);
|
||||
}
|
||||
|
||||
while (immediateSwitchLabel != null && isFallthrough(immediateSwitchLabel) && isSpecialCaseLabel(immediateSwitchLabel)) {
|
||||
while (immediateSwitchLabel != null && isFallthrough(immediateSwitchLabel) && isCaseNull(immediateSwitchLabel)) {
|
||||
immediateSwitchLabel = PsiTreeUtil.getPrevSiblingOfType(immediateSwitchLabel, PsiSwitchLabelStatementBase.class);
|
||||
}
|
||||
|
||||
@@ -136,18 +136,12 @@ public class PsiSwitchLabelStatementImpl extends PsiSwitchLabelStatementBaseImpl
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isSpecialCaseLabel(@NotNull PsiSwitchLabelStatementBase switchCaseLabel) {
|
||||
return isCase(switchCaseLabel, JavaTokenType.NULL_KEYWORD) ||
|
||||
isCase(switchCaseLabel, JavaTokenType.DEFAULT_KEYWORD) ||
|
||||
switchCaseLabel.isDefaultCase();
|
||||
}
|
||||
private static boolean isCaseNull(@NotNull PsiSwitchLabelStatementBase switchCaseLabel) {
|
||||
if (switchCaseLabel.getCaseLabelElementList() == null) return false;
|
||||
|
||||
private static boolean isCase(@NotNull PsiSwitchLabelStatementBase item, @NotNull IElementType keyword) {
|
||||
if (item.getCaseLabelElementList() == null) return false;
|
||||
|
||||
final PsiCaseLabelElement[] elements = item.getCaseLabelElementList().getElements();
|
||||
final PsiCaseLabelElement[] elements = switchCaseLabel.getCaseLabelElementList().getElements();
|
||||
if (elements.length != 1) return false;
|
||||
|
||||
return elements[0].getNode().getFirstChildNode().getElementType() == keyword;
|
||||
return elements[0].getNode().getFirstChildNode().getElementType() == JavaTokenType.NULL_KEYWORD;
|
||||
}
|
||||
}
|
||||
+31
@@ -5,7 +5,9 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PsiSwitchLabeledRuleStatementImpl extends PsiSwitchLabelStatementBaseImpl implements PsiSwitchLabeledRuleStatement {
|
||||
private static final TokenSet BODY_STATEMENTS =
|
||||
@@ -47,8 +49,37 @@ public class PsiSwitchLabeledRuleStatementImpl extends PsiSwitchLabelStatementBa
|
||||
// Do not resolve references that come from the list of elements in this case rule
|
||||
if (lastParent instanceof PsiCaseLabelElementList) return true;
|
||||
|
||||
if (!shouldProcess()) return true;
|
||||
|
||||
final PsiCaseLabelElementList patternsInCaseLabel = getCaseLabelElementList();
|
||||
if (patternsInCaseLabel == null) return true;
|
||||
return patternsInCaseLabel.processDeclarations(processor, state, null, place);
|
||||
}
|
||||
|
||||
private boolean shouldProcess() {
|
||||
final PsiCaseLabelElementList elementList = getCaseLabelElementList();
|
||||
if (elementList == null) return false;
|
||||
|
||||
final PsiCaseLabelElement[] elements = elementList.getElements();
|
||||
if (elements.length == 1) return true;
|
||||
else if (elements.length > 2 || elements.length == 0) return false;
|
||||
|
||||
final PsiElement first = stripParensIfNecessary(elements[0]);
|
||||
final PsiElement second = stripParensIfNecessary(elements[1]);
|
||||
|
||||
if (first == null || second == null) return true;
|
||||
|
||||
return firstPatternVariableSecondNull(first, second) || firstPatternVariableSecondNull(second, first);
|
||||
}
|
||||
|
||||
private static boolean firstPatternVariableSecondNull(PsiElement first, @NotNull PsiElement second) {
|
||||
return first instanceof PsiTypeTestPattern &&
|
||||
second.getNode().getFirstChildNode().getElementType() == JavaTokenType.NULL_KEYWORD;
|
||||
}
|
||||
|
||||
private static @Nullable PsiElement stripParensIfNecessary(@NotNull PsiCaseLabelElement element) {
|
||||
return element instanceof PsiExpression
|
||||
? PsiUtil.skipParenthesizedExprDown((PsiExpression)element)
|
||||
: element;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -4,9 +4,9 @@ class Main {
|
||||
switch (o) {
|
||||
case Integer i :
|
||||
System.out.println();
|
||||
case default:
|
||||
case null:
|
||||
System.out.println(i);
|
||||
case default:
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
|
||||
class Main {
|
||||
void f(Object o) {
|
||||
switch (o) {
|
||||
case Integer i :
|
||||
System.out.println(i);
|
||||
break;
|
||||
case String s:
|
||||
default:
|
||||
System.out.println(<error descr="Cannot resolve symbol 's'">s</error>);
|
||||
}
|
||||
}
|
||||
|
||||
void g(Object o) {
|
||||
switch (o) {
|
||||
case Integer i :
|
||||
System.out.println(i);
|
||||
break;
|
||||
case String s:
|
||||
case default:
|
||||
System.out.println(<error descr="Cannot resolve symbol 's'">s</error>);
|
||||
}
|
||||
}
|
||||
|
||||
void ff(Object o) {
|
||||
switch (o) {
|
||||
case Integer i -> System.out.println(i);
|
||||
case String s, default -> System.out.println(<error descr="Cannot resolve symbol 's'">s</error>);
|
||||
}
|
||||
}
|
||||
|
||||
void gg(Object o) {
|
||||
switch (o) {
|
||||
case Integer i -> System.out.println(i);
|
||||
case default, String s -> System.out.println(<error descr="Cannot resolve symbol 's'">s</error>);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -21,17 +21,17 @@ class Main {
|
||||
};
|
||||
|
||||
int i4 = switch(o) {
|
||||
case String s, <error descr="Illegal fall-through to a pattern">X x</error> -> x.f();
|
||||
case String s, X x -> <error descr="Cannot resolve symbol 'x'">x</error>.f();
|
||||
default -> 1;
|
||||
};
|
||||
|
||||
int i5 = switch(o) {
|
||||
case String s, <error descr="Illegal fall-through to a pattern">X x</error> -> x.f();
|
||||
case String s, X x -> <error descr="Cannot resolve symbol 'x'">x</error>.f();
|
||||
default -> 1;
|
||||
};
|
||||
|
||||
int i6 = switch(o) {
|
||||
case X x, <error descr="Illegal fall-through to a pattern">String s</error> -> x.f();
|
||||
case X x, String s -> <error descr="Cannot resolve symbol 'x'">x</error>.f();
|
||||
default -> 1;
|
||||
};
|
||||
return i1 + i2 + i3 + i4 + i5 + i6;
|
||||
|
||||
-3
@@ -4,9 +4,6 @@ class Main {
|
||||
switch (o) {
|
||||
case Integer i :
|
||||
System.out.println();
|
||||
case null:
|
||||
default: {}
|
||||
case default:
|
||||
case null:
|
||||
System.out.println(i<caret>);
|
||||
};
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class Main {
|
||||
private static final int i = 0;
|
||||
private void f(Object o) {
|
||||
switch (o) {
|
||||
case Integer i, null -> System.out.println(i<caret>);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class Main {
|
||||
private static final int i = 0;
|
||||
private void f(Object o) {
|
||||
switch (o) {
|
||||
case Integer i :
|
||||
System.out.println();
|
||||
default:
|
||||
System.out.println(i<caret>);
|
||||
};
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class Main {
|
||||
private static final int i = 0;
|
||||
private void f(Object o) {
|
||||
switch (o) {
|
||||
case Integer i, default -> System.out.println(i<caret>);
|
||||
};
|
||||
}
|
||||
}
|
||||
+4
@@ -99,6 +99,10 @@ public class LightPatternsForSwitchHighlightingTest extends LightJavaCodeInsight
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testFallthroughDefault() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testUnusedPatternVariable() {
|
||||
myFixture.enableInspections(new UnusedDeclarationInspection());
|
||||
doTest();
|
||||
|
||||
+28
-12
@@ -121,38 +121,47 @@ public class GotoDeclarationTest extends LightJavaCodeInsightTestCase {
|
||||
}
|
||||
|
||||
public void testPatternMatchingGuardInSwitchExpression() {
|
||||
doTestPatternMatchingGuard();
|
||||
doTestGoToField();
|
||||
}
|
||||
|
||||
public void testPatternMatchingGuardInSwitchStatement() {
|
||||
doTestPatternMatchingGuard();
|
||||
doTestGoToField();
|
||||
}
|
||||
|
||||
public void testPatternMatchingWithParensAroundReference() {
|
||||
doTestPatternMatchingGuard();
|
||||
doTestGoToField();
|
||||
}
|
||||
|
||||
|
||||
public void testReferenceFieldInPatternMatchingInSwitchStatement() {
|
||||
doTestPatternMatchingGuard();
|
||||
doTestGoToField();
|
||||
}
|
||||
|
||||
public void testCaseNullDefaultAfterPatternMatching() {
|
||||
configure();
|
||||
final PsiElement patternVariable = PsiTreeUtil.findChildOfType(getFile(), PsiPatternVariable.class);
|
||||
final PsiElement element = GotoDeclarationAction.findTargetElement(getProject(), getEditor(), getEditor().getCaretModel().getOffset());
|
||||
assertThat(element).isEqualTo(patternVariable);
|
||||
public void testCaseNullAfterPatternMatching() {
|
||||
doTestGoToPatternVariable();
|
||||
}
|
||||
|
||||
public void testCaseNullAfterPatternMatchingExpr() {
|
||||
doTestGoToPatternVariable();
|
||||
}
|
||||
|
||||
public void testDefaultAfterPatternMatching() {
|
||||
doTestGoToField();
|
||||
}
|
||||
|
||||
public void testDefaultAfterPatternMatchingExpr() {
|
||||
doTestGoToField();
|
||||
}
|
||||
|
||||
public void testGuardWithInstanceOfPatternMatchingInIf() {
|
||||
doTestGoToPatternVariable();
|
||||
doTestGoToSecondPatternVariable();
|
||||
}
|
||||
|
||||
public void testGuardWithInstanceOfPatternMatchingInSwitch() {
|
||||
doTestGoToPatternVariable();
|
||||
doTestGoToSecondPatternVariable();
|
||||
}
|
||||
|
||||
private void doTestPatternMatchingGuard() {
|
||||
private void doTestGoToField() {
|
||||
configure();
|
||||
final PsiField field = PsiTreeUtil.findChildOfType(getFile(), PsiField.class);
|
||||
final PsiElement element = GotoDeclarationAction.findTargetElement(getProject(), getEditor(), getEditor().getCaretModel().getOffset());
|
||||
@@ -160,6 +169,13 @@ public class GotoDeclarationTest extends LightJavaCodeInsightTestCase {
|
||||
}
|
||||
|
||||
private void doTestGoToPatternVariable() {
|
||||
configure();
|
||||
final PsiPatternVariable patternVariable = PsiTreeUtil.findChildOfType(getFile(), PsiPatternVariable.class);
|
||||
final PsiElement element = GotoDeclarationAction.findTargetElement(getProject(), getEditor(), getEditor().getCaretModel().getOffset());
|
||||
assertThat(element).isEqualTo(patternVariable);
|
||||
}
|
||||
|
||||
private void doTestGoToSecondPatternVariable() {
|
||||
configure();
|
||||
final Iterator<PsiPatternVariable> iterator = PsiTreeUtil.findChildrenOfType(getFile(), PsiPatternVariable.class).iterator();
|
||||
iterator.next();
|
||||
|
||||
Reference in New Issue
Block a user