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 29c30724b4f9..3d8956f4dd92 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 @@ -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 errorSink) { PsiCodeBlock switchBody = switchExpression.getBody(); 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 c798fb3ba634..bbc164f48015 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 @@ -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); } diff --git a/java/java-psi-impl/src/messages/JavaErrorBundle.properties b/java/java-psi-impl/src/messages/JavaErrorBundle.properties index aaab7531d70e..26173337ddf5 100644 --- a/java/java-psi-impl/src/messages/JavaErrorBundle.properties +++ b/java/java-psi-impl/src/messages/JavaErrorBundle.properties @@ -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 diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/SwitchStatement.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/SwitchStatement.java index ad4521c687fa..b7a2bba5713c 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/SwitchStatement.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/SwitchStatement.java @@ -21,5 +21,12 @@ class SwitchStatement { switch (0) { return; } + + switch (0) { + case 0: + class Local {} + case 1: + Local x = new Local(); + } } } \ No newline at end of file