Introduce warning REDUNDANT_ELSE_IN_WHEN #KT-17497 Fixed

This commit is contained in:
Mikhail Glukhikh
2017-04-28 14:45:13 +03:00
parent e53c548ead
commit 14886827a2
8 changed files with 172 additions and 20 deletions
@@ -57,6 +57,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils.*
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
import org.jetbrains.kotlin.types.isFlexible
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
import java.util.*
@@ -778,25 +779,34 @@ class ControlFlowInformationProvider private constructor(
for (element in instruction.owner.getValueElements(value)) {
if (element !is KtWhenExpression) continue
if (element.isUsedAsExpression(trace.bindingContext)) {
val usedAsExpression = element.isUsedAsExpression(trace.bindingContext)
if (usedAsExpression) {
checkImplicitCastOnConditionalExpression(element)
}
if (element.elseExpression != null) continue
val context = trace.bindingContext
val necessaryCases = WhenChecker.getNecessaryCases(element, context)
if (!necessaryCases.isEmpty()) {
trace.report(NO_ELSE_IN_WHEN.on(element, necessaryCases))
val missingCases = WhenChecker.getMissingCases(element, context)
val elseEntry = element.entries.find { it.isElse }
val subjectExpression = element.subjectExpression
if (usedAsExpression && missingCases.isNotEmpty()) {
if (elseEntry != null) continue
trace.report(NO_ELSE_IN_WHEN.on(element, missingCases))
}
else {
val subjectExpression = element.subjectExpression
if (subjectExpression != null) {
val enumClassDescriptor = WhenChecker.getClassDescriptorOfTypeIfEnum(trace.getType(subjectExpression))
else if (subjectExpression != null) {
val subjectType = trace.getType(subjectExpression)
if (elseEntry != null) {
if (missingCases.isEmpty() && subjectType != null && !subjectType.isFlexible()) {
trace.report(REDUNDANT_ELSE_IN_WHEN.on(elseEntry))
}
continue
}
if (!usedAsExpression) {
val enumClassDescriptor = WhenChecker.getClassDescriptorOfTypeIfEnum(subjectType)
if (enumClassDescriptor != null) {
val missingCases = WhenChecker.getEnumMissingCases(element, context, enumClassDescriptor)
if (!missingCases.isEmpty()) {
trace.report(NON_EXHAUSTIVE_WHEN.on(element, missingCases))
val enumMissingCases = WhenChecker.getEnumMissingCases(element, context, enumClassDescriptor)
if (!enumMissingCases.isEmpty()) {
trace.report(NON_EXHAUSTIVE_WHEN.on(element, enumMissingCases))
}
}
}
@@ -262,11 +262,6 @@ object WhenChecker {
WhenOnEnumExhaustivenessChecker,
WhenOnSealedExhaustivenessChecker)
@JvmStatic
fun getNecessaryCases(expression: KtWhenExpression, context: BindingContext) =
if (expression.isUsedAsExpression(context)) getMissingCases(expression, context)
else listOf()
@JvmStatic
fun isWhenByEnum(expression: KtWhenExpression, context: BindingContext) =
getClassDescriptorOfTypeIfEnum(whenSubjectType(expression, context)) != null
@@ -843,6 +843,7 @@ public interface Errors {
DiagnosticFactory0<KtWhenCondition> EXPECTED_CONDITION = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtWhenEntry> ELSE_MISPLACED_IN_WHEN = DiagnosticFactory0.create(ERROR, ELSE_ENTRY);
DiagnosticFactory0<KtWhenEntry> REDUNDANT_ELSE_IN_WHEN = DiagnosticFactory0.create(WARNING, ELSE_ENTRY);
DiagnosticFactory1<KtWhenExpression, List<WhenMissingCase>> NO_ELSE_IN_WHEN = DiagnosticFactory1.create(ERROR, WHEN_EXPRESSION);
DiagnosticFactory1<KtWhenExpression, List<WhenMissingCase>> NON_EXHAUSTIVE_WHEN = DiagnosticFactory1.create(WARNING, WHEN_EXPRESSION);
DiagnosticFactory0<PsiElement> COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT = DiagnosticFactory0.create(ERROR);
@@ -932,7 +933,7 @@ public interface Errors {
INVISIBLE_MEMBER, NON_PUBLIC_CALL_FROM_PUBLIC_INLINE, INVISIBLE_REFERENCE, INVISIBLE_SETTER);
ImmutableSet<? extends DiagnosticFactory<?>> UNUSED_ELEMENT_DIAGNOSTICS = ImmutableSet.of(
UNUSED_VARIABLE, UNUSED_PARAMETER, ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE, VARIABLE_WITH_REDUNDANT_INITIALIZER,
UNUSED_LAMBDA_EXPRESSION, USELESS_CAST, UNUSED_VALUE, USELESS_ELVIS, UNNECESSARY_LATEINIT);
UNUSED_LAMBDA_EXPRESSION, USELESS_CAST, UNUSED_VALUE, USELESS_ELVIS, UNNECESSARY_LATEINIT, REDUNDANT_ELSE_IN_WHEN);
ImmutableSet<? extends DiagnosticFactory<?>> TYPE_INFERENCE_ERRORS = ImmutableSet.of(
TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER, TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS,
TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR,
@@ -512,6 +512,7 @@ public class DefaultErrorMessages {
MAP.put(NULL_FOR_NONNULL_TYPE, "Null can not be a value of a non-null type {0}", RENDER_TYPE);
MAP.put(ELSE_MISPLACED_IN_WHEN, "'else' entry must be the last one in a when-expression");
MAP.put(REDUNDANT_ELSE_IN_WHEN, "'when' is exhaustive so 'else' is redundant here");
MAP.put(COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT, "Deprecated syntax. Use '||' instead of commas in when-condition for 'when' without argument");
MAP.put(DUPLICATE_LABEL_IN_WHEN, "Duplicate label in when");