mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
New Java parser (work in progress)
This commit is contained in:
@@ -773,7 +773,7 @@ public class ExpressionParser {
|
||||
}
|
||||
|
||||
private static void emptyExpression(final PsiBuilder builder) {
|
||||
builder.mark().done(JavaElementType.EMPTY_EXPRESSION);
|
||||
emptyElement(builder, JavaElementType.EMPTY_EXPRESSION);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -110,13 +110,7 @@ public class StatementParser {
|
||||
|
||||
parseStatements(builder, (parseUntilEof ? BraceMode.TILL_LAST : BraceMode.TILL_FIRST));
|
||||
|
||||
// todo: check closing brace
|
||||
//final TreeElement lastChild = elementToAdd.getLastChildNode();
|
||||
//if (lastChild == null || lastChild.getElementType() != JavaTokenType.RBRACE){
|
||||
// CompositeElement errorElement = Factory.createErrorElement(JavaErrorMessages.message("expected.rbrace"));
|
||||
// elementToAdd.rawAddChildren(errorElement);
|
||||
// elementToAdd.putUserData(TreeUtil.UNCLOSED_ELEMENT_PROPERTY, "");
|
||||
//}
|
||||
expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace"));
|
||||
|
||||
codeBlock.done(JavaElementType.CODE_BLOCK);
|
||||
return codeBlock;
|
||||
@@ -128,29 +122,26 @@ public class StatementParser {
|
||||
if (statement != null) continue;
|
||||
|
||||
final IElementType tokenType = builder.getTokenType();
|
||||
final PsiBuilder.Marker error = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
if (tokenType == JavaTokenType.RBRACE) {
|
||||
if (braceMode == BraceMode.TILL_FIRST) {
|
||||
error.drop();
|
||||
return;
|
||||
}
|
||||
else if (braceMode == BraceMode.TILL_LAST) {
|
||||
if (builder.getTokenType() == null) {
|
||||
error.drop();
|
||||
if (nextTokenType(builder) == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker error = builder.mark();
|
||||
builder.advanceLexer();
|
||||
if (tokenType == JavaTokenType.ELSE_KEYWORD) {
|
||||
error.error(JavaErrorMessages.message("else.without.if"));
|
||||
}
|
||||
else if (tokenType == JavaTokenType.CATCH_KEYWORD) {
|
||||
error.error(JavaErrorMessages.message("catch.without.try"));
|
||||
}
|
||||
else if (tokenType == JavaTokenType.FINAL_KEYWORD) {
|
||||
else if (tokenType == JavaTokenType.FINALLY_KEYWORD) {
|
||||
error.error(JavaErrorMessages.message("finally.without.try"));
|
||||
}
|
||||
else {
|
||||
@@ -516,22 +507,44 @@ public class StatementParser {
|
||||
return statement;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseSwitchLabelStatement(final PsiBuilder builder) {
|
||||
// todo: implement
|
||||
throw new UnsupportedOperationException(builder.toString());
|
||||
final PsiBuilder.Marker statement = builder.mark();
|
||||
final boolean isCase = builder.getTokenType() == JavaTokenType.CASE_KEYWORD;
|
||||
builder.advanceLexer();
|
||||
|
||||
if (isCase) {
|
||||
final PsiBuilder.Marker expr = ExpressionParser.parse(builder);
|
||||
if (expr == null) {
|
||||
statement.rollbackTo();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
expectOrError(builder, JavaTokenType.COLON, JavaErrorMessages.message("expected.colon"));
|
||||
|
||||
statement.done(JavaElementType.SWITCH_LABEL_STATEMENT);
|
||||
return statement;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiBuilder.Marker parseBreakStatement(final PsiBuilder builder) {
|
||||
// todo: implement
|
||||
throw new UnsupportedOperationException(builder.toString());
|
||||
final PsiBuilder.Marker statement = builder.mark();
|
||||
builder.advanceLexer();
|
||||
expect(builder, JavaTokenType.IDENTIFIER);
|
||||
semicolon(builder);
|
||||
statement.done(JavaElementType.BREAK_STATEMENT);
|
||||
return statement;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiBuilder.Marker parseContinueStatement(final PsiBuilder builder) {
|
||||
// todo: implement
|
||||
throw new UnsupportedOperationException(builder.toString());
|
||||
final PsiBuilder.Marker statement = builder.mark();
|
||||
builder.advanceLexer();
|
||||
expect(builder, JavaTokenType.IDENTIFIER);
|
||||
semicolon(builder);
|
||||
statement.done(JavaElementType.CONTINUE_STATEMENT);
|
||||
return statement;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -91,7 +91,7 @@ public interface JavaElementType {
|
||||
IElementType ARRAY_INITIALIZER_EXPRESSION = new IJavaElementType("ARRAY_INITIALIZER_EXPRESSION");
|
||||
IElementType INSTANCE_OF_EXPRESSION = new IJavaElementType("INSTANCE_OF_EXPRESSION");
|
||||
IElementType CLASS_OBJECT_ACCESS_EXPRESSION = new IJavaElementType("CLASS_OBJECT_ACCESS_EXPRESSION");
|
||||
IElementType EMPTY_EXPRESSION = new IJavaElementType("EMPTY_EXPRESSION");
|
||||
IElementType EMPTY_EXPRESSION = new IJavaElementType("EMPTY_EXPRESSION", true);
|
||||
|
||||
IElementType EXPRESSION_LIST = new IJavaElementType("EXPRESSION_LIST", true);
|
||||
|
||||
@@ -123,6 +123,8 @@ public interface JavaElementType {
|
||||
IElementType ANNOTATION_PARAMETER_LIST = new IJavaElementType("ANNOTATION_PARAMETER_LIST", true);
|
||||
IElementType METHOD_RECEIVER = new IJavaElementType("METHOD_RECEIVER");
|
||||
|
||||
IElementType INSTANT_CODE_BLOCK = new IJavaElementType("CODE_BLOCK");
|
||||
|
||||
ILazyParseableElementType CODE_BLOCK = new IErrorCounterReparseableElementType("CODE_BLOCK", StdLanguages.JAVA) {
|
||||
@Override
|
||||
public ASTNode createNode(CharSequence text) {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
PsiJavaFile:BlockEmpty.java
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiEmptyStatement
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,6 @@
|
||||
PsiJavaFile:BlockIncomplete0.java
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiErrorElement:'}' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
@@ -0,0 +1,11 @@
|
||||
PsiJavaFile:BlockIncomplete1.java
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiBlockStatement
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
PsiErrorElement:'}' expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,20 @@
|
||||
PsiJavaFile:BlockIncomplete2.java
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:'else' without 'if'
|
||||
PsiKeyword:else('else')
|
||||
PsiEmptyStatement
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:'catch' without 'try'
|
||||
PsiKeyword:catch('catch')
|
||||
PsiEmptyStatement
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:'finally' without 'try'
|
||||
PsiKeyword:finally('finally')
|
||||
PsiEmptyStatement
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,9 @@
|
||||
PsiJavaFile:BreakNormal0.java
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiBreakStatement
|
||||
PsiKeyword:break('break')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,11 @@
|
||||
PsiJavaFile:BreakNormal1.java
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiBreakStatement
|
||||
PsiKeyword:break('break')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:LABEL('LABEL')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,9 @@
|
||||
PsiJavaFile:ContinueNormal0.java
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiContinueStatement
|
||||
PsiKeyword:continue('continue')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,11 @@
|
||||
PsiJavaFile:ContinueNormal1.java
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiContinueStatement
|
||||
PsiKeyword:continue('continue')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:LABEL('LABEL')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,8 @@
|
||||
PsiJavaFile:SwitchLabelsIncomplete0.java
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:Unexpected token
|
||||
PsiKeyword:case('case')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,13 @@
|
||||
PsiJavaFile:SwitchLabelsIncomplete1.java
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiSwitchLabelStatement
|
||||
PsiKeyword:case('case')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:2
|
||||
PsiJavaToken:INTEGER_LITERAL('2')
|
||||
PsiErrorElement:':' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,10 @@
|
||||
PsiJavaFile:SwitchLabelsIncomplete2.java
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiSwitchLabelStatement
|
||||
PsiKeyword:default('default')
|
||||
PsiErrorElement:':' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,18 @@
|
||||
PsiJavaFile:SwitchLabelsIncomplete3.java
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiSwitchLabelStatement
|
||||
PsiKeyword:default('default')
|
||||
PsiErrorElement:':' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiExpressionStatement
|
||||
PsiLiteralExpression:3
|
||||
PsiJavaToken:INTEGER_LITERAL('3')
|
||||
PsiErrorElement:';' expected
|
||||
<empty list>
|
||||
PsiErrorElement:Unexpected token
|
||||
PsiJavaToken:COLON(':')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,24 @@
|
||||
PsiJavaFile:SwitchLabelsNormal.java
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiSwitchLabelStatement
|
||||
PsiKeyword:case('case')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiJavaToken:COLON(':')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiBreakStatement
|
||||
PsiKeyword:break('break')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiSwitchLabelStatement
|
||||
PsiKeyword:default('default')
|
||||
PsiJavaToken:COLON(':')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiBreakStatement
|
||||
PsiKeyword:break('break')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
+17
-1
@@ -31,7 +31,17 @@ public class StatementParserTest extends JavaParsingTestCase {
|
||||
public void testAssignmentSimple() { doParserTest("{ int[] a;\n a[0] = 0; }"); }
|
||||
|
||||
public void testBlockSimple() { doParserTest("{ {} }"); }
|
||||
//public void testAnonymousInSmartCompletion() { doParserTest("{ new Foo(hash\n#) {};\n new Foo(hash\n#, bar) {};\n new Foo(hash\n#x) {}; }"); } // todo: spaces
|
||||
public void testBlockEmpty() { doParserTest("{ ; }"); }
|
||||
public void testAnonymousInSmartCompletion() { doParserTest("{ new Foo(hash\n#) {};\n new Foo(hash\n#, bar) {};\n new Foo(hash\n#x) {}; }"); }
|
||||
public void testBlockIncomplete0() { doParserTest("{ "); }
|
||||
public void testBlockIncomplete1() { doParserTest("{ { }"); }
|
||||
public void testBlockIncomplete2() { doParserTest("{ else; catch; finally; }"); }
|
||||
|
||||
public void testBreakNormal0() { doParserTest("{ break; }"); }
|
||||
public void testBreakNormal1() { doParserTest("{ break LABEL; }"); }
|
||||
|
||||
public void testContinueNormal0() { doParserTest("{ continue; }"); }
|
||||
public void testContinueNormal1() { doParserTest("{ continue LABEL; }"); }
|
||||
|
||||
public void testLocalVar() { doParserTest("{ List<Integer> list; }"); }
|
||||
public void testFor() { doParserTest("{ for(Iterator<String> it = null; it.hasNext();) { String s = it.next(); } }"); }
|
||||
@@ -84,6 +94,12 @@ public class StatementParserTest extends JavaParsingTestCase {
|
||||
public void testSwitchIncomplete4() { doParserTest("{ switch(){} }"); }
|
||||
public void testSwitchIncomplete5() { doParserTest("{ switch(\n foo(); }"); }
|
||||
|
||||
public void testSwitchLabelsNormal() { doParserTest("{ case 1: break; default: break; }"); }
|
||||
public void testSwitchLabelsIncomplete0() { doParserTest("{ case }"); }
|
||||
public void testSwitchLabelsIncomplete1() { doParserTest("{ case 2 }"); }
|
||||
public void testSwitchLabelsIncomplete2() { doParserTest("{ default }"); }
|
||||
public void testSwitchLabelsIncomplete3() { doParserTest("{ default 3: }"); }
|
||||
|
||||
public void testSyncNormal() { doParserTest("{ synchronized(o){} }"); }
|
||||
public void testSyncIncomplete0() { doParserTest("{ synchronized }"); }
|
||||
public void testSyncIncomplete1() { doParserTest("{ synchronized( }"); }
|
||||
|
||||
Reference in New Issue
Block a user