[java-highlighting] getSwitchBranches moved from SwitchUtils to JavaPsiSwitchUtil

Part of IDEA-365344 Create a new Java error highlighter with minimal dependencies (PSI only)

GitOrigin-RevId: 9e356b8522c0bb5a8112d5c30913a4aa3d9cf45d
This commit is contained in:
Tagir Valeev
2025-02-27 19:55:56 +00:00
committed by intellij-monorepo-bot
parent 6d6d8d5725
commit 174ffe0cac
11 changed files with 39 additions and 42 deletions
@@ -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<PsiElement> getSwitchBranches(@NotNull PsiSwitchBlock block) {
final PsiCodeBlock body = block.getBody();
if (body == null) return Collections.emptyList();
List<PsiElement> 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)
@@ -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;
@@ -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<PsiCaseLabelElement> labelElements = StreamEx.of(SwitchUtils.getSwitchBranches(switchBlock)).select(PsiCaseLabelElement.class)
List<PsiCaseLabelElement> 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);
@@ -834,7 +834,7 @@ public abstract class DataFlowInspectionBase extends AbstractBaseJavaLocalInspec
PsiType selectorType = selector.getType();
if (selectorType == null) return Collections.emptySet();
List<PsiCaseLabelElement> labelElements =
ContainerUtil.filterIsInstance(SwitchUtils.getSwitchBranches(switchBlock), PsiCaseLabelElement.class);
ContainerUtil.filterIsInstance(JavaPsiSwitchUtil.getSwitchBranches(switchBlock), PsiCaseLabelElement.class);
if (labelElements.isEmpty()) return Collections.emptySet();
MultiMap<Object, PsiElement> duplicateCandidates = JavaPsiSwitchUtil.getValuesAndLabels(switchBlock);
@@ -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;
@@ -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<PsiElement> switchBranches = getSwitchBranches(block);
List<PsiElement> 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<PsiElement> getSwitchBranches(@NotNull PsiSwitchBlock block) {
final PsiCodeBlock body = block.getBody();
if (body == null) return Collections.emptyList();
List<PsiElement> 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.
*
@@ -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<String> branches = SwitchUtils.getSwitchBranches(switchBlock).stream()
Set<String> branches = JavaPsiSwitchUtil.getSwitchBranches(switchBlock).stream()
.map(branch -> branch instanceof PsiExpression expression ? ExpressionUtils.computeConstantExpression(expression) : null)
.filter(constant -> constant instanceof Boolean)
.map(branch -> branch.toString())
@@ -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
@@ -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<PsiElement> branches = SwitchUtils.getSwitchBranches(switchBlock);
List<PsiElement> 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;
@@ -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<PsiSwitchB
PsiExpression expression = block.getExpression();
Nullability nullability = NullabilityUtil.getExpressionNullability(expression, true);
if (nullability != Nullability.NULLABLE) return null;
List<PsiElement> branches = SwitchUtils.getSwitchBranches(block);
List<PsiElement> branches = JavaPsiSwitchUtil.getSwitchBranches(block);
if (ContainerUtil.or(branches,
branch -> branch instanceof PsiExpression psiExpression && ExpressionUtils.isNullLiteral(psiExpression))) {
return null;
@@ -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<PsiElement> branches = SwitchUtils.getSwitchBranches(block);
List<PsiElement> branches = JavaPsiSwitchUtil.getSwitchBranches(block);
PsiClassType boxedBooleanType = selectorPrimitiveType.getBoxedType(block);
if (boxedBooleanType == null) return null;
Set<String> existed = new HashSet<>();