[groovy] parse keywords as part of fqn (IDEA-134006)

This commit is contained in:
Daniil Ovchinnikov
2016-09-20 21:42:29 +03:00
parent 68d7db3dd3
commit 43cb44579a
8 changed files with 95 additions and 7 deletions
@@ -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);
@@ -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)) {
@@ -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,
@@ -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;
@@ -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(); }
@@ -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(); }
@@ -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')
@@ -0,0 +1,38 @@
in.com.foo.Bar a
def.baz.Foo b
-----
Groovy script
Variable definitions
Modifiers
<empty list>
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
<empty list>
Type element
Reference element
Reference element
Reference element
PsiElement(def)('def')
PsiElement(.)('.')
PsiElement(identifier)('baz')
PsiElement(.)('.')
PsiElement(identifier)('Foo')
PsiWhiteSpace(' ')
Variable
PsiElement(identifier)('b')