From 43cb44579a451c3820cf08a4c9daa9ea6db67613 Mon Sep 17 00:00:00 2001 From: Daniil Ovchinnikov Date: Tue, 20 Sep 2016 21:14:54 +0300 Subject: [PATCH] [groovy] parse keywords as part of fqn (IDEA-134006) --- .../groovy/lang/parser/GroovyParser.java | 8 ++++ .../arithmetic/PathExpression.java | 8 +++- .../primary/PrimaryExpression.java | 16 ++++++-- .../lang/parser/parsing/types/TypeSpec.java | 4 +- .../lang/parser/ExpressionsParsingTest.groovy | 2 + .../lang/parser/StatementsParsingTest.groovy | 2 + .../groovy/expressions/references/ref9.test | 24 ++++++++++++ .../groovy/statements/vardef/vardef4.test | 38 +++++++++++++++++++ 8 files changed, 95 insertions(+), 7 deletions(-) create mode 100644 plugins/groovy/testdata/parsing/groovy/expressions/references/ref9.test create mode 100644 plugins/groovy/testdata/parsing/groovy/statements/vardef/vardef4.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 54ee0df2c705..e43ba7051d3e 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,6 +34,7 @@ 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; @@ -398,6 +399,13 @@ 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/statements/expressions/arithmetic/PathExpression.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/PathExpression.java index 23310a517711..4d6daadf20d0 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/PathExpression.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/PathExpression.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. @@ -103,7 +103,7 @@ public class PathExpression { // Property reference - if (DOTS.contains(builder.getTokenType()) || ParserUtils.lookAhead(builder, GroovyTokenTypes.mNLS, GroovyTokenTypes.mDOT)) { + if (isQualicationDot(builder)) { if (ParserUtils.lookAhead(builder, GroovyTokenTypes.mNLS, GroovyTokenTypes.mDOT)) { ParserUtils.getToken(builder, GroovyTokenTypes.mNLS); } @@ -143,6 +143,10 @@ public class PathExpression { } } + public static boolean isQualicationDot(@NotNull PsiBuilder builder) { + return DOTS.contains(builder.getTokenType()) || ParserUtils.lookAhead(builder, GroovyTokenTypes.mNLS, GroovyTokenTypes.mDOT); + } + @NotNull private static Result parseAfterReference(@NotNull PsiBuilder builder, @NotNull GroovyParser parser, @NotNull PsiBuilder.Marker newMarker) { if (checkForLCurly(builder)) { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/primary/PrimaryExpression.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/primary/PrimaryExpression.java index fb86c2c25515..11d462c74deb 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/primary/PrimaryExpression.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/primary/PrimaryExpression.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. @@ -27,6 +27,7 @@ import org.jetbrains.plugins.groovy.lang.parser.GroovyParser; 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.arguments.ArgumentList; +import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.expressions.arithmetic.PathExpression; import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.typeDefinitions.ReferenceElement; import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.typeDefinitions.TypeDefinition; import org.jetbrains.plugins.groovy.lang.parser.parsing.types.TypeArguments; @@ -55,8 +56,17 @@ public class PrimaryExpression { return type; } if (GroovyTokenTypes.mIDENT == tokenType || GroovyTokenTypes.kSUPER == tokenType || GroovyTokenTypes.kTHIS == tokenType) { - ParserUtils.eatElement(builder, GroovyElementTypes.REFERENCE_EXPRESSION); - return GroovyElementTypes.REFERENCE_EXPRESSION; + return ParserUtils.eatElement(builder, GroovyElementTypes.REFERENCE_EXPRESSION); + } + if (TokenSets.CODE_REFERENCE_ELEMENT_NAME_TOKENS.contains(tokenType)) { + PsiBuilder.Marker marker = builder.mark(); + builder.advanceLexer(); + if (PathExpression.isQualicationDot(builder)) { + marker.done(GroovyElementTypes.REFERENCE_EXPRESSION); + return GroovyElementTypes.REFERENCE_EXPRESSION; + } else { + marker.rollbackTo(); + } } if (GroovyTokenTypes.mGSTRING_BEGIN == tokenType) { final boolean result = CompoundStringExpression.parse(builder, parser, false, GroovyTokenTypes.mGSTRING_BEGIN, diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/types/TypeSpec.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/types/TypeSpec.java index 89b7655d7ec9..65c3e87da06e 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/types/TypeSpec.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/parser/parsing/types/TypeSpec.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. @@ -37,7 +37,7 @@ public class TypeSpec { if (TokenSets.BUILT_IN_TYPES.contains(builder.getTokenType())) { return parseBuiltInType(builder); } - if (builder.getTokenType() == GroovyTokenTypes.mIDENT) { + if (TokenSets.CODE_REFERENCE_ELEMENT_NAME_TOKENS.contains(builder.getTokenType())) { return parseClassType(builder, isUpper, expressionPossible); } return ReferenceElement.ReferenceElementResult.FAIL; diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/ExpressionsParsingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/ExpressionsParsingTest.groovy index 8b4307d4cfec..c8b52521cb0d 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/ExpressionsParsingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/ExpressionsParsingTest.groovy @@ -264,6 +264,8 @@ class ExpressionsParsingTest extends GroovyParsingTestCase { void testreferences$ref8() throws Throwable { doTest(); } + void testreferences$ref9() throws Throwable { doTest(); } + void testreferences$emptyTypeArgs() { doTest() } void testregex$chen() throws Throwable { doTest(); } 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 c38f4951ba1f..de7fe6abb3bd 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 @@ -407,6 +407,8 @@ class StatementsParsingTest extends GroovyParsingTestCase { void testVardef$vardef3() throws Throwable { doTest(); } + void testVardef$vardef4() throws Throwable { doTest(); } + void testVardef$vardeferr() throws Throwable { doTest(); } void testVardef$vardeferrsingle4() throws Throwable { doTest(); } diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/references/ref9.test b/plugins/groovy/testdata/parsing/groovy/expressions/references/ref9.test new file mode 100644 index 000000000000..e8d19edef995 --- /dev/null +++ b/plugins/groovy/testdata/parsing/groovy/expressions/references/ref9.test @@ -0,0 +1,24 @@ +in.com.foo.Bar +def.baz.Foo +----- +Groovy script + Reference expression + Reference expression + Reference expression + Reference expression + PsiElement(in)('in') + PsiElement(.)('.') + PsiElement(identifier)('com') + PsiElement(.)('.') + PsiElement(identifier)('foo') + PsiElement(.)('.') + PsiElement(identifier)('Bar') + PsiElement(new line)('\n') + Reference expression + Reference expression + Reference expression + PsiElement(def)('def') + PsiElement(.)('.') + PsiElement(identifier)('baz') + PsiElement(.)('.') + PsiElement(identifier)('Foo') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/statements/vardef/vardef4.test b/plugins/groovy/testdata/parsing/groovy/statements/vardef/vardef4.test new file mode 100644 index 000000000000..8fa67bdf7d5a --- /dev/null +++ b/plugins/groovy/testdata/parsing/groovy/statements/vardef/vardef4.test @@ -0,0 +1,38 @@ +in.com.foo.Bar a +def.baz.Foo b +----- +Groovy script + Variable definitions + Modifiers + + Type element + Reference element + Reference element + Reference element + Reference element + PsiElement(in)('in') + PsiElement(.)('.') + PsiElement(identifier)('com') + PsiElement(.)('.') + PsiElement(identifier)('foo') + PsiElement(.)('.') + PsiElement(identifier)('Bar') + PsiWhiteSpace(' ') + Variable + PsiElement(identifier)('a') + PsiElement(new line)('\n') + Variable definitions + Modifiers + + Type element + Reference element + Reference element + Reference element + PsiElement(def)('def') + PsiElement(.)('.') + PsiElement(identifier)('baz') + PsiElement(.)('.') + PsiElement(identifier)('Foo') + PsiWhiteSpace(' ') + Variable + PsiElement(identifier)('b') \ No newline at end of file