diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
index 444b73295ca1..32f133ed83e0 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
@@ -515,7 +515,7 @@ public class HighlightUtil extends HighlightUtilBase {
@Nullable
static HighlightInfo checkReturnFromSwitchExpr(@NotNull PsiStatement statement) {
- if (PsiImplUtil.findEnclosingSwitchOrLoop(statement) instanceof PsiSwitchExpression) {
+ if (PsiImplUtil.findEnclosingSwitchExpression(statement) != null) {
String message = JavaErrorMessages.message("return.outside.switch.expr");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(message).create();
}
@@ -796,24 +796,9 @@ public class HighlightUtil extends HighlightUtilBase {
@Nullable
static HighlightInfo checkBreakTarget(@NotNull PsiBreakStatement statement, @NotNull LanguageLevel languageLevel) {
- if (statement.findExitedStatement() == null) {
- if (Feature.ENHANCED_SWITCH.isSufficient(languageLevel) && PsiImplUtil.findEnclosingSwitchOrLoop(statement) instanceof PsiSwitchExpression) {
- String message = JavaErrorMessages.message("break.outside.switch.expr");
- return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(message).create();
- }
-
- PsiIdentifier label = statement.getLabelIdentifier();
- if (label != null) {
- String message = JavaErrorMessages.message("unresolved.label", label.getText());
- return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(label).descriptionAndTooltip(message).create();
- }
- else {
- String message = JavaErrorMessages.message("break.outside.switch.or.loop");
- return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(message).create();
- }
- }
-
- return null;
+ return checkBreakOrContinueTarget(statement, statement.getLabelIdentifier(), statement.findExitedStatement(), languageLevel,
+ "break.outside.switch.or.loop",
+ "break.outside.switch.expr");
}
@Nullable
@@ -838,42 +823,45 @@ public class HighlightUtil extends HighlightUtilBase {
}
@Nullable
- static HighlightInfo checkContinueOutsideLoop(@NotNull PsiContinueStatement statement, LanguageLevel languageLevel) {
- if (PsiImplUtil.findEnclosingLoop(statement) == null) {
- String message = JavaErrorMessages.message("continue.outside.loop");
- return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(message).create();
- }
-
- return checkContinueOutsideOfSwitchExpression(statement, statement.findContinuedStatement(), languageLevel);
- }
-
- @Nullable
- static HighlightInfo checkContinueTarget(@NotNull PsiContinueStatement statement, @NotNull PsiIdentifier label, @NotNull LanguageLevel level) {
+ static HighlightInfo checkContinueTarget(@NotNull PsiContinueStatement statement, @NotNull LanguageLevel languageLevel) {
PsiStatement continuedStatement = statement.findContinuedStatement();
+ PsiIdentifier label = statement.getLabelIdentifier();
- if (continuedStatement == null) {
- String message = JavaErrorMessages.message("unresolved.label", label.getText());
- return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(label).descriptionAndTooltip(message).create();
- }
- if (!(continuedStatement instanceof PsiLoopStatement)) {
+ if (label != null && continuedStatement != null && !(continuedStatement instanceof PsiLoopStatement)) {
String message = JavaErrorMessages.message("not.loop.label", label.getText());
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(message).create();
}
- return checkContinueOutsideOfSwitchExpression(statement, continuedStatement, level);
+ return checkBreakOrContinueTarget(statement, label, continuedStatement, languageLevel,
+ "continue.outside.loop",
+ "continue.outside.switch.expr");
}
- private static HighlightInfo checkContinueOutsideOfSwitchExpression(PsiContinueStatement statement,
- PsiStatement continuedStatement,
- LanguageLevel level) {
+ @Nullable
+ private static HighlightInfo checkBreakOrContinueTarget(PsiStatement statement,
+ @Nullable PsiIdentifier label,
+ @Nullable PsiStatement target,
+ LanguageLevel level,
+ @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String misplacedKey,
+ @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String crossingKey) {
+ if (target == null && label != null) {
+ String message = JavaErrorMessages.message("unresolved.label", label.getText());
+ return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(label).descriptionAndTooltip(message).create();
+ }
+
if (Feature.ENHANCED_SWITCH.isSufficient(level)) {
- PsiElement enclosing = PsiImplUtil.findEnclosingSwitchOrLoop(statement);
- if (enclosing instanceof PsiSwitchExpression && PsiTreeUtil.isAncestor(continuedStatement, enclosing, true)) {
- String message = JavaErrorMessages.message("continue.outside.switch.expr");
+ PsiSwitchExpression expression = PsiImplUtil.findEnclosingSwitchExpression(statement);
+ if (expression != null && (target == null || PsiTreeUtil.isAncestor(target, expression, true))) {
+ String message = JavaErrorMessages.message(crossingKey);
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(message).create();
}
}
+ if (target == null) {
+ String message = JavaErrorMessages.message(misplacedKey);
+ return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).descriptionAndTooltip(message).create();
+ }
+
return null;
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
index 4a850724b063..f03d3b61c8cb 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightVisitorImpl.java
@@ -461,11 +461,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
@Override
public void visitContinueStatement(PsiContinueStatement statement) {
super.visitContinueStatement(statement);
- if (!myHolder.hasErrorResults()) {
- PsiIdentifier label = statement.getLabelIdentifier();
- myHolder.add(label == null ? HighlightUtil.checkContinueOutsideLoop(statement, myLanguageLevel)
- : HighlightUtil.checkContinueTarget(statement, label, myLanguageLevel));
- }
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkContinueTarget(statement, myLanguageLevel));
}
@Override
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiContinueStatement.java b/java/java-psi-api/src/com/intellij/psi/PsiContinueStatement.java
index d3b215e2390f..3b5a2b682acb 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiContinueStatement.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiContinueStatement.java
@@ -1,18 +1,4 @@
-/*
- * Copyright 2000-2009 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
+// Copyright 2000-2019 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.psi;
import org.jetbrains.annotations.Nullable;
@@ -22,19 +8,13 @@ import org.jetbrains.annotations.Nullable;
*/
public interface PsiContinueStatement extends PsiStatement {
/**
- * Returns the identifier representing the label specified on the statement.
- *
- * @return the identifier for the label, or null if the statement has no label.
+ * Returns an identifier element containing the statement's target label, if any.
*/
- @Nullable
- PsiIdentifier getLabelIdentifier();
+ @Nullable PsiIdentifier getLabelIdentifier();
/**
* Returns the statement instance ({@link PsiForStatement}, {@link PsiWhileStatement} etc.) representing
* the statement to the next iteration of which {@code continue} transfers control.
- *
- * @return the statement instance, or null if the statement is not valid in the context where it is located.
*/
- @Nullable
- PsiStatement findContinuedStatement();
-}
+ @Nullable PsiStatement findContinuedStatement();
+}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
index 218bf4b99c66..b33edc992879 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java
@@ -1,4 +1,4 @@
-// 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.
+// Copyright 2000-2019 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.psi.impl;
import com.intellij.codeInsight.AnnotationTargetUtil;
@@ -39,7 +39,6 @@ import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PairFunction;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -652,11 +651,6 @@ public class PsiImplUtil {
}
}
- @Contract("null -> false")
- public static boolean isUnqualifiedReference(@Nullable PsiExpression expression) {
- return expression instanceof PsiReferenceExpression && ((PsiReferenceExpression)expression).getQualifierExpression() == null;
- }
-
@Nullable
public static PsiLoopStatement findEnclosingLoop(@NotNull PsiElement start) {
for (PsiElement e = start; !isCodeBoundary(e); e = e.getParent()) {
@@ -666,9 +660,17 @@ public class PsiImplUtil {
}
@Nullable
- public static PsiElement findEnclosingSwitchOrLoop(@NotNull PsiElement start) {
+ public static PsiStatement findEnclosingSwitchOrLoop(@NotNull PsiElement start) {
for (PsiElement e = start; !isCodeBoundary(e); e = e.getParent()) {
- if (e instanceof PsiSwitchBlock || e instanceof PsiLoopStatement) return e;
+ if (e instanceof PsiSwitchStatement || e instanceof PsiLoopStatement) return (PsiStatement)e;
+ }
+ return null;
+ }
+
+ @Nullable
+ public static PsiSwitchExpression findEnclosingSwitchExpression(@NotNull PsiElement start) {
+ for (PsiElement e = start; !isCodeBoundary(e); e = e.getParent()) {
+ if (e instanceof PsiSwitchExpression) return (PsiSwitchExpression)e;
}
return null;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiBreakStatementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiBreakStatementImpl.java
index 431da9493f95..a871dd9dd96c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiBreakStatementImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiBreakStatementImpl.java
@@ -27,18 +27,14 @@ public class PsiBreakStatementImpl extends CompositePsiElement implements PsiBre
@Nullable
@Override
public PsiStatement findExitedStatement() {
- PsiElement enclosing = PsiImplUtil.findEnclosingSwitchOrLoop(this);
- if (enclosing instanceof PsiSwitchExpression) {
- return null;
- }
-
PsiIdentifier label = getLabelIdentifier();
if (label != null) {
PsiLabeledStatement labeled = PsiImplUtil.findEnclosingLabeledStatement(this, label.getText());
return labeled != null ? labeled.getStatement() : null;
}
-
- return (PsiStatement)enclosing;
+ else {
+ return PsiImplUtil.findEnclosingSwitchOrLoop(this);
+ }
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiContinueStatementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiContinueStatementImpl.java
index 013cef2f4e2b..cdb5d0f5cbf1 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiContinueStatementImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiContinueStatementImpl.java
@@ -1,4 +1,4 @@
-// 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.
+// Copyright 2000-2019 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.psi.impl.source.tree.java;
import com.intellij.lang.ASTNode;
@@ -29,16 +29,13 @@ public class PsiContinueStatementImpl extends CompositePsiElement implements Psi
@Override
public PsiStatement findContinuedStatement() {
PsiIdentifier label = getLabelIdentifier();
- if (label == null) {
+ if (label != null) {
+ PsiLabeledStatement labeled = PsiImplUtil.findEnclosingLabeledStatement(this, label.getText());
+ return labeled != null ? labeled.getStatement() : null;
+ }
+ else {
return PsiImplUtil.findEnclosingLoop(this);
}
-
- PsiLabeledStatement labeled = PsiImplUtil.findEnclosingLabeledStatement(this, label.getText());
- if (labeled != null) {
- return labeled.getStatement();
- }
-
- return null;
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiYieldStatementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiYieldStatementImpl.java
index 5b114da21b66..b3edfecdd83d 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiYieldStatementImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiYieldStatementImpl.java
@@ -22,12 +22,7 @@ public class PsiYieldStatementImpl extends CompositePsiElement implements PsiYie
@Nullable
@Override
public PsiSwitchExpression findEnclosingExpression() {
- PsiElement element = this, enclosing;
- while (element != null && (enclosing = PsiImplUtil.findEnclosingSwitchOrLoop(element)) != null) {
- if (enclosing instanceof PsiSwitchExpression) return (PsiSwitchExpression)enclosing;
- element = enclosing.getParent();
- }
- return null;
+ return PsiImplUtil.findEnclosingSwitchExpression(this);
}
@Override
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/switchExpressions/YieldStatements.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/switchExpressions/YieldStatements.java
index 9450e73d08d5..04593e8a837f 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/switchExpressions/YieldStatements.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/switchExpressions/YieldStatements.java
@@ -10,12 +10,12 @@ class YieldStatements {
default: yield 0;
}
- System.out.println(switch (i) {
+ out: System.out.println(switch (i) {
case 1 -> { while (true) yield ref; }
case 2 -> { while (true) break wtf; }
case 3 -> { yield ref; }
case 4 -> { yield (ref); }
- case 5 -> { break wtf; }
+ case 5 -> { break wtf; }
case 6 -> {
int a = 0;
a: switch (0) { default: yield a; }
@@ -34,6 +34,9 @@ class YieldStatements {
yield yield;
}
case 11 -> { yield m(0); }
+ case 12 -> {
+ switch (i) { default: break out;; }
+ }
default -> throw new RuntimeException();
});