Java: report local class accessed from another switch branch (IDEA-113520)

GitOrigin-RevId: 7a467fc0cda90dc1944185e83607d8a7d2579cf4
This commit is contained in:
Bas Leijdekkers
2024-01-07 11:21:02 +00:00
committed by intellij-monorepo-bot
parent 997ca97f44
commit 551728bdca
4 changed files with 37 additions and 2 deletions
@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2024 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.analysis;
import com.intellij.codeInsight.CodeInsightUtilCore;
@@ -2444,6 +2444,30 @@ public final class HighlightUtil {
return null;
}
static HighlightInfo.Builder checkLocalClassReferencedFromAnotherSwitchBranch(@NotNull PsiJavaCodeReferenceElement ref,
@NotNull PsiClass aClass) {
if (!(aClass.getParent() instanceof PsiDeclarationStatement declarationStatement) ||
!(declarationStatement.getParent() instanceof PsiCodeBlock codeBlock) ||
!(codeBlock.getParent() instanceof PsiSwitchBlock)) {
return null;
}
boolean classSeen = false;
for (PsiStatement statement : codeBlock.getStatements()) {
if (classSeen) {
if (PsiTreeUtil.isAncestor(statement, ref, true)) break;
if (statement instanceof PsiSwitchLabelStatement) {
String description =
JavaErrorBundle.message("local.class.referenced.from.other.switch.branch", HighlightUtil.formatClass(aClass));
return HighlightInfo.newHighlightInfo(HighlightInfoType.WRONG_REF).range(ref).descriptionAndTooltip(description);
}
}
else if (statement == declarationStatement) {
classSeen = true;
}
}
return null;
}
static void checkSwitchExpressionHasResult(@NotNull PsiSwitchExpression switchExpression,
@NotNull Consumer<? super HighlightInfo.Builder> errorSink) {
PsiCodeBlock switchBody = switchExpression.getBody();
@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2024 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.analysis;
import com.intellij.codeHighlighting.Pass;
@@ -1204,6 +1204,9 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (result != null) {
PsiElement resolved = result.getElement();
if (!hasErrorResults()) add(GenericsHighlightUtil.checkRawOnParameterizedType(ref, resolved));
if (!hasErrorResults() && resolved instanceof PsiClass aClass) {
add(HighlightUtil.checkLocalClassReferencedFromAnotherSwitchBranch(ref, aClass));
}
if (!hasErrorResults() && resolved instanceof PsiModifierListOwner) {
HighlightingFeature.checkPreviewFeature(ref, myPreviewFeatureVisitor);
}
@@ -124,6 +124,7 @@ invalid.qualified.new=Invalid qualified new
class.name.expected=Class name expected
no.enclosing.instance.in.scope=No enclosing instance of type ''{0}'' is in scope
is.not.an.enclosing.class=''{0}'' is not an enclosing class
local.class.referenced.from.other.switch.branch=Local class ''{0}'' cannot be referenced from another switch branch
cannot.be.referenced.from.static.context=''{0}'' cannot be referenced from a static context
no.default.constructor.available=There is no parameterless constructor available in ''{0}''
missing.return.statement=Missing return statement
@@ -21,5 +21,12 @@ class SwitchStatement {
switch (0) {
<error descr="Statement must be prepended with case label">return;</error>
}
switch (0) {
case 0:
class Local {}
case 1:
<error descr="Local class 'Local' cannot be referenced from another switch branch">Local</error> x = new <error descr="Local class 'Local' cannot be referenced from another switch branch">Local</error>();
}
}
}