From 75a51d915f588dbf3a2ab56fd53a68b3e7ffdbd2 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Thu, 15 Sep 2016 11:39:11 +0300 Subject: [PATCH] Implement parsing of desctructuring declarations in lambdas #KT-5828 In Progress --- .../parsing/KotlinExpressionParsing.java | 15 +- .../kotlin/parsing/KotlinParsing.java | 2 +- compiler/testData/psi/FunctionLiterals_ERR.kt | 15 +- .../testData/psi/FunctionLiterals_ERR.txt | 551 ++++++------------ .../testData/psi/destructuringInLambdas.kt | 10 + .../testData/psi/destructuringInLambdas.txt | 309 ++++++++++ .../psi/destructuringInLambdas_ERR.kt | 5 + .../psi/destructuringInLambdas_ERR.txt | 138 +++++ .../kotlin/parsing/ParsingTestGenerated.java | 12 + grammar/src/expressions.grm | 7 +- 10 files changed, 673 insertions(+), 391 deletions(-) create mode 100644 compiler/testData/psi/destructuringInLambdas.kt create mode 100644 compiler/testData/psi/destructuringInLambdas.txt create mode 100644 compiler/testData/psi/destructuringInLambdas_ERR.kt create mode 100644 compiler/testData/psi/destructuringInLambdas_ERR.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinExpressionParsing.java b/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinExpressionParsing.java index cda0e831712..0f16228b62e 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinExpressionParsing.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinExpressionParsing.java @@ -45,6 +45,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing { private static final IElementType[] LOCAL_DECLARATION_FIRST = new IElementType[] {CLASS_KEYWORD, INTERFACE_KEYWORD, FUN_KEYWORD, VAL_KEYWORD, VAR_KEYWORD, TYPE_ALIAS_KEYWORD}; + private static final TokenSet TOKEN_SET_TO_FOLLOW_AFTER_DESTRUCTURING_DECLARATION_IN_LAMBDA = TokenSet.create(ARROW, COMMA, COLON); private static ImmutableMap tokenSetToMap(TokenSet tokens) { ImmutableMap.Builder builder = ImmutableMap.builder(); @@ -1054,10 +1055,11 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing { advance(); // ARROW paramsFound = true; } - else if (at(IDENTIFIER) || at(COLON)) { + else if (at(IDENTIFIER) || at(COLON) || at(LPAR)) { // Try to parse a simple name list followed by an ARROW // {a -> ...} // {a, b -> ...} + // {(a, b) -> ... } PsiBuilder.Marker rollbackMarker = mark(); IElementType nextToken = lookahead(1); boolean preferParamsToExpressions = (nextToken == COMMA || nextToken == COLON); @@ -1144,7 +1146,11 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing { /* - * (SimpleName (":" type)?){","} + * lambdaParameter{","} + * + * lambdaParameter + * : variableDeclarationEntry + * : multipleVariableDeclarations (":" type)? */ private void parseFunctionLiteralParameterList() { PsiBuilder.Marker parameterList = mark(); @@ -1155,6 +1161,11 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing { if (at(COLON)) { error("Expecting parameter name"); } + else if (at(LPAR)) { + PsiBuilder.Marker destructuringDeclaration = mark(); + myKotlinParsing.parseMultiDeclarationName(TOKEN_SET_TO_FOLLOW_AFTER_DESTRUCTURING_DECLARATION_IN_LAMBDA); + destructuringDeclaration.done(DESTRUCTURING_DECLARATION); + } else { expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(ARROW)); } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java b/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java index cdc561bc844..c323364a8f4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/parsing/KotlinParsing.java @@ -1325,7 +1325,7 @@ public class KotlinParsing extends AbstractKotlinParsing { } /* - * (SimpleName (":" type)){","} + * (SimpleName (":" type){","}) */ public void parseMultiDeclarationName(TokenSet follow) { // Parsing multi-name, e.g. diff --git a/compiler/testData/psi/FunctionLiterals_ERR.kt b/compiler/testData/psi/FunctionLiterals_ERR.kt index 1efe41c4736..0337f3de9f8 100644 --- a/compiler/testData/psi/FunctionLiterals_ERR.kt +++ b/compiler/testData/psi/FunctionLiterals_ERR.kt @@ -3,8 +3,6 @@ fun foo() { {(a -> a} {(a : ) -> a} - {(a : A) : -> a} - {(a) : T -> } {(a, ) -> a} {(a : A, , a : B) -> a} @@ -28,17 +26,6 @@ fun foo() { {(a: Int, )} {a, } - {(a) -> a} - {(a : A) -> a} - - {(a : A) : T -> a} - {(a) : T -> a} - - {(a, a) -> a} - {(a : A, a : B) -> a} - {(a : A, a) : T -> a} - {(a, a : B) : T -> a} - {() -> a} {() -> a} {() : T -> a} @@ -54,4 +41,4 @@ fun foo() { {((a: Int = object { fun t() {} }) -> Int).(x: Int) : String -> "" } { A.B.(x: Int) -> } {((a: Boolean = true) -> Int).(x: Any) : Unit -> } -} \ No newline at end of file +} diff --git a/compiler/testData/psi/FunctionLiterals_ERR.txt b/compiler/testData/psi/FunctionLiterals_ERR.txt index c3d72c4389e..5e328ebcf6a 100644 --- a/compiler/testData/psi/FunctionLiterals_ERR.txt +++ b/compiler/testData/psi/FunctionLiterals_ERR.txt @@ -30,165 +30,148 @@ JetFile: FunctionLiterals_ERR.kt LAMBDA_EXPRESSION FUNCTION_LITERAL PsiElement(LBRACE)('{') - BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiErrorElement:Expecting ')' - - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACE)('}') - PsiWhiteSpace('\n ') - LAMBDA_EXPRESSION - FUNCTION_LITERAL - PsiElement(LBRACE)('{') - BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiErrorElement:Expecting ')' - - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACE)('}') - PsiWhiteSpace('\n ') - LAMBDA_EXPRESSION - FUNCTION_LITERAL - PsiElement(LBRACE)('{') - BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiErrorElement:Expecting ')' - - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('A') - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACE)('}') - PsiWhiteSpace('\n ') - LAMBDA_EXPRESSION - FUNCTION_LITERAL - PsiElement(LBRACE)('{') - BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('T') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiErrorElement:Expecting ')' + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + BLOCK + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + LAMBDA_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + PsiErrorElement:Type expected + + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + BLOCK + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a') PsiElement(RBRACE)('}') PsiWhiteSpace('\n\n ') LAMBDA_EXPRESSION FUNCTION_LITERAL PsiElement(LBRACE)('{') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(COMMA)(',') + PsiErrorElement:Expecting a name + + PsiWhiteSpace(' ') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiErrorElement:Expecting ')' - - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(COMMA)(',') - PsiWhiteSpace(' ') - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') + REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('a') PsiElement(RBRACE)('}') PsiWhiteSpace('\n ') LAMBDA_EXPRESSION FUNCTION_LITERAL PsiElement(LBRACE)('{') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('A') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + PsiErrorElement:Expecting a name + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('B') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiErrorElement:Expecting ')' - - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('A') - PsiElement(COMMA)(',') - PsiWhiteSpace(' ') - PsiElement(COMMA)(',') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiWhiteSpace(' ') - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('B') - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') + REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('a') PsiElement(RBRACE)('}') PsiWhiteSpace('\n ') LAMBDA_EXPRESSION FUNCTION_LITERAL PsiElement(LBRACE)('{') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('A') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + PsiErrorElement:Expecting a name + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + DESTRUCTURING_DECLARATION_ENTRY + PsiErrorElement:Expecting a name + + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('a') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('T') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiErrorElement:Expecting ')' - - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('A') - PsiElement(COMMA)(',') - PsiWhiteSpace(' ') - PsiElement(COMMA)(',') - PsiWhiteSpace(' ') - PsiElement(COMMA)(',') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('T') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') + REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('a') PsiElement(RBRACE)('}') PsiWhiteSpace('\n\n ') @@ -475,264 +458,86 @@ JetFile: FunctionLiterals_ERR.kt LAMBDA_EXPRESSION FUNCTION_LITERAL PsiElement(LBRACE)('{') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + PsiErrorElement:Expecting a name + + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') + REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('a') PsiElement(RBRACE)('}') PsiWhiteSpace('\n ') LAMBDA_EXPRESSION FUNCTION_LITERAL PsiElement(LBRACE)('{') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + PsiErrorElement:Expecting a name + + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiErrorElement:Expecting ')' - - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('A') - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACE)('}') - PsiWhiteSpace('\n\n ') - LAMBDA_EXPRESSION - FUNCTION_LITERAL - PsiElement(LBRACE)('{') - BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiErrorElement:Expecting ')' - - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('A') - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('T') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') + REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('a') PsiElement(RBRACE)('}') PsiWhiteSpace('\n ') LAMBDA_EXPRESSION FUNCTION_LITERAL PsiElement(LBRACE)('{') - BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) + VALUE_PARAMETER_LIST + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + PsiErrorElement:Expecting a name + + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') PsiElement(COLON)(':') PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('T') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACE)('}') - PsiWhiteSpace('\n\n ') - LAMBDA_EXPRESSION - FUNCTION_LITERAL - PsiElement(LBRACE)('{') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('T') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiErrorElement:Expecting ')' - - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(COMMA)(',') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') + REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('a') PsiElement(RBRACE)('}') PsiWhiteSpace('\n ') LAMBDA_EXPRESSION FUNCTION_LITERAL PsiElement(LBRACE)('{') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + PsiErrorElement:Expecting a name + + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('T') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiErrorElement:Expecting ')' - - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('A') - PsiElement(COMMA)(',') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiWhiteSpace(' ') - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('B') - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACE)('}') - PsiWhiteSpace('\n ') - LAMBDA_EXPRESSION - FUNCTION_LITERAL - PsiElement(LBRACE)('{') - BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiErrorElement:Expecting ')' - - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('A') - PsiElement(COMMA)(',') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('T') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACE)('}') - PsiWhiteSpace('\n ') - LAMBDA_EXPRESSION - FUNCTION_LITERAL - PsiElement(LBRACE)('{') - BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiErrorElement:Expecting ')' - - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(COMMA)(',') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiWhiteSpace(' ') - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('B') - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('T') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACE)('}') - PsiWhiteSpace('\n\n ') - LAMBDA_EXPRESSION - FUNCTION_LITERAL - PsiElement(LBRACE)('{') - BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - PsiErrorElement:Expecting an expression - - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACE)('}') - PsiWhiteSpace('\n ') - LAMBDA_EXPRESSION - FUNCTION_LITERAL - PsiElement(LBRACE)('{') - BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - PsiErrorElement:Expecting an expression - - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACE)('}') - PsiWhiteSpace('\n ') - LAMBDA_EXPRESSION - FUNCTION_LITERAL - PsiElement(LBRACE)('{') - BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - PsiErrorElement:Expecting an expression - - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('T') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACE)('}') - PsiWhiteSpace('\n ') - LAMBDA_EXPRESSION - FUNCTION_LITERAL - PsiElement(LBRACE)('{') - BLOCK - PARENTHESIZED - PsiElement(LPAR)('(') - PsiErrorElement:Expecting an expression - - PsiElement(RPAR)(')') - PsiWhiteSpace(' ') - PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) - PsiElement(COLON)(':') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('T') - PsiWhiteSpace(' ') - PsiElement(ARROW)('->') - PsiWhiteSpace(' ') + REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('a') PsiElement(RBRACE)('}') PsiWhiteSpace('\n\n ') @@ -1022,4 +827,4 @@ JetFile: FunctionLiterals_ERR.kt PsiWhiteSpace(' ') PsiElement(RBRACE)('}') PsiWhiteSpace('\n') - PsiElement(RBRACE)('}') \ No newline at end of file + PsiElement(RBRACE)('}') diff --git a/compiler/testData/psi/destructuringInLambdas.kt b/compiler/testData/psi/destructuringInLambdas.kt new file mode 100644 index 00000000000..ca21a67de22 --- /dev/null +++ b/compiler/testData/psi/destructuringInLambdas.kt @@ -0,0 +1,10 @@ +fun foo() { + a1.filter { (x, y) -> } + a2.filter { (x) -> } + a3.filter { z, (x, y) -> } + a4.filter { (x, y), z -> } + a5.filter { q, (x, y), z -> } + a6.filter { (x, y), (z, w) -> } + + a7.filter { (x, y): Type, (z: Type), (w, u: T) : V -> foo7() } +} diff --git a/compiler/testData/psi/destructuringInLambdas.txt b/compiler/testData/psi/destructuringInLambdas.txt new file mode 100644 index 00000000000..67fdc228a7a --- /dev/null +++ b/compiler/testData/psi/destructuringInLambdas.txt @@ -0,0 +1,309 @@ +JetFile: destructuringInLambdas.kt + PACKAGE_DIRECTIVE + + IMPORT_LIST + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + DOT_QUALIFIED_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a1') + PsiElement(DOT)('.') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('filter') + PsiWhiteSpace(' ') + LAMBDA_ARGUMENT + LAMBDA_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('x') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('y') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + BLOCK + + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + DOT_QUALIFIED_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a2') + PsiElement(DOT)('.') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('filter') + PsiWhiteSpace(' ') + LAMBDA_ARGUMENT + LAMBDA_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('x') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + BLOCK + + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + DOT_QUALIFIED_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a3') + PsiElement(DOT)('.') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('filter') + PsiWhiteSpace(' ') + LAMBDA_ARGUMENT + LAMBDA_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + PsiElement(IDENTIFIER)('z') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('x') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('y') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + BLOCK + + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + DOT_QUALIFIED_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a4') + PsiElement(DOT)('.') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('filter') + PsiWhiteSpace(' ') + LAMBDA_ARGUMENT + LAMBDA_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('x') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('y') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('z') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + BLOCK + + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + DOT_QUALIFIED_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a5') + PsiElement(DOT)('.') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('filter') + PsiWhiteSpace(' ') + LAMBDA_ARGUMENT + LAMBDA_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + PsiElement(IDENTIFIER)('q') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('x') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('y') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('z') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + BLOCK + + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + DOT_QUALIFIED_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a6') + PsiElement(DOT)('.') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('filter') + PsiWhiteSpace(' ') + LAMBDA_ARGUMENT + LAMBDA_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('x') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('y') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('z') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('w') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + BLOCK + + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + DOT_QUALIFIED_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a7') + PsiElement(DOT)('.') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('filter') + PsiWhiteSpace(' ') + LAMBDA_ARGUMENT + LAMBDA_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('x') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('y') + PsiElement(RPAR)(')') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Type') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('z') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Type') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('w') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('u') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('T') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('V') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + BLOCK + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('foo7') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') diff --git a/compiler/testData/psi/destructuringInLambdas_ERR.kt b/compiler/testData/psi/destructuringInLambdas_ERR.kt new file mode 100644 index 00000000000..01a9626cad0 --- /dev/null +++ b/compiler/testData/psi/destructuringInLambdas_ERR.kt @@ -0,0 +1,5 @@ +fun foo() { + a8.filter { ((x, y), z) -> foo8() } + a9.filter { (x -> foo9() } + a10.filter { (x, y :) : -> foo10() } +} diff --git a/compiler/testData/psi/destructuringInLambdas_ERR.txt b/compiler/testData/psi/destructuringInLambdas_ERR.txt new file mode 100644 index 00000000000..73e9bf4f7d5 --- /dev/null +++ b/compiler/testData/psi/destructuringInLambdas_ERR.txt @@ -0,0 +1,138 @@ +JetFile: destructuringInLambdas_ERR.kt + PACKAGE_DIRECTIVE + + IMPORT_LIST + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + DOT_QUALIFIED_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a8') + PsiElement(DOT)('.') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('filter') + PsiWhiteSpace(' ') + LAMBDA_ARGUMENT + LAMBDA_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace(' ') + BLOCK + PARENTHESIZED + PsiElement(LPAR)('(') + PARENTHESIZED + PsiElement(LPAR)('(') + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('x') + PsiErrorElement:Expecting ')' + + PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line) + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('y') + PsiElement(RPAR)(')') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('z') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('foo8') + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + DOT_QUALIFIED_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a9') + PsiElement(DOT)('.') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('filter') + PsiWhiteSpace(' ') + LAMBDA_ARGUMENT + LAMBDA_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('x') + PsiErrorElement:Expecting ')' + + PsiWhiteSpace(' ') + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + BLOCK + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('foo9') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n ') + DOT_QUALIFIED_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('a10') + PsiElement(DOT)('.') + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('filter') + PsiWhiteSpace(' ') + LAMBDA_ARGUMENT + LAMBDA_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + DESTRUCTURING_DECLARATION + PsiElement(LPAR)('(') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('x') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + DESTRUCTURING_DECLARATION_ENTRY + PsiElement(IDENTIFIER)('y') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + TYPE_REFERENCE + PsiErrorElement:Type expected + + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + PsiErrorElement:Type expected + + PsiElement(ARROW)('->') + PsiWhiteSpace(' ') + BLOCK + CALL_EXPRESSION + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('foo10') + VALUE_ARGUMENT_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/parsing/ParsingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/parsing/ParsingTestGenerated.java index bc03f38f286..bc7332112d8 100644 --- a/compiler/tests/org/jetbrains/kotlin/parsing/ParsingTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/parsing/ParsingTestGenerated.java @@ -145,6 +145,18 @@ public class ParsingTestGenerated extends AbstractParsingTest { doParsingTest(fileName); } + @TestMetadata("destructuringInLambdas.kt") + public void testDestructuringInLambdas() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/destructuringInLambdas.kt"); + doParsingTest(fileName); + } + + @TestMetadata("destructuringInLambdas_ERR.kt") + public void testDestructuringInLambdas_ERR() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/destructuringInLambdas_ERR.kt"); + doParsingTest(fileName); + } + @TestMetadata("DocCommentAfterFileAnnotations.kt") public void testDocCommentAfterFileAnnotations() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/psi/DocCommentAfterFileAnnotations.kt"); diff --git a/grammar/src/expressions.grm b/grammar/src/expressions.grm index 09edf68b597..22d3d72471f 100644 --- a/grammar/src/expressions.grm +++ b/grammar/src/expressions.grm @@ -254,7 +254,12 @@ jump // one can use "it" as a parameter name functionLiteral : "{" statements "}" - : "{" (modifiers SimpleName (":" type)?){","} "->" statements "}" + : "{" lambdaParameter{","} "->" statements "}" + ; + +lambdaParameter + : variableDeclarationEntry + : multipleVariableDeclarations (":" type)? ; statements