Warn about comma-separated conditions in when without argument.
See KT-5143.
This commit is contained in:
@@ -16,10 +16,17 @@
|
||||
|
||||
package org.jetbrains.kotlin.cfg;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.Modality;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.lexer.KtToken;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
@@ -33,8 +40,8 @@ import org.jetbrains.kotlin.types.TypeUtils;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumClass;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry;
|
||||
|
||||
public final class WhenChecker {
|
||||
private WhenChecker() {
|
||||
@@ -267,4 +274,19 @@ public final class WhenChecker {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void checkDeprecatedWhenSyntax(@NotNull BindingTrace trace, @NotNull KtWhenExpression expression) {
|
||||
if (expression.getSubjectExpression() != null) return;
|
||||
|
||||
for (KtWhenEntry entry : expression.getEntries()) {
|
||||
if (entry.isElse()) continue;
|
||||
for (PsiElement child = entry.getFirstChild(); child != null; child = child.getNextSibling()) {
|
||||
if (child.getNode().getElementType() == KtTokens.COMMA) {
|
||||
trace.report(Errors.COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT.on(child));
|
||||
}
|
||||
if (child.getNode().getElementType() == KtTokens.ARROW) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -684,6 +684,7 @@ public interface Errors {
|
||||
DiagnosticFactory0<KtWhenEntry> ELSE_MISPLACED_IN_WHEN = DiagnosticFactory0.create(ERROR, ELSE_ENTRY);
|
||||
DiagnosticFactory0<KtWhenExpression> NO_ELSE_IN_WHEN = DiagnosticFactory0.create(ERROR, WHEN_EXPRESSION);
|
||||
DiagnosticFactory0<KtWhenExpression> NON_EXHAUSTIVE_WHEN = DiagnosticFactory0.create(WARNING, WHEN_EXPRESSION);
|
||||
DiagnosticFactory0<PsiElement> COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
// Type mismatch
|
||||
|
||||
|
||||
+1
@@ -413,6 +413,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(COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT, "Deprecated syntax. Use '||' instead of commas in when-condition for 'when' without argument");
|
||||
|
||||
MAP.put(NO_ELSE_IN_WHEN, "'when' expression must contain 'else' branch");
|
||||
MAP.put(NON_EXHAUSTIVE_WHEN, "'when' expression contains only some variants and no 'else' branch");
|
||||
|
||||
+2
@@ -73,6 +73,8 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
}
|
||||
|
||||
public KotlinTypeInfo visitWhenExpression(KtWhenExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||
WhenChecker.checkDeprecatedWhenSyntax(contextWithExpectedType.trace, expression);
|
||||
|
||||
components.dataFlowAnalyzer.recordExpectedType(contextWithExpectedType.trace, expression, contextWithExpectedType.expectedType);
|
||||
|
||||
ExpressionTypingContext context = contextWithExpectedType.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
public fun test(o: String?): Boolean {
|
||||
return when {
|
||||
// Data flow info should propagate from o == null to o.length
|
||||
o == null, <!DEBUG_INFO_SMARTCAST!>o<!>.length == 0 -> false
|
||||
o == null<!COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT!>,<!> <!DEBUG_INFO_SMARTCAST!>o<!>.length == 0 -> false
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
fun foo(x: Int, y: Int): Int =
|
||||
when {
|
||||
x > 0<!COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT!>,<!> y > 0<!COMMA_IN_WHEN_CONDITION_WITHOUT_ARGUMENT!>,<!><!SYNTAX!>,<!> x < 0 -> 1
|
||||
else -> 0
|
||||
}
|
||||
|
||||
fun bar(x: Int): Int =
|
||||
when (x) {
|
||||
0 -> 0
|
||||
else -> 1
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
package
|
||||
|
||||
public fun bar(/*0*/ x: kotlin.Int): kotlin.Int
|
||||
public fun foo(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int): kotlin.Int
|
||||
@@ -17148,6 +17148,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("CommaInWhenConditionWithoutArgument.kt")
|
||||
public void testCommaInWhenConditionWithoutArgument() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/CommaInWhenConditionWithoutArgument.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ElseOnNullableEnum.kt")
|
||||
public void testElseOnNullableEnum() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/ElseOnNullableEnum.kt");
|
||||
|
||||
Reference in New Issue
Block a user