Fix parsing regression related to T!!
^KT-47445 Fixed
This commit is contained in:
committed by
teamcityserver
parent
768afc5ba4
commit
0ec693db89
+12
@@ -9451,6 +9451,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/inference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("isAsOperators.kt")
|
||||
public void testIsAsOperators() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/isAsOperators.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("isAsOperatorsEnabled.kt")
|
||||
public void testIsAsOperatorsEnabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/isAsOperatorsEnabled.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("notApplicable.kt")
|
||||
public void testNotApplicable() throws Exception {
|
||||
|
||||
+12
@@ -9451,6 +9451,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/inference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("isAsOperators.kt")
|
||||
public void testIsAsOperators() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/isAsOperators.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("isAsOperatorsEnabled.kt")
|
||||
public void testIsAsOperatorsEnabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/isAsOperatorsEnabled.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("notApplicable.kt")
|
||||
public void testNotApplicable() throws Exception {
|
||||
|
||||
@@ -196,6 +196,8 @@ public interface Errors {
|
||||
DiagnosticFactory1<KtElement, KotlinType> EXPANDED_TYPE_CANNOT_BE_CONSTRUCTED = DiagnosticFactory1.create(ERROR);
|
||||
DiagnosticFactory1<KtTypeElement, KotlinType> EXPANDED_TYPE_CANNOT_BE_INHERITED = DiagnosticFactory1.create(ERROR);
|
||||
|
||||
DiagnosticFactory0<KtPostfixExpression> DEPRECATED_SYNTAX_WITH_DEFINITELY_NOT_NULL = DiagnosticFactory0.create(WARNING);
|
||||
|
||||
DiagnosticFactory0<KtModifierList> MODIFIER_LIST_NOT_ALLOWED = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+1
@@ -601,6 +601,7 @@ public class DefaultErrorMessages {
|
||||
MAP.put(UNUSED_TYPEALIAS_PARAMETER, "Type alias parameter {0} is not used in the expanded type {1} and does not affect type checking", NAME, RENDER_TYPE);
|
||||
MAP.put(EXPANDED_TYPE_CANNOT_BE_CONSTRUCTED, "Expanded type {0} contains non-invariant projections in top-level arguments and cannot be constructed", RENDER_TYPE);
|
||||
MAP.put(EXPANDED_TYPE_CANNOT_BE_INHERITED, "Expanded type {0} contains non-invariant projections in top-level arguments and cannot be inherited from", RENDER_TYPE);
|
||||
MAP.put(DEPRECATED_SYNTAX_WITH_DEFINITELY_NOT_NULL, "Applying ''!!'' to the whole as/is expression without parentheses is deprecated. Please, put parentheses explicitly");
|
||||
|
||||
MAP.put(MODIFIER_LIST_NOT_ALLOWED, "Modifiers and annotations are not allowed here, because there are other modifiers or annotations outside of parenthesis");
|
||||
|
||||
|
||||
+2
@@ -293,6 +293,8 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
return facade.getTypeInfo(left, contextWithNoExpectedType).clearType();
|
||||
}
|
||||
|
||||
DefinitelyNotNullDeprecationKt.reportDeprecatedDefinitelyNotNullSyntax(expression, right, context);
|
||||
|
||||
IElementType operationType = expression.getOperationReference().getReferencedNameElementType();
|
||||
|
||||
boolean allowBareTypes = BARE_TYPES_ALLOWED.contains(operationType);
|
||||
|
||||
+2
@@ -60,6 +60,8 @@ class PatternMatchingTypingVisitor internal constructor(facade: ExpressionTyping
|
||||
context.trace.record(BindingContext.DATAFLOW_INFO_AFTER_CONDITION, expression, newDataFlowInfo)
|
||||
}
|
||||
|
||||
expression.reportDeprecatedDefinitelyNotNullSyntax(expression.typeReference, contextWithExpectedType)
|
||||
|
||||
val resultTypeInfo = components.dataFlowAnalyzer.checkType(
|
||||
typeInfo.replaceType(components.builtIns.booleanType),
|
||||
expression,
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.types.expressions
|
||||
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.KtOperationExpression
|
||||
import org.jetbrains.kotlin.psi.KtPostfixExpression
|
||||
import org.jetbrains.kotlin.psi.KtTypeReference
|
||||
import org.jetbrains.kotlin.psi.KtUserType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.nextLeaf
|
||||
|
||||
fun KtOperationExpression.reportDeprecatedDefinitelyNotNullSyntax(
|
||||
rhs: KtTypeReference?,
|
||||
context: ExpressionTypingContext
|
||||
) {
|
||||
val nextLeaf = nextLeaf()
|
||||
if (nextLeaf is LeafPsiElement && nextLeaf.elementType === KtTokens.EXCLEXCL && rhs?.typeElement is KtUserType) {
|
||||
val parent = PsiTreeUtil.findCommonParent(nextLeaf, this)
|
||||
if (parent is KtPostfixExpression && parent.operationToken === KtTokens.EXCLEXCL) {
|
||||
context.trace.report(Errors.DEPRECATED_SYNTAX_WITH_DEFINITELY_NOT_NULL.on((parent as KtPostfixExpression?)!!))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,7 +158,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
AS(AS_KEYWORD, AS_SAFE) {
|
||||
@Override
|
||||
public IElementType parseRightHandSide(IElementType operation, KotlinExpressionParsing parser) {
|
||||
parser.myKotlinParsing.parseTypeRef();
|
||||
parser.myKotlinParsing.parseTypeRefWithoutDefinitelyNotNull();
|
||||
return BINARY_WITH_TYPE;
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
@Override
|
||||
public IElementType parseRightHandSide(IElementType operation, KotlinExpressionParsing parser) {
|
||||
if (operation == IS_KEYWORD || operation == NOT_IS) {
|
||||
parser.myKotlinParsing.parseTypeRef();
|
||||
parser.myKotlinParsing.parseTypeRefWithoutDefinitelyNotNull();
|
||||
return IS_EXPRESSION;
|
||||
}
|
||||
|
||||
|
||||
@@ -833,7 +833,7 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
|
||||
PsiBuilder.Marker reference = mark();
|
||||
PsiBuilder.Marker typeReference = mark();
|
||||
parseUserType(/* forAnnotation */ true);
|
||||
parseUserType(/* allowNotNullTypeParameter */ false);
|
||||
typeReference.done(TYPE_REFERENCE);
|
||||
reference.done(CONSTRUCTOR_CALLEE);
|
||||
|
||||
@@ -2055,14 +2055,22 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
parseTypeRef(TokenSet.EMPTY);
|
||||
}
|
||||
|
||||
void parseTypeRefWithoutDefinitelyNotNull() {
|
||||
parseTypeRef(TokenSet.EMPTY, /* allowNotNullTypeParameters */ false);
|
||||
}
|
||||
|
||||
void parseTypeRef(TokenSet extraRecoverySet) {
|
||||
PsiBuilder.Marker typeRefMarker = parseTypeRefContents(extraRecoverySet);
|
||||
parseTypeRef(extraRecoverySet, /* allowNotNullTypeParameters */ true);
|
||||
}
|
||||
|
||||
private void parseTypeRef(TokenSet extraRecoverySet, boolean allowNotNullTypeParameters) {
|
||||
PsiBuilder.Marker typeRefMarker = parseTypeRefContents(extraRecoverySet, allowNotNullTypeParameters);
|
||||
typeRefMarker.done(TYPE_REFERENCE);
|
||||
}
|
||||
|
||||
// The extraRecoverySet is needed for the foo(bar<x, 1, y>(z)) case, to tell whether we should stop
|
||||
// on expression-indicating symbols or not
|
||||
private PsiBuilder.Marker parseTypeRefContents(TokenSet extraRecoverySet) {
|
||||
private PsiBuilder.Marker parseTypeRefContents(TokenSet extraRecoverySet, boolean allowNotNullTypeParameters) {
|
||||
PsiBuilder.Marker typeRefMarker = mark();
|
||||
|
||||
parseTypeModifierList();
|
||||
@@ -2078,14 +2086,14 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
dynamicType.done(DYNAMIC_TYPE);
|
||||
}
|
||||
else if (at(IDENTIFIER) || at(PACKAGE_KEYWORD) || atParenthesizedMutableForPlatformTypes(0)) {
|
||||
parseUserType(/* forAnnotation */ false);
|
||||
parseUserType(allowNotNullTypeParameters);
|
||||
}
|
||||
else if (at(LPAR)) {
|
||||
PsiBuilder.Marker functionOrParenthesizedType = mark();
|
||||
|
||||
// This may be a function parameter list or just a parenthesized type
|
||||
advance(); // LPAR
|
||||
parseTypeRefContents(TokenSet.EMPTY).drop(); // parenthesized types, no reference element around it is needed
|
||||
parseTypeRefContents(TokenSet.EMPTY, allowNotNullTypeParameters).drop(); // parenthesized types, no reference element around it is needed
|
||||
|
||||
if (at(RPAR)) {
|
||||
advance(); // RPAR
|
||||
@@ -2175,7 +2183,7 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
* - (Mutable)List<Foo>!
|
||||
* - Array<(out) Foo>!
|
||||
*/
|
||||
private void parseUserType(boolean forAnnotation) {
|
||||
private void parseUserType(boolean allowNotNullTypeParameter) {
|
||||
PsiBuilder.Marker userType = mark();
|
||||
|
||||
if (at(PACKAGE_KEYWORD)) {
|
||||
@@ -2221,7 +2229,7 @@ public class KotlinParsing extends AbstractKotlinParsing {
|
||||
|
||||
userType.done(USER_TYPE);
|
||||
|
||||
if (!forAnnotation && at(EXCLEXCL)) {
|
||||
if (allowNotNullTypeParameter && at(EXCLEXCL)) {
|
||||
PsiBuilder.Marker definitelyNotNull = userType.precede();
|
||||
advance(); // !!
|
||||
definitelyNotNull.done(DEFINITELY_NOT_NULL_TYPE);
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// SKIP_TXT
|
||||
// !LANGUAGE: -DefinitelyNotNullTypeParameters
|
||||
|
||||
fun Any.bar() {}
|
||||
fun Boolean.baz() {}
|
||||
|
||||
var x: Int = 0
|
||||
|
||||
inline fun <reified T> foo(v: Any?): T {
|
||||
if (x > 0) 1 else v as T!!
|
||||
if (x > 1) 2 else v as? T!!
|
||||
if (x > 2) 3 else v is T<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||
if (x > 3) 4 else v !is T<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||
|
||||
return v as T<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// SKIP_TXT
|
||||
// !LANGUAGE: -DefinitelyNotNullTypeParameters
|
||||
|
||||
fun Any.bar() {}
|
||||
fun Boolean.baz() {}
|
||||
|
||||
var x: Int = 0
|
||||
|
||||
inline fun <reified T> foo(v: Any?): T {
|
||||
<!DEPRECATED_SYNTAX_WITH_DEFINITELY_NOT_NULL!>if (x > 0) 1 else v as T!!<!>
|
||||
<!DEPRECATED_SYNTAX_WITH_DEFINITELY_NOT_NULL!>if (x > 1) 2 else v as? T!!<!>
|
||||
<!DEPRECATED_SYNTAX_WITH_DEFINITELY_NOT_NULL!>if (x > 2) 3 else v is T<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!><!>
|
||||
<!DEPRECATED_SYNTAX_WITH_DEFINITELY_NOT_NULL!>if (x > 3) 4 else v !is T<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!><!>
|
||||
|
||||
<!DEPRECATED_SYNTAX_WITH_DEFINITELY_NOT_NULL!>return v as T<!UNNECESSARY_NOT_NULL_ASSERTION, UNREACHABLE_CODE!>!!<!><!>
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// SKIP_TXT
|
||||
// !LANGUAGE: +DefinitelyNotNullTypeParameters
|
||||
|
||||
fun Any.bar() {}
|
||||
fun Boolean.baz() {}
|
||||
|
||||
var x: Int = 0
|
||||
|
||||
inline fun <reified T> foo(v: Any?): T {
|
||||
if (x > 0) 1 else v as T!!
|
||||
if (x > 1) 2 else v as? T!!
|
||||
if (x > 2) 3 else v is T<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||
if (x > 3) 4 else v !is T<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||
|
||||
return v as T<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!>
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// SKIP_TXT
|
||||
// !LANGUAGE: +DefinitelyNotNullTypeParameters
|
||||
|
||||
fun Any.bar() {}
|
||||
fun Boolean.baz() {}
|
||||
|
||||
var x: Int = 0
|
||||
|
||||
inline fun <reified T> foo(v: Any?): T {
|
||||
<!DEPRECATED_SYNTAX_WITH_DEFINITELY_NOT_NULL!>if (x > 0) 1 else v as T!!<!>
|
||||
<!DEPRECATED_SYNTAX_WITH_DEFINITELY_NOT_NULL!>if (x > 1) 2 else v as? T!!<!>
|
||||
<!DEPRECATED_SYNTAX_WITH_DEFINITELY_NOT_NULL!>if (x > 2) 3 else v is T<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!><!>
|
||||
<!DEPRECATED_SYNTAX_WITH_DEFINITELY_NOT_NULL!>if (x > 3) 4 else v !is T<!UNNECESSARY_NOT_NULL_ASSERTION!>!!<!><!>
|
||||
|
||||
<!DEPRECATED_SYNTAX_WITH_DEFINITELY_NOT_NULL!>return v as T<!UNNECESSARY_NOT_NULL_ASSERTION, UNREACHABLE_CODE!>!!<!><!>
|
||||
}
|
||||
Generated
+12
@@ -9457,6 +9457,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/inference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("isAsOperators.kt")
|
||||
public void testIsAsOperators() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/isAsOperators.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("isAsOperatorsEnabled.kt")
|
||||
public void testIsAsOperatorsEnabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/isAsOperatorsEnabled.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("notApplicable.kt")
|
||||
public void testNotApplicable() throws Exception {
|
||||
|
||||
+12
@@ -9451,6 +9451,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
||||
runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/inference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("isAsOperators.kt")
|
||||
public void testIsAsOperators() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/isAsOperators.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("isAsOperatorsEnabled.kt")
|
||||
public void testIsAsOperatorsEnabled() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/explicitDefinitelyNotNull/isAsOperatorsEnabled.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("notApplicable.kt")
|
||||
public void testNotApplicable() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user