Support nullable types on left-hand side of ::

#KT-1183 In Progress
This commit is contained in:
Alexander Udalov
2014-06-02 20:27:19 +04:00
parent 42991e05a1
commit a9b2fd964b
7 changed files with 107 additions and 10 deletions
@@ -372,7 +372,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
/*
* callableReference
* : userType? "::" SimpleName
* : (userType "?"*)? "::" SimpleName
* ;
*/
private boolean parseCallableReferenceExpression() {
@@ -381,7 +381,9 @@ public class JetExpressionParsing extends AbstractJetParsing {
if (!at(COLONCOLON)) {
PsiBuilder.Marker typeReference = mark();
myJetParsing.parseUserType();
typeReference = myJetParsing.parseNullableTypeSuffix(typeReference);
typeReference.done(TYPE_REFERENCE);
if (!at(COLONCOLON)) {
expression.rollbackTo();
return false;
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.parsing;
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeType;
import org.jetbrains.jet.lexer.JetKeywordToken;
@@ -1478,14 +1479,7 @@ public class JetParsing extends AbstractJetParsing {
TokenSet.create(EQ, COMMA, GT, RBRACKET, DOT, RPAR, RBRACE, LBRACE, SEMICOLON), extraRecoverySet));
}
while (at(QUEST)) {
PsiBuilder.Marker precede = typeRefMarker.precede();
advance(); // QUEST
typeRefMarker.done(NULLABLE_TYPE);
typeRefMarker = precede;
}
typeRefMarker = parseNullableTypeSuffix(typeRefMarker);
if (at(DOT)) {
// This is a receiver for a function type
@@ -1513,6 +1507,17 @@ public class JetParsing extends AbstractJetParsing {
return typeRefMarker;
}
@NotNull
PsiBuilder.Marker parseNullableTypeSuffix(@NotNull PsiBuilder.Marker typeRefMarker) {
while (at(QUEST)) {
PsiBuilder.Marker precede = typeRefMarker.precede();
advance(); // QUEST
typeRefMarker.done(NULLABLE_TYPE);
typeRefMarker = precede;
}
return typeRefMarker;
}
/*
* userType
* : ("package" ".")? simpleUserType{"."}
@@ -0,0 +1,8 @@
class A {
fun foo() {}
}
fun A?.foo() {}
val f = A::foo : KMemberFunction0<A, Unit>
val g = A?::foo : KExtensionFunction0<A, Unit>
+5
View File
@@ -23,6 +23,11 @@ fun ok() {
(a::b)()
a.(b::c)()
a.b::c()
a?::b
a??::b
a<b>?::c
a<b?,c?>?::d
}
fun err0() {
+72
View File
@@ -392,6 +392,78 @@ JetFile: DoubleColon.kt
PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line)
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n\n ')
CALLABLE_REFERENCE_EXPRESSION
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(QUEST)('?')
PsiElement(COLONCOLON)('::')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('b')
PsiWhiteSpace('\n ')
CALLABLE_REFERENCE_EXPRESSION
TYPE_REFERENCE
NULLABLE_TYPE
NULLABLE_TYPE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(QUEST)('?')
PsiElement(QUEST)('?')
PsiElement(COLONCOLON)('::')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('b')
PsiWhiteSpace('\n ')
CALLABLE_REFERENCE_EXPRESSION
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
TYPE_ARGUMENT_LIST
PsiElement(LT)('<')
TYPE_PROJECTION
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('b')
PsiElement(GT)('>')
PsiElement(QUEST)('?')
PsiElement(COLONCOLON)('::')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('c')
PsiWhiteSpace('\n ')
CALLABLE_REFERENCE_EXPRESSION
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
TYPE_ARGUMENT_LIST
PsiElement(LT)('<')
TYPE_PROJECTION
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('b')
PsiElement(QUEST)('?')
PsiElement(COMMA)(',')
TYPE_PROJECTION
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('c')
PsiElement(QUEST)('?')
PsiElement(GT)('>')
PsiElement(QUEST)('?')
PsiElement(COLONCOLON)('::')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('d')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
@@ -192,6 +192,11 @@ public class JetDiagnosticsTestWithStdLibGenerated extends AbstractJetDiagnostic
doTest("compiler/testData/diagnostics/testsWithStdLib/callableReference/function/extensionInClassDisallowed.kt");
}
@TestMetadata("extensionOnNullable.kt")
public void testExtensionOnNullable() throws Exception {
doTest("compiler/testData/diagnostics/testsWithStdLib/callableReference/function/extensionOnNullable.kt");
}
@TestMetadata("genericClassFromTopLevel.kt")
public void testGenericClassFromTopLevel() throws Exception {
doTest("compiler/testData/diagnostics/testsWithStdLib/callableReference/function/genericClassFromTopLevel.kt");
+1 -1
View File
@@ -104,7 +104,7 @@ postfixUnaryExpression
// TODO: callSuffix is forbidden after callableReference, since parentheses will be used to provide parameter types
callableReference
: userType? "::" SimpleName
: (userType "?"*)? "::" SimpleName
;
// !!! When you add here, remember to update the FIRST set in the parser