PsiType (@Nullable PsiType type, @NotNull PsiSubstitutor beforeSubstitutor) { if (type == null) return null; return type.accept(new PsiTypeVisitor<PsiType>() { @NotNull @Override public PsiType visitType(@NotNull PsiType type) { return type; } @Override public PsiType visitClassType(@NotNull PsiClassType classType) { final PsiClass aClass = classType.resolve(); if (aClass instanceof PsiTypeParameter && !isFreshVariable((PsiTypeParameter)aClass)) { return typeParameterErasure((PsiTypeParameter)aClass, beforeSubstitutor); } return classType.rawType(); } @Override public PsiType visitWildcardType(@NotNull PsiWildcardType wildcardType) { return wildcardType; } @Nullable @Override public PsiType visitCapturedWildcardType(@NotNull PsiCapturedWildcardType capturedWildcardType) { return capturedWildcardType.getUpperBound().accept(this); } @Override public PsiType visitPrimitiveType(@NotNull PsiPrimitiveType primitiveType) { return primitiveType; } @Override public PsiType visitArrayType(@NotNull PsiArrayType arrayType) { final PsiType componentType = arrayType.getComponentType(); final PsiType newComponentType = componentType.accept(this); if (newComponentType == componentType) return arrayType; return newComponentType != null ? newComponentType.createArrayType() : null; } @Override public PsiType visitDisjunctionType(@NotNull PsiDisjunctionType disjunctionType) { final PsiClassType lub = PsiTypesUtil.getLowestUpperBoundClassType(disjunctionType); return lub != null ? erasure(lub, beforeSubstitutor) : disjunctionType; } }); }