void (@NotNull PsiSwitchExpression switchExpression, @NotNull Consumer<? super HighlightInfo.Builder> errorSink) { PsiCodeBlock switchBody = switchExpression.getBody(); if (switchBody != null) { PsiStatement lastStatement = PsiTreeUtil.getPrevSiblingOfType(switchBody.getRBrace(), PsiStatement.class); boolean hasResult = false; if (lastStatement instanceof PsiSwitchLabeledRuleStatement) { boolean reported = false; for (PsiSwitchLabeledRuleStatement rule = (PsiSwitchLabeledRuleStatement)lastStatement; rule != null; rule = PsiTreeUtil.getPrevSiblingOfType(rule, PsiSwitchLabeledRuleStatement.class)) { PsiStatement ruleBody = rule.getBody(); if (ruleBody instanceof PsiExpressionStatement) { hasResult = true; } // the expression and throw statements are fine, only the block statement could be an issue // 15.28.1 If the switch block consists of switch rules, then any switch rule block cannot complete normally if (ruleBody instanceof PsiBlockStatement) { if (ControlFlowUtils.statementMayCompleteNormally(ruleBody)) { PsiElement target = ObjectUtils.notNull(tryCast(rule.getFirstChild(), PsiKeyword.class), rule); String message = JavaErrorBundle.message("switch.expr.rule.should.produce.result"); HighlightInfo.Builder info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(target).descriptionAndTooltip(message); errorSink.accept(info); reported = true; } else if (!hasResult && hasYield(switchExpression, ruleBody)) { hasResult = true; } } } if (reported) { return; } } else { // previous statements may have no result as well, but in that case they fall through to the last one, which needs to be checked anyway if (lastStatement != null && ControlFlowUtils.statementMayCompleteNormally(lastStatement)) { PsiElement target = ObjectUtils.notNull(tryCast(switchExpression.getFirstChild(), PsiKeyword.class), switchExpression); String message = JavaErrorBundle.message("switch.expr.should.produce.result"); HighlightInfo.Builder info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(target).descriptionAndTooltip(message); errorSink.accept(info); return; } hasResult = hasYield(switchExpression, switchBody); } if (!hasResult) { PsiElement target = ObjectUtils.notNull(tryCast(switchExpression.getFirstChild(), PsiKeyword.class), switchExpression); HighlightInfo.Builder info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(target) .descriptionAndTooltip(JavaErrorBundle.message("switch.expr.no.result")); errorSink.accept(info); } } }