Dummy Java element with pluggable parser

This commit is contained in:
Roman Shevchenko
2010-12-16 14:51:10 +03:00
parent 6cf386c376
commit 2e8fa6eb9b
4 changed files with 121 additions and 6 deletions
@@ -184,13 +184,18 @@ public class JavaParserUtil {
return builder;
}
@Nullable
public static ASTNode parseFragment(final ASTNode chameleon, final ParserWrapper wrapper) {
return parseFragment(chameleon, wrapper, true, LanguageLevel.HIGHEST);
}
@Nullable
public static ASTNode parseFragment(final ASTNode chameleon, final ParserWrapper wrapper, final boolean eatAll, final LanguageLevel level) {
final PsiElement psi = (chameleon.getTreeParent() != null ? chameleon.getTreeParent().getPsi() : chameleon.getPsi());
assert psi != null : chameleon;
final Project project = psi.getProject();
final PsiBuilderFactory factory = PsiBuilderFactory.getInstance();
final LanguageLevel level = LanguageLevel.HIGHEST;
final Lexer lexer = JavaParserDefinition.createLexer(level);
final PsiBuilder builder = factory.createBuilder(project, chameleon, lexer, chameleon.getElementType().getLanguage(), chameleon.getChars());
setLanguageLevel(builder, level);
@@ -198,6 +203,7 @@ public class JavaParserUtil {
final PsiBuilder.Marker root = builder.mark();
wrapper.parse(builder);
if (!builder.eof()) {
if (!eatAll) throw new AssertionError("Unexpected tokens");
final PsiBuilder.Marker extras = builder.mark();
while (!builder.eof()) builder.advanceLexer();
extras.error(JavaErrorMessages.message("unexpected.tokens"));
@@ -389,4 +395,4 @@ public class JavaParserUtil {
myDelegate.putUserDataUnprotected(key, value);
}
}
}
}
@@ -0,0 +1,82 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.impl.source;
import com.intellij.lang.java.parser.JavaParserUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.impl.source.tree.TreeElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Dummy file element for using together with DummyHolder.
* See {@link com.intellij.psi.impl.PsiJavaParserFacadeImpl} for details.
*/
public class JavaDummyElement extends FileElement {
@NotNull private final JavaParserUtil.ParserWrapper myParser;
private final boolean myConsumeAll;
@NotNull private final LanguageLevel myLanguageLevel;
public JavaDummyElement(@Nullable final CharSequence text, @NotNull final JavaParserUtil.ParserWrapper parser, final boolean consumeAll) {
this(text, parser, consumeAll, LanguageLevel.HIGHEST);
}
public JavaDummyElement(@Nullable final CharSequence text,
@NotNull final JavaParserUtil.ParserWrapper parser,
final boolean consumeAll,
@NotNull final LanguageLevel level) {
super(JavaElementType.DUMMY_ELEMENT, text);
myParser = parser;
myConsumeAll = consumeAll;
myLanguageLevel = level;
}
@NotNull
public JavaParserUtil.ParserWrapper getParser() {
return myParser;
}
public boolean consumeAll() {
return myConsumeAll;
}
@NotNull
public LanguageLevel getLanguageLevel() {
return myLanguageLevel;
}
@Override
public TreeElement getFirstChildNode() {
try {
return super.getFirstChildNode();
}
catch (AssertionError e) {
return null; // masquerade parser errors
}
}
@Override
public TreeElement getLastChildNode() {
try {
return super.getLastChildNode();
}
catch (AssertionError e) {
return null; // masquerade parser errors
}
}
}
@@ -28,6 +28,7 @@ import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.source.JavaDummyElement;
import com.intellij.psi.impl.source.parsing.JavaParsingContext;
import com.intellij.psi.impl.source.parsing.Parsing;
import com.intellij.psi.impl.source.tree.java.PsiCodeBlockImpl;
@@ -40,6 +41,7 @@ import com.intellij.psi.tree.java.IJavaElementType;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.CharTable;
import com.intellij.util.diff.FlyweightCapableTreeStructure;
import org.jetbrains.annotations.Nullable;
import static com.intellij.lang.PsiBuilderUtil.expect;
@@ -158,6 +160,7 @@ public interface JavaElementType {
seq, 0, seq.length(), 0).getFirstChildNode();
}
@Override
public int getErrorsCount(final CharSequence seq, final Project project) {
final Lexer lexer = new JavaLexer(LanguageLevel.HIGHEST);
@@ -184,6 +187,7 @@ public interface JavaElementType {
class ICodeBlockNewElementType extends ICodeBlockElementType implements ILightLazyParseableElementType {
private ICodeBlockNewElementType() { }
@Override
public FlyweightCapableTreeStructure<LighterASTNode> parseContents(final LighterLazyParseableNode chameleon) {
final PsiBuilder builder = JavaParserUtil.createBuilder(chameleon);
StatementParser.parseCodeBlockDeep(builder, true);
@@ -194,6 +198,8 @@ public interface JavaElementType {
ILazyParseableElementType CODE_BLOCK = JavaParserDefinition.USE_NEW_PARSER ? new ICodeBlockNewElementType() : new ICodeBlockElementType();
IElementType STATEMENTS = new ICodeFragmentElementType("STATEMENTS", StdLanguages.JAVA) {
@Nullable
@Override
public ASTNode parseContents(final ASTNode chameleon) {
if (JavaParserDefinition.USE_NEW_PARSER) {
return JavaParserUtil.parseFragment(chameleon,
@@ -213,6 +219,8 @@ public interface JavaElementType {
};
IElementType EXPRESSION_TEXT = new ICodeFragmentElementType("EXPRESSION_TEXT", StdLanguages.JAVA) {
@Nullable
@Override
public ASTNode parseContents(final ASTNode chameleon) {
if (JavaParserDefinition.USE_NEW_PARSER) {
return JavaParserUtil.parseFragment(chameleon,
@@ -231,6 +239,8 @@ public interface JavaElementType {
};
IElementType REFERENCE_TEXT = new ICodeFragmentElementType("REFERENCE_TEXT", StdLanguages.JAVA) {
@Nullable
@Override
public ASTNode parseContents(final ASTNode chameleon) {
if (JavaParserDefinition.USE_NEW_PARSER) {
return JavaParserUtil.parseFragment(chameleon,
@@ -248,6 +258,8 @@ public interface JavaElementType {
};
IElementType TYPE_TEXT = new ICodeFragmentElementType("TYPE_TEXT", StdLanguages.JAVA) {
@Nullable
@Override
public ASTNode parseContents(final ASTNode chameleon) {
if (JavaParserDefinition.USE_NEW_PARSER) {
return JavaParserUtil.parseFragment(chameleon,
@@ -264,4 +276,14 @@ public interface JavaElementType {
SharedImplUtil.findCharTableByTree(chameleon));
}
};
IElementType DUMMY_ELEMENT = new ILazyParseableElementType("DUMMY_ELEMENT", StdLanguages.JAVA) {
@Nullable
@Override
public ASTNode parseContents(final ASTNode chameleon) {
assert chameleon instanceof JavaDummyElement : chameleon;
final JavaDummyElement dummyElement = (JavaDummyElement)chameleon;
return JavaParserUtil.parseFragment(chameleon, dummyElement.getParser(), dummyElement.consumeAll(), dummyElement.getLanguageLevel());
}
};
}
@@ -56,7 +56,12 @@ public class DummyHolder extends PsiFileImpl {
((DummyHolderViewProvider)getViewProvider()).setDummyHolder(this);
myContext = context;
myTable = table != null ? table : IdentityCharTable.INSTANCE;
if(contentElement != null) {
if (contentElement instanceof FileElement) {
myFileElement = (FileElement)contentElement;
myFileElement.setPsi(this);
if (myTable != null) myFileElement.setCharTable(myTable);
}
else if (contentElement != null) {
getTreeElement().rawAddChildren(contentElement);
clearCaches();
}
@@ -81,7 +86,7 @@ public class DummyHolder extends PsiFileImpl {
}
public boolean isValid() {
if(myExplicitlyValid != null) return myExplicitlyValid.booleanValue();
if (myExplicitlyValid != null) return myExplicitlyValid.booleanValue();
return super.isValid() && !(myContext != null && !myContext.isValid());
}
@@ -112,10 +117,10 @@ public class DummyHolder extends PsiFileImpl {
}
public FileElement getTreeElementNoLock() {
if(myFileElement == null){
if (myFileElement == null) {
myFileElement = new FileElement(TokenType.DUMMY_HOLDER, null);
myFileElement.setPsi(this);
if(myTable != null) myFileElement.setCharTable(myTable);
if (myTable != null) myFileElement.setCharTable(myTable);
clearCaches();
}
return myFileElement;