mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-08 15:09:39 +07:00
New Java parser (dead loop in expression parsing parsing fixed)
This commit is contained in:
@@ -290,7 +290,7 @@ public class ExpressionParser {
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parsePostfix(final PsiBuilder builder) {
|
||||
PsiBuilder.Marker operand = parsePrimary(builder, false);
|
||||
PsiBuilder.Marker operand = parsePrimary(builder, null);
|
||||
if (operand == null) return null;
|
||||
|
||||
while (POSTFIX_OPS.contains(builder.getTokenType())) {
|
||||
@@ -303,8 +303,10 @@ public class ExpressionParser {
|
||||
return operand;
|
||||
}
|
||||
|
||||
private enum BreakPoint {P1, P2, P3, P4}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parsePrimary(final PsiBuilder builder, final boolean planB) {
|
||||
private static PsiBuilder.Marker parsePrimary(final PsiBuilder builder, final BreakPoint breakPoint) {
|
||||
PsiBuilder.Marker startMarker = builder.mark();
|
||||
|
||||
PsiBuilder.Marker expr = parsePrimaryExpressionStart(builder);
|
||||
@@ -321,7 +323,7 @@ public class ExpressionParser {
|
||||
|
||||
final IElementType dotTokenType = builder.getTokenType();
|
||||
if (dotTokenType == JavaTokenType.CLASS_KEYWORD && exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) {
|
||||
if (planB) {
|
||||
if (breakPoint == BreakPoint.P1) {
|
||||
error(builder, JavaErrorMessages.message("expected.identifier"));
|
||||
PsiBuilderUtil.drop(startMarker, dotPos);
|
||||
return expr;
|
||||
@@ -333,7 +335,7 @@ public class ExpressionParser {
|
||||
final PsiBuilder.Marker classObjAccess = parseClassObjectAccess(builder);
|
||||
if (classObjAccess == null) {
|
||||
copy.rollbackTo();
|
||||
return parsePrimary(builder, true);
|
||||
return parsePrimary(builder, BreakPoint.P1);
|
||||
}
|
||||
|
||||
startMarker = copy;
|
||||
@@ -345,7 +347,7 @@ public class ExpressionParser {
|
||||
}
|
||||
else if ((dotTokenType == JavaTokenType.THIS_KEYWORD || dotTokenType == JavaTokenType.SUPER_KEYWORD) &&
|
||||
exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) {
|
||||
if (planB) {
|
||||
if (breakPoint == BreakPoint.P2) {
|
||||
dotPos.rollbackTo();
|
||||
startMarker.drop();
|
||||
return expr;
|
||||
@@ -357,13 +359,13 @@ public class ExpressionParser {
|
||||
final PsiBuilder.Marker ref = ReferenceParser.parseJavaCodeReference(builder, false, true, false);
|
||||
if (ref == null || builder.getTokenType() != JavaTokenType.DOT) {
|
||||
copy.rollbackTo();
|
||||
return parsePrimary(builder, true);
|
||||
return parsePrimary(builder, BreakPoint.P2);
|
||||
}
|
||||
builder.advanceLexer();
|
||||
|
||||
if (builder.getTokenType() != dotTokenType) {
|
||||
copy.rollbackTo();
|
||||
return parsePrimary(builder, true);
|
||||
return parsePrimary(builder, BreakPoint.P2);
|
||||
}
|
||||
builder.advanceLexer();
|
||||
|
||||
@@ -396,7 +398,7 @@ public class ExpressionParser {
|
||||
else if (tokenType == JavaTokenType.LPARENTH) {
|
||||
if (exprType(expr) != JavaElementType.REFERENCE_EXPRESSION) {
|
||||
if (exprType(expr) == JavaElementType.SUPER_EXPRESSION) {
|
||||
if (planB) {
|
||||
if (breakPoint == BreakPoint.P3) {
|
||||
startMarker.drop();
|
||||
return expr;
|
||||
}
|
||||
@@ -420,7 +422,7 @@ public class ExpressionParser {
|
||||
}
|
||||
|
||||
copy.rollbackTo();
|
||||
return parsePrimary(builder, true);
|
||||
return parsePrimary(builder, BreakPoint.P3);
|
||||
}
|
||||
else {
|
||||
startMarker.drop();
|
||||
@@ -434,7 +436,7 @@ public class ExpressionParser {
|
||||
expr = callExpr;
|
||||
}
|
||||
else if (tokenType == JavaTokenType.LBRACKET) {
|
||||
if (planB) {
|
||||
if (breakPoint == BreakPoint.P4) {
|
||||
startMarker.drop();
|
||||
return expr;
|
||||
}
|
||||
@@ -442,13 +444,14 @@ public class ExpressionParser {
|
||||
builder.advanceLexer();
|
||||
|
||||
if (builder.getTokenType() == JavaTokenType.RBRACKET && exprType(expr) == JavaElementType.REFERENCE_EXPRESSION) {
|
||||
final int pos = builder.getCurrentOffset();
|
||||
final PsiBuilder.Marker copy = startMarker.precede();
|
||||
startMarker.rollbackTo();
|
||||
|
||||
final PsiBuilder.Marker classObjAccess = parseClassObjectAccess(builder);
|
||||
if (classObjAccess == null) {
|
||||
if (classObjAccess == null || builder.getCurrentOffset() <= pos) {
|
||||
copy.rollbackTo();
|
||||
return parsePrimary(builder, true);
|
||||
return parsePrimary(builder, BreakPoint.P4);
|
||||
}
|
||||
|
||||
startMarker = copy;
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
PsiJavaFile:SCR5202.java
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiExpressionStatement
|
||||
PsiReferenceExpression:String.class.
|
||||
String
|
||||
PsiClassObjectAccessExpression:String.class
|
||||
PsiTypeElement:String
|
||||
PsiJavaCodeReferenceElement:String
|
||||
PsiIdentifier:String('String')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiKeyword:class('class')
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiIdentifier:String('String')
|
||||
PsiErrorElement:';' expected
|
||||
<empty list>
|
||||
PsiErrorElement:Unexpected token
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiErrorElement:Unexpected token
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiExpressionStatement
|
||||
PsiReferenceExpression:strings
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:strings('strings')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -36,6 +36,7 @@ public class StatementParserTest extends JavaParsingTestCase {
|
||||
public void testBlockIncomplete0() { doParserTest("{ /*}"); }
|
||||
public void testBlockIncomplete1() { doParserTest("{ { }"); }
|
||||
public void testBlockIncomplete2() { doParserTest("{ else; catch; finally; }"); }
|
||||
public void testSCR5202() { doParserTest("{ String.class.\n String[] strings; }"); }
|
||||
|
||||
public void testBreakNormal0() { doParserTest("{ break; }"); }
|
||||
public void testBreakNormal1() { doParserTest("{ break LABEL; }"); }
|
||||
|
||||
Reference in New Issue
Block a user