[FE 1.0] Report NON_EXHAUSTIVE_WHEN_STATEMENT/NO_ELSE_IN_WHEN for when's on logical types

^KT-47709 In Progress
This commit is contained in:
Dmitriy Novozhilov
2021-07-13 12:29:54 +03:00
committed by teamcityserver
parent 85c7f386eb
commit ef635f6a96
35 changed files with 930 additions and 44 deletions
@@ -62,6 +62,7 @@ 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.types.typeUtil.isBooleanOrNullableBoolean
import org.jetbrains.kotlin.util.OperatorNameConventions
class ControlFlowInformationProviderImpl private constructor(
@@ -1024,19 +1025,19 @@ class ControlFlowInformationProviderImpl private constructor(
}
continue
}
if (!usedAsExpression) {
val enumClassDescriptor = WhenChecker.getClassDescriptorOfTypeIfEnum(subjectType)
if (enumClassDescriptor != null) {
val enumMissingCases = WhenChecker.getEnumMissingCases(element, context, enumClassDescriptor)
if (enumMissingCases.isNotEmpty()) {
trace.report(NON_EXHAUSTIVE_WHEN.on(element, enumMissingCases))
}
if (!usedAsExpression && missingCases.isNotEmpty()) {
val kind = when {
WhenChecker.getClassDescriptorOfTypeIfSealed(subjectType) != null -> AlgebraicTypeKind.Sealed
WhenChecker.getClassDescriptorOfTypeIfEnum(subjectType) != null -> AlgebraicTypeKind.Enum
subjectType?.isBooleanOrNullableBoolean() == true -> AlgebraicTypeKind.Boolean
else -> null
}
val sealedClassDescriptor = WhenChecker.getClassDescriptorOfTypeIfSealed(subjectType)
if (sealedClassDescriptor != null) {
val sealedMissingCases = WhenChecker.getSealedMissingCases(element, context, sealedClassDescriptor)
if (sealedMissingCases.isNotEmpty()) {
trace.report(NON_EXHAUSTIVE_WHEN_ON_SEALED_CLASS.on(element, sealedMissingCases))
if (kind != null) {
if (languageVersionSettings.supportsFeature(LanguageFeature.ProhibitNonExhaustiveWhenOnAlgebraicTypes)) {
trace.report(NO_ELSE_IN_WHEN.on(element, missingCases))
} else {
trace.report(NON_EXHAUSTIVE_WHEN_STATEMENT.on(element, kind.displayName, missingCases))
}
}
}
@@ -1045,6 +1046,12 @@ class ControlFlowInformationProviderImpl private constructor(
}
}
private enum class AlgebraicTypeKind(val displayName: String) {
Sealed("sealed class/interface"),
Enum("enum"),
Boolean("Boolean")
}
private fun checkConstructorConsistency() {
when (subroutine) {
is KtClassOrObject -> ConstructorConsistencyChecker.check(subroutine, trace, pseudocode, pseudocodeVariablesData)
@@ -1080,6 +1080,7 @@ public interface Errors {
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);
DiagnosticFactory2<KtWhenExpression, String, List<WhenMissingCase>> NON_EXHAUSTIVE_WHEN_STATEMENT = DiagnosticFactory2.create(WARNING, WHEN_EXPRESSION);
DiagnosticFactory1<KtWhenExpression, List<WhenMissingCase>>
NON_EXHAUSTIVE_WHEN_ON_SEALED_CLASS = DiagnosticFactory1.create(INFO, WHEN_EXPRESSION);
DiagnosticFactory1<KtWhenExpression, String> EXPECT_TYPE_IN_WHEN_WITHOUT_ELSE = DiagnosticFactory1.create(ERROR, WHEN_EXPRESSION);
@@ -631,6 +631,7 @@ public class DefaultErrorMessages {
MAP.put(NO_ELSE_IN_WHEN, "''when'' expression must be exhaustive, add necessary {0}", RENDER_WHEN_MISSING_CASES);
MAP.put(NON_EXHAUSTIVE_WHEN, "''when'' expression on enum is recommended to be exhaustive, add {0}", RENDER_WHEN_MISSING_CASES);
MAP.put(NON_EXHAUSTIVE_WHEN_STATEMENT, "Non exhaustive ''when'' statements on {0} will be prohibited in 1.7, add {1}", STRING, RENDER_WHEN_MISSING_CASES);
MAP.put(NON_EXHAUSTIVE_WHEN_ON_SEALED_CLASS, "''when'' expression on sealed classes is recommended to be exhaustive, add {0}", RENDER_WHEN_MISSING_CASES);
MAP.put(EXPECT_TYPE_IN_WHEN_WITHOUT_ELSE, "'when' with expect {0} as subject can not be exhaustive without else branch", STRING);