From c07b75ed2fe6e0049ea64782ed777586b5bf41b4 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Wed, 21 Sep 2016 15:22:56 +0300 Subject: [PATCH] [groovy] parse modifier list until the subsequent modifier if not a qualifier of some path (follow up IDEA-134006) --- .../groovy/lang/parser/GroovyParser.java | 8 --- .../auxiliary/modifiers/Modifiers.java | 52 ++++++++++--------- .../lang/parser/StatementsParsingTest.groovy | 2 + .../groovy/statements/methods/method6.test | 25 +++++++++ 4 files changed, 54 insertions(+), 33 deletions(-) create mode 100644 plugins/groovy/testdata/parsing/groovy/statements/methods/method6.test diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/GroovyParser.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/GroovyParser.java index e43ba7051d3e..54ee0df2c705 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/GroovyParser.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/GroovyParser.java @@ -34,7 +34,6 @@ import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.declaration.D 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.statements.expressions.ExpressionStatement; -import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.arithmetic.PathExpression; import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.imports.ImportStatement; import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.typeDefinitions.TypeDefinition; import org.jetbrains.plugins.groovy.lang.parser.parsing.toplevel.CompilationUnit; @@ -399,13 +398,6 @@ public class GroovyParser implements PsiParser { PsiBuilder.Marker declMarker = builder.mark(); boolean modifiersParsed = Modifiers.parse(builder, this); - if (modifiersParsed && PathExpression.isQualicationDot(builder)) { - modifiersParsed = false; - declMarker.rollbackTo(); - declMarker = builder.mark(); - builder.mark().done(GroovyElementTypes.MODIFIERS); - } - if (GroovyTokenTypes.kIMPORT == builder.getTokenType()) { final PsiBuilder.Marker impMarker = declMarker.precede(); ImportStatement.parseAfterModifiers(builder); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/modifiers/Modifiers.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/modifiers/Modifiers.java index d54be64bb766..da3d274444d2 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/modifiers/Modifiers.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/modifiers/Modifiers.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.parser.GroovyParser; import org.jetbrains.plugins.groovy.lang.parser.parsing.auxiliary.annotations.Annotation; +import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.arithmetic.PathExpression; import org.jetbrains.plugins.groovy.lang.parser.parsing.util.ParserUtils; /** @@ -30,40 +31,41 @@ import org.jetbrains.plugins.groovy.lang.parser.parsing.util.ParserUtils; */ /* - * Modifiers ::= "def" nls - * | {modifier nls}+ - * | {annotation nls}+ + * Modifiers ::= {modifier|annotation} (nls? {modifier|annotation})+ */ public class Modifiers { public static boolean parse(PsiBuilder builder, GroovyParser parser) { - boolean endsWithNewLine; + PsiBuilder.Marker modifiersMarker = builder.mark(); + boolean hasModifiers = false; - if (!Annotation.parse(builder, parser) && !parseModifier(builder)) { - modifiersMarker.done(GroovyElementTypes.MODIFIERS); - return false; + do { + final PsiBuilder.Marker modifierListItem = builder.mark(); + + if (hasModifiers) ParserUtils.getToken(builder, GroovyTokenTypes.mNLS); + final boolean parsed = Annotation.parse(builder, parser) || parseModifier(builder); + + if (parsed) { + if (PathExpression.isQualicationDot(builder)) { + modifierListItem.rollbackTo(); + break; + } + else { + modifierListItem.drop(); + hasModifiers = true; + } + } + else { + modifierListItem.rollbackTo(); + break; + } } + while (true); - PsiBuilder.Marker newLineMarker = builder.mark(); - while (true) { - newLineMarker.drop(); - newLineMarker = builder.mark(); - endsWithNewLine = ParserUtils.getToken(builder, GroovyTokenTypes.mNLS); - - if (!Annotation.parse(builder, parser) && !parseModifier(builder)) break; - } - - // Do not include last newline - if (endsWithNewLine) { - newLineMarker.rollbackTo(); - } else { - newLineMarker.drop(); - } modifiersMarker.done(GroovyElementTypes.MODIFIERS); ParserUtils.getToken(builder, GroovyTokenTypes.mNLS); - return true; - + return hasModifiers; } public static boolean parseModifier(PsiBuilder builder) { 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 de7fe6abb3bd..394e920894c0 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 @@ -201,6 +201,8 @@ class StatementsParsingTest extends GroovyParsingTestCase { void testMethods$method5() throws Throwable { doTest(); } + void testMethods$method6() throws Throwable { doTest(); } + void testMethods$vararg() throws Throwable { doTest(); } void testMultiple_assign$grvy2086() throws Throwable { doTest("multiple_assign/grvy-2086.test"); } diff --git a/plugins/groovy/testdata/parsing/groovy/statements/methods/method6.test b/plugins/groovy/testdata/parsing/groovy/statements/methods/method6.test new file mode 100644 index 000000000000..7cb17ad39810 --- /dev/null +++ b/plugins/groovy/testdata/parsing/groovy/statements/methods/method6.test @@ -0,0 +1,25 @@ +public def.MyClass foo() {} +----- +Groovy script + Method + Modifiers + PsiElement(public)('public') + PsiWhiteSpace(' ') + Type element + Reference element + Reference element + PsiElement(def)('def') + PsiElement(.)('.') + PsiElement(identifier)('MyClass') + PsiWhiteSpace(' ') + PsiElement(identifier)('foo') + PsiElement(()('(') + Parameter list + + PsiElement())(')') + Throw clause + + PsiWhiteSpace(' ') + Open block + PsiElement({)('{') + PsiElement(})('}') \ No newline at end of file