[PSI, FE] Support functional types

This commit is contained in:
Anastasiya Shadrina
2021-08-12 01:15:58 +07:00
committed by TeamCityServer
parent e53cee77a3
commit e3f987459c
45 changed files with 507 additions and 40 deletions
@@ -2172,6 +2172,12 @@ public class KotlinParsing extends AbstractKotlinParsing {
IElementType lookahead = lookahead(1);
IElementType lookahead2 = lookahead(2);
boolean typeBeforeDot = true;
boolean withContextReceiver = at(CONTEXT_KEYWORD) && lookahead == LPAR;
if (withContextReceiver) {
parseContextReceiverList();
}
if (at(IDENTIFIER) && !(lookahead == DOT && lookahead2 == IDENTIFIER) && lookahead != LT && at(DYNAMIC_KEYWORD)) {
PsiBuilder.Marker dynamicType = mark();
advance(); // DYNAMIC_KEYWORD
@@ -2180,7 +2186,7 @@ public class KotlinParsing extends AbstractKotlinParsing {
else if (at(IDENTIFIER) || at(PACKAGE_KEYWORD) || atParenthesizedMutableForPlatformTypes(0)) {
parseUserType(allowSimpleIntersectionTypes);
}
else if (at(LPAR)) {
else if (at(LPAR) && !withContextReceiver) {
PsiBuilder.Marker functionOrParenthesizedType = mark();
// This may be a function parameter list or just a parenthesized type
@@ -2211,7 +2217,7 @@ public class KotlinParsing extends AbstractKotlinParsing {
}
}
else {
else if (!withContextReceiver) {
errorWithRecovery("Type expected",
TokenSet.orSet(TOP_LEVEL_DECLARATION_FIRST,
TokenSet.create(EQ, COMMA, GT, RBRACKET, DOT, RPAR, RBRACE, LBRACE, SEMICOLON),
@@ -2240,8 +2246,10 @@ public class KotlinParsing extends AbstractKotlinParsing {
intersectionType.done(INTERSECTION_TYPE);
wasIntersection = true;
}
boolean withExtensionReceiver = typeBeforeDot && at(DOT);
if (typeBeforeDot && !wasIntersection && at(DOT)) {
if (withExtensionReceiver && !wasIntersection || withContextReceiver) {
// This is a receiver for a function type
// A.(B) -> C
// ^
@@ -2253,7 +2261,9 @@ public class KotlinParsing extends AbstractKotlinParsing {
receiverTypeRef.done(TYPE_REFERENCE);
receiverType.done(FUNCTION_TYPE_RECEIVER);
advance(); // DOT
if (withExtensionReceiver) {
advance(); // DOT
}
if (at(LPAR)) {
parseFunctionTypeContents().drop();
@@ -45,6 +45,10 @@ public class KtFunctionType extends KtElementImplStub<KotlinPlaceHolderStub<KtFu
@Override
public List<KtTypeReference> getTypeArgumentsAsTypes() {
ArrayList<KtTypeReference> result = Lists.newArrayList();
List<KtTypeReference> contextReceiversTypeRefs = getContextReceiversTypeReferences();
if (contextReceiversTypeRefs != null) {
result.addAll(contextReceiversTypeRefs);
}
KtTypeReference receiverTypeRef = getReceiverTypeReference();
if (receiverTypeRef != null) {
result.add(receiverTypeRef);
@@ -89,6 +93,20 @@ public class KtFunctionType extends KtElementImplStub<KotlinPlaceHolderStub<KtFu
return receiverDeclaration.getTypeReference();
}
public List<KtTypeReference> getContextReceiversTypeReferences() {
KtFunctionTypeReceiver receiverDeclaration = getReceiver();
if (receiverDeclaration == null) {
return null;
}
KtTypeReference receiverTypeRef = receiverDeclaration.getTypeReference();
KtContextReceiverList contextReceiverList = receiverTypeRef.getStubOrPsiChild(KtStubElementTypes.CONTEXT_RECEIVER_LIST);
if (contextReceiverList != null) {
return contextReceiverList.typeReferences();
} else {
return Collections.emptyList();
}
}
@Nullable
public KtTypeReference getReturnTypeReference() {
return getStubOrPsiChild(KtStubElementTypes.TYPE_REFERENCE);