mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 11:50:54 +07:00
[java] invalid "for" statements highlighting (IDEA-167353)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -2929,14 +2929,16 @@ public class HighlightUtil extends HighlightUtilBase {
|
||||
@Nullable
|
||||
static HighlightInfo checkForStatement(@NotNull PsiForStatement statement) {
|
||||
PsiStatement init = statement.getInitialization();
|
||||
if (!(init == null || init instanceof PsiEmptyStatement ||
|
||||
init instanceof PsiDeclarationStatement ||
|
||||
init instanceof PsiExpressionStatement || init instanceof PsiExpressionListStatement)) {
|
||||
String message = JavaErrorMessages.message("invalid.statement");
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(init).descriptionAndTooltip(message).create();
|
||||
if (init == null ||
|
||||
init instanceof PsiEmptyStatement ||
|
||||
init instanceof PsiDeclarationStatement && ArrayUtil.getFirstElement(((PsiDeclarationStatement)init).getDeclaredElements()) instanceof PsiLocalVariable ||
|
||||
init instanceof PsiExpressionStatement ||
|
||||
init instanceof PsiExpressionListStatement) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
String message = JavaErrorMessages.message("invalid.statement");
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(init).descriptionAndTooltip(message).create();
|
||||
}
|
||||
|
||||
private static void registerChangeParameterClassFix(PsiType lType, PsiType rType, HighlightInfo info) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -381,7 +381,7 @@ public class StatementParser {
|
||||
final PsiBuilder.Marker param = myParser.getDeclarationParser().parseParameter(builder, false, false);
|
||||
if (param == null || exprType(param) != JavaElementType.PARAMETER || builder.getTokenType() != JavaTokenType.COLON) {
|
||||
afterParenth.rollbackTo();
|
||||
return parseForLoopFromInitialization(builder, statement);
|
||||
return parseForLoopFromInitializer(builder, statement);
|
||||
}
|
||||
else {
|
||||
afterParenth.drop();
|
||||
@@ -390,9 +390,9 @@ public class StatementParser {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PsiBuilder.Marker parseForLoopFromInitialization(final PsiBuilder builder, final PsiBuilder.Marker statement) {
|
||||
final PsiBuilder.Marker init = parseStatement(builder);
|
||||
if (init == null){
|
||||
private PsiBuilder.Marker parseForLoopFromInitializer(PsiBuilder builder, PsiBuilder.Marker statement) {
|
||||
PsiBuilder.Marker init = parseStatement(builder);
|
||||
if (init == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.statement"));
|
||||
if (!expect(builder, JavaTokenType.RPARENTH)) {
|
||||
done(statement, JavaElementType.FOR_STATEMENT);
|
||||
@@ -400,9 +400,18 @@ public class StatementParser {
|
||||
}
|
||||
}
|
||||
else {
|
||||
myParser.getExpressionParser().parse(builder);
|
||||
boolean missingSemicolon = false;
|
||||
if (getLastToken(builder) != JavaTokenType.SEMICOLON) {
|
||||
missingSemicolon = !expectOrError(builder, JavaTokenType.SEMICOLON, "expected.semicolon");
|
||||
}
|
||||
|
||||
PsiBuilder.Marker expr = myParser.getExpressionParser().parse(builder);
|
||||
missingSemicolon &= expr == null;
|
||||
|
||||
if (!expect(builder, JavaTokenType.SEMICOLON)) {
|
||||
error(builder, JavaErrorMessages.message("expected.semicolon"));
|
||||
if (!missingSemicolon) {
|
||||
error(builder, JavaErrorMessages.message("expected.semicolon"));
|
||||
}
|
||||
if (!expect(builder, JavaTokenType.RPARENTH)) {
|
||||
done(statement, JavaElementType.FOR_STATEMENT);
|
||||
return statement;
|
||||
@@ -418,7 +427,7 @@ public class StatementParser {
|
||||
}
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker bodyStatement = parseStatement(builder);
|
||||
PsiBuilder.Marker bodyStatement = parseStatement(builder);
|
||||
if (bodyStatement == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.statement"));
|
||||
}
|
||||
@@ -427,6 +436,13 @@ public class StatementParser {
|
||||
return statement;
|
||||
}
|
||||
|
||||
private static IElementType getLastToken(PsiBuilder builder) {
|
||||
IElementType token;
|
||||
int offset = -1;
|
||||
while (ElementType.JAVA_COMMENT_OR_WHITESPACE_BIT_SET.contains((token = builder.rawLookup(offset)))) offset--;
|
||||
return token;
|
||||
}
|
||||
|
||||
private void parseExpressionOrExpressionList(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker expr = myParser.getExpressionParser().parse(builder);
|
||||
if (expr == null) return;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class a {
|
||||
class ff { }
|
||||
static class ff { }
|
||||
|
||||
void f() {
|
||||
<error descr="Continue outside of loop">continue;</error>
|
||||
@@ -61,5 +61,6 @@ class a {
|
||||
for (<error descr="Not a statement">i==0?7:8;</error> ; ) ;
|
||||
for (<error descr="Invalid statement">if (i<0) i++;</error> ; ) ;
|
||||
for (new ff(), new ff(); ; ) ;
|
||||
for (<error descr="Invalid statement">class C { }</error>; true; ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
PsiJavaFile:ForInvalid0.java
|
||||
PsiForStatement
|
||||
PsiKeyword:for('for')
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiIfStatement
|
||||
PsiKeyword:if('if')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiBinaryExpression:i<0
|
||||
PsiReferenceExpression:i
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:i('i')
|
||||
PsiJavaToken:LT('<')
|
||||
PsiLiteralExpression:0
|
||||
PsiJavaToken:INTEGER_LITERAL('0')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiExpressionStatement
|
||||
PsiPostfixExpression:i++
|
||||
PsiReferenceExpression:i
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:i('i')
|
||||
PsiJavaToken:PLUSPLUS('++')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiEmptyStatement
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
@@ -0,0 +1,28 @@
|
||||
PsiJavaFile:ForInvalid1.java
|
||||
PsiForStatement
|
||||
PsiKeyword:for('for')
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiDeclarationStatement
|
||||
PsiClass:C
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiKeyword:class('class')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:C('C')
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiEmptyStatement
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2016 JetBrains s.r.o.
|
||||
* Copyright 2000-2017 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.
|
||||
@@ -46,8 +46,6 @@ public class StatementParserTest extends JavaParsingTestCase {
|
||||
public void testLocalVar0() { doParserTest("List<Integer> list;"); }
|
||||
public void testLocalVar1() { doParserTest("p.@A T<P> x;"); }
|
||||
|
||||
public void testFor() { doParserTest("for(Iterator<String> it = null; it.hasNext();) { String s = it.next(); }"); }
|
||||
|
||||
public void testDoNormal() { doParserTest("do{}while(true);"); }
|
||||
public void testDoIncomplete0() { doParserTest("do"); }
|
||||
public void testDoIncomplete1() { doParserTest("do foo();"); }
|
||||
@@ -57,9 +55,9 @@ public class StatementParserTest extends JavaParsingTestCase {
|
||||
public void testDoIncomplete5() { doParserTest("do foo(); while(\n g();"); }
|
||||
public void testDoIncomplete6() { doParserTest("do foo(); while(cond)"); }
|
||||
|
||||
public void testFor() { doParserTest("for(Iterator<String> it = null; it.hasNext();) { String s = it.next(); }"); }
|
||||
public void testForNormal0() { doParserTest("for(int i = 0; i < 10; i++)\n ;"); }
|
||||
public void testForNormal1() { doParserTest("for( ; ; ) foo();"); }
|
||||
public void testForEach() { doParserTest("for(Object o : map.entrySet()) ;"); }
|
||||
public void testForIncomplete0() { doParserTest("for"); }
|
||||
public void testForIncomplete1() { doParserTest("for("); }
|
||||
public void testForIncomplete2() { doParserTest("for(int i = 0;"); }
|
||||
@@ -70,6 +68,10 @@ public class StatementParserTest extends JavaParsingTestCase {
|
||||
public void testForIncomplete7() { doParserTest("for() foo();"); }
|
||||
public void testForIncomplete8() { doParserTest("for(int i = 0;) foo();"); }
|
||||
public void testForIncomplete9() { doParserTest("for(int i = 0; i < 0) foo();"); }
|
||||
public void testForInvalid0() { doParserTest("for(if (i<0) i++; ;) ;"); }
|
||||
public void testForInvalid1() { doParserTest("for(class C { }; ;) ;"); }
|
||||
|
||||
public void testForEach() { doParserTest("for(Object o : map.entrySet()) ;"); }
|
||||
public void testForEachIncomplete0() { doParserTest("for(Object : list) ;"); }
|
||||
|
||||
public void testIfNormalWithElse() { doParserTest("if (a){ f1(); } else{ f2(); }"); }
|
||||
|
||||
Reference in New Issue
Block a user