From b72a3de86eadd518d90c69d86da4cf32ef57910a Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Mon, 4 May 2015 15:43:36 +0300 Subject: [PATCH] Parse annotations on lambda-argument --- .../kotlin/parsing/JetExpressionParsing.java | 77 ++-- .../kotlin/psi/JetFunctionLiteralArgument.kt | 15 +- .../annotationsOnLambdaAsCallArgument.kt | 16 + .../annotationsOnLambdaAsCallArgument.txt | 12 + compiler/testData/psi/Labels.txt | 4 +- compiler/testData/psi/annotation/lambda.kt | 40 ++ compiler/testData/psi/annotation/lambda.txt | 341 ++++++++++++++++++ .../testData/psi/annotation/lambdaRecovery.kt | 40 ++ .../psi/annotation/lambdaRecovery.txt | 307 ++++++++++++++++ .../psi/newLabels/oldSyntaxExpressions.txt | 43 ++- compiler/testData/psi/newLabels/recovery.txt | 4 +- .../checkers/JetDiagnosticsTestGenerated.java | 6 + .../parsing/JetParsingTestGenerated.java | 12 + grammar/src/expressions.grm | 7 +- 14 files changed, 869 insertions(+), 55 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/annotations/annotationsOnLambdaAsCallArgument.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/annotationsOnLambdaAsCallArgument.txt create mode 100644 compiler/testData/psi/annotation/lambda.kt create mode 100644 compiler/testData/psi/annotation/lambda.txt create mode 100644 compiler/testData/psi/annotation/lambdaRecovery.kt create mode 100644 compiler/testData/psi/annotation/lambdaRecovery.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetExpressionParsing.java b/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetExpressionParsing.java index 82d8782d90f..775b4eca895 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetExpressionParsing.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/parsing/JetExpressionParsing.java @@ -477,13 +477,13 @@ public class JetExpressionParsing extends AbstractJetParsing { /* * callSuffix - * : typeArguments? valueArguments (getEntryPoint? functionLiteral*) - * : typeArguments (getEntryPoint? functionLiteral*) + * : typeArguments? valueArguments annotatedLambda + * : typeArguments annotatedLambda * ; */ private boolean parseCallSuffix() { if (parseCallWithClosure()) { - parseCallWithClosure(); + // do nothing } else if (at(LPAR)) { parseValueArgumentList(); @@ -529,19 +529,19 @@ public class JetExpressionParsing extends AbstractJetParsing { } /* - * element (getEntryPoint? functionLiteral)? + * annotatedLambda* */ protected boolean parseCallWithClosure() { boolean success = false; - while (at(LBRACE) || isAtLabelDefinitionBeforeLBrace()) { + while (true) { PsiBuilder.Marker argument = mark(); - if (!at(LBRACE)) { - parseLabeledExpression(); - } - else { - parseFunctionLiteral(); + + if (!parseAnnotatedLambda(/* preferBlock = */false)) { + argument.drop(); + break; } + argument.done(FUNCTION_LITERAL_ARGUMENT); success = true; } @@ -549,6 +549,47 @@ public class JetExpressionParsing extends AbstractJetParsing { return success; } + /* + * annotatedLambda + * : ("@" annotationEntry)* labelDefinition? functionLiteral + */ + private boolean parseAnnotatedLambda(boolean preferBlock) { + PsiBuilder.Marker annotated = mark(); + + boolean wereAnnotations = myJetParsing.parseAnnotations(ONLY_ESCAPED_REGULAR_ANNOTATIONS); + PsiBuilder.Marker labeled = mark(); + + boolean wasLabel = isAtLabelDefinitionOrMissingIdentifier(); + if (wasLabel) { + parseLabelDefinition(); + } + + if (!at(LBRACE)) { + annotated.rollbackTo(); + return false; + } + + parseFunctionLiteral(preferBlock); + + doneOrDrop(labeled, LABELED_EXPRESSION, wasLabel); + doneOrDrop(annotated, ANNOTATED_EXPRESSION, wereAnnotations); + + return true; + } + + private static void doneOrDrop( + @NotNull PsiBuilder.Marker marker, + @NotNull IElementType type, + boolean condition + ) { + if (condition) { + marker.done(type); + } + else { + marker.drop(); + } + } + private boolean isAtLabelDefinitionBeforeLBrace() { if (at(IDENTIFIER)) { if (myBuilder.rawLookup(1) != AT) return false; @@ -1014,7 +1055,7 @@ public class JetExpressionParsing extends AbstractJetParsing { * ; */ private void parseFunctionLiteral() { - parseFunctionLiteral(false); + parseFunctionLiteral(/* preferBlock = */false); } private void parseFunctionLiteral(boolean preferBlock) { @@ -1462,19 +1503,7 @@ public class JetExpressionParsing extends AbstractJetParsing { * If it has no ->, it's a block, otherwise a function literal */ private void parseExpressionPreferringBlocks() { - if (at(LBRACE)) { - parseFunctionLiteral(true); - } - else if (isAtLabelDefinitionBeforeLBrace()) { - PsiBuilder.Marker mark = mark(); - - parseLabelDefinition(); - - parseFunctionLiteral(true); - - mark.done(LABELED_EXPRESSION); - } - else { + if (!parseAnnotatedLambda(/* preferBlock = */true)) { parseExpression(); } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetFunctionLiteralArgument.kt b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetFunctionLiteralArgument.kt index 8cee6b8e6f3..d3633e3b7e2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/psi/JetFunctionLiteralArgument.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/psi/JetFunctionLiteralArgument.kt @@ -26,13 +26,14 @@ public class JetFunctionLiteralArgument(node: ASTNode) : JetValueArgument(node) override fun getArgumentExpression() = super.getArgumentExpression() ?: assertFL() - public fun getFunctionLiteral(): JetFunctionLiteralExpression { - val expression = getArgumentExpression() + public fun getFunctionLiteral(): JetFunctionLiteralExpression = unpackFunctionLiteral(getArgumentExpression()) - return when (expression) { - is JetLabeledExpression -> expression.getBaseExpression() as? JetFunctionLiteralExpression ?: assertFL() - else -> expression as? JetFunctionLiteralExpression ?: assertFL() - } - } + private fun unpackFunctionLiteral(expression: JetExpression?): JetFunctionLiteralExpression = + when (expression) { + is JetFunctionLiteralExpression -> expression + is JetLabeledExpression -> unpackFunctionLiteral(expression.getBaseExpression()) + is JetAnnotatedExpression -> unpackFunctionLiteral(expression.getBaseExpression()) + else -> assertFL() + } } diff --git a/compiler/testData/diagnostics/tests/annotations/annotationsOnLambdaAsCallArgument.kt b/compiler/testData/diagnostics/tests/annotations/annotationsOnLambdaAsCallArgument.kt new file mode 100644 index 00000000000..523b794eadb --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/annotationsOnLambdaAsCallArgument.kt @@ -0,0 +1,16 @@ +annotation class Ann(val x: Int = 1) + +inline fun bar(block: () -> Int): Int = block() + +fun foo() { + bar() [Ann(1)] @Ann(2) { 101 } + bar() @Ann(3) { 102 } + + bar @Ann l1@ { + return@l1 103 + } + + bar @Ann("") { + 104 + } +} diff --git a/compiler/testData/diagnostics/tests/annotations/annotationsOnLambdaAsCallArgument.txt b/compiler/testData/diagnostics/tests/annotations/annotationsOnLambdaAsCallArgument.txt new file mode 100644 index 00000000000..e765ee0269a --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/annotationsOnLambdaAsCallArgument.txt @@ -0,0 +1,12 @@ +package + +kotlin.inline() internal fun bar(/*0*/ block: () -> kotlin.Int): kotlin.Int +internal fun foo(): kotlin.Unit + +internal final annotation class Ann : kotlin.Annotation { + public constructor Ann(/*0*/ x: kotlin.Int = ...) + internal final val x: kotlin.Int + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/psi/Labels.txt b/compiler/testData/psi/Labels.txt index d45c92da134..144543a9234 100644 --- a/compiler/testData/psi/Labels.txt +++ b/compiler/testData/psi/Labels.txt @@ -230,8 +230,8 @@ JetFile: Labels.kt PsiElement(IDENTIFIER)('filter') PsiWhiteSpace(' ') FUNCTION_LITERAL_ARGUMENT - LABELED_EXPRESSION - PsiErrorElement:Label must be named + ANNOTATED_EXPRESSION + PsiErrorElement:Expected annotation identifier after '@' PsiElement(AT)('@') FUNCTION_LITERAL_EXPRESSION FUNCTION_LITERAL diff --git a/compiler/testData/psi/annotation/lambda.kt b/compiler/testData/psi/annotation/lambda.kt new file mode 100644 index 00000000000..796e2d8bf08 --- /dev/null +++ b/compiler/testData/psi/annotation/lambda.kt @@ -0,0 +1,40 @@ +fun foo() { + bar @ann { + print(1) + } + + bar [ann] { // parsed as array access + print(2) + } + + bar @ann [ann] { + print(2) + } + + bar() @ann { + print(1) + } + + bar() [ann] { + print(2) + } + + bar() @ann [ann] { + print(2) + } + + bar(@ann { + param -> param + }) + + if (true) @ann { + + } + else [ann] @ann { + + } + + foo label@ @ann { + + } +} diff --git a/compiler/testData/psi/annotation/lambda.txt b/compiler/testData/psi/annotation/lambda.txt new file mode 100644 index 00000000000..0117e66031d --- /dev/null +++ b/compiler/testData/psi/annotation/lambda.txt @@ -0,0 +1,341 @@ +JetFile: lambda.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_ARGUMENT + ANNOTATED_EXPRESSION + ANNOTATION_ENTRY + PsiElement(AT)('@') + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + BLOCK + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('print') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + CALL_EXPRESSION + ARRAY_ACCESS_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace(' ') + INDICES + PsiElement(LBRACKET)('[') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_ARGUMENT + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace(' ') + PsiComment(EOL_COMMENT)('// parsed as array access') + PsiWhiteSpace('\n ') + BLOCK + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('print') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('2') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_ARGUMENT + ANNOTATED_EXPRESSION + ANNOTATION_ENTRY + PsiElement(AT)('@') + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiWhiteSpace(' ') + ANNOTATION + PsiElement(LBRACKET)('[') + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + BLOCK + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('print') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('2') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_ARGUMENT + ANNOTATED_EXPRESSION + ANNOTATION_ENTRY + PsiElement(AT)('@') + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + BLOCK + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('print') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_ARGUMENT + ANNOTATED_EXPRESSION + ANNOTATION + PsiElement(LBRACKET)('[') + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + BLOCK + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('print') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('2') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_ARGUMENT + ANNOTATED_EXPRESSION + ANNOTATION_ENTRY + PsiElement(AT)('@') + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiWhiteSpace(' ') + ANNOTATION + PsiElement(LBRACKET)('[') + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + BLOCK + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('print') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('2') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + ANNOTATED_EXPRESSION + ANNOTATION_ENTRY + PsiElement(AT)('@') + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + PsiElement(IDENTIFIER)('param') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + BLOCK + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('param') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n\n ') + IF + PsiElement(if)('if') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + CONDITION + BOOLEAN_CONSTANT + PsiElement(true)('true') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + THEN + ANNOTATED_EXPRESSION + ANNOTATION_ENTRY + PsiElement(AT)('@') + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + PsiElement(else)('else') + PsiWhiteSpace(' ') + ELSE + ANNOTATED_EXPRESSION + ANNOTATION + PsiElement(LBRACKET)('[') + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + ANNOTATION_ENTRY + PsiElement(AT)('@') + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + BINARY_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + OPERATION_REFERENCE + PsiElement(IDENTIFIER)('label') + ANNOTATED_EXPRESSION + PsiErrorElement:Expected annotation identifier after '@' + PsiElement(AT)('@') + PsiWhiteSpace(' ') + ANNOTATION_ENTRY + PsiElement(AT)('@') + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + BLOCK + + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/annotation/lambdaRecovery.kt b/compiler/testData/psi/annotation/lambdaRecovery.kt new file mode 100644 index 00000000000..cda4eea9b97 --- /dev/null +++ b/compiler/testData/psi/annotation/lambdaRecovery.kt @@ -0,0 +1,40 @@ +fun foo() { + bar @ ann { + print(1) + } + + bar @ { + print(1) + } + + bar @ [ann] { + print(2) + } + + bar [] @ { + print(2) + } + + bar() @ { + print(1) + } + + bar() [] @ { + print(2) + } + + bar(@ { + param -> param + }) + + bar(@ ann { + param -> param + }) + + if (true) @ { + + } + else [ann] @ ann { + + } +} diff --git a/compiler/testData/psi/annotation/lambdaRecovery.txt b/compiler/testData/psi/annotation/lambdaRecovery.txt new file mode 100644 index 00000000000..f31646fa12d --- /dev/null +++ b/compiler/testData/psi/annotation/lambdaRecovery.txt @@ -0,0 +1,307 @@ +JetFile: lambdaRecovery.kt + PACKAGE_DIRECTIVE + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace(' ') + PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) + PsiElement(AT)('@') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('ann') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + BLOCK + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('print') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_ARGUMENT + ANNOTATED_EXPRESSION + PsiErrorElement:Expected annotation identifier after '@' + PsiElement(AT)('@') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + BLOCK + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('print') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_ARGUMENT + ANNOTATED_EXPRESSION + PsiErrorElement:Expected annotation identifier after '@' + PsiElement(AT)('@') + PsiWhiteSpace(' ') + ANNOTATION + PsiElement(LBRACKET)('[') + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + BLOCK + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('print') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('2') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + CALL_EXPRESSION + ARRAY_ACCESS_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + PsiWhiteSpace(' ') + INDICES + PsiElement(LBRACKET)('[') + PsiErrorElement:Expecting an index element + + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_ARGUMENT + ANNOTATED_EXPRESSION + PsiErrorElement:Expected annotation identifier after '@' + PsiElement(AT)('@') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + BLOCK + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('print') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('2') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_ARGUMENT + ANNOTATED_EXPRESSION + PsiErrorElement:Expected annotation identifier after '@' + PsiElement(AT)('@') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + BLOCK + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('print') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_ARGUMENT + ANNOTATED_EXPRESSION + ANNOTATION + PsiElement(LBRACKET)('[') + PsiErrorElement:Expecting a list of annotations + + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + PsiErrorElement:Expected annotation identifier after '@' + PsiElement(AT)('@') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + BLOCK + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('print') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('2') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + ANNOTATED_EXPRESSION + PsiErrorElement:Expected annotation identifier after '@' + PsiElement(AT)('@') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + PsiElement(IDENTIFIER)('param') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + BLOCK + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('param') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n\n ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('bar') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + VALUE_ARGUMENT + ANNOTATED_EXPRESSION + PsiErrorElement:Expected annotation identifier after '@' + PsiElement(AT)('@') + PsiWhiteSpace(' ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_ARGUMENT + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + PsiElement(IDENTIFIER)('param') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + BLOCK + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('param') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiElement(RPAR)(')') + PsiWhiteSpace('\n\n ') + IF + PsiElement(if)('if') + PsiWhiteSpace(' ') + PsiElement(LPAR)('(') + CONDITION + BOOLEAN_CONSTANT + PsiElement(true)('true') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + THEN + ANNOTATED_EXPRESSION + PsiErrorElement:Expected annotation identifier after '@' + PsiElement(AT)('@') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + PsiElement(else)('else') + PsiWhiteSpace(' ') + ELSE + ANNOTATED_EXPRESSION + ANNOTATION + PsiElement(LBRACKET)('[') + ANNOTATION_ENTRY + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiElement(RBRACKET)(']') + PsiWhiteSpace(' ') + PsiErrorElement:Expected annotation identifier after '@' + PsiElement(AT)('@') + PsiWhiteSpace(' ') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('ann') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_ARGUMENT + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n\n ') + BLOCK + + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/testData/psi/newLabels/oldSyntaxExpressions.txt b/compiler/testData/psi/newLabels/oldSyntaxExpressions.txt index f46c8f2ab0e..69f6f74d6b4 100644 --- a/compiler/testData/psi/newLabels/oldSyntaxExpressions.txt +++ b/compiler/testData/psi/newLabels/oldSyntaxExpressions.txt @@ -50,25 +50,32 @@ JetFile: oldSyntaxExpressions.kt REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('x2') PsiElement(DOT)('.') - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('filter') - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(AT)('@') - PsiElement(IDENTIFIER)('f') - PsiWhiteSpace(' ') - FUNCTION_LITERAL_EXPRESSION - FUNCTION_LITERAL - PsiElement(LBRACE)('{') - PsiWhiteSpace('\n ') - BLOCK - RETURN - PsiElement(return)('return') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('filter') + PsiWhiteSpace(' ') + FUNCTION_LITERAL_ARGUMENT + ANNOTATED_EXPRESSION + ANNOTATION_ENTRY + PsiElement(AT)('@') + CONSTRUCTOR_CALLEE + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('f') PsiWhiteSpace(' ') - INTEGER_CONSTANT - PsiElement(INTEGER_LITERAL)('2') - PsiWhiteSpace('\n ') - PsiElement(RBRACE)('}') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + BLOCK + RETURN + PsiElement(return)('return') + PsiWhiteSpace(' ') + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('2') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') PsiWhiteSpace('\n\n ') RETURN PsiElement(return)('return') diff --git a/compiler/testData/psi/newLabels/recovery.txt b/compiler/testData/psi/newLabels/recovery.txt index 51c3100ae66..1879cacef8b 100644 --- a/compiler/testData/psi/newLabels/recovery.txt +++ b/compiler/testData/psi/newLabels/recovery.txt @@ -51,8 +51,8 @@ JetFile: recovery.kt PsiElement(IDENTIFIER)('filter') PsiWhiteSpace(' ') FUNCTION_LITERAL_ARGUMENT - LABELED_EXPRESSION - PsiErrorElement:Label must be named + ANNOTATED_EXPRESSION + PsiErrorElement:Expected annotation identifier after '@' PsiElement(AT)('@') PsiWhiteSpace(' ') FUNCTION_LITERAL_EXPRESSION diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 22fe444e609..d574ad5e6b5 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -639,6 +639,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("annotationsOnLambdaAsCallArgument.kt") + public void testAnnotationsOnLambdaAsCallArgument() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/annotationsOnLambdaAsCallArgument.kt"); + doTest(fileName); + } + @TestMetadata("atAnnotationResolve.kt") public void testAtAnnotationResolve() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/annotations/atAnnotationResolve.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java index 74ea19d6b34..586c8af1f2d 100644 --- a/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/parsing/JetParsingTestGenerated.java @@ -651,6 +651,18 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest { doParsingTest(fileName); } + @TestMetadata("lambda.kt") + public void testLambda() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/annotation/lambda.kt"); + doParsingTest(fileName); + } + + @TestMetadata("lambdaRecovery.kt") + public void testLambdaRecovery() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/annotation/lambdaRecovery.kt"); + doParsingTest(fileName); + } + @TestMetadata("ShortAnnotations.kt") public void testShortAnnotations() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/annotation/ShortAnnotations.kt"); diff --git a/grammar/src/expressions.grm b/grammar/src/expressions.grm index de6d4c01dbe..b124b45d8a8 100644 --- a/grammar/src/expressions.grm +++ b/grammar/src/expressions.grm @@ -225,10 +225,13 @@ postfixUnaryOperation ; callSuffix - : typeArguments? valueArguments (labelDefinition? functionLiteral) - : typeArguments (labelDefinition? functionLiteral) + : typeArguments? valueArguments annotatedLambda + : typeArguments annotatedLambda ; +annotatedLambda + : ("@" annotationEntry)* labelDefinition? functionLiteral + memberAccessOperation : "." : "?." : "?" ;