New Java parser - unification and cleanup

This commit is contained in:
Roman Shevchenko
2010-09-02 16:10:43 +04:00
parent bc3413b7bf
commit aefacae4b2
2 changed files with 49 additions and 6 deletions
@@ -33,15 +33,11 @@ import static com.intellij.lang.java.parser.JavaParserUtil.semicolon;
public class FileParser {
public interface TopLevelDeclarationParser {
@Nullable PsiBuilder.Marker parse(PsiBuilder builder);
}
private static final TokenSet IMPORT_LIST_STOPPER_SET = TokenSet.orSet(
ElementType.MODIFIER_BIT_SET,
TokenSet.create(JavaTokenType.CLASS_KEYWORD, JavaTokenType.INTERFACE_KEYWORD, JavaTokenType.ENUM_KEYWORD, JavaTokenType.AT));
private static final TopLevelDeclarationParser TOP_LEVEL_DECLARATION_PARSER = new TopLevelDeclarationParser() {
private static final JavaParserUtil.MarkingParserWrapper TOP_LEVEL_DECLARATION_PARSER = new JavaParserUtil.MarkingParserWrapper() {
public PsiBuilder.Marker parse(final PsiBuilder builder) {
return DeclarationParser.parse(builder, DeclarationParser.Context.FILE);
}
@@ -54,7 +50,7 @@ public class FileParser {
}
public static void parseFile(final PsiBuilder builder, final TokenSet importListStoppers,
final TopLevelDeclarationParser declarationParser, final String errorMessage) {
final JavaParserUtil.MarkingParserWrapper declarationParser, final String errorMessage) {
parsePackageStatement(builder);
final Pair<PsiBuilder.Marker, Boolean> impListInfo = parseImportList(builder, importListStoppers);
@@ -17,10 +17,14 @@ package com.intellij.lang.java.parser;
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.lang.*;
import com.intellij.lang.java.JavaParserDefinition;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.tree.ElementType;
import com.intellij.psi.impl.source.tree.JavaDocElementType;
import com.intellij.psi.impl.source.tree.JavaElementType;
@@ -37,6 +41,14 @@ import java.util.List;
public class JavaParserUtil {
private static final Key<LanguageLevel> LANG_LEVEL_KEY = Key.create("JavaParserUtil.LanguageLevel");
public interface ParserWrapper {
void parse(PsiBuilder builder);
}
public interface MarkingParserWrapper {
@Nullable PsiBuilder.Marker parse(PsiBuilder builder);
}
public static final WhitespacesAndCommentsProcessor GREEDY_RIGHT_EDGE_PROCESSOR = new WhitespacesAndCommentsProcessor() {
public int process(final List<IElementType> tokens, final boolean atStreamEdge, final TokenTextGetter getter) {
return tokens.size();
@@ -130,6 +142,41 @@ public class JavaParserUtil {
return level;
}
@NotNull
public static PsiBuilder createBuilder(final ASTNode chameleon) {
final PsiElement psi = chameleon.getPsi();
assert psi != null : chameleon;
final Project project = psi.getProject();
final PsiBuilderFactory factory = PsiBuilderFactory.getInstance();
final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(StdLanguages.JAVA);
final PsiBuilder builder = factory.createBuilder(parserDefinition.createLexer(project), StdLanguages.JAVA, chameleon.getChars());
final LanguageLevel level = LanguageLevelProjectExtension.getInstance(project).getLanguageLevel();
setLanguageLevel(builder, level);
return builder;
}
@NotNull
public static ASTNode parseFragment(final ASTNode chameleon, final ParserWrapper wrapper) {
final PsiBuilderFactory factory = PsiBuilderFactory.getInstance();
final LanguageLevel level = LanguageLevel.HIGHEST;
final PsiBuilder builder = factory.createBuilder(JavaParserDefinition.createLexer(level), StdLanguages.JAVA, chameleon.getChars());
setLanguageLevel(builder, level);
final PsiBuilder.Marker root = builder.mark();
wrapper.parse(builder);
if (!builder.eof()) {
final PsiBuilder.Marker extras = builder.mark();
while (!builder.eof()) builder.advanceLexer();
extras.error(JavaErrorMessages.message("unexpected.tokens"));
}
root.done(chameleon.getElementType());
return builder.getTreeBuilt().getFirstChildNode();
}
public static void done(final PsiBuilder.Marker marker, final IElementType type) {
marker.done(type);
final WhitespacesAndCommentsProcessor left = PRECEDING_COMMENT_SET.contains(type) ? PRECEDING_COMMENT_BINDER : null;