diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/declaration/VariableDefinitions.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/declaration/VariableDefinitions.java index 73f04f469c00..66d1a3d01b2d 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/declaration/VariableDefinitions.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/declaration/VariableDefinitions.java @@ -27,6 +27,7 @@ import org.jetbrains.plugins.groovy.lang.parser.parsing.auxiliary.parameters.Par import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.TupleParse; import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.blocks.OpenOrClosableBlock; import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.AssignmentExpression; +import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.ConditionalExpression; import org.jetbrains.plugins.groovy.lang.parser.parsing.util.ParserUtils; /** diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/AssignmentExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/AssignmentExpression.java index f43fa6498d99..ee983d7bcba7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/AssignmentExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/AssignmentExpression.java @@ -80,12 +80,16 @@ public class AssignmentExpression implements GroovyElementTypes { if (comExprAllowed) { Marker marker = builder.mark(); - if (ExpressionStatement.parse(builder, parser)) { - marker.drop(); - return true; - } - else { - marker.rollbackTo(); + final ExpressionStatement.Result result = ExpressionStatement.parse(builder, parser); + switch (result) { + case EXPR_STATEMENT: + marker.drop(); + return true; + case EXPRESSION: + ConditionalExpression.parseAfterCondition(builder, parser, marker); + return true; + case WRONG_WAY: + marker.rollbackTo(); } } return ConditionalExpression.parse(builder, parser); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/ConditionalExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/ConditionalExpression.java index b2482ae1bffb..138523b5b8e9 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/ConditionalExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/ConditionalExpression.java @@ -31,32 +31,36 @@ public class ConditionalExpression implements GroovyElementTypes { PsiBuilder.Marker marker = builder.mark(); if (BinaryExpression.parseLogicalExpression(builder, parser)) { - if (ParserUtils.getToken(builder, mQUESTION)) { - ParserUtils.getToken(builder, mNLS); - if (!AssignmentExpression.parse(builder, parser)) { - builder.error(GroovyBundle.message("expression.expected")); - } - if (ParserUtils.getToken(builder, mCOLON, GroovyBundle.message("colon.expected"))) { - ParserUtils.getToken(builder, mNLS); - parse(builder, parser); - } - marker.done(CONDITIONAL_EXPRESSION); - } else if (ParserUtils.getToken(builder, mELVIS)) { - ParserUtils.getToken(builder, mNLS); - if (!parse(builder, parser)) { - builder.error(GroovyBundle.message("expression.expected")); - } - marker.done(ELVIS_EXPRESSION); - } else { - marker.drop(); - } + parseAfterCondition(builder, parser, marker); return true; - } else { + } + else { marker.drop(); return false; } - - } + public static void parseAfterCondition(PsiBuilder builder, GroovyParser parser, PsiBuilder.Marker marker) { + if (ParserUtils.getToken(builder, mQUESTION)) { + ParserUtils.getToken(builder, mNLS); + if (!AssignmentExpression.parse(builder, parser)) { + builder.error(GroovyBundle.message("expression.expected")); + } + if (ParserUtils.getToken(builder, mCOLON, GroovyBundle.message("colon.expected"))) { + ParserUtils.getToken(builder, mNLS); + parse(builder, parser); + } + marker.done(CONDITIONAL_EXPRESSION); + } + else if (ParserUtils.getToken(builder, mELVIS)) { + ParserUtils.getToken(builder, mNLS); + if (!parse(builder, parser)) { + builder.error(GroovyBundle.message("expression.expected")); + } + marker.done(ELVIS_EXPRESSION); + } + else { + marker.drop(); + } + } } \ No newline at end of file diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/ExpressionStatement.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/ExpressionStatement.java index 05ca516a27ff..a67f3e3b94f4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/ExpressionStatement.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/ExpressionStatement.java @@ -18,7 +18,6 @@ package org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions; import com.intellij.lang.PsiBuilder; import com.intellij.psi.tree.IElementType; -import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.lexer.GroovyElementType; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.parser.GroovyParser; @@ -42,7 +41,6 @@ import static org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expres */ public class ExpressionStatement implements GroovyElementTypes { - @Nullable private static IElementType parseExpressionStatement(PsiBuilder builder, GroovyParser parser) { if (checkForTypeCast(builder, parser)) return CAST_EXPRESSION; PsiBuilder.Marker marker = builder.mark(); @@ -78,15 +76,21 @@ public class ExpressionStatement implements GroovyElementTypes { return AssignmentExpression.parse(builder, parser); } - public static boolean parse(PsiBuilder builder, GroovyParser parser) { + enum Result { + WRONG_WAY, EXPR_STATEMENT, EXPRESSION + } + + public static Result parse(PsiBuilder builder, GroovyParser parser) { PsiBuilder.Marker marker = builder.mark(); final IElementType result = parseExpressionStatement(builder, parser); if (result != CALL_EXPRESSION && result != PATH_METHOD_CALL) { marker.drop(); - return result != WRONGWAY; + return result == WRONGWAY ? Result.WRONG_WAY : Result.EXPRESSION; } + boolean isExprStatement = result == CALL_EXPRESSION; + while (true) { boolean nameParsed = namePartParse(builder, parser) == REFERENCE_EXPRESSION; @@ -123,6 +127,7 @@ public class ExpressionStatement implements GroovyElementTypes { exprStatement.done(PATH_METHOD_CALL); } else if (nameParsed && CommandArguments.parseCommandArguments(builder, parser)) { + isExprStatement = true; exprStatement.done(CALL_EXPRESSION); } else { @@ -133,7 +138,7 @@ public class ExpressionStatement implements GroovyElementTypes { marker = exprStatement.precede(); } - return true; + return isExprStatement ? Result.EXPR_STATEMENT : Result.EXPRESSION; } private static GroovyElementType namePartParse(PsiBuilder builder, GroovyParser parser) { diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/StatementsParsingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/StatementsParsingTest.groovy index 8e212ef6bb03..2d4f42bb7635 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/StatementsParsingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/StatementsParsingTest.groovy @@ -45,6 +45,10 @@ public class StatementsParsingTest extends GroovyParsingTestCase { public void testDeclaration$decl9() throws Throwable { doTest(); } public void testDeclaration$decl12() throws Throwable { doTest(); } public void testDeclaration$decl13() throws Throwable { doTest(); } + public void testDeclaration$exprStatement() throws Throwable { doTest(); } + public void testDeclaration$conditional1() throws Throwable { doTest(); } + public void testDeclaration$conditional2() throws Throwable { doTest(); } + public void testDeclaration$conditional3() throws Throwable { doTest(); } public void testDeclaration$dollar() throws Throwable {doTest();} public void testDeclaration$groovyMain() throws Throwable { doTest(); } diff --git a/plugins/groovy/testdata/parsing/groovy/statements/declaration/conditional1.test b/plugins/groovy/testdata/parsing/groovy/statements/declaration/conditional1.test new file mode 100644 index 000000000000..b22462e07537 --- /dev/null +++ b/plugins/groovy/testdata/parsing/groovy/statements/declaration/conditional1.test @@ -0,0 +1,28 @@ +def a = foo() ? bar: test +----- +Groovy script + Variable definitions + Modifiers + PsiElement(def)('def') + PsiWhiteSpace(' ') + Variable + PsiElement(identifier)('a') + PsiWhiteSpace(' ') + PsiElement(=)('=') + PsiWhiteSpace(' ') + Conditional expression + Method call + Reference expression + PsiElement(identifier)('foo') + Arguments + PsiElement(()('(') + PsiElement())(')') + PsiWhiteSpace(' ') + PsiElement(?)('?') + PsiWhiteSpace(' ') + Reference expression + PsiElement(identifier)('bar') + PsiElement(:)(':') + PsiWhiteSpace(' ') + Reference expression + PsiElement(identifier)('test') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/statements/declaration/conditional2.test b/plugins/groovy/testdata/parsing/groovy/statements/declaration/conditional2.test new file mode 100644 index 000000000000..18fdcc22d4ee --- /dev/null +++ b/plugins/groovy/testdata/parsing/groovy/statements/declaration/conditional2.test @@ -0,0 +1,20 @@ +def a = foo ?: test +----- +Groovy script + Variable definitions + Modifiers + PsiElement(def)('def') + PsiWhiteSpace(' ') + Variable + PsiElement(identifier)('a') + PsiWhiteSpace(' ') + PsiElement(=)('=') + PsiWhiteSpace(' ') + Elvis expression + Reference expression + PsiElement(identifier)('foo') + PsiWhiteSpace(' ') + PsiElement(?:)('?:') + PsiWhiteSpace(' ') + Reference expression + PsiElement(identifier)('test') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/statements/declaration/conditional3.test b/plugins/groovy/testdata/parsing/groovy/statements/declaration/conditional3.test new file mode 100644 index 000000000000..105c6c05c65d --- /dev/null +++ b/plugins/groovy/testdata/parsing/groovy/statements/declaration/conditional3.test @@ -0,0 +1,45 @@ +def a = foo(1, 2).bar().test ? ab : c +----- +Groovy script + Variable definitions + Modifiers + PsiElement(def)('def') + PsiWhiteSpace(' ') + Variable + PsiElement(identifier)('a') + PsiWhiteSpace(' ') + PsiElement(=)('=') + PsiWhiteSpace(' ') + Conditional expression + Reference expression + Method call + Reference expression + Method call + Reference expression + PsiElement(identifier)('foo') + Arguments + PsiElement(()('(') + Literal + PsiElement(Integer)('1') + PsiElement(,)(',') + PsiWhiteSpace(' ') + Literal + PsiElement(Integer)('2') + PsiElement())(')') + PsiElement(.)('.') + PsiElement(identifier)('bar') + Arguments + PsiElement(()('(') + PsiElement())(')') + PsiElement(.)('.') + PsiElement(identifier)('test') + PsiWhiteSpace(' ') + PsiElement(?)('?') + PsiWhiteSpace(' ') + Reference expression + PsiElement(identifier)('ab') + PsiWhiteSpace(' ') + PsiElement(:)(':') + PsiWhiteSpace(' ') + Reference expression + PsiElement(identifier)('c') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/statements/declaration/exprStatement.test b/plugins/groovy/testdata/parsing/groovy/statements/declaration/exprStatement.test new file mode 100644 index 000000000000..d2dcb4fca43e --- /dev/null +++ b/plugins/groovy/testdata/parsing/groovy/statements/declaration/exprStatement.test @@ -0,0 +1,34 @@ +def a = foo 1, 2 bar 4 foo +----- +Groovy script + Variable definitions + Modifiers + PsiElement(def)('def') + PsiWhiteSpace(' ') + Variable + PsiElement(identifier)('a') + PsiWhiteSpace(' ') + PsiElement(=)('=') + PsiWhiteSpace(' ') + Reference expression + Call expression + Reference expression + Call expression + Reference expression + PsiElement(identifier)('foo') + PsiWhiteSpace(' ') + Command arguments + Literal + PsiElement(Integer)('1') + PsiElement(,)(',') + PsiWhiteSpace(' ') + Literal + PsiElement(Integer)('2') + PsiWhiteSpace(' ') + PsiElement(identifier)('bar') + PsiWhiteSpace(' ') + Command arguments + Literal + PsiElement(Integer)('4') + PsiWhiteSpace(' ') + PsiElement(identifier)('foo') \ No newline at end of file