From 05be23db87df2a882fde6132e5e002007db90c57 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Wed, 4 Aug 2010 15:27:47 +0400 Subject: [PATCH] New Java parser (extra '}' handling) --- .../lang/java/parser/DeclarationParser.java | 55 +++++++++---------- 1 file changed, 27 insertions(+), 28 deletions(-) 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 cd7a35024b76..bf413016b16d 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 @@ -64,7 +64,7 @@ public class DeclarationParser { @Nullable private static PsiBuilder.Marker parseClassFromKeyword(final PsiBuilder builder, final PsiBuilder.Marker declaration, - final boolean isAnnotation) { + final boolean isAnnotation, final Context context) { final IElementType keywordTokenType = builder.getTokenType(); assert ElementType.CLASS_KEYWORD_BIT_SET.contains(keywordTokenType) : keywordTokenType; builder.advanceLexer(); @@ -90,6 +90,30 @@ public class DeclarationParser { parseClassBodyWithBraces(builder, isAnnotation, isEnum); + if (context == Context.FILE) { + boolean declarationsAfterEnd = false; + + while (builder.getTokenType() != null && builder.getTokenType() != JavaTokenType.RBRACE) { + final PsiBuilder.Marker position = builder.mark(); + final PsiBuilder.Marker extra = parse(builder, Context.CLASS); + if (extra != null && AFTER_END_DECLARATION_SET.contains(exprType(extra))) { + if (!declarationsAfterEnd) { + error(builder, JavaErrorMessages.message("expected.class.or.interface"), extra); + } + declarationsAfterEnd = true; + position.drop(); + } + else { + position.rollbackTo(); + break; + } + } + + if (declarationsAfterEnd) { + expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace")); + } + } + declaration.done(JavaElementType.CLASS); return declaration; } @@ -220,7 +244,7 @@ public class DeclarationParser { if (expect(builder, JavaTokenType.AT)) { if (builder.getTokenType() == JavaTokenType.INTERFACE_KEYWORD) { - return parseClassFromKeyword(builder, declaration, true); + return parseClassFromKeyword(builder, declaration, true, context); } else { declaration.rollbackTo(); @@ -228,32 +252,7 @@ public class DeclarationParser { } } else if (ElementType.CLASS_KEYWORD_BIT_SET.contains(builder.getTokenType())) { - final PsiBuilder.Marker root = parseClassFromKeyword(builder, declaration, false); - if (context == Context.FILE) { - // todo: append following declarations to root (?) - boolean declarationsAfterEnd = false; - - while (builder.getTokenType() != null && builder.getTokenType() != JavaTokenType.RBRACE) { - final PsiBuilder.Marker position = builder.mark(); - final PsiBuilder.Marker element = parse(builder, Context.CLASS); - if (element != null && AFTER_END_DECLARATION_SET.contains(exprType(element))) { - if (!declarationsAfterEnd) { - element.precede().error(JavaErrorMessages.message("expected.class.or.interface")); - } - declarationsAfterEnd = true; - position.drop(); - } - else { - position.rollbackTo(); - break; - } - } - - if (declarationsAfterEnd) { - expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace")); - } - } - return root; + return parseClassFromKeyword(builder, declaration, false, context); } PsiBuilder.Marker typeParams = null;