package pl.charmas.parcelablegenerator.util; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiType; import com.intellij.psi.util.PsiTypesUtil; import java.util.ArrayList; import java.util.List; /** * Utils for introspecting Psi* stuff * * @author Dallas Gutauckis [dallas@gutauckis.com] */ final public class PsiUtils { private PsiUtils() { } /** * Checks that the given type is an implementer of the given canonicalName with the given typed parameters * * @param type what we're checking against * @param canonicalName the type must extend/implement this generic * @param canonicalParamNames the type that the generic(s) must be (in this order) * @return */ public static boolean isTypedClass(PsiType type, String canonicalName, String... canonicalParamNames) { PsiClass parameterClass = PsiTypesUtil.getPsiClass(type); if (parameterClass == null) { return false; } // This is a safe cast, for if parameterClass != null, the type was checked in PsiTypesUtil#getPsiClass(...) PsiClassType pct = (PsiClassType) type; // Main class name doesn't match; exit early if (!canonicalName.equals(parameterClass.getQualifiedName())) { return false; } List<PsiType> psiTypes = new ArrayList<PsiType>(pct.resolveGenerics().getSubstitutor().getSubstitutionMap().values()); for (int i = 0; i < canonicalParamNames.length; i++) { if (!isOfType(psiTypes.get(i), canonicalParamNames[i])) { return false; } } // Passed all screenings; must be a match! return true; } /** * Resolves generics on the given type and returns them (if any) or null if there are none * * @param type * @return */ public static List<PsiType> getResolvedGenerics(PsiType type) { List<PsiType> psiTypes = null; if (type instanceof PsiClassType) { PsiClassType pct = (PsiClassType) type; psiTypes = new ArrayList<PsiType>(pct.resolveGenerics().getSubstitutor().getSubstitutionMap().values()); } return psiTypes; } public static boolean isOfType(PsiType type, String canonicalName) { if (type.getCanonicalText().equals(canonicalName)) { return true; } final String nonGenericType = getNonGenericType(type); if (nonGenericType != null && nonGenericType.equals(canonicalName)) { return true; } for (PsiType iterType : type.getSuperTypes()) { if (isOfType(iterType, canonicalName)) { return true; } } return false; } public static String getNonGenericType(PsiType type) { if (type instanceof PsiClassType) { PsiClassType pct = (PsiClassType) type; final PsiClass psiClass = pct.resolve(); return psiClass != null ? psiClass.getQualifiedName() : null; } return type.getCanonicalText(); } }