@SuppressWarnings({"unchecked"}) @NotNull public static <T extends PsiType> T originalize(@NotNull T type) { if (!type.isValid()) { return type; } T result = new PsiTypeMapper() { private final Set<PsiClassType> myVisited = ContainerUtil.newIdentityTroveSet(); @Override public PsiType visitClassType(final PsiClassType classType) { if (!myVisited.add(classType)) return classType; final PsiClassType.ClassResolveResult classResolveResult = classType.resolveGenerics(); final PsiClass psiClass = classResolveResult.getElement(); final PsiSubstitutor substitutor = classResolveResult.getSubstitutor(); if (psiClass == null) return classType; return new PsiImmediateClassType( CompletionUtil.getOriginalOrSelf(psiClass), originalizeSubstitutor(substitutor)); } private PsiSubstitutor originalizeSubstitutor(final PsiSubstitutor substitutor) { PsiSubstitutor originalSubstitutor = PsiSubstitutor.EMPTY; for (final Map.Entry<PsiTypeParameter, PsiType> entry : substitutor.getSubstitutionMap().entrySet()) { final PsiType value = entry.getValue(); originalSubstitutor = originalSubstitutor.put( CompletionUtil.getOriginalOrSelf(entry.getKey()), value == null ? null : mapType(value)); } return originalSubstitutor; } @Override public PsiType visitType(PsiType type) { return type; } }.mapType(type); if (result == null) { throw new AssertionError("Null result for type " + type + " of class " + type.getClass()); } return result; }