/*
* Copyright 2013 Guidewire Software, Inc.
*/
package gw.plugin.ij.lang.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.OrderEntry;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.search.GlobalSearchScope;
import gw.plugin.ij.lang.psi.IGosuNamedElement;
import gw.plugin.ij.lang.psi.api.auxilary.IGosuModifierList;
import gw.plugin.ij.lang.psi.api.expressions.IGosuIdentifier;
import gw.plugin.ij.lang.psi.api.statements.typedef.IGosuMember;
import gw.plugin.ij.lang.psi.impl.expressions.GosuMethodCallExpressionImpl;
import gw.plugin.ij.lang.psi.impl.expressions.LightGosuIdentifierImpl;
import gw.plugin.ij.lang.psi.impl.statements.typedef.GosuClassDefinitionImpl;
import gw.plugin.ij.lang.psi.util.GosuPsiParseUtil;
import gw.plugin.ij.util.JavaPsiFacadeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import static com.intellij.psi.util.PsiTreeUtil.findChildOfType;
public class GosuPsiImplUtil {
private GosuPsiImplUtil() {
}
public static String getFileSource(@NotNull PsiFile file) {
final PsiLanguageInjectionHost host = InjectedLanguageManager.getInstance(file.getProject()).getInjectionHost(file);
if (host != null) {
final LiteralTextEscaper<? extends PsiLanguageInjectionHost> escaper = host.createLiteralTextEscaper();
final StringBuilder sb = new StringBuilder();
escaper.decode(ElementManipulators.getValueTextRange(host), sb);
return sb.toString();
} else {
return file.getText();
}
}
@Nullable
public static PsiElement getOriginalElement(@NotNull PsiClass clazz, @NotNull PsiFile containingFile) {
VirtualFile vFile = containingFile.getVirtualFile();
final ProjectFileIndex idx = ProjectRootManager.getInstance(containingFile.getProject()).getFileIndex();
if (vFile == null || !idx.isInLibrarySource(vFile)) {
return clazz;
}
final String qName = clazz.getQualifiedName();
if (qName == null) {
return null;
}
final List<OrderEntry> orderEntries = idx.getOrderEntriesForFile(vFile);
PsiClass original = JavaPsiFacadeUtil.findClass(containingFile.getProject(), qName,
new GlobalSearchScope(containingFile.getProject()) {
public int compare(VirtualFile file1, VirtualFile file2) {
return 0;
}
public boolean contains(@NotNull VirtualFile file) {
// order for file and vFile has non empty intersection.
List<OrderEntry> entries = idx.getOrderEntriesForFile(file);
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < entries.size(); i++) {
final OrderEntry entry = entries.get(i);
if (orderEntries.contains(entry)) {
return true;
}
}
return false;
}
public boolean isSearchInModuleContent(@NotNull Module aModule) {
return false;
}
public boolean isSearchInLibraries() {
return true;
}
});
return original != null ? original : clazz;
}
public static PsiMethod[] mapToMethods(@Nullable List<CandidateInfo> list) {
if (list == null) {
return PsiMethod.EMPTY_ARRAY;
}
PsiMethod[] result = new PsiMethod[list.size()];
for (int i = 0; i < list.size(); i++) {
result[i] = (PsiMethod) list.get(i).getElement();
}
return result;
}
@Nullable
public static String getName(@NotNull IGosuNamedElement namedElement) {
final PsiElement nameElement = namedElement.getNameIdentifier();
final ASTNode node = nameElement == null ? null : nameElement.getNode();
if (node == null) {
return "#empty";
}
String strName = nameElement.getText();
if (nameElement instanceof LightGosuIdentifierImpl) {
strName = ((LightGosuIdentifierImpl) nameElement).getName();
}
if (strName.isEmpty()) {
if (namedElement instanceof GosuClassDefinitionImpl) {
// E.g. return the relative name of the program
return ((IGosuIdentifier) ((GosuBaseElementImpl) namedElement).getNameIdentifierImpl()).getName();
}
return "#empty";
}
return strName;
}
public static PsiElement setName(@NotNull PsiElement element, @NotNull String name) {
PsiIdentifier newNameIdentifier = GosuPsiParseUtil.parseIdentifier(name, element);
return element.replace(newNameIdentifier);
}
public static boolean isDeprecatedByAnnotation(@NotNull PsiModifierListOwner owner) {
// Java
if (PsiImplUtil.isDeprecatedByAnnotation(owner)) {
return true;
}
// Gosu
final PsiModifierList modifierList = owner.getModifierList();
return modifierList != null && modifierList.findAnnotation("gw.lang.Deprecated") != null;
}
public static final PsiElement getSuperOrThisCall(PsiElement[] children) {
if (children.length > 0) {
PsiElement callExpr = findChildOfType(children[0], GosuMethodCallExpressionImpl.class);
if (callExpr != null && (isCallOf("super", callExpr) || isCallOf("this", callExpr))) {
return callExpr;
}
}
return null;
}
private static boolean isCallOf(String name, PsiElement stmt) {
if (stmt instanceof PsiReference) {
return name.equals(((PsiReference) stmt).getCanonicalText());
}
return false;
}
public static PsiMethod findMethod(String mname, PsiMethod[] methods) {
for (PsiMethod m : methods) {
if (mname.equals(m.getName())) {
return m;
}
}
return null;
}
public static PsiElement getModifier(IGosuMember member, String modifierName) {
IGosuModifierList modifierList = member.getModifierList();
if (modifierList != null) {
PsiElement[] modifiers = modifierList.getModifiers();
if (modifiers != null) {
for (PsiElement m : modifiers) {
if (modifierName.equals(m.getText())) {
return m;
}
}
}
}
return null;
}
}