下面列出了怎么用com.intellij.psi.impl.source.tree.LeafElement的API类实例代码及写法,或者点击链接到github查看源代码。
private static FuncallExpression getRuleFuncallExpression(PsiElement element) {
PsiFile parentFile = element.getContainingFile();
if (!(parentFile instanceof BuildFile)
|| ((BuildFile) parentFile).getBlazeFileType() != BlazeFileType.BuildPackage) {
return null;
}
if (!(element instanceof LeafElement)
|| element instanceof PsiWhiteSpace
|| element instanceof PsiComment) {
return null;
}
if (!(element.getParent() instanceof ReferenceExpression)) {
return null;
}
PsiElement grandParent = element.getParent().getParent();
return grandParent instanceof FuncallExpression
&& ((FuncallExpression) grandParent).isTopLevel()
? (FuncallExpression) grandParent
: null;
}
/** Create a parse tree (AST) leaf node from a token. Doubles as a PSI leaf node.
* Does not see whitespace tokens. Default impl makes {@link LeafPsiElement}
* or {@link PsiCoreCommentImpl} depending on {@link ParserDefinition#getCommentTokens()}.
*/
@NotNull
@Override
public LeafElement createLeaf(@NotNull IElementType type, CharSequence text) {
if ( type instanceof TokenIElementType &&
((TokenIElementType) type).getANTLRTokenType()==SampleLanguageLexer.ID)
{
// found an ID node; here we do not distinguish between definitions and references
// because we have no context information here. All we know is that
// we have an identifier node that will be connected somewhere in a tree.
//
// You can only rename, find usages, etc... on leaves implementing PsiNamedElement
//
// TODO: try not to create one for IDs under def subtree roots like vardef, function
return new IdentifierPSINode(type, text);
}
LeafElement leaf = super.createLeaf(type, text);
return leaf;
}
private static TreeElement findNextLeafElementAt(ASTNode scopeNode, TreeElement last, int offset) {
int offsetR = offset;
if (last != null) {
offsetR -= last.getStartOffset() - scopeNode.getStartOffset() + last.getTextLength();
while (offsetR >= 0) {
TreeElement next = last.getTreeNext();
if (next == null) {
last = last.getTreeParent();
continue;
}
int length = next.getTextLength();
offsetR -= length;
last = next;
}
scopeNode = last;
offsetR += scopeNode.getTextLength();
}
return (LeafElement)scopeNode.findLeafElementAt(offsetR);
}
@Nonnull
@Override
public LeafElement createLeaf(@Nonnull IElementType type, @Nonnull LanguageVersion languageVersion, @Nonnull CharSequence text) {
final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(type.getLanguage());
if(parserDefinition != null) {
if(parserDefinition.getCommentTokens(languageVersion).contains(type)) {
return new PsiCoreCommentImpl(type, text);
}
}
// this is special case, then type is WHITE_SPACE, but no parser definition
if(type == TokenType.WHITE_SPACE) {
return new PsiWhiteSpaceImpl(text);
}
if (type instanceof ILeafElementType) {
return (LeafElement)((ILeafElementType)type).createLeafNode(text);
}
return new LeafPsiElement(type, text);
}
@Override
public int getNodeHash(PsiElement node) {
if (node == null) {
return 0;
}
if (node instanceof PsiWhiteSpace || node instanceof PsiErrorElement) {
return 0;
}
else if (node instanceof LeafElement) {
if (isToSkipAsLiteral(node)) {
return 0;
}
return node.getText().hashCode();
}
return node.getClass().getName().hashCode();
}
public static boolean isIgnoredNode(PsiElement element) {
// ex. "var i = 0" in AS: empty JSAttributeList should be skipped
/*if (element.getText().length() == 0) {
return true;
}*/
if (element instanceof PsiWhiteSpace || element instanceof PsiErrorElement || element instanceof PsiComment) {
return true;
}
if (!(element instanceof LeafElement)) {
return false;
}
if (CharArrayUtil.containsOnlyWhiteSpaces(element.getText())) {
return true;
}
EquivalenceDescriptorProvider descriptorProvider = EquivalenceDescriptorProvider.getInstance(element);
if (descriptorProvider == null) {
return false;
}
final IElementType elementType = ((LeafElement)element).getElementType();
return descriptorProvider.getIgnoredTokens().contains(elementType);
}
@Nullable
@Override
public Info getInfo(@NotNull PsiElement element) {
// We look for leaf nodes of a PSI tree matching the pattern of a Dart unit test, and place
// the line marker at that leaf node; see #4036 for some background.
//
// The pattern we're matching below is:
// DartCallExpression
// DartReferenceExpression
// DartId
// LeafPsiElement
if (element instanceof LeafElement && element.getParent() instanceof DartId) {
final DartId dartId = (DartId)element.getParent();
if (dartId.getParent() != null && dartId.getParent().getParent() instanceof DartCallExpression) {
final DartCallExpression dartCallExpression = (DartCallExpression)dartId.getParent().getParent();
final TestType testCall = testConfigUtils.asTestCall(dartCallExpression);
if (testCall != null) {
final Icon icon = getTestStateIcon(element, testCall.getIcon());
final Function<PsiElement, String> tooltipProvider =
psiElement -> testCall.getTooltip(psiElement, testConfigUtils);
return new RunLineMarkerContributor.Info(icon, tooltipProvider, ExecutorAction.getActions());
}
}
}
return null;
}
@Nullable
@Override
public Info getInfo(@NotNull PsiElement element) {
// We look for leaf nodes of a PSI tree matching the pattern of a Dart unit test, and place
// the line marker at that leaf node; see #4036 for some background.
//
// The pattern we're matching below is:
// DartCallExpression
// DartReferenceExpression
// DartId
// LeafPsiElement
if (element instanceof LeafElement && element.getParent() instanceof DartId) {
final DartId dartId = (DartId)element.getParent();
if (dartId.getParent() != null && dartId.getParent().getParent() instanceof DartCallExpression) {
final DartCallExpression dartCallExpression = (DartCallExpression)dartId.getParent().getParent();
final TestType testCall = testConfigUtils.asTestCall(dartCallExpression);
if (testCall != null) {
final Icon icon = getTestStateIcon(element, testCall.getIcon());
final Function<PsiElement, String> tooltipProvider =
psiElement -> testCall.getTooltip(psiElement, testConfigUtils);
return new RunLineMarkerContributor.Info(icon, tooltipProvider, ExecutorAction.getActions());
}
}
}
return null;
}
private void nodeToString(PsiElement psi, StringBuilder builder) {
if (psi.getNode() instanceof LeafElement) {
return;
}
PsiElement[] children =
Arrays.stream(psi.getChildren())
.filter(t -> t instanceof ProjectViewPsiElement)
.toArray(PsiElement[]::new);
if (psi instanceof ProjectViewPsiElement) {
builder.append(psi.getNode().getElementType());
appendChildren(children, builder, true);
} else {
appendChildren(children, builder, false);
}
}
private void nodeToString(ASTNode node, StringBuilder builder) {
if (node instanceof LeafElement || node.getPsi() == null) {
return;
}
PsiElement[] childPsis = getChildBuildPsis(node);
if (node instanceof FileASTNode) {
appendChildren(childPsis, builder, false);
return;
}
builder.append(node.getElementType());
appendChildren(childPsis, builder, true);
}
@Override
public PsiElement setName(@NotNull String newName) throws IncorrectOperationException {
final GraphQLIdentifier nameIdentifier = getNameIdentifier();
if (nameIdentifier != null) {
final LeafElement renamedLeaf = Factory.createSingleLeafElement(GraphQLElementTypes.NAME, newName, null, nameIdentifier.getManager());
final PsiElement renamedPsiElement = SourceTreeToPsiMap.treeElementToPsi(renamedLeaf);
if (renamedPsiElement != null) {
nameIdentifier.getFirstChild().replace(renamedPsiElement);
}
}
return this;
}
@Override
public GraphQLIdentifierImpl handleContentChange(@NotNull GraphQLIdentifierImpl element, @NotNull TextRange range, String newContent) throws IncorrectOperationException {
// replace the NAME leaf element inside the identifier
final LeafElement renamedLeaf = Factory.createSingleLeafElement(GraphQLElementTypes.NAME, newContent, null, element.getManager());
final PsiElement renamedPsiElement = SourceTreeToPsiMap.treeElementToPsi(renamedLeaf);
if (renamedPsiElement != null) {
element.getFirstChild().replace(renamedPsiElement);
}
return element;
}
@Override
public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException {
final PsiElement nameIdentifier = getNameIdentifier();
if(nameIdentifier != null) {
final LeafElement renamedLeaf = Factory.createSingleLeafElement(JSGraphQLEndpointTokenTypes.STRING_BODY, name, null, getManager());
final PsiElement renamedPsiElement = SourceTreeToPsiMap.treeElementToPsi(renamedLeaf);
if (renamedPsiElement != null) {
nameIdentifier.replace(renamedPsiElement);
}
}
return this;
}
/**
* Renames an identifier, e.g. during a refactoring
*/
public static PsiElement renameIdentifier(PsiNameIdentifierOwner owner, String name) throws IncorrectOperationException {
final PsiElement identifier = owner.getNameIdentifier();
if (identifier == null) {
throw new IncorrectOperationException();
}
final LeafElement renamedLeaf = Factory.createSingleLeafElement(JSGraphQLEndpointTokenTypes.IDENTIFIER, name, null, identifier.getManager());
final PsiElement renamedPsiElement = SourceTreeToPsiMap.treeElementToPsi(renamedLeaf);
if (renamedPsiElement != null) {
identifier.replace(renamedPsiElement);
}
return owner;
}
@Nullable
@Override
public LeafElement createLeaf(IElementType type, CharSequence text) {
if (HaxeTokenTypeSets.COMMENTS.contains(type)) {
return new PsiCommentImpl(type, text);
}
return new HaxePsiTokenImpl(type, text);
}
@Override
@Nonnull
public PsiElement createWhiteSpaceFromText(@Nonnull @NonNls String text) throws IncorrectOperationException {
final FileElement holderElement = DummyHolderFactory.createHolder(myManager, null).getTreeElement();
final LeafElement newElement = ASTFactory.leaf(TokenType.WHITE_SPACE, holderElement.getCharTable().intern(text));
holderElement.rawAddChildren(newElement);
GeneratedMarkerVisitor.markGenerated(newElement.getPsi());
return newElement.getPsi();
}
public static void replaceChild(ASTNode parent, @Nonnull ASTNode oldChild, @Nonnull ASTNode newChild) {
saveWhitespacesInfo(oldChild);
saveWhitespacesInfo(newChild);
checkForOuters(oldChild);
checkForOuters(newChild);
LeafElement oldFirst = TreeUtil.findFirstLeaf(oldChild);
parent.replaceChild(oldChild, newChild);
final LeafElement firstLeaf = TreeUtil.findFirstLeaf(newChild);
final ASTNode prevToken = TreeUtil.prevLeaf(newChild);
if (firstLeaf != null) {
final ASTNode nextLeaf = TreeUtil.nextLeaf(newChild);
makePlaceHolderBetweenTokens(prevToken, firstLeaf, isFormattingRequired(prevToken, newChild), false);
if (nextLeaf != null && !CharArrayUtil.containLineBreaks(nextLeaf.getText())) {
makePlaceHolderBetweenTokens(TreeUtil.prevLeaf(nextLeaf), nextLeaf, false, false);
}
}
else {
if (oldFirst != null && prevToken == null) {
ASTNode whitespaceNode = newChild.getTreeNext();
if (whitespaceNode != null && whitespaceNode.getElementType() == TokenType.WHITE_SPACE) {
// Replacing non-empty prefix to empty shall remove whitespace
parent.removeChild(whitespaceNode);
}
}
makePlaceHolderBetweenTokens(prevToken, TreeUtil.nextLeaf(newChild), isFormattingRequired(prevToken, newChild), false);
}
}
@Nullable
private static ASTNode findFirstLeaf(ASTNode first, ASTNode last) {
do {
final LeafElement leaf = TreeUtil.findFirstLeaf(first);
if (leaf != null) return leaf;
first = first.getTreeNext();
if (first == null) return null;
}
while (first != last);
return null;
}
@Override
public LeafElement split(LeafElement leaf, int offset, final CharTable table) {
final CharSequence chars = leaf.getChars();
final LeafElement leftPart = ASTFactory.leaf(leaf.getElementType(), table.intern(chars, 0, offset));
final LeafElement rightPart = ASTFactory.leaf(leaf.getElementType(), table.intern(chars, offset, chars.length()));
leaf.rawInsertAfterMe(leftPart);
leftPart.rawInsertAfterMe(rightPart);
leaf.rawRemove();
return leftPart;
}
private boolean isLiteral(PsiElement node) {
if (node instanceof LeafElement) {
final IElementType elementType = ((LeafElement)node).getElementType();
if (myDuplicatesProfile.getLiterals().contains(elementType)) {
return true;
}
}
return false;
}
public static boolean shouldSkip(PsiElement element, PsiElement elementToMatchWith) {
if (element == null || elementToMatchWith == null) {
return false;
}
if (element.getClass() == elementToMatchWith.getClass()) {
return false;
}
if (element.getFirstChild() == null && element.getTextLength() == 0 && !(element instanceof LeafElement)) {
return true;
}
return false;
}
@Nullable
@Override
public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull final InspectionManager manager, final boolean isOnTheFly) {
if (!(file instanceof HaxeFile)) return null;
final List<ProblemDescriptor> result = new ArrayList<ProblemDescriptor>();
final ProblemReporter reporter = new ProblemReporter() {
@Override
public void reportProblem(ASTNode node, String message) {
result.add( manager.createProblemDescriptor( node.getPsi(),
message,
(LocalQuickFix)null,
ProblemHighlightType.ERROR,
isOnTheFly));
}
};
FileASTNode node1 = file.getNode();
LeafElement firstLeaf = TreeUtil.findFirstLeaf(node1);
Stack<List<ASTNode>> levels = new Stack<List<ASTNode>>();
List<ASTNode> nodes = new ArrayList<ASTNode>();
// Push the root node, just in case there is no #if to start it off.
levels.push(nodes);
ASTNode leaf = firstLeaf;
while (leaf != null) {
IElementType leafElementType = leaf.getElementType();
if (leafElementType.equals(HaxeTokenTypes.PPIF)) {
nodes = new ArrayList<ASTNode>();
levels.push(nodes);
nodes.add(leaf);
}
else if (leafElementType.equals(HaxeTokenTypes.PPEND)) {
nodes.add(leaf);
// Leave the base level in place, even if there are extra ends.
if (levels.size() > 1) {
validateLevel(nodes, reporter);
levels.pop();
nodes = levels.peek();
}
}
else if (leafElementType.equals(HaxeTokenTypes.PPELSEIF)) {
nodes.add(leaf);
}
else if (leafElementType.equals(HaxeTokenTypes.PPELSE)) {
nodes.add(leaf);
}
leaf = TreeUtil.nextLeaf(leaf);
}
// Any levels that are still left need to be validated.
for (List<ASTNode> level : levels) {
validateLevel(level, reporter);
}
return ArrayUtil.toObjectArray(result, ProblemDescriptor.class);
}
@Nonnull
LeafElement createLeaf(@Nonnull IElementType type, @Nonnull LanguageVersion languageVersion, @Nonnull CharSequence text);
@Nonnull
public static LeafElement leaf(@Nonnull final IElementType type, final CharSequence text) {
return leaf(type, LanguageVersionUtil.findDefaultVersion(type.getLanguage()), text);
}
@Nonnull
public static LeafElement leaf(@Nonnull final IElementType type, @Nonnull LanguageVersion languageVersion, final CharSequence text) {
return ASTLeafFactory.EP.getValue(type).createLeaf(type, languageVersion, text);
}
@Nonnull
public static LeafElement whitespace(final CharSequence text) {
final PsiWhiteSpaceImpl w = new PsiWhiteSpaceImpl(WHITESPACES.intern(text));
CodeEditUtil.setNodeGenerated(w, true);
return w;
}
@Override
public PsiElement findElementAt(final int offset) {
final LeafElement element = myHolder.calcTreeElement().findLeafElementAt(offset);
return element != null ? element.getPsi() : null;
}
@Nullable
private static ASTNode makePlaceHolderBetweenTokens(ASTNode left, ASTNode right, boolean forceReformat, boolean normalizeTrailingWS) {
if (right == null) return left;
markToReformatBefore(right, false);
if (left == null) {
markToReformatBefore(right, true);
}
else if (left.getElementType() == TokenType.WHITE_SPACE && left.getTreeNext() == null && normalizeTrailingWS) {
// handle tailing whitespaces if element on the left has been removed
final ASTNode prevLeaf = TreeUtil.prevLeaf(left);
left.getTreeParent().removeChild(left);
markToReformatBeforeOrInsertWhitespace(prevLeaf, right);
left = right;
}
else if (left.getElementType() == TokenType.WHITE_SPACE && right.getElementType() == TokenType.WHITE_SPACE) {
final String text;
final int leftBlankLines = getBlankLines(left.getText());
final int rightBlankLines = getBlankLines(right.getText());
final boolean leaveRightText = leftBlankLines < rightBlankLines;
if (leftBlankLines == 0 && rightBlankLines == 0) {
text = left.getText() + right.getText();
}
else if (leaveRightText) {
text = right.getText();
}
else {
text = left.getText();
}
if (leaveRightText || forceReformat) {
final LeafElement merged = ASTFactory.whitespace(text);
if (!leaveRightText) {
left.getTreeParent().replaceChild(left, merged);
right.getTreeParent().removeChild(right);
}
else {
right.getTreeParent().replaceChild(right, merged);
left.getTreeParent().removeChild(left);
}
left = merged;
}
else {
right.getTreeParent().removeChild(right);
}
}
else if (left.getElementType() != TokenType.WHITE_SPACE || forceReformat) {
if (right.getElementType() == TokenType.WHITE_SPACE) {
markWhitespaceForReformat(right);
}
else if (left.getElementType() == TokenType.WHITE_SPACE) {
markWhitespaceForReformat(left);
}
else {
markToReformatBeforeOrInsertWhitespace(left, right);
}
}
return left;
}
private static void markWhitespaceForReformat(final ASTNode right) {
final String text = right.getText();
final LeafElement merged = ASTFactory.whitespace(text);
right.getTreeParent().replaceChild(right, merged);
}
@Override
public boolean addWhitespace(@Nonnull ASTNode treePrev, @Nonnull LeafElement whiteSpaceElement) {
return false;
}