Fix parsing regression related to T!!

^KT-47445 Fixed
This commit is contained in:
Denis.Zharkov
2021-06-25 18:07:06 +03:00
committed by teamcityserver
parent 768afc5ba4
commit 0ec693db89
15 changed files with 165 additions and 9 deletions
@@ -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 {
@@ -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);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -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");
@@ -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);
@@ -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,
@@ -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);
@@ -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!>!!<!>
}
@@ -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!>!!<!><!>
}
@@ -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!>!!<!>
}
@@ -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!>!!<!><!>
}
@@ -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 {
@@ -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 {