IDEA-119396 (be picky about unfinished annotated new array expressions)

This commit is contained in:
Roman Shevchenko
2014-02-19 19:30:35 +01:00
parent ead0734f08
commit 9495ef2667
6 changed files with 60 additions and 20 deletions

View File

@@ -28,7 +28,9 @@ import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static com.intellij.lang.PsiBuilderUtil.drop;
import static com.intellij.lang.PsiBuilderUtil.expect;
import static com.intellij.lang.PsiBuilderUtil.rollbackTo;
import static com.intellij.lang.java.parser.JavaParserUtil.*;
public class ExpressionParser {
@@ -342,7 +344,7 @@ public class ExpressionParser {
if (dotTokenType == JavaTokenType.CLASS_KEYWORD && exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) {
if (breakPoint == BreakPoint.P1 && builder.getCurrentOffset() == breakOffset) {
error(builder, JavaErrorMessages.message("expected.identifier"));
PsiBuilderUtil.drop(startMarker, dotPos);
drop(startMarker, dotPos);
return expr;
}
@@ -701,9 +703,7 @@ public class ExpressionParser {
PsiBuilder.Marker anno = myParser.getDeclarationParser().parseAnnotations(builder);
IElementType tokenType = builder.getTokenType();
if (tokenType == JavaTokenType.IDENTIFIER) {
if (anno != null) {
anno.rollbackTo();
}
rollbackTo(anno);
refOrType = myParser.getReferenceParser().parseJavaCodeReference(builder, true, true, true, true);
if (refOrType == null) {
error(builder, JavaErrorMessages.message("expected.identifier"));
@@ -732,9 +732,10 @@ public class ExpressionParser {
return newExpr;
}
myParser.getDeclarationParser().parseAnnotations(builder);
anno = myParser.getDeclarationParser().parseAnnotations(builder);
if (builder.getTokenType() != JavaTokenType.LBRACKET) {
rollbackTo(anno);
error(builder, refOrType == null ? JavaErrorMessages.message("expected.lbracket") : JavaErrorMessages.message("expected.lparen.or.lbracket"));
newExpr.done(JavaElementType.NEW_EXPRESSION);
return newExpr;
@@ -743,9 +744,12 @@ public class ExpressionParser {
int bracketCount = 0;
int dimCount = 0;
while (true) {
myParser.getDeclarationParser().parseAnnotations(builder);
anno = myParser.getDeclarationParser().parseAnnotations(builder);
if (builder.getTokenType() != JavaTokenType.LBRACKET) break;
if (builder.getTokenType() != JavaTokenType.LBRACKET) {
rollbackTo(anno);
break;
}
builder.advanceLexer();
if (bracketCount == dimCount) {

View File

@@ -104,7 +104,6 @@ class Outer {
void arrays(String @TA ... docs) {
@TA String @TA [] @TA [] docs1 = new @TA String @TA [2] @TA [2];
@TA int @TA [] ints = new @TA int @TA [2];
new Boolean @TA [2] <error descr="Annotations are not allowed here">@TA</error>;
}
int @TA [] mixedArrays @TA [] <error descr="Annotations are not allowed here">@TA</error> = new int[0][0];

View File

@@ -55,7 +55,6 @@ PsiJavaFile:Errors4.java
PsiJavaToken:EQ('=')
PsiWhiteSpace(' ')
PsiNewExpression:new Linked
@Deprecated
PsiKeyword:new('new')
PsiReferenceParameterList
<empty list>
@@ -64,22 +63,22 @@ PsiJavaFile:Errors4.java
PsiIdentifier:Linked('Linked')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace('\n ')
PsiAnnotation
PsiJavaToken:AT('@')
PsiJavaCodeReferenceElement:Deprecated
PsiIdentifier:Deprecated('Deprecated')
PsiReferenceParameterList
<empty list>
PsiAnnotationParameterList
<empty list>
PsiErrorElement:'(' or '[' expected
<empty list>
PsiErrorElement:';' expected
<empty list>
PsiWhiteSpace(' ')
PsiWhiteSpace('\n ')
PsiDeclarationStatement
PsiTypeElement:List<Object>
PsiTypeElement:@Deprecated List<Object>
PsiAnnotation
PsiJavaToken:AT('@')
PsiJavaCodeReferenceElement:Deprecated
PsiIdentifier:Deprecated('Deprecated')
PsiReferenceParameterList
<empty list>
PsiAnnotationParameterList
<empty list>
PsiWhiteSpace(' ')
PsiJavaCodeReferenceElement:List<Object>
PsiIdentifier:List('List')
PsiReferenceParameterList

View File

@@ -0,0 +1,25 @@
PsiJavaFile:New18.java
PsiNewExpression:new int @A [2]
PsiKeyword:new('new')
PsiReferenceParameterList
<empty list>
PsiWhiteSpace(' ')
PsiKeyword:int('int')
PsiWhiteSpace(' ')
PsiAnnotation
PsiJavaToken:AT('@')
PsiJavaCodeReferenceElement:A
PsiIdentifier:A('A')
PsiReferenceParameterList
<empty list>
PsiAnnotationParameterList
<empty list>
PsiWhiteSpace(' ')
PsiJavaToken:LBRACKET('[')
PsiLiteralExpression:2
PsiJavaToken:INTEGER_LITERAL('2')
PsiJavaToken:RBRACKET(']')
PsiWhiteSpace(' ')
PsiErrorElement:Unparsed tokens
PsiJavaToken:AT('@')
PsiIdentifier:B('B')

View File

@@ -77,6 +77,7 @@ public class ExpressionParserTest extends JavaParsingTestCase {
public void testNew15() { doParserTest("new C<?>.B()"); }
public void testNew16() { doParserTest("new C<>()"); }
public void testNew17() { doParserTest("new Map<String, >()"); }
public void testNew18() { doParserTest("new int @A [2] @B"); }
public void testExprList0() { doParserTest("f(1,2)"); }
public void testExprList1() { doParserTest("f("); }

View File

@@ -17,6 +17,7 @@ package com.intellij.lang;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import org.jetbrains.annotations.Nullable;
public class PsiBuilderUtil {
private PsiBuilderUtil() { }
@@ -74,4 +75,15 @@ public class PsiBuilderUtil {
if (marker != null) marker.drop();
}
}
/**
* Rolls the lexer back to position before given marker - if not null.
*
* @param marker marker to roll back to.
*/
public static void rollbackTo(@Nullable PsiBuilder.Marker marker) {
if (marker != null) {
marker.rollbackTo();
}
}
}