'sealed' reserved in front of when
This commit is contained in:
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.descriptors.Modality;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils;
|
||||
@@ -283,4 +284,7 @@ public final class WhenChecker {
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkReservedPrefix(@NotNull BindingTrace trace, @NotNull KtWhenExpression expression) {
|
||||
KtPsiUtilKt.checkReservedPrefixWord(trace, expression.getWhenKeyword(), "sealed", "sealed when");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -599,6 +599,25 @@ public class KtPsiUtil {
|
||||
return PsiTreeUtil.skipSiblingsForward(element, PsiWhiteSpace.class, PsiComment.class);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement prevLeafIgnoringWhitespaceAndComments(@NotNull PsiElement element) {
|
||||
PsiElement prev = PsiTreeUtil.prevLeaf(element, true);
|
||||
while (prev != null && KtTokens.WHITE_SPACE_OR_COMMENT_BIT_SET.contains(prev.getNode().getElementType())) {
|
||||
prev = PsiTreeUtil.prevLeaf(prev, true);
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiElement getPreviousWord(@NotNull PsiElement element, @NotNull String word) {
|
||||
PsiElement prev = prevLeafIgnoringWhitespaceAndComments(element);
|
||||
if (prev != null && prev.getNode().getElementType() == KtTokens.IDENTIFIER && word.equals(prev.getText())) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final Predicate<KtElement> ANY_JET_ELEMENT = new Predicate<KtElement>() {
|
||||
@Override
|
||||
public boolean apply(@Nullable KtElement input) {
|
||||
|
||||
@@ -25,6 +25,8 @@ import com.intellij.psi.PsiWhiteSpace
|
||||
import com.intellij.psi.stubs.StubElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -36,7 +38,6 @@ import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
|
||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||
import java.util.*
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.text.Regex
|
||||
|
||||
// NOTE: in this file we collect only Kotlin-specific methods working with PSI and not modifying it
|
||||
|
||||
@@ -431,4 +432,10 @@ private val BAD_NEIGHBOUR_FOR_SIMPLE_TEMPLATE_ENTRY_PATTERN = Regex("[a-zA-Z0-9_
|
||||
fun canPlaceAfterSimpleNameEntry(element: PsiElement?): Boolean {
|
||||
val entryText = element?.text ?: return true
|
||||
return !BAD_NEIGHBOUR_FOR_SIMPLE_TEMPLATE_ENTRY_PATTERN.matches(entryText)
|
||||
}
|
||||
|
||||
fun checkReservedPrefixWord(sink: DiagnosticSink, element: PsiElement, word: String, message: String) {
|
||||
KtPsiUtil.getPreviousWord(element, word)?.let {
|
||||
sink.report(Errors.UNSUPPORTED.on(it, message))
|
||||
}
|
||||
}
|
||||
+1
@@ -75,6 +75,7 @@ public class PatternMatchingTypingVisitor extends ExpressionTypingVisitor {
|
||||
|
||||
public KotlinTypeInfo visitWhenExpression(KtWhenExpression expression, ExpressionTypingContext contextWithExpectedType, boolean isStatement) {
|
||||
WhenChecker.checkDeprecatedWhenSyntax(contextWithExpectedType.trace, expression);
|
||||
WhenChecker.checkReservedPrefix(contextWithExpectedType.trace, expression);
|
||||
|
||||
components.dataFlowAnalyzer.recordExpectedType(contextWithExpectedType.trace, expression, contextWithExpectedType.expectedType);
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
|
||||
infix fun Any.sealed(a: Any?) {}
|
||||
|
||||
val x = 1 <!UNSUPPORTED!>sealed<!> when (1) {
|
||||
1 -> 1
|
||||
else -> 2
|
||||
}
|
||||
|
||||
val x1 = 1 <!UNSUPPORTED!>sealed<!> /**/ when (1) {
|
||||
1 -> 1
|
||||
else -> 2
|
||||
}
|
||||
|
||||
fun foo() {
|
||||
<!UNRESOLVED_REFERENCE, UNSUPPORTED!>sealed<!><!SYNTAX!><!> when {
|
||||
else -> {}
|
||||
}
|
||||
|
||||
1 <!UNSUPPORTED!>sealed<!> when {
|
||||
else -> {}
|
||||
}
|
||||
|
||||
1 sealed (when {
|
||||
else -> {}
|
||||
})
|
||||
|
||||
<!UNUSED_EXPRESSION!>1<!>
|
||||
<!UNRESOLVED_REFERENCE, UNSUPPORTED!>sealed<!><!SYNTAX!><!> when {
|
||||
else -> {}
|
||||
}
|
||||
|
||||
1 <!UNSUPPORTED!>sealed<!>
|
||||
when {
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package
|
||||
|
||||
public val x: kotlin.Unit
|
||||
public val x1: kotlin.Unit
|
||||
public fun foo(): kotlin.Unit
|
||||
public infix fun kotlin.Any.sealed(/*0*/ a: kotlin.Any?): kotlin.Unit
|
||||
@@ -18186,6 +18186,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ReservedExhaustiveWhen.kt")
|
||||
public void testReservedExhaustiveWhen() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/ReservedExhaustiveWhen.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("When.kt")
|
||||
public void testWhen() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/When.kt");
|
||||
|
||||
Reference in New Issue
Block a user