void (@NotNull PsiSwitchBlock switchBlock) { final PsiExpression expression = PsiUtil.skipParenthesizedExprDown(switchBlock.getExpression()); if (expression == null) return; final PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(expression.getType()); if (aClass == null || !aClass.isEnum()) return; Set<String> constants = StreamEx.of(aClass.getAllFields()).select(PsiEnumConstant.class).map(PsiEnumConstant::getName) .toCollection(LinkedHashSet::new); if (constants.isEmpty()) return; boolean hasDefault = false; boolean hasNull = false; ProblemHighlightType highlighting = ProblemHighlightType.GENERIC_ERROR_OR_WARNING; for (PsiSwitchLabelStatementBase child : PsiTreeUtil .getChildrenOfTypeAsList(switchBlock.getBody(), PsiSwitchLabelStatementBase.class)) { hasNull |= hasMatchingNull(child); if (SwitchUtils.isDefaultLabel(child)) { hasDefault = true; if (ignoreSwitchStatementsWithDefault) { if (!isOnTheFly) return; highlighting = ProblemHighlightType.INFORMATION; } if (child.isDefaultCase()) { continue; } } List<PsiEnumConstant> enumConstants = SwitchUtils.findEnumConstants(child); if (enumConstants.isEmpty()) { PsiCaseLabelElementList labelElementList = child.getCaseLabelElementList(); if (labelElementList == null || !ContainerUtil.and(labelElementList.getElements(), labelElement -> isDefaultOrNull(labelElement))) { // Syntax error or unresolved constant: do not report anything on incomplete code return; } } for (PsiEnumConstant constant : enumConstants) { if (constant.getContainingClass() != aClass) { // Syntax error or unresolved constant: do not report anything on incomplete code return; } constants.remove(constant.getName()); } } if (!hasDefault && (switchBlock instanceof PsiSwitchExpression || hasNull)) { // non-exhaustive switch expression: it's a compilation error // switch statement using any of the new features detailed in JEP 406, such as // matching null, must be exhaustive, otherwise it's a compilation error as well // and the compilation fix should be suggested instead of normal inspection return; } if (constants.isEmpty()) return; CommonDataflow.DataflowResult dataflow = CommonDataflow.getDataflowResult(expression); if (dataflow != null) { DfType type = dataflow.getDfType(expression); Set<?> notValues = type instanceof DfAntiConstantType ? ((DfAntiConstantType<?>)type).getNotValues() : Collections.emptySet(); for (Object value : notValues) { if (value instanceof PsiEnumConstant) { constants.remove(((PsiEnumConstant)value).getName()); } } Set<String> values = StreamEx.of(dataflow.getExpressionValues(expression)).select(PsiEnumConstant.class) .map(PsiEnumConstant::getName).toSet(); if (!values.isEmpty()) { constants.retainAll(values); } } if (constants.isEmpty()) return; String message = buildErrorString(aClass.getQualifiedName(), constants); var fix = new CreateEnumMissingSwitchBranchesFix(switchBlock, constants); if (highlighting == ProblemHighlightType.INFORMATION || InspectionProjectProfileManager.isInformationLevel(getShortName(), switchBlock)) { holder.problem(switchBlock, message).highlight(highlighting).fix(fix).register(); } else { int length = switchBlock.getFirstChild().getTextLength(); holder.problem(switchBlock, message).range(new TextRange(0, length)).fix(fix).register(); if (isOnTheFly) { TextRange range = new TextRange(length, switchBlock.getTextLength()); holder.problem(switchBlock, message).highlight(ProblemHighlightType.INFORMATION).range(range).fix(fix).register(); } } }