From 900143af5b90336f02f898a937fdc084fbff1be1 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Wed, 6 Jul 2011 20:21:22 +0400 Subject: [PATCH] JET-172 Allow many parameters of a function literals to be declared without parentheses --- grammar/src/expressions.grm | 2 +- .../lang/parsing/JetExpressionParsing.java | 38 ++++++++++++------- .../jet/plugin/annotations/JetPsiChecker.java | 4 +- idea/testData/psi/FunctionLiterals.jet | 2 + idea/testData/psi/FunctionLiterals.txt | 18 +++++++++ idea/testData/psi/FunctionLiterals_ERR.jet | 1 - idea/testData/psi/FunctionLiterals_ERR.txt | 23 ++--------- 7 files changed, 52 insertions(+), 36 deletions(-) diff --git a/grammar/src/expressions.grm b/grammar/src/expressions.grm index 04896c9eeb4..f795fd5259c 100644 --- a/grammar/src/expressions.grm +++ b/grammar/src/expressions.grm @@ -245,7 +245,7 @@ tupleLiteral // one can use "it" as a parameter name functionLiteral : "{" statements "}" - : "{" (type ".")? modifiers SimpleName "=>" statements "}" + : "{" (modifiers SimpleName){","} "=>" statements "}" : "{" (type ".")? "(" (modifiers SimpleName (":" type)?){","} ")" (":" type)? "=>" statements "}" ; diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index 39252c64f51..2cf2182da74 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -987,7 +987,7 @@ public class JetExpressionParsing extends AbstractJetParsing { /* * functionLiteral // one can use "it" as a parameter name * : "{" expressions "}" - * : "{" (type ".")? modifiers SimpleName "=>" expressions "}" + * : "{" (modifiers SimpleName){","} "=>" statements "}" * : "{" (type ".")? "(" (modifiers SimpleName (":" type)?){","} ")" (":" type)? "=>" expressions "}" * ; */ @@ -1038,27 +1038,37 @@ public class JetExpressionParsing extends AbstractJetParsing { advance(); // COLON if (at(DOUBLE_ARROW)) { error("Expecting a type"); - } else { + } + else { myJetParsing.parseTypeRef(); } } - } else if (!dontExpectParameters) { + } + else if (!dontExpectParameters) { PsiBuilder.Marker parameterList = mark(); - PsiBuilder.Marker parameter = mark(); - int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtOffset(doubleArrowPos))); - createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST); + while (!eof()) { + PsiBuilder.Marker parameter = mark(); + int parameterNamePos = matchTokenStreamPredicate(new LastBefore(new At(IDENTIFIER), new AtOffset(doubleArrowPos))); - expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(DOUBLE_ARROW)); + createTruncatedBuilder(parameterNamePos).parseModifierList(MODIFIER_LIST); - parameter.done(VALUE_PARAMETER); + expect(IDENTIFIER, "Expecting parameter name", TokenSet.create(DOUBLE_ARROW)); - if (at(COLON)) { - errorUntilOffset("To specify a type of a parameter or a return type, use the full notation: {(parameter : Type) : ReturnType => ...}", doubleArrowPos); - } else if (at(COMMA)) { - errorUntilOffset("To specify many parameters, use the full notation: {(p1, p2, ...) => ...}", doubleArrowPos); - } else if (!at(DOUBLE_ARROW)) { - errorUntilOffset("Expecting '=>'", doubleArrowPos); + parameter.done(VALUE_PARAMETER); + + if (at(COLON)) { + errorUntilOffset("To specify a type of a parameter or a return type, use the full notation: {(parameter : Type) : ReturnType => ...}", doubleArrowPos); + } + else if (at(DOUBLE_ARROW)) { + break; + } + else if (!at(COMMA)) { + errorUntilOffset("Expecting '=>' or ','", doubleArrowPos); + } + else { + advance(); // COMMA + } } parameterList.done(VALUE_PARAMETER_LIST); diff --git a/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java b/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java index ddeb88d09de..0cf5d8bdf25 100644 --- a/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java +++ b/idea/src/org/jetbrains/jet/plugin/annotations/JetPsiChecker.java @@ -77,7 +77,9 @@ public class JetPsiChecker implements Annotator { if (!redeclarations.add(redeclaration)) return; PsiElement declarationPsiElement = bindingContext.getDeclarationPsiElement(redeclaration); if (declarationPsiElement instanceof JetNamedDeclaration) { - holder.createErrorAnnotation(((JetNamedDeclaration) declarationPsiElement).getNameIdentifier(), "Redeclaration"); + PsiElement nameIdentifier = ((JetNamedDeclaration) declarationPsiElement).getNameIdentifier(); + assert nameIdentifier != null : declarationPsiElement.getText() + " has nameIdentifier 'null'"; + holder.createErrorAnnotation(nameIdentifier, "Redeclaration"); } else if (declarationPsiElement != null) { holder.createErrorAnnotation(declarationPsiElement, "Redeclaration"); diff --git a/idea/testData/psi/FunctionLiterals.jet b/idea/testData/psi/FunctionLiterals.jet index 92f389fa1eb..ec6e34c6aa5 100644 --- a/idea/testData/psi/FunctionLiterals.jet +++ b/idea/testData/psi/FunctionLiterals.jet @@ -24,4 +24,6 @@ fun foo() { {T.(a : A) => a} {T.(a : A) : T => a} {T.(a) : T => a} + + {x, y => 1} } diff --git a/idea/testData/psi/FunctionLiterals.txt b/idea/testData/psi/FunctionLiterals.txt index 4601d8d3472..05249115e0b 100644 --- a/idea/testData/psi/FunctionLiterals.txt +++ b/idea/testData/psi/FunctionLiterals.txt @@ -435,5 +435,23 @@ JetFile: FunctionLiterals.jet REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('a') PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + FUNCTION_LITERAL_EXPRESSION + FUNCTION_LITERAL + PsiElement(LBRACE)('{') + VALUE_PARAMETER_LIST + VALUE_PARAMETER + PsiElement(IDENTIFIER)('x') + PsiElement(COMMA)(',') + PsiWhiteSpace(' ') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('y') + PsiWhiteSpace(' ') + PsiElement(DOUBLE_ARROW)('=>') + PsiWhiteSpace(' ') + BLOCK + INTEGER_CONSTANT + PsiElement(INTEGER_LITERAL)('1') + PsiElement(RBRACE)('}') PsiWhiteSpace('\n') PsiElement(RBRACE)('}') \ No newline at end of file diff --git a/idea/testData/psi/FunctionLiterals_ERR.jet b/idea/testData/psi/FunctionLiterals_ERR.jet index 54ecc770b99..e0fb54a1dc0 100644 --- a/idea/testData/psi/FunctionLiterals_ERR.jet +++ b/idea/testData/psi/FunctionLiterals_ERR.jet @@ -1,6 +1,5 @@ fun foo() { { => a} - {a, b => a} {(a => a} {(a : ) => a} diff --git a/idea/testData/psi/FunctionLiterals_ERR.txt b/idea/testData/psi/FunctionLiterals_ERR.txt index c14df9c9553..846d93a7a81 100644 --- a/idea/testData/psi/FunctionLiterals_ERR.txt +++ b/idea/testData/psi/FunctionLiterals_ERR.txt @@ -25,24 +25,6 @@ JetFile: FunctionLiterals_ERR.jet REFERENCE_EXPRESSION PsiElement(IDENTIFIER)('a') PsiElement(RBRACE)('}') - PsiWhiteSpace('\n ') - FUNCTION_LITERAL_EXPRESSION - FUNCTION_LITERAL - PsiElement(LBRACE)('{') - VALUE_PARAMETER_LIST - VALUE_PARAMETER - PsiElement(IDENTIFIER)('a') - PsiErrorElement:To specify many parameters, use the full notation: {(p1, p2, ...) => ...} - PsiElement(COMMA)(',') - PsiWhiteSpace(' ') - PsiElement(IDENTIFIER)('b') - PsiWhiteSpace(' ') - PsiElement(DOUBLE_ARROW)('=>') - PsiWhiteSpace(' ') - BLOCK - REFERENCE_EXPRESSION - PsiElement(IDENTIFIER)('a') - PsiElement(RBRACE)('}') PsiWhiteSpace('\n\n ') FUNCTION_LITERAL_EXPRESSION FUNCTION_LITERAL @@ -297,7 +279,10 @@ JetFile: FunctionLiterals_ERR.jet PsiElement(COLON)(':') PsiWhiteSpace(' ') PsiElement(IDENTIFIER)('b') - PsiWhiteSpace(' ') + PsiWhiteSpace(' ') + VALUE_PARAMETER + PsiErrorElement:Expecting parameter name + PsiElement(DOUBLE_ARROW)('=>') PsiWhiteSpace(' ') BLOCK