diff --git a/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetExpressionParsing.java b/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetExpressionParsing.java index b39c57c3388..6510b1ed12a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetExpressionParsing.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetExpressionParsing.java @@ -370,7 +370,7 @@ public class JetExpressionParsing extends AbstractJetParsing { /* * callableReference - * : (userType "?"*)? "::" SimpleName + * : (userType "?"*)? "::" SimpleName typeArguments? * ; */ private boolean parseDoubleColonExpression() { @@ -396,6 +396,17 @@ public class JetExpressionParsing extends AbstractJetParsing { } else { parseSimpleNameExpression(); + + if (at(LT)) { + PsiBuilder.Marker typeArgumentList = mark(); + if (myJetParsing.tryParseTypeArgumentList(TYPE_ARGUMENT_LIST_STOPPERS)) { + typeArgumentList.error("Type arguments are not allowed"); + } + else { + typeArgumentList.rollbackTo(); + } + } + expression.done(CALLABLE_REFERENCE_EXPRESSION); } diff --git a/compiler/testData/psi/DoubleColon.kt b/compiler/testData/psi/DoubleColon.kt index 9eee0c27cdc..00b1ad88868 100644 --- a/compiler/testData/psi/DoubleColon.kt +++ b/compiler/testData/psi/DoubleColon.kt @@ -50,3 +50,11 @@ fun err2() { fun err3() { :: } + +fun typeArgumentsError() { + ::a + ::a> + a::b + + ::a() +} diff --git a/compiler/testData/psi/DoubleColon.txt b/compiler/testData/psi/DoubleColon.txt index 714a59f3a71..facafdc4bc0 100644 --- a/compiler/testData/psi/DoubleColon.txt +++ b/compiler/testData/psi/DoubleColon.txt @@ -609,3 +609,86 @@ JetFile: DoubleColon.kt PsiErrorElement:Expecting an identifier PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('typeArgumentsError') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CALLABLE_REFERENCE_EXPRESSION + PsiElement(COLONCOLON)('::') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a') + PsiErrorElement:Type arguments are not allowed + PsiElement(LT)('<') + TYPE_PROJECTION + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(GT)('>') + PsiWhiteSpace('\n ') + CALLABLE_REFERENCE_EXPRESSION + PsiElement(COLONCOLON)('::') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a') + PsiErrorElement:Type arguments are not allowed + PsiElement(LT)('<') + TYPE_PROJECTION + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(COMMA)(',') + TYPE_PROJECTION + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('c') + TYPE_ARGUMENT_LIST + PsiElement(LT)('<') + TYPE_PROJECTION + PsiElement(MUL)('*') + PsiElement(GT)('>') + PsiElement(GT)('>') + PsiWhiteSpace('\n ') + CALLABLE_REFERENCE_EXPRESSION + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a') + PsiElement(COLONCOLON)('::') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiErrorElement:Type arguments are not allowed + PsiElement(LT)('<') + TYPE_PROJECTION + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('c') + PsiElement(GT)('>') + PsiWhiteSpace('\n\n ') + CALLABLE_REFERENCE_EXPRESSION + PsiElement(COLONCOLON)('::') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a') + PsiErrorElement:Type arguments are not allowed + PsiElement(LT)('<') + TYPE_PROJECTION + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('b') + PsiElement(GT)('>') + PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/grammar/src/expressions.grm b/grammar/src/expressions.grm index 94363961b48..59cf593b70a 100644 --- a/grammar/src/expressions.grm +++ b/grammar/src/expressions.grm @@ -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 typeArguments? ; // !!! When you add here, remember to update the FIRST set in the parser