IDEA-119328 parse code reference elements without name element

This commit is contained in:
Max Medvedev
2014-01-24 16:58:38 +04:00
parent 3c69c63a24
commit eef5c145af
13 changed files with 179 additions and 42 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -100,6 +100,8 @@ public abstract class TokenSets {
public static final TokenSet REFERENCE_NAMES = TokenSet.orSet(KEYWORDS, PROPERTY_NAMES, NUMBERS);
public static final TokenSet REFERENCE_NAMES_WITHOUT_NUMBERS = TokenSet.orSet(KEYWORDS, PROPERTY_NAMES);
public static final TokenSet REFERENCE_NAME_PREFIXES = TokenSet.orSet(NUMBERS, KEYWORDS, TokenSet.create(mIDENT, mSTRING_LITERAL, mGSTRING_LITERAL, mGSTRING_BEGIN, mREGEX_BEGIN, mDOLLAR_SLASH_REGEX_BEGIN, mAT));
public static final TokenSet VISIBILITY_MODIFIERS = TokenSet.create(
kPRIVATE,
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -39,16 +39,16 @@ public class ThrowClause implements GroovyElementTypes {
ParserUtils.getToken(builder, mNLS);
if (ReferenceElement.parseReferenceElement(builder) == FAIL) {
throwClauseMarker.done(THROW_CLAUSE);
if (ReferenceElement.parse(builder, false, true, true, false, false) == FAIL) {
builder.error(GroovyBundle.message("identifier.expected"));
throwClauseMarker.done(THROW_CLAUSE);
return;
}
while (ParserUtils.getToken(builder, mCOMMA)) {
ParserUtils.getToken(builder, mNLS);
if (ReferenceElement.parseReferenceElement(builder) == FAIL) {
if (ReferenceElement.parse(builder, false, true, true, false, false) == FAIL) {
break;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -48,7 +48,7 @@ public class Annotation implements GroovyElementTypes {
return false;
}
if (ReferenceElement.parseReferenceElement(builder) == FAIL) {
if (ReferenceElement.parse(builder, false, true, true, false, false) == FAIL) {
builder.error("Annotation name expected");
annMarker.drop();
return false;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -36,7 +36,9 @@ public class ImportReference implements GroovyElementTypes {
return false;
}
ReferenceElement.parseForImport(builder);
if (ReferenceElement.parseForImport(builder) == ReferenceElement.ReferenceElementResult.FAIL) {
return false;
}
if (ParserUtils.getToken(builder, mDOT)) {
ParserUtils.getToken(builder, mNLS);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -21,6 +21,7 @@ import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyBundle;
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.parser.parsing.types.TypeArguments;
@@ -90,7 +91,7 @@ public class ReferenceElement implements GroovyElementTypes {
}
public enum ReferenceElementResult {
IDENTIFIER, PATH_REF, REF_WITH_TYPE_PARAMS, FAIL
IDENTIFIER, PATH_REF, REF_WITH_TYPE_PARAMS, PATH_REF_WITHOUT_NAME_ELEMENT, FAIL
}
public static ReferenceElementResult parseForImport(@NotNull PsiBuilder builder) {
@@ -98,10 +99,9 @@ public class ReferenceElement implements GroovyElementTypes {
}
public static ReferenceElementResult parseForPackage(@NotNull PsiBuilder builder) {
return parse(builder, false, false, false, false, false);
return parse(builder, false, false, true, false, false);
}
//it doesn't important first letter of identifier of ThrowClause, of Annotation, of new Expression, of implements, extends, superclass clauses
public static ReferenceElementResult parseReferenceElement(@NotNull PsiBuilder builder) {
return parseReferenceElement(builder, false, true);
@@ -114,7 +114,7 @@ public class ReferenceElement implements GroovyElementTypes {
public static ReferenceElementResult parse(@NotNull PsiBuilder builder,
boolean checkUpperCase,
boolean parseTypeArgs,
boolean forImport,
boolean lineFeedAllowed,
boolean allowDiamond,
boolean expressionPossible) {
PsiBuilder.Marker internalTypeMarker = builder.mark();
@@ -127,8 +127,8 @@ public class ReferenceElement implements GroovyElementTypes {
}
boolean hasTypeArguments = false;
if (parseTypeArgs) {
hasTypeArguments = TypeArguments.parseTypeArguments(builder, expressionPossible, allowDiamond);
if (parseTypeArgs && TypeArguments.parseTypeArguments(builder, expressionPossible, allowDiamond)) {
hasTypeArguments = true;
}
internalTypeMarker.done(REFERENCE_ELEMENT);
@@ -138,26 +138,31 @@ public class ReferenceElement implements GroovyElementTypes {
while (builder.getTokenType() == mDOT) {
if ((ParserUtils.lookAhead(builder, mDOT, mSTAR) || ParserUtils.lookAhead(builder, mDOT, mNLS, mSTAR)) && forImport) {
if ((ParserUtils.lookAhead(builder, mDOT, mSTAR) || ParserUtils.lookAhead(builder, mDOT, mNLS, mSTAR)) && lineFeedAllowed) {
internalTypeMarker.drop();
return PATH_REF;
}
ParserUtils.getToken(builder, mDOT);
if (forImport) {
if (lineFeedAllowed) {
ParserUtils.getToken(builder, mNLS);
}
lastIdentifier = builder.getTokenText();
if (!ParserUtils.getToken(builder, TokenSets.CODE_REFERENCE_ELEMENT_NAME_TOKENS)) {
internalTypeMarker.rollbackTo();
return FAIL;
if (TokenSets.REFERENCE_NAME_PREFIXES.contains(builder.getTokenType())) {
internalTypeMarker.rollbackTo();
return FAIL;
}
builder.error(GroovyBundle.message("identifier.expected"));
internalTypeMarker.done(REFERENCE_ELEMENT);
return PATH_REF;
}
if (parseTypeArgs) {
hasTypeArguments = TypeArguments.parseTypeArguments(builder, expressionPossible, allowDiamond) || hasTypeArguments;
if (parseTypeArgs && TypeArguments.parseTypeArguments(builder, expressionPossible, allowDiamond)) {
hasTypeArguments = true;
}
internalTypeMarker.done(REFERENCE_ELEMENT);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -19,13 +19,13 @@ package org.jetbrains.plugins.groovy.lang.parser.parsing.toplevel.packaging;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiBuilder.Marker;
import org.jetbrains.plugins.groovy.GroovyBundle;
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.modifiers.Modifiers;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.typeDefinitions.ReferenceElement;
import org.jetbrains.plugins.groovy.lang.parser.parsing.util.ParserUtils;
import static org.jetbrains.plugins.groovy.lang.parser.parsing.statements.typeDefinitions.ReferenceElement.ReferenceElementResult.FAIL;
/**
* @author ilyas
@@ -42,8 +42,7 @@ public class PackageDefinition implements GroovyElementTypes {
return false;
}
if (!TokenSets.CODE_REFERENCE_ELEMENT_NAME_TOKENS.contains(builder.getTokenType()) ||
ReferenceElement.parseForPackage(builder) == ReferenceElement.ReferenceElementResult.FAIL) {
if (ReferenceElement.parseForPackage(builder) == FAIL) {
builder.error(GroovyBundle.message("identifier.expected"));
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -38,6 +38,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
import org.jetbrains.plugins.groovy.intentions.base.ErrorUtil;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyLexer;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
@@ -1248,8 +1249,7 @@ public class PsiUtil {
public static List<GrImportStatement> getValidImportStatements(final GroovyFile file) {
final List<GrImportStatement> oldImports = new ArrayList<GrImportStatement>();
for (GrImportStatement statement : file.getImportStatements()) {
final GrCodeReferenceElement reference = statement.getImportReference();
if (reference != null && reference.multiResolve(false).length > 0) {
if (!ErrorUtil.containsError(statement)) {
oldImports.add(statement);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -95,6 +95,7 @@ public class StatementsParsingTest extends GroovyParsingTestCase {
public void testImports$imp5() throws Throwable { doTest(); }
public void testImports$imp6() throws Throwable { doTest(); }
public void testImports$imp7() throws Throwable { doTest(); }
public void testImports$imp8() throws Throwable { doTest(); }
public void testKing_regex$king1() throws Throwable { doTest(); }
public void testKing_regex$king2() throws Throwable { doTest(); }
public void testKing_regex$king3() throws Throwable { doTest(); }
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -34,6 +34,8 @@ public class TypesParsingTest extends GroovyParsingTestCase {
public void testType11() throws Throwable { doTest(); }
public void testType12() throws Throwable { doTest(); }
public void testType13() throws Throwable { doTest(); }
public void testType14() throws Throwable { doTest(); }
public void testType15() throws Throwable { doTest(); }
public void testType2() throws Throwable { doTest(); }
public void testType3() throws Throwable { doTest(); }
public void testType4() throws Throwable { doTest(); }
+9 -11
View File
@@ -7,16 +7,14 @@ Groovy script
Modifiers
<empty list>
PsiElement(package)('package')
PsiErrorElement:Identifier expected
<empty list>
PsiWhiteSpace(' ')
Reference expression
Reference expression
Reference expression
PsiElement(identifier)('a')
PsiWhiteSpace(' ')
Reference element
Reference element
Reference element
PsiElement(identifier)('a')
PsiElement(.)('.')
PsiElement(new line)('\n')
PsiElement(identifier)('b')
PsiElement(.)('.')
PsiElement(new line)('\n')
PsiElement(identifier)('b')
PsiElement(.)('.')
PsiElement(new line)('\n')
PsiElement(identifier)('c')
PsiElement(identifier)('c')
@@ -0,0 +1,56 @@
import a.;
import a.b.;
import;
import a.b.c
-----
Groovy script
Import statement
Modifiers
<empty list>
PsiElement(import)('import')
PsiWhiteSpace(' ')
Reference element
Reference element
PsiElement(identifier)('a')
PsiElement(.)('.')
PsiErrorElement:Identifier expected
<empty list>
PsiElement(;)(';')
PsiElement(new line)('\n')
Import statement
Modifiers
<empty list>
PsiElement(import)('import')
PsiWhiteSpace(' ')
Reference element
Reference element
Reference element
PsiElement(identifier)('a')
PsiElement(.)('.')
PsiElement(identifier)('b')
PsiElement(.)('.')
PsiErrorElement:Identifier expected
<empty list>
PsiElement(;)(';')
PsiElement(new line)('\n')
Import statement
Modifiers
<empty list>
PsiElement(import)('import')
PsiErrorElement:package or class name expected
<empty list>
PsiElement(;)(';')
PsiElement(new line)('\n')
Import statement
Modifiers
<empty list>
PsiElement(import)('import')
PsiWhiteSpace(' ')
Reference element
Reference element
Reference element
PsiElement(identifier)('a')
PsiElement(.)('.')
PsiElement(identifier)('b')
PsiElement(.)('.')
PsiElement(identifier)('c')
@@ -0,0 +1,32 @@
def foo() throws java.
lang.RuntimeException {
}
-----
Groovy script
Method
Modifiers
PsiElement(def)('def')
PsiWhiteSpace(' ')
PsiElement(identifier)('foo')
PsiElement(()('(')
Parameter list
<empty list>
PsiElement())(')')
PsiWhiteSpace(' ')
Throw clause
PsiElement(throws)('throws')
PsiWhiteSpace(' ')
Reference element
Reference element
Reference element
PsiElement(identifier)('java')
PsiElement(.)('.')
PsiElement(new line)('\n')
PsiElement(identifier)('lang')
PsiElement(.)('.')
PsiElement(identifier)('RuntimeException')
PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n')
PsiElement(})('}')
@@ -0,0 +1,40 @@
def foo() throws java
.lang.RuntimeException {
}
-----
Groovy script
Method
Modifiers
PsiElement(def)('def')
PsiWhiteSpace(' ')
PsiElement(identifier)('foo')
PsiElement(()('(')
Parameter list
<empty list>
PsiElement())(')')
PsiWhiteSpace(' ')
Throw clause
PsiElement(throws)('throws')
PsiWhiteSpace(' ')
Reference element
PsiElement(identifier)('java')
PsiElement(new line)('\n')
PsiErrorElement:Unexpected symbol
PsiElement(.)('.')
PsiErrorElement:';' or new line expected
<empty list>
Method call
Reference expression
Reference expression
PsiElement(identifier)('lang')
PsiElement(.)('.')
PsiElement(identifier)('RuntimeException')
PsiWhiteSpace(' ')
Arguments
<empty list>
Closable block
PsiElement({)('{')
PsiWhiteSpace('\n')
Parameter list
<empty list>
PsiElement(})('}')