diff --git a/java/codeserver/core/src/com/intellij/java/codeserver/core/JavaPsiSwitchUtil.java b/java/codeserver/core/src/com/intellij/java/codeserver/core/JavaPsiSwitchUtil.java index 70529c93753e..f7e952d57f06 100644 --- a/java/codeserver/core/src/com/intellij/java/codeserver/core/JavaPsiSwitchUtil.java +++ b/java/codeserver/core/src/com/intellij/java/codeserver/core/JavaPsiSwitchUtil.java @@ -5,11 +5,9 @@ import com.intellij.codeInsight.ExpressionUtil; import com.intellij.openapi.util.Comparing; import com.intellij.pom.java.JavaFeature; import com.intellij.psi.*; -import com.intellij.psi.util.ConstantExpressionUtil; -import com.intellij.psi.util.JavaPsiPatternUtil; -import com.intellij.psi.util.PsiUtil; -import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.psi.util.*; import com.intellij.util.ObjectUtils; +import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import org.jetbrains.annotations.Contract; @@ -383,6 +381,27 @@ public final class JavaPsiSwitchUtil { labelElement -> labelElement instanceof PsiDefaultCaseLabelElement); } + /** + * @param block the switch block + * @return a list of switch branches consisting of either {@link PsiSwitchLabelStatementBase} or {@link PsiCaseLabelElement} + */ + public static @NotNull List getSwitchBranches(@NotNull PsiSwitchBlock block) { + final PsiCodeBlock body = block.getBody(); + if (body == null) return Collections.emptyList(); + List result = new SmartList<>(); + for (PsiSwitchLabelStatementBase child : PsiTreeUtil.getChildrenOfTypeAsList(body, PsiSwitchLabelStatementBase.class)) { + if (child.isDefaultCase()) { + result.add(child); + } + else { + PsiCaseLabelElementList labelElementList = child.getCaseLabelElementList(); + if (labelElementList == null) continue; + Collections.addAll(result, labelElementList.getElements()); + } + } + return result; + } + /** * Kinds of switch selector * @see #getSwitchSelectorKind(PsiType) diff --git a/java/codeserver/core/src/com/intellij/java/codeserver/core/package-info.java b/java/codeserver/core/src/com/intellij/java/codeserver/core/package-info.java index f99db2c713ff..2fd741d3f714 100644 --- a/java/codeserver/core/src/com/intellij/java/codeserver/core/package-info.java +++ b/java/codeserver/core/src/com/intellij/java/codeserver/core/package-info.java @@ -1,6 +1,7 @@ // Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. /** * Core functionality required by Java codeserver and other parts of Java plugin. - * Mostly contains utility classes. + * Mostly contains utility classes. + * The utility methods in this package are aimed to help reading the PSI and extract some facts from it. */ package com.intellij.java.codeserver.core; diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/SwitchBlockHighlightingModel.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/SwitchBlockHighlightingModel.java index c048f31fd927..b3e9a1a23e16 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/SwitchBlockHighlightingModel.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/SwitchBlockHighlightingModel.java @@ -20,7 +20,6 @@ import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.util.containers.SmartHashSet; -import com.siyeh.ig.psiutils.SwitchUtils; import com.siyeh.ig.psiutils.TypeUtils; import one.util.streamex.StreamEx; import org.jetbrains.annotations.NotNull; @@ -306,7 +305,7 @@ public class SwitchBlockHighlightingModel { if (switchModel == null) return SwitchExhaustivenessState.UNEVALUATED; PsiCodeBlock switchBody = switchModel.myBlock.getBody(); if (switchBody == null) return SwitchExhaustivenessState.UNEVALUATED; - List labelElements = StreamEx.of(SwitchUtils.getSwitchBranches(switchBlock)).select(PsiCaseLabelElement.class) + List labelElements = StreamEx.of(JavaPsiSwitchUtil.getSwitchBranches(switchBlock)).select(PsiCaseLabelElement.class) .filter(element -> !(element instanceof PsiDefaultCaseLabelElement)).toList(); if (labelElements.isEmpty()) return SwitchExhaustivenessState.UNEVALUATED; boolean needToCheckCompleteness = ExpressionUtil.isEnhancedSwitch(switchBlock); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java index 191ba11de9f8..17facef2cfe7 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java @@ -834,7 +834,7 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec PsiType selectorType = selector.getType(); if (selectorType == null) return Collections.emptySet(); List labelElements = - ContainerUtil.filterIsInstance(SwitchUtils.getSwitchBranches(switchBlock), PsiCaseLabelElement.class); + ContainerUtil.filterIsInstance(JavaPsiSwitchUtil.getSwitchBranches(switchBlock), PsiCaseLabelElement.class); if (labelElements.isEmpty()) return Collections.emptySet(); MultiMap duplicateCandidates = JavaPsiSwitchUtil.getValuesAndLabels(switchBlock); diff --git a/java/java-analysis-impl/src/com/intellij/psi/util/RedundantCastUtil.java b/java/java-analysis-impl/src/com/intellij/psi/util/RedundantCastUtil.java index 5b2e76d1a8d8..cf44d12e3fb2 100644 --- a/java/java-analysis-impl/src/com/intellij/psi/util/RedundantCastUtil.java +++ b/java/java-analysis-impl/src/com/intellij/psi/util/RedundantCastUtil.java @@ -4,6 +4,7 @@ package com.intellij.psi.util; import com.intellij.codeInsight.ExceptionUtil; import com.intellij.codeInsight.NullableNotNullManager; import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil; +import com.intellij.java.codeserver.core.JavaPsiSwitchUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Comparing; @@ -19,7 +20,6 @@ import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import com.siyeh.ig.bugs.NullArgumentToVariableArgMethodInspection; import com.siyeh.ig.psiutils.ExpectedTypeUtils; -import com.siyeh.ig.psiutils.SwitchUtils; import one.util.streamex.StreamEx; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -814,7 +814,7 @@ public final class RedundantCastUtil { } if (opType instanceof PsiPrimitiveType) { if (PsiUtil.isAvailable(JavaFeature.PATTERN_GUARDS_AND_RECORD_PATTERNS, switchBlock)) { - for (PsiElement branch : SwitchUtils.getSwitchBranches(switchBlock)) { + for (PsiElement branch : JavaPsiSwitchUtil.getSwitchBranches(switchBlock)) { // 14.11.1 A null case element is switch compatible with T if T is a reference type (JEP 427) if (branch instanceof PsiExpression expression && TypeConversionUtil.isNullType(expression.getType())) return; // 14.30.3 A type pattern that declares a pattern variable of a reference type U is @@ -826,7 +826,7 @@ public final class RedundantCastUtil { else if (PsiUtil.isAvailable(JavaFeature.PATTERNS_IN_SWITCH, switchBlock)) { boolean needToCheckCompleteness = switchBlock instanceof PsiSwitchExpression; boolean hasDefault = false; - for (PsiElement branch : SwitchUtils.getSwitchBranches(switchBlock)) { + for (PsiElement branch : JavaPsiSwitchUtil.getSwitchBranches(switchBlock)) { // 14.11.1. A null case label element is compatible with e if the type of e is a reference type (JEP 406 and JEP 420) if (branch instanceof PsiExpression expression && TypeConversionUtil.isNullType(expression.getType())) return; needToCheckCompleteness |= branch instanceof PsiPattern; diff --git a/java/java-analysis-impl/src/com/siyeh/ig/psiutils/SwitchUtils.java b/java/java-analysis-impl/src/com/siyeh/ig/psiutils/SwitchUtils.java index ce4b71c9e8bc..3b8d5c2e620c 100644 --- a/java/java-analysis-impl/src/com/siyeh/ig/psiutils/SwitchUtils.java +++ b/java/java-analysis-impl/src/com/siyeh/ig/psiutils/SwitchUtils.java @@ -27,7 +27,6 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.ObjectUtils; -import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.siyeh.ig.callMatcher.CallMatcher; import com.siyeh.ipp.psiutils.ErrorUtil; @@ -69,7 +68,7 @@ public final class SwitchUtils { * @return a negative number if a default case was encountered. */ public static int calculateBranchCount(@NotNull PsiSwitchBlock block) { - List switchBranches = getSwitchBranches(block); + List switchBranches = JavaPsiSwitchUtil.getSwitchBranches(block); if (switchBranches.isEmpty()) return 0; int branches = 0; boolean defaultFound = false; @@ -95,27 +94,6 @@ public final class SwitchUtils { return defaultFound ? -branches - 1 : branches; } - /** - * @param block the switch block - * @return a list of switch branches consisting of either {@link PsiSwitchLabelStatementBase} or {@link PsiCaseLabelElement} - */ - public static @NotNull List getSwitchBranches(@NotNull PsiSwitchBlock block) { - final PsiCodeBlock body = block.getBody(); - if (body == null) return Collections.emptyList(); - List result = new SmartList<>(); - for (PsiSwitchLabelStatementBase child : PsiTreeUtil.getChildrenOfTypeAsList(body, PsiSwitchLabelStatementBase.class)) { - if (child.isDefaultCase()) { - result.add(child); - } - else { - PsiCaseLabelElementList labelElementList = child.getCaseLabelElementList(); - if (labelElementList == null) continue; - Collections.addAll(result, labelElementList.getElements()); - } - } - return result; - } - /** * Counts the number of unconditional patterns applicable to the provided selector type. * diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaKeywordCompletion.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaKeywordCompletion.java index 488c67fb126a..ccbb47f146dd 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaKeywordCompletion.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaKeywordCompletion.java @@ -30,7 +30,6 @@ import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import com.siyeh.ig.psiutils.ExpressionUtils; import com.siyeh.ig.psiutils.SealedUtils; -import com.siyeh.ig.psiutils.SwitchUtils; import one.util.streamex.StreamEx; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; @@ -1198,7 +1197,7 @@ public class JavaKeywordCompletion { if (switchBlock != null && switchBlock.getExpression() != null) { PsiType type = switchBlock.getExpression().getType(); if (PsiTypes.booleanType().equals(PsiPrimitiveType.getOptionallyUnboxedType(type))) { - Set branches = SwitchUtils.getSwitchBranches(switchBlock).stream() + Set branches = JavaPsiSwitchUtil.getSwitchBranches(switchBlock).stream() .map(branch -> branch instanceof PsiExpression expression ? ExpressionUtils.computeConstantExpression(expression) : null) .filter(constant -> constant instanceof Boolean) .map(branch -> branch.toString()) diff --git a/java/java-impl/src/com/siyeh/ig/controlflow/SwitchStatementWithTooFewBranchesInspection.java b/java/java-impl/src/com/siyeh/ig/controlflow/SwitchStatementWithTooFewBranchesInspection.java index 508bdf4232e3..ecc456d73ab2 100644 --- a/java/java-impl/src/com/siyeh/ig/controlflow/SwitchStatementWithTooFewBranchesInspection.java +++ b/java/java-impl/src/com/siyeh/ig/controlflow/SwitchStatementWithTooFewBranchesInspection.java @@ -20,6 +20,7 @@ import com.intellij.codeInspection.CommonQuickFixBundle; import com.intellij.codeInspection.LocalQuickFix; import com.intellij.codeInspection.UpdateInspectionOptionFix; import com.intellij.codeInspection.options.OptPane; +import com.intellij.java.codeserver.core.JavaPsiSwitchUtil; import com.intellij.modcommand.ModPsiUpdater; import com.intellij.modcommand.PsiUpdateModCommandQuickFix; import com.intellij.openapi.project.Project; @@ -166,7 +167,7 @@ public final class SwitchStatementWithTooFewBranchesInspection extends BaseInspe // Empty switch is reported by another inspection return null; } - boolean patternSwitch = ContainerUtil.exists(SwitchUtils.getSwitchBranches(block), e -> e instanceof PsiPattern); + boolean patternSwitch = ContainerUtil.exists(JavaPsiSwitchUtil.getSwitchBranches(block), e -> e instanceof PsiPattern); if (patternSwitch && ignorePatternSwitch) return null; if (branchCount > 0 && (patternSwitch || block instanceof PsiSwitchExpression)) { // Absence of 'default' branch makes the pattern-switch or expression-switch exhaustive diff --git a/java/java-impl/src/com/siyeh/ig/dataflow/CreateNullBranchFix.java b/java/java-impl/src/com/siyeh/ig/dataflow/CreateNullBranchFix.java index 7edba488cf70..854929a561a0 100644 --- a/java/java-impl/src/com/siyeh/ig/dataflow/CreateNullBranchFix.java +++ b/java/java-impl/src/com/siyeh/ig/dataflow/CreateNullBranchFix.java @@ -1,6 +1,7 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.siyeh.ig.dataflow; +import com.intellij.java.codeserver.core.JavaPsiSwitchUtil; import com.intellij.modcommand.ActionContext; import com.intellij.modcommand.ModPsiUpdater; import com.intellij.pom.java.JavaFeature; @@ -51,7 +52,7 @@ public final class CreateNullBranchFix extends BaseSwitchFix { if (selector == null) return; PsiType selectorType = selector.getType(); if (selectorType == null) return; - List branches = SwitchUtils.getSwitchBranches(switchBlock); + List branches = JavaPsiSwitchUtil.getSwitchBranches(switchBlock); for (PsiElement branch : branches) { // just for the case if we already contain null, there is no need to apply the fix if (branch instanceof PsiExpression expression && TypeConversionUtil.isNullType(expression.getType())) return; diff --git a/java/java-impl/src/com/siyeh/ig/fixes/BaseSwitchFix.java b/java/java-impl/src/com/siyeh/ig/fixes/BaseSwitchFix.java index 9d5df482f547..d97fb67b1da9 100644 --- a/java/java-impl/src/com/siyeh/ig/fixes/BaseSwitchFix.java +++ b/java/java-impl/src/com/siyeh/ig/fixes/BaseSwitchFix.java @@ -4,6 +4,7 @@ package com.siyeh.ig.fixes; import com.intellij.codeInsight.Nullability; import com.intellij.codeInspection.dataFlow.NullabilityUtil; import com.intellij.codeInspection.util.IntentionName; +import com.intellij.java.codeserver.core.JavaPsiSwitchUtil; import com.intellij.modcommand.*; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiExpression; @@ -13,7 +14,6 @@ import com.intellij.util.containers.ContainerUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.dataflow.CreateNullBranchFix; import com.siyeh.ig.psiutils.ExpressionUtils; -import com.siyeh.ig.psiutils.SwitchUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -42,7 +42,7 @@ public abstract class BaseSwitchFix extends PsiUpdateModCommandAction branches = SwitchUtils.getSwitchBranches(block); + List branches = JavaPsiSwitchUtil.getSwitchBranches(block); if (ContainerUtil.or(branches, branch -> branch instanceof PsiExpression psiExpression && ExpressionUtils.isNullLiteral(psiExpression))) { return null; diff --git a/java/java-impl/src/com/siyeh/ig/fixes/CreateMissingBooleanPrimitiveBranchesFix.java b/java/java-impl/src/com/siyeh/ig/fixes/CreateMissingBooleanPrimitiveBranchesFix.java index a2e8ea542ee7..dc03a9f0c08c 100644 --- a/java/java-impl/src/com/siyeh/ig/fixes/CreateMissingBooleanPrimitiveBranchesFix.java +++ b/java/java-impl/src/com/siyeh/ig/fixes/CreateMissingBooleanPrimitiveBranchesFix.java @@ -7,7 +7,6 @@ import com.intellij.psi.*; import com.intellij.util.containers.ContainerUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.psiutils.ExpressionUtils; -import com.siyeh.ig.psiutils.SwitchUtils; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -32,7 +31,7 @@ public final class CreateMissingBooleanPrimitiveBranchesFix extends CreateMissin if (selectorPrimitiveType == null) return null; if (!PsiTypes.booleanType().equals(selectorPrimitiveType)) return null; if (JavaPsiSwitchUtil.findDefaultElement(block) != null) return null; - List branches = SwitchUtils.getSwitchBranches(block); + List branches = JavaPsiSwitchUtil.getSwitchBranches(block); PsiClassType boxedBooleanType = selectorPrimitiveType.getBoxedType(block); if (boxedBooleanType == null) return null; Set existed = new HashSet<>();