Warn about comma-separated conditions in when without argument.

See KT-5143.
This commit is contained in:
Dmitry Petrov
2015-11-19 18:21:46 +03:00
parent b9e9c47b28
commit da90c21284
18 changed files with 215 additions and 19 deletions
@@ -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
@@ -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");
@@ -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 -1
View File
@@ -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
}
}
@@ -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
}
@@ -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");