From d9f8050ad355b7d89bf3b7cb9065e3462e742a25 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Sun, 1 Aug 2010 22:04:25 +0400 Subject: [PATCH] New Java parser (completion hack) --- .../lang/java/parser/DeclarationParser.java | 17 +++++++++++-- .../declarations/CompletionHack2.txt | 25 +++++++++++++++++++ .../parser/partial/DeclarationParserTest.java | 1 + 3 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 java/java-tests/testData/psi/parser-partial/declarations/CompletionHack2.txt diff --git a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index c9e55e75cded..34f5ae8bda41 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -40,6 +40,8 @@ public class DeclarationParser { private static final TokenSet AFTER_END_DECLARATION_SET = TokenSet.create(JavaElementType.FIELD, JavaElementType.METHOD); private static final TokenSet BEFORE_LBRACE_ELEMENTS_SET = TokenSet.create( JavaTokenType.IDENTIFIER, JavaTokenType.COMMA, JavaTokenType.EXTENDS_KEYWORD, JavaTokenType.IMPLEMENTS_KEYWORD); + private static final TokenSet APPEND_TO_METHOD_SET = TokenSet.create( + JavaTokenType.IDENTIFIER, JavaTokenType.COMMA, JavaTokenType.THROWS_KEYWORD); private DeclarationParser() { } @@ -411,8 +413,19 @@ public class DeclarationParser { StatementParser.parseCodeBlock(builder); } else { - error(builder, JavaErrorMessages.message("expected.lbrace.or.semicolon")); - // todo: special treatment - like in fields (DeclarationParserTest.testMultiLineUnclosed()) + final PsiBuilder.Marker error = builder.mark(); + // heuristic: going to next line obviously means method signature is over, starting new method (actually, another one completion hack) + final CharSequence text = builder.getOriginalText(); + Loop: + while (true) { + for (int i = builder.getCurrentOffset() - 1; i >= 0; i--) { + final char ch = text.charAt(i); + if (ch == '\n') break Loop; + else if (ch != ' ' && ch != '\t') break; + } + if (!expect(builder, APPEND_TO_METHOD_SET)) break; + } + error.error(JavaErrorMessages.message("expected.lbrace.or.semicolon")); } declaration.done(anno ? JavaElementType.ANNOTATION_METHOD : JavaElementType.METHOD); diff --git a/java/java-tests/testData/psi/parser-partial/declarations/CompletionHack2.txt b/java/java-tests/testData/psi/parser-partial/declarations/CompletionHack2.txt new file mode 100644 index 000000000000..9c43b6b5b3df --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/declarations/CompletionHack2.txt @@ -0,0 +1,25 @@ +PsiJavaFile:CompletionHack2.java + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiAnnotationMethod:foo + PsiModifierList: + + PsiTypeParameterList + + PsiTypeElement:String + PsiJavaCodeReferenceElement:String + PsiIdentifier:String('String') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:foo('foo') + PsiParameterList:() + PsiJavaToken:LPARENTH('(') + PsiJavaToken:RPARENTH(')') + PsiReferenceList + + PsiWhiteSpace(' ') + PsiErrorElement:'{' or ';' expected + PsiIdentifier:def('def') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/DeclarationParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/DeclarationParserTest.java index e72df739108f..8a51afbf9b6d 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/DeclarationParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/DeclarationParserTest.java @@ -96,6 +96,7 @@ public class DeclarationParserTest extends JavaParsingTestCase { public void testErrors() { doParserTest("{ public static protected int f1 = 0; }", false, false); } public void testCompletionHack0() { doParserTest("{ \n String s = \"\"; }", false, false); } public void testCompletionHack1() { doParserTest("{ x(Collection x); }", false, false); } public void testParameterAnnotation() { doParserTest("{ void foo (@Annotation(value=77) int param) {} }", false, false); } public void testParameterizedMethod() { doParserTest("{ @Nullable T bar() {} }", false, false); }