Support new form of definitely non-nullable types: T & Any

^KT-26245 In Progress
This commit is contained in:
Denis.Zharkov
2021-08-09 12:10:51 +03:00
committed by teamcityserver
parent cdd8d1c163
commit 302eacbf59
53 changed files with 2139 additions and 196 deletions
@@ -76,6 +76,7 @@ public interface KtNodeTypes {
IElementType FUNCTION_TYPE_RECEIVER = KtStubElementTypes.FUNCTION_TYPE_RECEIVER;
IElementType NULLABLE_TYPE = KtStubElementTypes.NULLABLE_TYPE;
IElementType DEFINITELY_NOT_NULL_TYPE = KtStubElementTypes.DEFINITELY_NOT_NULL_TYPE;
IElementType INTERSECTION_TYPE = KtStubElementTypes.INTERSECTION_TYPE;
IElementType TYPE_PROJECTION = KtStubElementTypes.TYPE_PROJECTION;
IElementType PROPERTY_ACCESSOR = KtStubElementTypes.PROPERTY_ACCESSOR;
@@ -158,7 +158,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
AS(AS_KEYWORD, AS_SAFE) {
@Override
public IElementType parseRightHandSide(IElementType operation, KotlinExpressionParsing parser) {
parser.myKotlinParsing.parseTypeRefWithoutDefinitelyNotNull();
parser.myKotlinParsing.parseTypeRefWithoutIntersections();
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.parseTypeRefWithoutDefinitelyNotNull();
parser.myKotlinParsing.parseTypeRefWithoutIntersections();
return IS_EXPRESSION;
}
@@ -833,7 +833,7 @@ public class KotlinParsing extends AbstractKotlinParsing {
PsiBuilder.Marker reference = mark();
PsiBuilder.Marker typeReference = mark();
parseUserType(/* allowNotNullTypeParameter */ false);
parseUserType(/* allowSimpleIntersectionTypes */ false);
typeReference.done(TYPE_REFERENCE);
reference.done(CONSTRUCTOR_CALLEE);
@@ -1713,7 +1713,7 @@ public class KotlinParsing extends AbstractKotlinParsing {
if (!receiverPresent) return false;
createTruncatedBuilder(lastDot).parseTypeRef();
createTruncatedBuilder(lastDot).parseTypeRefWithoutIntersections();
if (atSet(RECEIVER_TYPE_TERMINATORS)) {
advance(); // expectation
@@ -2055,22 +2055,22 @@ public class KotlinParsing extends AbstractKotlinParsing {
parseTypeRef(TokenSet.EMPTY);
}
void parseTypeRefWithoutDefinitelyNotNull() {
parseTypeRef(TokenSet.EMPTY, /* allowNotNullTypeParameters */ false);
void parseTypeRefWithoutIntersections() {
parseTypeRef(TokenSet.EMPTY, /* allowSimpleIntersectionTypes */ false);
}
void parseTypeRef(TokenSet extraRecoverySet) {
parseTypeRef(extraRecoverySet, /* allowNotNullTypeParameters */ true);
parseTypeRef(extraRecoverySet, /* allowSimpleIntersectionTypes */ true);
}
private void parseTypeRef(TokenSet extraRecoverySet, boolean allowNotNullTypeParameters) {
PsiBuilder.Marker typeRefMarker = parseTypeRefContents(extraRecoverySet, allowNotNullTypeParameters);
private void parseTypeRef(TokenSet extraRecoverySet, boolean allowSimpleIntersectionTypes) {
PsiBuilder.Marker typeRefMarker = parseTypeRefContents(extraRecoverySet, allowSimpleIntersectionTypes);
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, boolean allowNotNullTypeParameters) {
private PsiBuilder.Marker parseTypeRefContents(TokenSet extraRecoverySet, boolean allowSimpleIntersectionTypes) {
PsiBuilder.Marker typeRefMarker = mark();
parseTypeModifierList();
@@ -2086,14 +2086,14 @@ public class KotlinParsing extends AbstractKotlinParsing {
dynamicType.done(DYNAMIC_TYPE);
}
else if (at(IDENTIFIER) || at(PACKAGE_KEYWORD) || atParenthesizedMutableForPlatformTypes(0)) {
parseUserType(allowNotNullTypeParameters);
parseUserType(allowSimpleIntersectionTypes);
}
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, allowNotNullTypeParameters).drop(); // parenthesized types, no reference element around it is needed
parseTypeRefContents(TokenSet.EMPTY, /* allowSimpleIntersectionTypes */ true).drop(); // parenthesized types, no reference element around it is needed
if (at(RPAR)) {
advance(); // RPAR
@@ -2133,7 +2133,23 @@ public class KotlinParsing extends AbstractKotlinParsing {
typeElementMarker = parseNullableTypeSuffix(typeElementMarker);
myBuilder.restoreJoiningComplexTokensState();
if (typeBeforeDot && at(DOT)) {
boolean wasIntersection = false;
if (allowSimpleIntersectionTypes && at(AND)) {
PsiBuilder.Marker leftTypeRef = typeElementMarker;
typeElementMarker = typeElementMarker.precede();
PsiBuilder.Marker intersectionType = leftTypeRef.precede();
leftTypeRef.done(TYPE_REFERENCE);
advance(); // &
parseTypeRef(extraRecoverySet, /* allowSimpleIntersectionTypes */ true);
intersectionType.done(INTERSECTION_TYPE);
wasIntersection = true;
}
if (typeBeforeDot && !wasIntersection && at(DOT)) {
// This is a receiver for a function type
// A.(B) -> C
// ^
@@ -2183,7 +2199,7 @@ public class KotlinParsing extends AbstractKotlinParsing {
* - (Mutable)List<Foo>!
* - Array<(out) Foo>!
*/
private void parseUserType(boolean allowNotNullTypeParameter) {
private void parseUserType(boolean allowSimpleIntersectionTypes) {
PsiBuilder.Marker userType = mark();
if (at(PACKAGE_KEYWORD)) {
@@ -2228,12 +2244,6 @@ public class KotlinParsing extends AbstractKotlinParsing {
}
userType.done(USER_TYPE);
if (allowNotNullTypeParameter && at(EXCLEXCL)) {
PsiBuilder.Marker definitelyNotNull = userType.precede();
advance(); // !!
definitelyNotNull.done(DEFINITELY_NOT_NULL_TYPE);
}
}
private boolean atParenthesizedMutableForPlatformTypes(int offset) {
@@ -0,0 +1,24 @@
/*
* 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.psi
import com.intellij.lang.ASTNode
import org.jetbrains.kotlin.psi.stubs.KotlinPlaceHolderStub
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes
class KtIntersectionType : KtElementImplStub<KotlinPlaceHolderStub<KtIntersectionType>>, KtTypeElement {
constructor(node: ASTNode) : super(node)
constructor(stub: KotlinPlaceHolderStub<KtIntersectionType>) : super(stub, KtStubElementTypes.INTERSECTION_TYPE)
override fun getTypeArgumentsAsTypes(): List<KtTypeReference> = emptyList()
fun getLeftTypeRef(): KtTypeReference? = getStubOrPsiChildrenAsList(KtStubElementTypes.TYPE_REFERENCE).getOrNull(0)
fun getRightTypeRef(): KtTypeReference? = getStubOrPsiChildrenAsList(KtStubElementTypes.TYPE_REFERENCE).getOrNull(1)
override fun <R, D> accept(visitor: KtVisitor<R, D>, data: D): R {
return visitor.visitIntersectionType(this, data)
}
}
@@ -406,6 +406,10 @@ public class KtVisitor<R, D> extends PsiElementVisitor {
return visitTypeElement(definitelyNotNullType, data);
}
public R visitIntersectionType(@NotNull KtIntersectionType definitelyNotNullType, D data) {
return visitTypeElement(definitelyNotNullType, data);
}
public R visitTypeProjection(@NotNull KtTypeProjection typeProjection, D data) {
return visitKtElement(typeProjection, data);
}
@@ -389,6 +389,10 @@ public class KtVisitorVoid extends KtVisitor<Void, Void> {
super.visitDefinitelyNotNullType(definitelyNotNullType, null);
}
public void visitIntersectionType(@NotNull KtIntersectionType intersectionType) {
super.visitIntersectionType(intersectionType, null);
}
public void visitTypeProjection(@NotNull KtTypeProjection typeProjection) {
super.visitTypeProjection(typeProjection, null);
}
@@ -982,6 +986,12 @@ public class KtVisitorVoid extends KtVisitor<Void, Void> {
return null;
}
@Override
public Void visitIntersectionType(@NotNull KtIntersectionType intersectionType, Void data) {
visitIntersectionType(intersectionType);
return null;
}
@Override
public final Void visitTypeProjection(@NotNull KtTypeProjection typeProjection, Void data) {
visitTypeProjection(typeProjection);
@@ -82,6 +82,9 @@ public interface KtStubElementTypes {
KtPlaceHolderStubElementType<KtDefinitelyNotNullType> DEFINITELY_NOT_NULL_TYPE =
new KtPlaceHolderStubElementType<>("DEFINITELY_NOT_NULL_TYPE", KtDefinitelyNotNullType.class);
KtPlaceHolderStubElementType<KtIntersectionType> INTERSECTION_TYPE =
new KtPlaceHolderStubElementType<>("INTERSECTION_TYPE", KtIntersectionType.class);
KtPlaceHolderStubElementType<KtTypeReference> TYPE_REFERENCE =
new KtPlaceHolderStubElementType<>("TYPE_REFERENCE", KtTypeReference.class);
@@ -170,7 +173,7 @@ public interface KtStubElementTypes {
TokenSet SUPER_TYPE_LIST_ENTRIES = TokenSet.create(DELEGATED_SUPER_TYPE_ENTRY, SUPER_TYPE_CALL_ENTRY, SUPER_TYPE_ENTRY);
TokenSet TYPE_ELEMENT_TYPES = TokenSet.create(USER_TYPE, NULLABLE_TYPE, FUNCTION_TYPE, DYNAMIC_TYPE, DEFINITELY_NOT_NULL_TYPE);
TokenSet TYPE_ELEMENT_TYPES = TokenSet.create(USER_TYPE, NULLABLE_TYPE, FUNCTION_TYPE, DYNAMIC_TYPE, INTERSECTION_TYPE);
TokenSet INSIDE_DIRECTIVE_EXPRESSIONS = TokenSet.create(REFERENCE_EXPRESSION, DOT_QUALIFIED_EXPRESSION);
}