From 8905ab83ae29617bcac9667a205d5493a2286a01 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Mon, 3 Dec 2018 17:08:04 +0700 Subject: [PATCH] IDEA-203447 Switch statement without default branch: support Java 12 --- ...tchStatementsWithoutDefaultInspection.java | 19 +++++++++--- .../com/siyeh/ig/psiutils/SwitchUtils.java | 29 +++++++++++++++++++ .../SwitchStatementsWithoutDefault.java | 17 +++++++++++ ...tatementsWithoutDefaultInspectionTest.java | 8 +++++ 4 files changed, 69 insertions(+), 4 deletions(-) diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SwitchStatementsWithoutDefaultInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SwitchStatementsWithoutDefaultInspection.java index 8b76e7013482..3cc26cf01090 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SwitchStatementsWithoutDefaultInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SwitchStatementsWithoutDefaultInspection.java @@ -17,16 +17,19 @@ package com.siyeh.ig.controlflow; import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; -import com.siyeh.ig.psiutils.ControlFlowUtils; import com.siyeh.ig.psiutils.SwitchUtils; +import one.util.streamex.StreamEx; import org.intellij.lang.annotations.Pattern; import org.jetbrains.annotations.NotNull; import javax.swing.*; +import java.util.List; +import java.util.Set; public class SwitchStatementsWithoutDefaultInspection extends BaseInspection { @@ -72,19 +75,27 @@ public class SwitchStatementsWithoutDefaultInspection extends BaseInspection { if (count <= 0) { return; } - if (m_ignoreFullyCoveredEnums && switchStatementIsFullyCoveredEnum(statement, count)) { + if (m_ignoreFullyCoveredEnums && switchStatementIsFullyCoveredEnum(statement)) { return; } registerStatementError(statement); } - private boolean switchStatementIsFullyCoveredEnum(PsiSwitchStatement statement, int branchCount) { + private boolean switchStatementIsFullyCoveredEnum(PsiSwitchStatement statement) { final PsiExpression expression = statement.getExpression(); if (expression == null) { return true; // don't warn on incomplete code } final PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(expression.getType()); - return aClass != null && aClass.isEnum() && ControlFlowUtils.hasChildrenOfTypeCount(aClass, branchCount, PsiEnumConstant.class); + if (aClass == null || !aClass.isEnum()) return false; + List labels = PsiTreeUtil.getChildrenOfTypeAsList(statement.getBody(), PsiSwitchLabelStatementBase.class); + Set constants = StreamEx.of(labels).flatCollection(SwitchUtils::findEnumConstants).toSet(); + for (PsiField field : aClass.getFields()) { + if (field instanceof PsiEnumConstant && !constants.remove(field)) { + return false; + } + } + return true; } } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SwitchUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SwitchUtils.java index b98118233737..e9fc7566510d 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SwitchUtils.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/SwitchUtils.java @@ -271,6 +271,35 @@ public class SwitchUtils { return visitor.isUsed(); } + /** + * @param element a switch label element + * @return list of enum constants which are targets of the specified label; empty list if the supplied element is not a switch label, + * or it is not an enum switch. + */ + @NotNull + public static List findEnumConstants(PsiElement element) { + if (!(element instanceof PsiSwitchLabelStatementBase)) { + return Collections.emptyList(); + } + final PsiSwitchLabelStatementBase switchLabelStatement = (PsiSwitchLabelStatementBase)element; + final PsiExpressionList list = switchLabelStatement.getCaseValues(); + if (list == null) { + return Collections.emptyList(); + } + List constants = new ArrayList<>(); + for (PsiExpression value : list.getExpressions()) { + if (value instanceof PsiReferenceExpression) { + final PsiElement target = ((PsiReferenceExpression)value).resolve(); + if (target instanceof PsiEnumConstant) { + constants.add((PsiEnumConstant)target); + continue; + } + } + return Collections.emptyList(); + } + return constants; + } + private static class LabelSearchVisitor extends JavaRecursiveElementWalkingVisitor { private final String m_labelName; diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/switch_statements_without_default/SwitchStatementsWithoutDefault.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/switch_statements_without_default/SwitchStatementsWithoutDefault.java index 080f88dac74a..98a243f80fe5 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/switch_statements_without_default/SwitchStatementsWithoutDefault.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/controlflow/switch_statements_without_default/SwitchStatementsWithoutDefault.java @@ -81,6 +81,23 @@ public class SwitchStatementsWithoutDefault break; } } + + public void testRules(T t, MyEnum my) { + switch (t) { + case A -> {} + case B -> {} + } + switch (t) { + case A, B -> {} + } + switch (my) { + case foo, bar -> {} + } + switch (my) { + case foo, bar -> {} + case baz -> {} + } + } void empty(T t) { switch (t) { diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/SwitchStatementsWithoutDefaultInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/SwitchStatementsWithoutDefaultInspectionTest.java index fb6ae2300324..667dbc25ed26 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/SwitchStatementsWithoutDefaultInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/SwitchStatementsWithoutDefaultInspectionTest.java @@ -16,7 +16,9 @@ package com.siyeh.ig.controlflow; import com.intellij.codeInspection.InspectionProfileEntry; +import com.intellij.testFramework.LightProjectDescriptor; import com.siyeh.ig.LightInspectionTestCase; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class SwitchStatementsWithoutDefaultInspectionTest extends LightInspectionTestCase { @@ -25,6 +27,12 @@ public class SwitchStatementsWithoutDefaultInspectionTest extends LightInspectio doTest(); } + @NotNull + @Override + protected LightProjectDescriptor getProjectDescriptor() { + return JAVA_12; + } + @Nullable @Override protected InspectionProfileEntry getInspection() {