diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java index 536698a45a58..3fa6965e5feb 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java @@ -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, diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/ThrowClause.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/ThrowClause.java index e3489662a034..13f99db7ee2c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/ThrowClause.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/ThrowClause.java @@ -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; } } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/Annotation.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/Annotation.java index 313fb600fbd0..c6b15d9b91d5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/Annotation.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/Annotation.java @@ -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; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/imports/ImportReference.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/imports/ImportReference.java index 62381a57c72f..6bb48b3b9d7b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/imports/ImportReference.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/imports/ImportReference.java @@ -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); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/ReferenceElement.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/ReferenceElement.java index 79763dfeab7e..8cea8ecee7fa 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/ReferenceElement.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/ReferenceElement.java @@ -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); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/toplevel/packaging/PackageDefinition.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/toplevel/packaging/PackageDefinition.java index f0e5a4a13e32..fa432a8b8421 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/toplevel/packaging/PackageDefinition.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/toplevel/packaging/PackageDefinition.java @@ -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")); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java index 28f69556a7a6..bd0d4619484f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java @@ -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 getValidImportStatements(final GroovyFile file) { final List oldImports = new ArrayList(); 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); } } 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 acd40a2314f7..98a5cf5536a2 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 @@ -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(); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/TypesParsingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/TypesParsingTest.groovy index 489a2feefbe9..a4fc8ad3eff9 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/TypesParsingTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/TypesParsingTest.groovy @@ -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(); } diff --git a/plugins/groovy/testdata/parsing/groovy/packaging/pack3.test b/plugins/groovy/testdata/parsing/groovy/packaging/pack3.test index bd24b1fa86b3..179df1ed9dc9 100644 --- a/plugins/groovy/testdata/parsing/groovy/packaging/pack3.test +++ b/plugins/groovy/testdata/parsing/groovy/packaging/pack3.test @@ -7,16 +7,14 @@ Groovy script Modifiers PsiElement(package)('package') - PsiErrorElement:Identifier expected - - 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') \ No newline at end of file + PsiElement(identifier)('c') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/statements/imports/imp8.test b/plugins/groovy/testdata/parsing/groovy/statements/imports/imp8.test new file mode 100644 index 000000000000..f20b09ba26cb --- /dev/null +++ b/plugins/groovy/testdata/parsing/groovy/statements/imports/imp8.test @@ -0,0 +1,56 @@ +import a.; +import a.b.; +import; +import a.b.c +----- +Groovy script + Import statement + Modifiers + + PsiElement(import)('import') + PsiWhiteSpace(' ') + Reference element + Reference element + PsiElement(identifier)('a') + PsiElement(.)('.') + PsiErrorElement:Identifier expected + + PsiElement(;)(';') + PsiElement(new line)('\n') + Import statement + Modifiers + + PsiElement(import)('import') + PsiWhiteSpace(' ') + Reference element + Reference element + Reference element + PsiElement(identifier)('a') + PsiElement(.)('.') + PsiElement(identifier)('b') + PsiElement(.)('.') + PsiErrorElement:Identifier expected + + PsiElement(;)(';') + PsiElement(new line)('\n') + Import statement + Modifiers + + PsiElement(import)('import') + PsiErrorElement:package or class name expected + + PsiElement(;)(';') + PsiElement(new line)('\n') + Import statement + Modifiers + + PsiElement(import)('import') + PsiWhiteSpace(' ') + Reference element + Reference element + Reference element + PsiElement(identifier)('a') + PsiElement(.)('.') + PsiElement(identifier)('b') + PsiElement(.)('.') + PsiElement(identifier)('c') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/types/type14.test b/plugins/groovy/testdata/parsing/groovy/types/type14.test new file mode 100644 index 000000000000..2f2bcba36277 --- /dev/null +++ b/plugins/groovy/testdata/parsing/groovy/types/type14.test @@ -0,0 +1,32 @@ +def foo() throws java. +lang.RuntimeException { +} +----- +Groovy script + Method + Modifiers + PsiElement(def)('def') + PsiWhiteSpace(' ') + PsiElement(identifier)('foo') + PsiElement(()('(') + Parameter 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(})('}') \ No newline at end of file diff --git a/plugins/groovy/testdata/parsing/groovy/types/type15.test b/plugins/groovy/testdata/parsing/groovy/types/type15.test new file mode 100644 index 000000000000..387614bcedcb --- /dev/null +++ b/plugins/groovy/testdata/parsing/groovy/types/type15.test @@ -0,0 +1,40 @@ +def foo() throws java +.lang.RuntimeException { +} +----- +Groovy script + Method + Modifiers + PsiElement(def)('def') + PsiWhiteSpace(' ') + PsiElement(identifier)('foo') + PsiElement(()('(') + Parameter 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 + + Method call + Reference expression + Reference expression + PsiElement(identifier)('lang') + PsiElement(.)('.') + PsiElement(identifier)('RuntimeException') + PsiWhiteSpace(' ') + Arguments + + Closable block + PsiElement({)('{') + PsiWhiteSpace('\n') + Parameter list + + PsiElement(})('}') \ No newline at end of file