mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
correct brace structure in case of switch with no matching )
more meaningful code block error recovery
This commit is contained in:
+1
-1
@@ -59,7 +59,7 @@ public class GroovyClassNameInsertHandler implements InsertHandler<JavaPsiClassR
|
||||
boolean parens = shouldInsertParentheses(position, item.getObject());
|
||||
|
||||
final PsiClass psiClass = item.getObject();
|
||||
if (isInVariable(position) || GroovyCompletionContributor.isInClosurePropertyParameters(position)) {
|
||||
if (isInVariable(position) || GroovyCompletionContributor.isInPossibleClosureParameter(position)) {
|
||||
Project project = context.getProject();
|
||||
String qname = psiClass.getQualifiedName();
|
||||
String shortName = psiClass.getName();
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrRefere
|
||||
public class GroovyCompletionConfidence extends CompletionConfidence {
|
||||
|
||||
private static boolean isPossibleClosureParameter(GrReferenceExpression ref) {
|
||||
return PsiJavaPatterns.psiElement().withParent(GrClosableBlock.class).afterLeaf("{").accepts(ref);
|
||||
return PsiJavaPatterns.psiElement().withParent(GrClosableBlock.class).afterLeaf("{").accepts(ref) || GroovyCompletionContributor.isInPossibleClosureParameter(ref);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+40
-17
@@ -31,8 +31,10 @@ import com.intellij.patterns.StandardPatterns;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.NameUtil;
|
||||
import com.intellij.psi.filters.ElementFilter;
|
||||
import com.intellij.psi.filters.FilterPositionUtil;
|
||||
import com.intellij.psi.filters.TrueFilter;
|
||||
import com.intellij.psi.filters.types.AssignableFromFilter;
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -69,7 +71,6 @@ import static com.intellij.patterns.PlatformPatterns.psiElement;
|
||||
import static com.intellij.patterns.PsiJavaPatterns.elementType;
|
||||
import static com.intellij.util.containers.CollectionFactory.hashMap;
|
||||
import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils.*;
|
||||
import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.skipWhitespaces;
|
||||
|
||||
/**
|
||||
* @author ilyas
|
||||
@@ -522,30 +523,52 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
if (semicolonNeeded(context)) {
|
||||
context.setDummyIdentifier(CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED + ";");
|
||||
}
|
||||
else if (isInClosurePropertyParameters(context.getFile().findElementAt(context.getStartOffset()))) {
|
||||
else if (isInPossibleClosureParameter(context.getFile().findElementAt(context.getStartOffset()))) {
|
||||
context.setDummyIdentifier(CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED + "->");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isInClosurePropertyParameters(PsiElement position) { //Closure cl={String x, <caret>...
|
||||
public static boolean isInPossibleClosureParameter(PsiElement position) { //Closure cl={String x, <caret>...
|
||||
if (position == null) return false;
|
||||
|
||||
GrVariableDeclaration declaration = PsiTreeUtil.getParentOfType(position, GrVariableDeclaration.class, false, GrStatement.class);
|
||||
if (declaration == null) {
|
||||
if (position.getParent() instanceof PsiErrorElement) position = position.getParent();
|
||||
PsiElement prev = position.getPrevSibling();
|
||||
prev = skipWhitespaces(prev, false);
|
||||
if (prev instanceof PsiErrorElement) {
|
||||
prev = prev.getPrevSibling();
|
||||
}
|
||||
prev = skipWhitespaces(prev, false);
|
||||
if (prev instanceof GrVariableDeclaration) declaration = (GrVariableDeclaration)prev;
|
||||
if (position instanceof PsiWhiteSpace || position.getNode().getElementType() == GroovyElementTypes.mNLS) {
|
||||
position = FilterPositionUtil.searchNonSpaceNonCommentBack(position);
|
||||
}
|
||||
if (declaration != null) {
|
||||
if (!(declaration.getParent() instanceof GrClosableBlock)) return false;
|
||||
PsiElement prevSibling = skipWhitespaces(declaration.getPrevSibling(), false);
|
||||
return prevSibling instanceof GrParameterList;
|
||||
|
||||
boolean hasCommas = false;
|
||||
while (position != null) {
|
||||
PsiElement parent = position.getParent();
|
||||
if (parent instanceof GrVariable) {
|
||||
PsiElement prev = FilterPositionUtil.searchNonSpaceNonCommentBack(parent);
|
||||
hasCommas = prev != null && prev.getNode().getElementType() == GroovyElementTypes.mCOMMA;
|
||||
}
|
||||
|
||||
if (parent instanceof GrClosableBlock) {
|
||||
PsiElement sibling = position.getPrevSibling();
|
||||
while (sibling != null) {
|
||||
if (sibling instanceof GrParameterList) {
|
||||
return hasCommas;
|
||||
}
|
||||
|
||||
boolean isComma = sibling instanceof LeafPsiElement && GroovyElementTypes.mCOMMA == ((LeafPsiElement)sibling).getElementType();
|
||||
hasCommas |= isComma;
|
||||
|
||||
if (isComma ||
|
||||
sibling instanceof PsiWhiteSpace ||
|
||||
sibling instanceof PsiErrorElement ||
|
||||
sibling instanceof GrVariableDeclaration ||
|
||||
sibling instanceof GrReferenceExpression && !((GrReferenceExpression)sibling).isQualified()
|
||||
) {
|
||||
sibling = sibling.getPrevSibling();
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
position = parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+4
@@ -30,6 +30,10 @@ import org.jetbrains.annotations.NonNls;
|
||||
*/
|
||||
public class InstanceOfFilter implements ElementFilter {
|
||||
public boolean isAcceptable(Object element, PsiElement context) {
|
||||
return isInfixOperatorPosition(context);
|
||||
}
|
||||
|
||||
public static boolean isInfixOperatorPosition(PsiElement context) {
|
||||
if (context.getParent() != null &&
|
||||
context.getParent() instanceof GrReferenceExpression &&
|
||||
context.getParent().getParent() != null &&
|
||||
|
||||
+6
@@ -21,6 +21,7 @@ import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.filters.ElementFilter;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionUtil;
|
||||
import org.jetbrains.plugins.groovy.lang.completion.filters.exprs.InstanceOfFilter;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
|
||||
@@ -37,8 +38,13 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
|
||||
*/
|
||||
public class BuiltInTypeFilter implements ElementFilter {
|
||||
public boolean isAcceptable(Object element, PsiElement context) {
|
||||
if (InstanceOfFilter.isInfixOperatorPosition(context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiElement parent = context.getParent();
|
||||
if (parent == null) return false;
|
||||
|
||||
PsiElement previous = PsiImplUtil.realPrevious(parent.getPrevSibling());
|
||||
if (previous != null && GroovyTokenTypes.mAT.equals(previous.getNode().getElementType())) {
|
||||
return false;
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lang.PsiParser;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.GroovyBundle;
|
||||
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
|
||||
@@ -46,6 +47,9 @@ import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.*;
|
||||
*/
|
||||
public class GroovyParser implements PsiParser {
|
||||
|
||||
public static final TokenSet RCURLY_ONLY = TokenSet.create(mRCURLY);
|
||||
public static final TokenSet CASE_SECTION_END = TokenSet.create(kCASE, kDEFAULT, mRCURLY);
|
||||
|
||||
public boolean parseDeep() {
|
||||
return false;
|
||||
}
|
||||
@@ -202,29 +206,8 @@ public class GroovyParser implements PsiParser {
|
||||
}
|
||||
|
||||
public void parseSwitchCaseList(PsiBuilder builder) {
|
||||
if (!parseStatement(builder, false) && !parseExtendedStatement(builder)) {
|
||||
builder.error(GroovyBundle.message("wrong.statement"));
|
||||
return;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
while (ParserUtils.getToken(builder, mSEMI)) {}
|
||||
PsiBuilder.Marker beforeSeparators = builder.mark();
|
||||
ParserUtils.getToken(builder, mNLS);
|
||||
if (builder.eof() || builder.getTokenType() == kCASE || builder.getTokenType() == kDEFAULT || builder.getTokenType() == mRCURLY) {
|
||||
beforeSeparators.rollbackTo();
|
||||
break;
|
||||
}
|
||||
beforeSeparators.drop();
|
||||
boolean first = true;
|
||||
if (!parseStatement(builder, false) && !parseExtendedStatement(builder)) {
|
||||
if (first) {
|
||||
builder.error("statement expected");
|
||||
first = false;
|
||||
}
|
||||
assert builder.getTokenType() != mLCURLY && builder.getTokenType() != mRCURLY;
|
||||
builder.advanceLexer();
|
||||
}
|
||||
if (parseGenericStatement(builder, CASE_SECTION_END)) {
|
||||
parseCodeBlock(builder, CASE_SECTION_END);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,76 +264,71 @@ public class GroovyParser implements PsiParser {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rolls marker forward after possible errors
|
||||
*/
|
||||
private void cleanAfterError(PsiBuilder builder, boolean rCurlyNeeded) {
|
||||
int braceLevel = 1;
|
||||
int i = 0;
|
||||
PsiBuilder.Marker em = builder.mark();
|
||||
public void parseBlockBody(PsiBuilder builder) {
|
||||
skipSeparators(builder);
|
||||
parseCodeBlock(builder, RCURLY_ONLY);
|
||||
ParserUtils.getToken(builder, mNLS);
|
||||
}
|
||||
|
||||
private void parseCodeBlock(PsiBuilder builder, TokenSet until) {
|
||||
while (true) {
|
||||
if (builder.eof()) {
|
||||
break;
|
||||
}
|
||||
final IElementType type = builder.getTokenType();
|
||||
if (GroovyTokenTypes.mLCURLY == type) {
|
||||
braceLevel++;
|
||||
}
|
||||
else if (GroovyTokenTypes.mRCURLY == type) {
|
||||
braceLevel--;
|
||||
if (braceLevel == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (braceLevel == 1) {
|
||||
if (!rCurlyNeeded && (GroovyTokenTypes.mNLS.equals(type) || GroovyTokenTypes.mSEMI.equals(type))) {
|
||||
break;
|
||||
}
|
||||
if (isExtendedSeparator(type)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
builder.advanceLexer();
|
||||
i++;
|
||||
}
|
||||
if (i > 0) {
|
||||
em.error(GroovyBundle.message("separator.or.rcurly.expected"));
|
||||
} else {
|
||||
em.drop();
|
||||
if (builder.eof() || until.contains(builder.getTokenType())) break;
|
||||
if (!parseGenericStatement(builder, until)) break;
|
||||
}
|
||||
}
|
||||
|
||||
public void parseBlockBody(PsiBuilder builder) {
|
||||
private boolean parseGenericStatement(PsiBuilder builder, TokenSet until) {
|
||||
boolean plainStatement = parseStatement(builder, false);
|
||||
|
||||
|
||||
parseExtendedStatement(builder);
|
||||
if (GroovyTokenTypes.mSEMI.equals(builder.getTokenType()) || GroovyTokenTypes.mNLS.equals(builder.getTokenType())) {
|
||||
Separators.parse(builder);
|
||||
}
|
||||
while (parseExtendedStatement(builder)) {
|
||||
Separators.parse(builder);
|
||||
}
|
||||
|
||||
boolean result = parseStatement(builder, false);
|
||||
|
||||
while (result &&
|
||||
(GroovyTokenTypes.mSEMI.equals(builder.getTokenType()) ||
|
||||
GroovyTokenTypes.mNLS.equals(builder.getTokenType()) || parseExtendedStatement(builder))) {
|
||||
Separators.parse(builder);
|
||||
while (parseExtendedStatement(builder)) {
|
||||
Separators.parse(builder);
|
||||
if (plainStatement || parseExtendedStatement(builder)) {
|
||||
if (parseSeparatorsWithoutLastNls(builder, plainStatement, until)) {
|
||||
return false;
|
||||
}
|
||||
result = parseStatement(builder, false);
|
||||
if (!isExtendedSeparator(builder.getTokenType())) {
|
||||
cleanAfterError(builder, false);
|
||||
} else {
|
||||
builder.error(GroovyBundle.message("wrong.statement"));
|
||||
assert builder.getTokenType() != mLCURLY && builder.getTokenType() != mRCURLY;
|
||||
builder.advanceLexer();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean parseSeparatorsWithoutLastNls(PsiBuilder builder, boolean requireSeparator, TokenSet until) {
|
||||
boolean hasSeparator = false;
|
||||
while (true) {
|
||||
while (builder.getTokenType() == mSEMI || isExtendedSeparator(builder.getTokenType())) {
|
||||
hasSeparator = true;
|
||||
builder.advanceLexer();
|
||||
}
|
||||
|
||||
if (builder.getTokenType() == mNLS) {
|
||||
PsiBuilder.Marker beforeNls = builder.mark();
|
||||
hasSeparator = true;
|
||||
builder.advanceLexer();
|
||||
if (builder.eof() || until.contains(builder.getTokenType())) {
|
||||
beforeNls.rollbackTo();
|
||||
return true;
|
||||
}
|
||||
beforeNls.drop();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
cleanAfterError(builder, true);
|
||||
Separators.parse(builder);
|
||||
while (parseExtendedStatement(builder)) {
|
||||
Separators.parse(builder);
|
||||
if (builder.eof() || until.contains(builder.getTokenType())) {
|
||||
return true;
|
||||
}
|
||||
if (requireSeparator && !hasSeparator) {
|
||||
builder.error(GroovyBundle.message("separator.or.rcurly.expected"));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean skipSeparators(PsiBuilder builder) {
|
||||
boolean hasSeparators = false;
|
||||
while (builder.getTokenType() == mSEMI || isExtendedSeparator(builder.getTokenType()) || builder.getTokenType() == mNLS) {
|
||||
hasSeparators = true;
|
||||
builder.advanceLexer();
|
||||
}
|
||||
return hasSeparators;
|
||||
}
|
||||
|
||||
public boolean parseStatement(PsiBuilder builder, boolean isBlockStatementNeeded) {
|
||||
@@ -372,7 +350,8 @@ public class GroovyParser implements PsiParser {
|
||||
return parseIfStatement(builder);
|
||||
}
|
||||
if (GroovyTokenTypes.kSWITCH.equals(builder.getTokenType())) {
|
||||
return SwitchStatement.parseSwitch(builder, this);
|
||||
SwitchStatement.parseSwitch(builder, this);
|
||||
return true;
|
||||
}
|
||||
if (GroovyTokenTypes.kTRY.equals(builder.getTokenType())) {
|
||||
return TryCatchStatement.parse(builder, this);
|
||||
|
||||
+6
-13
@@ -31,13 +31,13 @@ import org.jetbrains.plugins.groovy.lang.parser.parsing.util.ParserUtils;
|
||||
*/
|
||||
public class SwitchStatement implements GroovyElementTypes {
|
||||
|
||||
public static boolean parseSwitch(PsiBuilder builder, GroovyParser parser) {
|
||||
public static void parseSwitch(PsiBuilder builder, GroovyParser parser) {
|
||||
PsiBuilder.Marker marker = builder.mark();
|
||||
ParserUtils.getToken(builder, kSWITCH);
|
||||
|
||||
if (!ParserUtils.getToken(builder, mLPAREN, GroovyBundle.message("lparen.expected"))) {
|
||||
marker.done(SWITCH_STATEMENT);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (!StrictContextExpression.parse(builder, parser)) {
|
||||
builder.error(GroovyBundle.message("expression.expected"));
|
||||
@@ -45,14 +45,9 @@ public class SwitchStatement implements GroovyElementTypes {
|
||||
ParserUtils.getToken(builder, mNLS);
|
||||
|
||||
if (!ParserUtils.getToken(builder, mRPAREN, GroovyBundle.message("rparen.expected"))) {
|
||||
while (!builder.eof() && !mNLS.equals(builder.getTokenType()) && !mRPAREN.equals(builder.getTokenType())) {
|
||||
builder.error(GroovyBundle.message("rparen.expected"));
|
||||
builder.advanceLexer();
|
||||
}
|
||||
if (!ParserUtils.getToken(builder, mRPAREN)) {
|
||||
marker.done(SWITCH_STATEMENT);
|
||||
return true;
|
||||
}
|
||||
builder.error(GroovyBundle.message("rparen.expected"));
|
||||
marker.done(SWITCH_STATEMENT);
|
||||
return;
|
||||
}
|
||||
PsiBuilder.Marker warn = builder.mark();
|
||||
ParserUtils.getToken(builder, mNLS);
|
||||
@@ -61,13 +56,11 @@ public class SwitchStatement implements GroovyElementTypes {
|
||||
warn.rollbackTo();
|
||||
builder.error(GroovyBundle.message("case.block.expected"));
|
||||
marker.done(SWITCH_STATEMENT);
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
warn.drop();
|
||||
parseCaseBlock(builder, parser);
|
||||
marker.done(SWITCH_STATEMENT);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
private static void parseCaseBlock(PsiBuilder builder, GroovyParser parser) {
|
||||
|
||||
+2
-3
@@ -169,9 +169,8 @@ public class GroovyCompletionTest extends GroovyCompletionTestBase {
|
||||
doBasicTest();
|
||||
}
|
||||
|
||||
public void testCompletionInParameterListInClosableBlock() throws Throwable {
|
||||
doBasicTest();
|
||||
}
|
||||
public void testCompletionInParameterListInClosableBlock() throws Throwable { doBasicTest(); }
|
||||
public void testCompletionInParameterListInClosableBlock3() throws Throwable { doBasicTest(); }
|
||||
|
||||
public void testCompletionInParameterListInClosableBlock2() throws Throwable {
|
||||
myFixture.testCompletionVariants(getTestName(false) + ".groovy", "aDouble");
|
||||
|
||||
@@ -81,7 +81,6 @@ public class KeywordCompletionTest extends CompletionTestBase {
|
||||
public void testVar6() throws Throwable { doTest(); }
|
||||
public void testVar7() throws Throwable { doTest(); }
|
||||
public void testVar8() throws Throwable { doTest(); }
|
||||
public void testVar9() throws Throwable { doTest(); }
|
||||
public void testWhile55() throws Throwable { doTest(); }
|
||||
|
||||
|
||||
|
||||
+1
@@ -194,6 +194,7 @@ public class ExpressionsParsingTest extends GroovyParsingTestCase {
|
||||
public void testDollar() throws Throwable { doTest(); }
|
||||
|
||||
public void testNoArrowClosure() throws Throwable { doTest(); }
|
||||
public void testNoArrowClosure2() throws Throwable { doTest(); }
|
||||
|
||||
public void testPropertyAccessError() throws Throwable {
|
||||
checkParsing "a[b{}}", """Groovy script
|
||||
|
||||
+2
-1
@@ -36,6 +36,7 @@ public abstract class GroovyParsingTestCase extends LightCodeInsightFixtureTestC
|
||||
protected void checkParsing(String input, String output) {
|
||||
final PsiFile psiFile = TestUtils.createPseudoPhysicalGroovyFile(getProject(), input);
|
||||
String psiTree = DebugUtil.psiToString(psiFile, false);
|
||||
assertEquals(output.trim(), psiTree.trim());
|
||||
String prefix = input.trim() + "\n-----\n";
|
||||
assertEquals(prefix + output.trim(), prefix + psiTree.trim());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,5 +138,16 @@ def foo() {
|
||||
""", "\b"
|
||||
}
|
||||
|
||||
public void testSwitchRParen() {
|
||||
checkReparse """
|
||||
def foo() {
|
||||
switch (word w w)<caret> {
|
||||
case 2:
|
||||
def x = (y)
|
||||
}
|
||||
}
|
||||
""", "\b"
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+3
-42
@@ -187,49 +187,10 @@ public class StatementsParsingTest extends GroovyParsingTestCase {
|
||||
public void testVardef$vardeferrsingle4() throws Throwable { doTest(); }
|
||||
public void testWith$with1() throws Throwable { doTest(); }
|
||||
public void testWith$with2() throws Throwable { doTest(); }
|
||||
|
||||
public void testAfterAs() throws Throwable { doTest(); }
|
||||
public void testUnnamedField() throws Throwable { doTest(); }
|
||||
|
||||
public void testIfRecovery() throws Throwable {
|
||||
checkParsing """def test239() {
|
||||
if (foo() {}
|
||||
}""",
|
||||
"""Groovy script
|
||||
Method
|
||||
Modifiers
|
||||
PsiElement(def)('def')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(identifier)('test239')
|
||||
PsiElement(()('(')
|
||||
Parameter list
|
||||
<empty list>
|
||||
PsiElement())(')')
|
||||
PsiWhiteSpace(' ')
|
||||
Throw clause
|
||||
<empty list>
|
||||
Open block
|
||||
PsiElement({)('{')
|
||||
PsiWhiteSpace('\\n ')
|
||||
IF statement
|
||||
PsiElement(if)('if')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(()('(')
|
||||
Method call
|
||||
Reference expression
|
||||
PsiElement(identifier)('foo')
|
||||
Arguments
|
||||
PsiElement(()('(')
|
||||
PsiElement())(')')
|
||||
PsiWhiteSpace(' ')
|
||||
Closable block
|
||||
PsiElement({)('{')
|
||||
Parameter list
|
||||
<empty list>
|
||||
PsiElement(})('}')
|
||||
PsiErrorElement:')' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace('\\n ')
|
||||
PsiElement(})('}')"""
|
||||
}
|
||||
public void testIfRecovery() throws Throwable { doTest(); }
|
||||
public void testSemicolonsOnDifferentLines() throws Throwable { doTest(); }
|
||||
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
def x = {
|
||||
def a, Doubl<caret>
|
||||
|
||||
}
|
||||
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
def x = {
|
||||
def a, Double<caret>
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
package a.b.c
|
||||
|
||||
import org.*
|
||||
|
||||
class A {
|
||||
def foo() {
|
||||
switch <caret> (k){
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
-----
|
||||
@@ -15,8 +15,12 @@ Groovy script
|
||||
PsiElement({)('{')
|
||||
Parameter list
|
||||
<empty list>
|
||||
PsiErrorElement:';', '}' or new line expected
|
||||
PsiElement(@)('@')
|
||||
PsiElement(wrong token)('#')
|
||||
PsiErrorElement:Wrong statement
|
||||
<empty list>
|
||||
PsiElement(@)('@')
|
||||
PsiErrorElement:Wrong statement
|
||||
<empty list>
|
||||
PsiElement(wrong token)('#')
|
||||
Literal
|
||||
PsiElement(Integer)('2')
|
||||
PsiElement(})('}')
|
||||
@@ -0,0 +1,42 @@
|
||||
{ a, b, c
|
||||
println a+b+c
|
||||
}
|
||||
-----
|
||||
Groovy script
|
||||
Closable block
|
||||
PsiElement({)('{')
|
||||
PsiWhiteSpace(' ')
|
||||
Parameter list
|
||||
<empty list>
|
||||
Reference expression
|
||||
PsiElement(identifier)('a')
|
||||
PsiErrorElement:';', '}' or new line expected
|
||||
<empty list>
|
||||
PsiElement(,)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
Reference expression
|
||||
PsiElement(identifier)('b')
|
||||
PsiErrorElement:';', '}' or new line expected
|
||||
<empty list>
|
||||
PsiElement(,)(',')
|
||||
PsiWhiteSpace(' ')
|
||||
Reference expression
|
||||
PsiElement(identifier)('c')
|
||||
PsiElement(new line)('\n ')
|
||||
Call expression
|
||||
Reference expression
|
||||
PsiElement(identifier)('println')
|
||||
PsiWhiteSpace(' ')
|
||||
Command arguments
|
||||
Additive expression
|
||||
Additive expression
|
||||
Reference expression
|
||||
PsiElement(identifier)('a')
|
||||
PsiElement(+)('+')
|
||||
Reference expression
|
||||
PsiElement(identifier)('b')
|
||||
PsiElement(+)('+')
|
||||
Reference expression
|
||||
PsiElement(identifier)('c')
|
||||
PsiElement(new line)('\n')
|
||||
PsiElement(})('}')
|
||||
@@ -28,8 +28,10 @@ Groovy script
|
||||
Command arguments
|
||||
Literal
|
||||
PsiElement(Gstring)('"bugaga"')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:';', '}' or new line expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
Literal
|
||||
PsiElement(Integer)('3')
|
||||
PsiElement(})('}')
|
||||
PsiElement(Gstring content)(' ved')
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
def test239() {
|
||||
if (foo() {}
|
||||
}
|
||||
-----
|
||||
Groovy script
|
||||
Method
|
||||
Modifiers
|
||||
PsiElement(def)('def')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(identifier)('test239')
|
||||
PsiElement(()('(')
|
||||
Parameter list
|
||||
<empty list>
|
||||
PsiElement())(')')
|
||||
PsiWhiteSpace(' ')
|
||||
Throw clause
|
||||
<empty list>
|
||||
Open block
|
||||
PsiElement({)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
IF statement
|
||||
PsiElement(if)('if')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(()('(')
|
||||
Method call
|
||||
Reference expression
|
||||
PsiElement(identifier)('foo')
|
||||
Arguments
|
||||
PsiElement(()('(')
|
||||
PsiElement())(')')
|
||||
PsiWhiteSpace(' ')
|
||||
Closable block
|
||||
PsiElement({)('{')
|
||||
Parameter list
|
||||
<empty list>
|
||||
PsiElement(})('}')
|
||||
PsiErrorElement:')' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n')
|
||||
PsiElement(})('}')
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
def foo() {
|
||||
;
|
||||
;;
|
||||
|
||||
;
|
||||
}
|
||||
-----
|
||||
Groovy script
|
||||
Method
|
||||
Modifiers
|
||||
PsiElement(def)('def')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(identifier)('foo')
|
||||
PsiElement(()('(')
|
||||
Parameter list
|
||||
<empty list>
|
||||
PsiElement())(')')
|
||||
PsiWhiteSpace(' ')
|
||||
Throw clause
|
||||
<empty list>
|
||||
Open block
|
||||
PsiElement({)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiElement(;)(';')
|
||||
PsiElement(new line)('\n ')
|
||||
PsiElement(;)(';')
|
||||
PsiElement(;)(';')
|
||||
PsiElement(new line)('\n\n ')
|
||||
PsiElement(;)(';')
|
||||
PsiElement(new line)('\n')
|
||||
PsiElement(})('}')
|
||||
@@ -28,9 +28,13 @@ Groovy script
|
||||
Reference expression
|
||||
PsiElement(identifier)('e1')
|
||||
PsiErrorElement:';', '}' or new line expected
|
||||
PsiElement())(')')
|
||||
PsiWhiteSpace(' ')
|
||||
<empty list>
|
||||
PsiElement())(')')
|
||||
PsiWhiteSpace(' ')
|
||||
Closable block
|
||||
PsiElement({)('{')
|
||||
Parameter list
|
||||
<empty list>
|
||||
PsiElement(})('}')
|
||||
PsiElement(new line)('\n')
|
||||
PsiErrorElement:'catch' without 'try'
|
||||
@@ -49,9 +53,13 @@ Groovy script
|
||||
Reference expression
|
||||
PsiElement(identifier)('e2')
|
||||
PsiErrorElement:';', '}' or new line expected
|
||||
PsiElement())(')')
|
||||
PsiWhiteSpace(' ')
|
||||
<empty list>
|
||||
PsiElement())(')')
|
||||
PsiWhiteSpace(' ')
|
||||
Closable block
|
||||
PsiElement({)('{')
|
||||
Parameter list
|
||||
<empty list>
|
||||
PsiElement(})('}')
|
||||
PsiElement(new line)('\n')
|
||||
PsiErrorElement:'finally' without 'try'
|
||||
|
||||
@@ -86,16 +86,28 @@ Groovy script
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiElement(identifier)('simplePlugins')
|
||||
PsiErrorElement:';', '}' or new line expected
|
||||
PsiElement(.)('.')
|
||||
PsiElement(identifier)('each')
|
||||
<empty list>
|
||||
PsiElement(.)('.')
|
||||
Method call
|
||||
Reference expression
|
||||
PsiElement(identifier)('each')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement({)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiElement(identifier)('layoutPlugin')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(identifier)('it')
|
||||
PsiElement(new line)('\n ')
|
||||
PsiElement(})('}')
|
||||
Arguments
|
||||
<empty list>
|
||||
Closable block
|
||||
PsiElement({)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
Parameter list
|
||||
<empty list>
|
||||
Call expression
|
||||
Reference expression
|
||||
PsiElement(identifier)('layoutPlugin')
|
||||
PsiWhiteSpace(' ')
|
||||
Command arguments
|
||||
Reference expression
|
||||
PsiElement(identifier)('it')
|
||||
PsiElement(new line)('\n ')
|
||||
PsiElement(})('}')
|
||||
PsiWhiteSpace('\n\n')
|
||||
PsiElement(})('}')
|
||||
PsiElement(new line)('\n')
|
||||
|
||||
@@ -79,6 +79,8 @@ Groovy script
|
||||
PsiElement(new line)('\n ')
|
||||
Reference expression
|
||||
PsiElement(identifier)('do')
|
||||
PsiErrorElement:';', '}' or new line expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
RETURN statement
|
||||
PsiElement(return)('return')
|
||||
|
||||
+5
-1
@@ -112,12 +112,16 @@ Groovy script
|
||||
PsiElement(.)('.')
|
||||
PsiElement(new line)('\n ')
|
||||
PsiElement(case)('case')
|
||||
PsiErrorElement:';', '}' or new line expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
Literal
|
||||
PsiElement(Integer)('3')
|
||||
PsiErrorElement:statement expected
|
||||
PsiErrorElement:';', '}' or new line expected
|
||||
<empty list>
|
||||
PsiElement(:)(':')
|
||||
PsiErrorElement:Wrong statement
|
||||
<empty list>
|
||||
PsiElement(new line)('\n ')
|
||||
RETURN statement
|
||||
PsiElement(return)('return')
|
||||
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
Groovy script
|
||||
PsiElement(new line)('\n')
|
||||
Method
|
||||
Modifiers
|
||||
PsiElement(def)('def')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(identifier)('foo')
|
||||
PsiElement(()('(')
|
||||
Parameter list
|
||||
<empty list>
|
||||
PsiElement())(')')
|
||||
PsiWhiteSpace(' ')
|
||||
Throw clause
|
||||
<empty list>
|
||||
Open block
|
||||
PsiElement({)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
Switch statement
|
||||
PsiElement(switch)('switch')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(()('(')
|
||||
Reference expression
|
||||
PsiElement(identifier)('word')
|
||||
PsiErrorElement:')' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
Call expression
|
||||
Reference expression
|
||||
PsiElement(identifier)('w')
|
||||
PsiWhiteSpace(' ')
|
||||
Command arguments
|
||||
Reference expression
|
||||
PsiElement(identifier)('w')
|
||||
PsiErrorElement:';', '}' or new line expected
|
||||
<empty list>
|
||||
PsiElement())(')')
|
||||
PsiWhiteSpace(' ')
|
||||
Closable block
|
||||
PsiElement({)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
Parameter list
|
||||
<empty list>
|
||||
PsiErrorElement:'case' outside 'switch' block
|
||||
Case label
|
||||
PsiElement(case)('case')
|
||||
PsiWhiteSpace(' ')
|
||||
Literal
|
||||
PsiElement(Integer)('2')
|
||||
PsiElement(:)(':')
|
||||
PsiElement(new line)('\n ')
|
||||
Variable definitions
|
||||
Modifiers
|
||||
PsiElement(def)('def')
|
||||
PsiWhiteSpace(' ')
|
||||
Variable
|
||||
PsiElement(identifier)('x')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(=)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
Parenthesized expression
|
||||
PsiElement(()('(')
|
||||
Reference expression
|
||||
PsiElement(identifier)('y')
|
||||
PsiElement())(')')
|
||||
PsiElement(new line)('\n ')
|
||||
PsiElement(})('}')
|
||||
PsiElement(new line)('\n ')
|
||||
PsiElement(})('}')
|
||||
PsiElement(new line)('\n')
|
||||
---
|
||||
Groovy script
|
||||
PsiElement(new line)('\n')
|
||||
Method
|
||||
Modifiers
|
||||
PsiElement(def)('def')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(identifier)('foo')
|
||||
PsiElement(()('(')
|
||||
Parameter list
|
||||
<empty list>
|
||||
PsiElement())(')')
|
||||
PsiWhiteSpace(' ')
|
||||
Throw clause
|
||||
<empty list>
|
||||
Open block
|
||||
PsiElement({)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
Switch statement
|
||||
PsiElement(switch)('switch')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(()('(')
|
||||
Reference expression
|
||||
PsiElement(identifier)('word')
|
||||
PsiErrorElement:')' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
Call expression
|
||||
Reference expression
|
||||
PsiElement(identifier)('w')
|
||||
PsiWhiteSpace(' ')
|
||||
Command arguments
|
||||
Method call
|
||||
Reference expression
|
||||
PsiElement(identifier)('w')
|
||||
PsiWhiteSpace(' ')
|
||||
Arguments
|
||||
<empty list>
|
||||
Closable block
|
||||
PsiElement({)('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
Parameter list
|
||||
<empty list>
|
||||
PsiErrorElement:'case' outside 'switch' block
|
||||
Case label
|
||||
PsiElement(case)('case')
|
||||
PsiWhiteSpace(' ')
|
||||
Literal
|
||||
PsiElement(Integer)('2')
|
||||
PsiElement(:)(':')
|
||||
PsiElement(new line)('\n ')
|
||||
Variable definitions
|
||||
Modifiers
|
||||
PsiElement(def)('def')
|
||||
PsiWhiteSpace(' ')
|
||||
Variable
|
||||
PsiElement(identifier)('x')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(=)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
Parenthesized expression
|
||||
PsiElement(()('(')
|
||||
Reference expression
|
||||
PsiElement(identifier)('y')
|
||||
PsiElement())(')')
|
||||
PsiElement(new line)('\n ')
|
||||
PsiElement(})('}')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiElement(})('}')
|
||||
PsiElement(new line)('\n')
|
||||
Reference in New Issue
Block a user