package de.plushnikov.intellij.plugin.util; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.psi.CommonClassNames; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiElementFactory; import com.intellij.psi.PsiKeyword; import com.intellij.psi.PsiManager; import com.intellij.psi.PsiPrimitiveType; import com.intellij.psi.PsiSubstitutor; import com.intellij.psi.PsiType; import com.intellij.psi.PsiTypeParameter; import com.intellij.psi.PsiWildcardType; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class PsiTypeUtil { @NotNull public static PsiType extractOneElementType(@NotNull PsiType psiType, @NotNull PsiManager psiManager) { return extractOneElementType(psiType, psiManager, CommonClassNames.JAVA_LANG_ITERABLE, 0); } @NotNull public static PsiType extractOneElementType(@NotNull PsiType psiType, @NotNull PsiManager psiManager, final String superClass, final int paramIndex) { PsiType oneElementType = PsiUtil.substituteTypeParameter(psiType, superClass, paramIndex, true); if (oneElementType instanceof PsiWildcardType) { oneElementType = ((PsiWildcardType) oneElementType).getBound(); } if (null == oneElementType) { oneElementType = PsiType.getJavaLangObject(psiManager, GlobalSearchScope.allScope(psiManager.getProject())); } return oneElementType; } @NotNull public static PsiType extractAllElementType(@NotNull PsiType psiType, @NotNull PsiManager psiManager) { return extractAllElementType(psiType, psiManager, CommonClassNames.JAVA_LANG_ITERABLE, 0); } @NotNull public static PsiType extractAllElementType(@NotNull PsiType psiType, @NotNull PsiManager psiManager, final String superClass, final int paramIndex) { PsiType oneElementType = PsiUtil.substituteTypeParameter(psiType, superClass, paramIndex, true); if (oneElementType instanceof PsiWildcardType) { oneElementType = ((PsiWildcardType) oneElementType).getBound(); } PsiType result; final PsiClassType javaLangObject = PsiType.getJavaLangObject(psiManager, GlobalSearchScope.allScope(psiManager.getProject())); if (null == oneElementType || Comparing.equal(javaLangObject, oneElementType)) { result = PsiWildcardType.createUnbounded(psiManager); } else { result = PsiWildcardType.createExtends(psiManager, oneElementType); } return result; } @NotNull public static PsiType createCollectionType(@NotNull PsiManager psiManager, final String collectionQualifiedName, @NotNull PsiType... psiTypes) { final Project project = psiManager.getProject(); final GlobalSearchScope globalsearchscope = GlobalSearchScope.allScope(project); final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); PsiClass genericClass = facade.findClass(collectionQualifiedName, globalsearchscope); return JavaPsiFacade.getElementFactory(project).createType(genericClass, psiTypes); } @NotNull public static PsiType[] extractTypeParameters(@NotNull PsiType psiType, @NotNull PsiManager psiManager) { if (!(psiType instanceof PsiClassType)) { return PsiType.EMPTY_ARRAY; } final PsiClassType classType = (PsiClassType) psiType; final PsiClassType.ClassResolveResult classResolveResult = classType.resolveGenerics(); final PsiClass psiClass = classResolveResult.getElement(); if (psiClass == null) { return PsiType.EMPTY_ARRAY; } final PsiSubstitutor psiSubstitutor = classResolveResult.getSubstitutor(); final PsiTypeParameter[] typeParameters = psiClass.getTypeParameters(); final PsiType[] psiTypes = PsiType.createArray(typeParameters.length); for (int i = 0; i < typeParameters.length; i++) { PsiType psiSubstituteKeyType = psiSubstitutor.substitute(typeParameters[i]); if (null == psiSubstituteKeyType) { psiSubstituteKeyType = PsiType.getJavaLangObject(psiManager, GlobalSearchScope.allScope(psiManager.getProject())); } psiTypes[i] = psiSubstituteKeyType; } return psiTypes; } @NotNull public static PsiClassType getGenericCollectionClassType(@NotNull PsiType psiType, @NotNull Project project, @NotNull String qualifiedName) { final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); final GlobalSearchScope globalsearchscope = GlobalSearchScope.allScope(project); PsiClass genericClass = facade.findClass(qualifiedName, globalsearchscope); if (null != genericClass) { PsiSubstitutor genericSubstitutor = PsiSubstitutor.EMPTY.putAll(genericClass, new PsiType[]{psiType}); return elementFactory.createType(genericClass, genericSubstitutor); } return elementFactory.createTypeByFQClassName(qualifiedName, globalsearchscope); } @NotNull public static PsiClassType getCollectionClassType(@NotNull PsiClassType psiType, @NotNull Project project, @NotNull String qualifiedName) { final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); final GlobalSearchScope globalsearchscope = GlobalSearchScope.allScope(project); PsiClass genericClass = facade.findClass(qualifiedName, globalsearchscope); if (null != genericClass) { final PsiClassType.ClassResolveResult classResolveResult = psiType.resolveGenerics(); final PsiSubstitutor derivedSubstitutor = classResolveResult.getSubstitutor(); final List<PsiType> typeList = new ArrayList<PsiType>(2); final Map<String, PsiType> nameTypeMap = new HashMap<String, PsiType>(); for (Map.Entry<PsiTypeParameter, PsiType> entry : derivedSubstitutor.getSubstitutionMap().entrySet()) { final PsiType entryValue = entry.getValue(); if (null != entryValue) { nameTypeMap.put(entry.getKey().getName(), entryValue); typeList.add(entryValue); } } PsiSubstitutor genericSubstitutor = PsiSubstitutor.EMPTY; final PsiTypeParameter[] typeParameters = genericClass.getTypeParameters(); for (int i = 0; i < typeParameters.length; i++) { final PsiTypeParameter psiTypeParameter = typeParameters[i]; PsiType mappedType = nameTypeMap.get(psiTypeParameter.getName()); if (null == mappedType && typeList.size() > i) { mappedType = typeList.get(i); } if (null == mappedType) { mappedType = PsiType.getJavaLangObject(PsiManager.getInstance(project), globalsearchscope); } if (mappedType instanceof PsiWildcardType) { mappedType = ((PsiWildcardType) mappedType).getBound(); } genericSubstitutor = genericSubstitutor.put(psiTypeParameter, mappedType); } return elementFactory.createType(genericClass, genericSubstitutor); } return elementFactory.createTypeByFQClassName(qualifiedName, globalsearchscope); } @Nullable public static String getQualifiedName(@NotNull PsiType psiType) { final PsiClass psiFieldClass = PsiUtil.resolveClassInType(psiType); return psiFieldClass != null ? psiFieldClass.getQualifiedName() : null; } @NotNull public static String getReturnValueOfType(@Nullable PsiType type) { if (type instanceof PsiPrimitiveType) { if (PsiType.BOOLEAN.equals(type)) { return PsiKeyword.FALSE; } else { return "0"; } } else if (PsiType.VOID.equals(type)) { return ""; } else { return PsiKeyword.NULL; } } }