From 551728bdca7a7dff8122a701d5d0f51209146496 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Sat, 6 Jan 2024 09:25:18 +0100 Subject: [PATCH] Java: report local class accessed from another switch branch (IDEA-113520) GitOrigin-RevId: 7a467fc0cda90dc1944185e83607d8a7d2579cf4 --- .../daemon/impl/analysis/HighlightUtil.java | 26 ++++++++++++++++++- .../impl/analysis/HighlightVisitorImpl.java | 5 +++- .../src/messages/JavaErrorBundle.properties | 1 + .../advHighlighting/SwitchStatement.java | 7 +++++ 4 files changed, 37 insertions(+), 2 deletions(-) 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