package gw.plugin.ij.util;
import com.google.common.collect.Lists;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import gw.lang.parser.IBlockClass;
import gw.lang.reflect.IMetaType;
import gw.lang.reflect.IType;
import gw.lang.reflect.ITypeVariableType;
import gw.lang.reflect.TypeSystem;
import gw.lang.reflect.module.IModule;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.List;
public class TypeUtil {
public static IType getTrueEnclosingType(@NotNull IType type) {
IType enclosingType = type.getEnclosingType();
while (enclosingType instanceof IBlockClass) {
enclosingType = enclosingType.getEnclosingType();
}
return enclosingType;
}
public static IType getConcreteType(IType type) {
while (type instanceof IMetaType) {
type = ((IMetaType) type).getType();
}
while (type.isArray()) {
type = type.getComponentType();
}
while (type.isParameterizedType()) {
type = type.getGenericType();
}
if (type instanceof ITypeVariableType) {
type = getConcreteType(((ITypeVariableType) type).getBoundingType());
}
return type;
}
public static IType getType(PsiClass psiClass) {
final String qualifiedName = psiClass.getQualifiedName();
final IModule module = GosuModuleUtil.findModuleForPsiElement(psiClass);
TypeSystem.pushModule(module);
try {
return TypeSystem.getByFullNameIfValid(qualifiedName, module);
} finally {
TypeSystem.popModule(module);
}
}
public static IType getType(PsiClass psiClass, IModule module) {
TypeSystem.pushModule(module);
try {
return TypeSystem.getByFullNameIfValid(psiClass.getQualifiedName(), module);
} catch (NoClassDefFoundError e) {
// Probably, can't load dependencies of the class, just ignore the type itself
// FIXME: better way of doing that?
return null;
}
finally {
TypeSystem.popModule(module);
}
}
@NotNull
public static List<String> getTypesForFile(IModule module, VirtualFile file) {
return Arrays.asList(TypeSystem.getTypesForFile(module, FileUtil.toIFile(file)));
}
@NotNull
public static List<String> getTypesForFiles(IModule module, List<VirtualFile> files) {
final List<String> types = Lists.newArrayList();
for (VirtualFile file : files) {
types.addAll(getTypesForFile(module, file));
}
return types;
}
}