IDEA-203447 Switch statement without default branch: support Java 12

This commit is contained in:
Tagir Valeev
2018-12-03 18:53:09 +07:00
parent 211066509c
commit 8905ab83ae
4 changed files with 69 additions and 4 deletions
@@ -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<PsiSwitchLabelStatementBase> labels = PsiTreeUtil.getChildrenOfTypeAsList(statement.getBody(), PsiSwitchLabelStatementBase.class);
Set<PsiEnumConstant> constants = StreamEx.of(labels).flatCollection(SwitchUtils::findEnumConstants).toSet();
for (PsiField field : aClass.getFields()) {
if (field instanceof PsiEnumConstant && !constants.remove(field)) {
return false;
}
}
return true;
}
}
}
@@ -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<PsiEnumConstant> 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<PsiEnumConstant> 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;
@@ -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 -> {}
}
<warning descr="'switch' statement without 'default' branch">switch</warning> (my) {
case foo, bar -> {}
}
switch (my) {
case foo, bar -> {}
case baz -> {}
}
}
void empty(T t) {
switch (t) {
@@ -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() {