/*
* Copyright 2015-present Facebook, Inc.
*
* 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.facebook.buck.intellij.ideabuck.lang.psi;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import java.util.List;
public final class BuckPsiUtils {
public static final TokenSet STRING_LITERALS =
TokenSet.create(BuckTypes.SINGLE_QUOTED_STRING, BuckTypes.DOUBLE_QUOTED_STRING);
private BuckPsiUtils() {}
/**
* Check that element type of the given AST node belongs to the token set.
*
* <p>It slightly less verbose than {@code set.contains(node.getElementType())} and overloaded
* methods with the same name allow check ASTNode/PsiElement against both concrete element types
* and token sets in uniform way.
*/
public static boolean hasElementType(ASTNode node, TokenSet set) {
return set.contains(node.getElementType());
}
/** @see #hasElementType(com.intellij.lang.ASTNode, com.intellij.psi.tree.TokenSet) */
public static boolean hasElementType(ASTNode node, IElementType... types) {
return hasElementType(node, TokenSet.create(types));
}
/** @see #hasElementType(com.intellij.lang.ASTNode, com.intellij.psi.tree.TokenSet) */
public static boolean hasElementType(PsiElement element, TokenSet set) {
return element.getNode() != null && hasElementType(element.getNode(), set);
}
/** @see #hasElementType(com.intellij.lang.ASTNode, com.intellij.psi.tree.IElementType...) */
public static boolean hasElementType(PsiElement element, IElementType... types) {
return element.getNode() != null && hasElementType(element.getNode(), types);
}
/** Test the text value of a PSI element. */
public static boolean testType(PsiElement element, IElementType type) {
return element.getNode() != null && element.getNode().getElementType() == type;
}
/** Find the ancestor element with a specific type */
public static PsiElement findAncestorWithType(PsiElement element, IElementType type) {
PsiElement parent = element.getParent();
while (parent != null) {
if (parent.getNode() != null && parent.getNode().getElementType() == type) {
return parent;
}
parent = parent.getParent();
}
return null;
}
/** Find the first child with a specific type */
public static PsiElement findChildWithType(PsiElement element, IElementType type) {
PsiElement[] children = element.getChildren();
for (PsiElement child : children) {
if (child.getNode().getElementType() == type) {
return child;
}
}
return null;
}
/**
* Return the text content if the given BuckExpression has only one string value. Return null if
* this expression has multiple values, for example: "a" + "b"
*/
public static String getStringValueFromExpression(BuckExpression expression) {
List<BuckValue> values = expression.getValueList();
if (values.size() != 1) {
return null;
}
PsiElement value = values.get(0); // This should be a "Value" type.
if (value.getFirstChild() != null
&& BuckPsiUtils.hasElementType(value.getFirstChild(), BuckPsiUtils.STRING_LITERALS)) {
String text = value.getFirstChild().getText();
return text.length() > 2 ? text.substring(1, text.length() - 1) : null;
} else {
return null;
}
}
}