mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-highlighting] Migrate checkRedundantDefaultBranch
Part of IDEA-365344 Create a new Java error highlighter with minimal dependencies (PSI only) GitOrigin-RevId: 8bf45e8e4e26a2766c9755a90dfba6d6cc94e198
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b3b3fcf587
commit
fc6de8a515
@@ -343,6 +343,9 @@ switch.label.combination.constants.and.patterns.unnamed=Invalid case label combi
|
||||
switch.label.multiple.patterns=Invalid case label combination: a case label must not consist of more than one case pattern
|
||||
switch.label.multiple.patterns.unnamed=Invalid case label combination: multiple patterns are allowed only if none of them declare any pattern variables
|
||||
switch.dominance.violation=Label is dominated by a preceding case label ''{0}''
|
||||
switch.unconditional.pattern.and.default='switch' has both an unconditional pattern and a default label
|
||||
switch.default.and.boolean='switch' has all boolean values and a default label
|
||||
switch.unconditional.pattern.and.boolean='switch' has all boolean values and an unconditional pattern
|
||||
|
||||
guard.misplaced=Guard is allowed after patterns only
|
||||
guard.evaluated.to.false=Case label has a guard that is a constant expression with value 'false'
|
||||
|
||||
+24
@@ -33,6 +33,7 @@ final class SwitchChecker {
|
||||
if (!myVisitor.hasErrorResults()) checkDuplicates(block);
|
||||
if (!myVisitor.hasErrorResults()) checkFallthroughLegality(block);
|
||||
if (!myVisitor.hasErrorResults()) checkDominance(block);
|
||||
if (!myVisitor.hasErrorResults()) checkNoDefaultBranchAllowed(block);
|
||||
}
|
||||
|
||||
void checkSwitchExpressionReturnTypeCompatible(@NotNull PsiSwitchExpression switchExpression) {
|
||||
@@ -618,4 +619,27 @@ final class SwitchChecker {
|
||||
myVisitor.report(JavaErrorKinds.SWITCH_DOMINANCE_VIOLATION.create(overWhom, who));
|
||||
}
|
||||
}
|
||||
|
||||
private void checkNoDefaultBranchAllowed(@NotNull PsiSwitchBlock block) {
|
||||
if (!myVisitor.isApplicable(JavaFeature.PATTERNS_IN_SWITCH)) return;
|
||||
//T is an intersection type T1& ... &Tn, and P covers Ti, for one of the type Ti (1≤i≤n)
|
||||
PsiCaseLabelElement elementCoversType = JavaPsiSwitchUtil.getUnconditionalPatternLabel(block);
|
||||
PsiElement defaultElement = JavaPsiSwitchUtil.findDefaultElement(block);
|
||||
if (defaultElement != null && elementCoversType != null) {
|
||||
myVisitor.report(JavaErrorKinds.SWITCH_UNCONDITIONAL_PATTERN_AND_DEFAULT.create(defaultElement.getFirstChild()));
|
||||
myVisitor.report(JavaErrorKinds.SWITCH_UNCONDITIONAL_PATTERN_AND_DEFAULT.create(elementCoversType));
|
||||
return;
|
||||
}
|
||||
//default (or unconditional), TRUE and FALSE cannot be together
|
||||
if ((defaultElement != null || elementCoversType != null) &&
|
||||
JavaPsiSwitchUtil.isBooleanSwitchWithTrueAndFalse(block)) {
|
||||
if (defaultElement != null) {
|
||||
myVisitor.report(JavaErrorKinds.SWITCH_DEFAULT_AND_BOOLEAN.create(defaultElement.getFirstChild()));
|
||||
}
|
||||
if (elementCoversType != null) {
|
||||
myVisitor.report(JavaErrorKinds.SWITCH_UNCONDITIONAL_PATTERN_AND_BOOLEAN.create(elementCoversType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
@@ -1015,6 +1015,12 @@ public final class JavaErrorKinds {
|
||||
public static final Parameterized<PsiCaseLabelElement, PsiElement> SWITCH_DOMINANCE_VIOLATION =
|
||||
parameterized(PsiCaseLabelElement.class, PsiElement.class, "switch.dominance.violation")
|
||||
.withDescription((overWhom, who) -> message("switch.dominance.violation", who.getText()));
|
||||
public static final Simple<PsiElement> SWITCH_UNCONDITIONAL_PATTERN_AND_DEFAULT =
|
||||
error("switch.unconditional.pattern.and.default");
|
||||
public static final Simple<PsiElement> SWITCH_DEFAULT_AND_BOOLEAN =
|
||||
error("switch.default.and.boolean");
|
||||
public static final Simple<PsiCaseLabelElement> SWITCH_UNCONDITIONAL_PATTERN_AND_BOOLEAN =
|
||||
error("switch.unconditional.pattern.and.boolean");
|
||||
|
||||
public static final Simple<PsiReferenceExpression> EXPRESSION_EXPECTED = error("expression.expected");
|
||||
public static final Parameterized<PsiReferenceExpression, PsiSuperExpression> EXPRESSION_SUPER_UNQUALIFIED_DEFAULT_METHOD =
|
||||
|
||||
+5
@@ -760,6 +760,11 @@ final class JavaErrorFixProvider {
|
||||
sink.accept(myFactory.createDeleteSwitchLabelFix(overWhom));
|
||||
}
|
||||
});
|
||||
fix(SWITCH_UNCONDITIONAL_PATTERN_AND_DEFAULT, error -> error.psi() instanceof PsiCaseLabelElement elementCoversType
|
||||
? myFactory.createDeleteSwitchLabelFix(elementCoversType)
|
||||
: myFactory.createDeleteDefaultFix(null, error.psi()));
|
||||
fix(SWITCH_UNCONDITIONAL_PATTERN_AND_BOOLEAN, error -> myFactory.createDeleteSwitchLabelFix(error.psi()));
|
||||
fix(SWITCH_DEFAULT_AND_BOOLEAN, error -> myFactory.createDeleteDefaultFix(null, error.psi()));
|
||||
}
|
||||
|
||||
private void createAccessFixes() {
|
||||
|
||||
+8
-59
@@ -2,7 +2,6 @@
|
||||
package com.intellij.codeInsight.daemon.impl.analysis;
|
||||
|
||||
import com.intellij.codeInsight.ExpressionUtil;
|
||||
import com.intellij.codeInsight.daemon.JavaErrorBundle;
|
||||
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.QuickFixFactory;
|
||||
@@ -53,59 +52,21 @@ public class PatternsInSwitchBlockHighlightingModel extends SwitchBlockHighlight
|
||||
PsiCodeBlock body = myBlock.getBody();
|
||||
if (body == null) return;
|
||||
|
||||
List<PsiCaseLabelElement> elementsToCheckCompleteness = new ArrayList<>();
|
||||
for (PsiStatement st : body.getStatements()) {
|
||||
if (!(st instanceof PsiSwitchLabelStatementBase labelStatement) || labelStatement.isDefaultCase()) continue;
|
||||
PsiCaseLabelElementList labelElementList = labelStatement.getCaseLabelElementList();
|
||||
if (labelElementList != null) {
|
||||
Collections.addAll(elementsToCheckCompleteness, labelElementList.getElements());
|
||||
}
|
||||
}
|
||||
if (ExpressionUtil.isEnhancedSwitch(myBlock)) {
|
||||
if (checkRedundantDefaultBranch(errorSink)) return;
|
||||
if (JavaPsiSwitchUtil.getUnconditionalPatternLabel(myBlock) != null) return;
|
||||
if (JavaPsiSwitchUtil.findDefaultElement(myBlock) != null) return;
|
||||
List<PsiCaseLabelElement> elementsToCheckCompleteness = new ArrayList<>();
|
||||
for (PsiStatement st : body.getStatements()) {
|
||||
if (!(st instanceof PsiSwitchLabelStatementBase labelStatement) || labelStatement.isDefaultCase()) continue;
|
||||
PsiCaseLabelElementList labelElementList = labelStatement.getCaseLabelElementList();
|
||||
if (labelElementList != null) {
|
||||
Collections.addAll(elementsToCheckCompleteness, labelElementList.getElements());
|
||||
}
|
||||
}
|
||||
checkCompleteness(elementsToCheckCompleteness, errorSink);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean checkRedundantDefaultBranch(@NotNull Consumer<? super HighlightInfo.Builder> errorSink) {
|
||||
//T is an intersection type T1& ... &Tn, and P covers Ti, for one of the type Ti (1≤i≤n)
|
||||
PsiCaseLabelElement elementCoversType = JavaPsiSwitchUtil.getUnconditionalPatternLabel(myBlock);
|
||||
PsiElement defaultElement = JavaPsiSwitchUtil.findDefaultElement(myBlock);
|
||||
if (defaultElement != null && elementCoversType != null) {
|
||||
HighlightInfo.Builder defaultInfo =
|
||||
createError(defaultElement.getFirstChild(), JavaErrorBundle.message("switch.unconditional.pattern.and.default.exist"));
|
||||
registerDeleteFixForDefaultElement(defaultInfo, defaultElement, defaultElement.getFirstChild());
|
||||
errorSink.accept(defaultInfo);
|
||||
HighlightInfo.Builder patternInfo = createError(elementCoversType, JavaErrorBundle.message(
|
||||
"switch.unconditional.pattern.and.default.exist"));
|
||||
IntentionAction action = getFixFactory().createDeleteSwitchLabelFix(elementCoversType);
|
||||
patternInfo.registerFix(action, null, null, null, null);
|
||||
errorSink.accept(patternInfo);
|
||||
return true;
|
||||
}
|
||||
//default (or unconditional), TRUE and FALSE cannot be together
|
||||
if ((defaultElement != null || elementCoversType != null) &&
|
||||
JavaPsiSwitchUtil.isBooleanSwitchWithTrueAndFalse(myBlock)) {
|
||||
if (defaultElement != null) {
|
||||
HighlightInfo.Builder defaultInfo =
|
||||
createError(defaultElement.getFirstChild(), JavaErrorBundle.message("switch.unconditional.boolean.and.default.exist"));
|
||||
registerDeleteFixForDefaultElement(defaultInfo, defaultElement, defaultElement.getFirstChild());
|
||||
errorSink.accept(defaultInfo);
|
||||
}
|
||||
if (elementCoversType != null) {
|
||||
HighlightInfo.Builder patternInfo = createError(elementCoversType,
|
||||
JavaErrorBundle.message(
|
||||
"switch.unconditional.boolean.and.unconditional.exist"));
|
||||
IntentionAction action = getFixFactory().createDeleteSwitchLabelFix(elementCoversType);
|
||||
patternInfo.registerFix(action, null, null, null, null);
|
||||
errorSink.accept(patternInfo);
|
||||
}
|
||||
}
|
||||
return defaultElement != null || elementCoversType != null;
|
||||
}
|
||||
|
||||
private void checkCompleteness(@NotNull List<? extends PsiCaseLabelElement> elements,
|
||||
@NotNull Consumer<? super HighlightInfo.Builder> errorSink) {
|
||||
if (isExhaustiveForSwitchSelectorPrimitiveWrapper(elements)) return;
|
||||
@@ -197,18 +158,6 @@ public class PatternsInSwitchBlockHighlightingModel extends SwitchBlockHighlight
|
||||
return ContainerUtil.exists(elements, element -> extractPattern(element) != null);
|
||||
}
|
||||
|
||||
private static void registerDeleteFixForDefaultElement(@NotNull HighlightInfo.Builder info,
|
||||
PsiElement defaultElement,
|
||||
@NotNull PsiElement duplicateElement) {
|
||||
if (defaultElement instanceof PsiCaseLabelElement caseElement) {
|
||||
IntentionAction action = getFixFactory().createDeleteSwitchLabelFix(caseElement);
|
||||
info.registerFix(action, null, null, null, null);
|
||||
return;
|
||||
}
|
||||
IntentionAction action = getFixFactory().createDeleteDefaultFix(null, duplicateElement);
|
||||
info.registerFix(action, null, null, null, null);
|
||||
}
|
||||
|
||||
private @Nullable HighlightInfo.Builder checkSealedClassCompleteness(@NotNull PsiType selectorType,
|
||||
@NotNull List<? extends PsiCaseLabelElement> elements) {
|
||||
Set<PsiClass> missedClasses;
|
||||
|
||||
-4
@@ -117,10 +117,6 @@ public class SwitchBlockHighlightingModel {
|
||||
return QuickFixFactory.getInstance();
|
||||
}
|
||||
|
||||
static @Nullable Object evaluateConstant(@NotNull PsiCaseLabelElement constant) {
|
||||
return JavaPsiFacade.getInstance(constant.getProject()).getConstantEvaluationHelper().computeConstantExpression(constant, false);
|
||||
}
|
||||
|
||||
void checkEnumCompleteness(@NotNull PsiClass selectorClass,
|
||||
@NotNull List<PsiEnumConstant> enumElements,
|
||||
@NotNull Consumer<? super HighlightInfo.Builder> errorSink) {
|
||||
|
||||
@@ -37,9 +37,6 @@ variable.already.defined=Variable ''{0}'' is already defined in the scope
|
||||
# suppress inspection "UnusedProperty"
|
||||
incompatible.types=Incompatible types. Found: ''{1}'', required: ''{0}''
|
||||
switch.dominance.of.preceding.label=Label is dominated by a preceding case label ''{0}''
|
||||
switch.unconditional.pattern.and.default.exist='switch' has both an unconditional pattern and a default label
|
||||
switch.unconditional.boolean.and.default.exist='switch' has all boolean values and a default label
|
||||
switch.unconditional.boolean.and.unconditional.exist='switch' has all boolean values and an unconditional pattern
|
||||
expression.expected=Expression expected
|
||||
qualified.enum.constant.in.switch.remove.fix=Remove qualifier
|
||||
deconstruction.pattern.requires.record=Deconstruction pattern can only be applied to a record, ''{0}'' is not a record
|
||||
|
||||
Reference in New Issue
Block a user