@Nullable
 private PsiType extractContentTypeFromType(PsiType collectionType) {
   if (!(collectionType instanceof PsiClassType)) {
     return null;
   }
   final PsiClassType classType = (PsiClassType) collectionType;
   final PsiType[] parameterTypes = classType.getParameters();
   if (parameterTypes.length == 0) {
     return null;
   }
   final PsiType parameterType = parameterTypes[0];
   if (parameterType == null) {
     return null;
   }
   if (parameterType instanceof PsiWildcardType) {
     final PsiWildcardType wildcardType = (PsiWildcardType) parameterType;
     return wildcardType.getExtendsBound();
   } else if (parameterType instanceof PsiCapturedWildcardType) {
     final PsiCapturedWildcardType capturedWildcardType =
         (PsiCapturedWildcardType) parameterType;
     final PsiWildcardType wildcardType = capturedWildcardType.getWildcard();
     return wildcardType.getExtendsBound();
   }
   return parameterType;
 }
Пример #2
0
  @Nullable
  private static PsiType doNormalizeWildcardByPosition(
      final PsiType type, final GrExpression expression, final GrExpression toplevel) {
    if (type instanceof PsiCapturedWildcardType) {
      return doNormalizeWildcardByPosition(
          ((PsiCapturedWildcardType) type).getWildcard(), expression, toplevel);
    }

    if (type instanceof PsiWildcardType) {
      final PsiWildcardType wildcardType = (PsiWildcardType) type;

      if (PsiUtil.isAccessedForWriting(toplevel)) {
        return wildcardType.isSuper()
            ? wildcardType.getBound()
            : PsiCapturedWildcardType.create(wildcardType, expression);
      } else {
        if (wildcardType.isExtends()) {
          return wildcardType.getBound();
        } else {
          return PsiType.getJavaLangObject(expression.getManager(), expression.getResolveScope());
        }
      }
    } else if (type instanceof PsiArrayType) {
      final PsiType componentType = ((PsiArrayType) type).getComponentType();
      final PsiType normalizedComponentType =
          doNormalizeWildcardByPosition(componentType, expression, toplevel);
      if (normalizedComponentType != componentType) {
        assert normalizedComponentType != null;
        return normalizedComponentType.createArrayType();
      }
    }

    return type;
  }
  public static void addCompletions(
      @NotNull final JavaSmartCompletionParameters parameters,
      @NotNull Consumer<LookupElement> result,
      final PrefixMatcher matcher) {

    final Condition<String> shortNameCondition =
        new Condition<String>() {
          public boolean value(String s) {
            return matcher.prefixMatches(s);
          }
        };

    PsiType classParameter =
        PsiUtil.substituteTypeParameter(
            parameters.getExpectedType(), CommonClassNames.JAVA_LANG_CLASS, 0, false);

    boolean addInheritors = false;
    PsiElement position = parameters.getPosition();
    if (classParameter instanceof PsiWildcardType) {
      final PsiWildcardType wildcardType = (PsiWildcardType) classParameter;
      classParameter = wildcardType.getBound();
      addInheritors = wildcardType.isExtends() && classParameter instanceof PsiClassType;
    } else if (!matcher.getPrefix().isEmpty()) {
      addInheritors = true;
      classParameter = PsiType.getJavaLangObject(position.getManager(), position.getResolveScope());
    }
    if (classParameter != null) {
      PsiFile file = position.getContainingFile();
      addClassLiteralLookupElement(classParameter, result, file);
      if (addInheritors) {
        addInheritorClassLiterals(file, shortNameCondition, classParameter, result, matcher);
      }
    }
  }
Пример #4
0
    public PsiType substitute(final PsiType t) {
      if (t instanceof PsiWildcardType) {
        final PsiWildcardType wcType = (PsiWildcardType) t;
        final PsiType bound = wcType.getBound();

        if (bound == null) {
          return t;
        }

        final PsiManager manager = PsiManager.getInstance(myProject);
        final PsiType subst = substitute(bound);
        if (subst == null) return null;
        return subst instanceof PsiWildcardType
            ? subst
            : wcType.isExtends()
                ? PsiWildcardType.createExtends(manager, subst)
                : PsiWildcardType.createSuper(manager, subst);
      } else if (t instanceof PsiTypeVariable) {
        final PsiType b = apply(t);

        if (b instanceof Bottom || b instanceof PsiTypeVariable) {
          return null;
        }

        return substitute(b);
      } else if (t instanceof Bottom) {
        return null;
      } else if (t instanceof PsiArrayType) {
        return substitute(((PsiArrayType) t).getComponentType()).createArrayType();
      } else if (t instanceof PsiClassType) {
        final PsiClassType.ClassResolveResult result = ((PsiClassType) t).resolveGenerics();

        final PsiClass aClass = result.getElement();
        final PsiSubstitutor aSubst = result.getSubstitutor();

        if (aClass != null) {
          PsiSubstitutor theSubst = PsiSubstitutor.EMPTY;

          for (final PsiTypeParameter parm : aSubst.getSubstitutionMap().keySet()) {
            final PsiType type = aSubst.substitute(parm);

            theSubst = theSubst.put(parm, substitute(type));
          }

          return JavaPsiFacade.getInstance(aClass.getProject())
              .getElementFactory()
              .createType(aClass, theSubst);
        }
      }
      return t;
    }
Пример #5
0
 @Nullable
 @Override
 public Boolean visitWildcardType(PsiWildcardType wildcardType) {
   final PsiType bound = wildcardType.getBound();
   if (bound != null) return bound.accept(this);
   return false;
 }
Пример #6
0
    public PsiType apply(final PsiType type) {
      if (type instanceof PsiTypeVariable) {
        final PsiType t = myBindings.get(((PsiTypeVariable) type).getIndex());
        return t == null ? type : t;
      } else if (type instanceof PsiArrayType) {
        return apply(((PsiArrayType) type).getComponentType()).createArrayType();
      } else if (type instanceof PsiClassType) {
        final PsiClassType.ClassResolveResult result = Util.resolveType(type);
        final PsiClass theClass = result.getElement();
        final PsiSubstitutor aSubst = result.getSubstitutor();

        PsiSubstitutor theSubst = PsiSubstitutor.EMPTY;

        if (theClass != null) {
          for (final PsiTypeParameter aParm : aSubst.getSubstitutionMap().keySet()) {
            final PsiType aType = aSubst.substitute(aParm);

            theSubst = theSubst.put(aParm, apply(aType));
          }

          return JavaPsiFacade.getInstance(theClass.getProject())
              .getElementFactory()
              .createType(theClass, theSubst);
        } else {
          return type;
        }
      } else if (type instanceof PsiWildcardType) {
        final PsiWildcardType wcType = (PsiWildcardType) type;
        final PsiType bound = wcType.getBound();

        if (bound != null) {
          final PsiType abound = apply(bound);

          if (abound instanceof PsiWildcardType) {
            return null;
          }

          return wcType.isExtends()
              ? PsiWildcardType.createExtends(PsiManager.getInstance(myProject), abound)
              : PsiWildcardType.createSuper(PsiManager.getInstance(myProject), abound);
        }

        return type;
      } else {
        return type;
      }
    }
  private PsiType addBounds(PsiType substituted, final PsiTypeParameter typeParameter) {
    PsiElement captureContext = null;
    if (substituted instanceof PsiCapturedWildcardType) {
      final PsiCapturedWildcardType captured = (PsiCapturedWildcardType) substituted;
      substituted = captured.getWildcard();
      captureContext = captured.getContext();
    }
    if (substituted instanceof PsiWildcardType && !((PsiWildcardType) substituted).isSuper()) {
      PsiType originalBound = ((PsiWildcardType) substituted).getBound();
      PsiManager manager = typeParameter.getManager();
      final PsiType[] boundTypes = typeParameter.getExtendsListTypes();
      for (PsiType boundType : boundTypes) {
        PsiType substitutedBoundType = boundType.accept(mySimpleSubstitutionVisitor);
        PsiWildcardType wildcardType = (PsiWildcardType) substituted;
        if (substitutedBoundType != null
            && !(substitutedBoundType instanceof PsiWildcardType)
            && !substitutedBoundType.equalsToText("java.lang.Object")) {
          if (originalBound == null
              || (!TypeConversionUtil.erasure(substitutedBoundType)
                      .isAssignableFrom(TypeConversionUtil.erasure(originalBound))
                  && !TypeConversionUtil.erasure(substitutedBoundType)
                      .isAssignableFrom(
                          originalBound))) { // erasure is essential to avoid infinite recursion
            if (wildcardType.isExtends()) {
              final PsiType glb =
                  GenericsUtil.getGreatestLowerBound(wildcardType.getBound(), substitutedBoundType);
              if (glb != null) {
                substituted = PsiWildcardType.createExtends(manager, glb);
              }
            } else {
              // unbounded
              substituted = PsiWildcardType.createExtends(manager, substitutedBoundType);
            }
          }
        }
      }
    }

    if (captureContext != null) {
      LOG.assertTrue(substituted instanceof PsiWildcardType);
      substituted = PsiCapturedWildcardType.create((PsiWildcardType) substituted, captureContext);
    }
    return substituted;
  }
    @Override
    public PsiType visitWildcardType(PsiWildcardType wildcardType) {
      final PsiType bound = wildcardType.getBound();
      if (bound == null) {
        return wildcardType;
      } else {
        final PsiType newBound = bound.accept(this);
        if (newBound == null) {
          return null;
        }
        assert newBound.isValid() : newBound.getClass() + "; " + bound.isValid();
        if (newBound instanceof PsiWildcardType) {
          final PsiType newBoundBound = ((PsiWildcardType) newBound).getBound();
          return !((PsiWildcardType) newBound).isBounded()
              ? PsiWildcardType.createUnbounded(wildcardType.getManager())
              : rebound(wildcardType, newBoundBound);
        }

        return newBound == PsiType.NULL ? newBound : rebound(wildcardType, newBound);
      }
    }
    private PsiWildcardType rebound(PsiWildcardType type, PsiType newBound) {
      LOG.assertTrue(type.getBound() != null);
      LOG.assertTrue(newBound.isValid());

      if (type.isExtends()) {
        if (newBound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
          return PsiWildcardType.createUnbounded(type.getManager());
        } else {
          return PsiWildcardType.createExtends(type.getManager(), newBound);
        }
      } else {
        return PsiWildcardType.createSuper(type.getManager(), newBound);
      }
    }
    @Override
    public PsiType visitWildcardType(PsiWildcardType wildcardType) {
      final PsiType bound = wildcardType.getBound();
      if (bound == null) {
        return wildcardType;
      } else {
        final PsiType newBound = bound.accept(this);
        if (newBound == null) {
          return null;
        }
        if (newBound instanceof PsiWildcardType) {
          return handleBoundComposition(wildcardType, (PsiWildcardType) newBound);
        }
        if (newBound instanceof PsiCapturedWildcardType
            && wildcardType.isExtends()
                != ((PsiCapturedWildcardType) newBound).getWildcard().isExtends()) {
          return handleBoundComposition(
              wildcardType, ((PsiCapturedWildcardType) newBound).getWildcard());
        }

        return PsiWildcardType.changeBound(wildcardType, newBound);
      }
    }
 private static PsiType handleBoundComposition(
     PsiWildcardType wildcardType, PsiWildcardType bound) {
   if (bound.isExtends() == wildcardType.isExtends()) {
     final PsiType newBoundBound = bound.getBound();
     if (newBoundBound != null) {
       return PsiWildcardType.changeBound(wildcardType, newBoundBound);
     }
   }
   return PsiWildcardType.createUnbounded(wildcardType.getManager());
 }
 public static boolean try2ProveTypeParameterDistinct(PsiType type, PsiClass typeParameter) {
   final PsiClassType[] types = typeParameter.getExtendsListTypes();
   if (types.length == 0) return false;
   return provablyDistinct(
       PsiWildcardType.createExtends(typeParameter.getManager(), types[0]), type);
 }
  public static boolean provablyDistinct(PsiWildcardType type1, PsiWildcardType type2) {
    if (type1.isSuper() && type2.isSuper()) return false;
    if (type1.isExtends() && type2.isExtends()) {
      final PsiType extendsBound1 = type1.getExtendsBound();
      final PsiType extendsBound2 = type2.getExtendsBound();
      if (extendsBound1 instanceof PsiArrayType
              && proveArrayTypeDistinct(
                  type1.getManager().getProject(), (PsiArrayType) extendsBound1, extendsBound2)
          || extendsBound2 instanceof PsiArrayType
              && proveArrayTypeDistinct(
                  type1.getManager().getProject(), (PsiArrayType) extendsBound2, extendsBound1))
        return true;

      final PsiClass boundClass1 = PsiUtil.resolveClassInType(extendsBound1);
      final PsiClass boundClass2 = PsiUtil.resolveClassInType(extendsBound2);
      if (boundClass1 != null && boundClass2 != null) {
        return proveExtendsBoundsDistinct(type1, type2, boundClass1, boundClass2);
      }
      return provablyDistinct(extendsBound1, extendsBound2, 1);
    }
    if (type2.isExtends()) return provablyDistinct(type2, type1);
    if (type1.isExtends() && type2.isSuper()) {
      final PsiType extendsBound = type1.getExtendsBound();
      final PsiType superBound = type2.getSuperBound();
      if (extendsBound instanceof PsiArrayType
              && proveArrayTypeDistinct(
                  type1.getManager().getProject(), (PsiArrayType) extendsBound, superBound)
          || superBound instanceof PsiArrayType
              && proveArrayTypeDistinct(
                  type1.getManager().getProject(), (PsiArrayType) superBound, extendsBound))
        return true;

      final PsiClass extendsBoundClass = PsiUtil.resolveClassInType(extendsBound);
      final PsiClass superBoundClass = PsiUtil.resolveClassInType(superBound);
      if (extendsBoundClass != null && superBoundClass != null) {
        if (extendsBoundClass instanceof PsiTypeParameter) {
          return try2ProveTypeParameterDistinct(type2, extendsBoundClass);
        }
        if (superBoundClass instanceof PsiTypeParameter) return false;
        return !InheritanceUtil.isInheritorOrSelf(superBoundClass, extendsBoundClass, true);
      }
      return true;
    }

    if (!type1.isBounded() || !type2.isBounded()) {
      return false;
    }
    return !type1.equals(type2);
  }
Пример #14
0
  private static PsiType getLeastContainingTypeArgument(
      PsiType type1,
      PsiType type2,
      Set<Pair<PsiType, PsiType>> compared,
      PsiManager manager,
      PsiClass nestedLayer,
      PsiTypeParameter parameter) {
    Pair<PsiType, PsiType> types = new Pair<PsiType, PsiType>(type1, type2);
    if (compared.contains(types)) {
      if (nestedLayer != null) {
        PsiSubstitutor subst = PsiSubstitutor.EMPTY;
        for (PsiTypeParameter param : PsiUtil.typeParametersIterable(nestedLayer)) {
          subst = subst.put(param, PsiWildcardType.createUnbounded(manager));
        }
        subst =
            subst.put(
                parameter,
                getLeastContainingTypeArgument(type1, type2, compared, manager, null, null));

        final PsiClassType boundType =
            JavaPsiFacade.getInstance(manager.getProject())
                .getElementFactory()
                .createType(nestedLayer, subst);
        return PsiWildcardType.createExtends(manager, boundType);
      }
      return PsiWildcardType.createUnbounded(manager);
    }
    compared.add(types);

    try {
      if (type1 instanceof PsiWildcardType) {
        PsiWildcardType wild1 = (PsiWildcardType) type1;
        final PsiType bound1 = wild1.getBound();
        if (bound1 == null) return type1;
        if (type2 instanceof PsiWildcardType) {
          PsiWildcardType wild2 = (PsiWildcardType) type2;
          final PsiType bound2 = wild2.getBound();
          if (bound2 == null) return type2;
          if (wild1.isExtends() == wild2.isExtends()) {
            return wild1.isExtends()
                ? PsiWildcardType.createExtends(
                    manager, getLeastUpperBound(bound1, bound2, compared, manager))
                : PsiWildcardType.createSuper(manager, getGreatestLowerBound(bound1, bound2));
          } else {
            return bound1.equals(bound2) ? bound1 : PsiWildcardType.createUnbounded(manager);
          }
        } else {
          return wild1.isExtends()
              ? PsiWildcardType.createExtends(
                  manager, getLeastUpperBound(bound1, type2, compared, manager))
              : wild1.isSuper()
                  ? PsiWildcardType.createSuper(manager, getGreatestLowerBound(bound1, type2))
                  : wild1;
        }
      } else if (type2 instanceof PsiWildcardType) {
        return getLeastContainingTypeArgument(type2, type1, compared, manager, null, null);
      }
      // Done with wildcards

      if (type1.equals(type2)) return type1;
      return PsiWildcardType.createExtends(
          manager, getLeastUpperBound(type1, type2, compared, manager));
    } finally {
      compared.remove(types);
    }
  }
 public Boolean visitWildcardType(final PsiWildcardType wildcardType) {
   final PsiType bound = wildcardType.getBound();
   return bound != null && bound.accept(this).booleanValue();
 }
  static void setupPatternMethods(
      PsiManager manager,
      GlobalSearchScope searchScope,
      List<PsiMethod> patternMethods,
      IntArrayList indices) {
    final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(manager.getProject());
    final PsiClass collectionClass =
        javaPsiFacade.findClass(CommonClassNames.JAVA_UTIL_COLLECTION, searchScope);
    PsiType[] javaLangObject = {PsiType.getJavaLangObject(manager, searchScope)};
    MethodSignature removeSignature =
        MethodSignatureUtil.createMethodSignature(
            "remove", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY);
    if (collectionClass != null) {
      PsiMethod remove =
          MethodSignatureUtil.findMethodBySignature(collectionClass, removeSignature, false);
      addMethod(remove, 0, patternMethods, indices);

      MethodSignature containsSignature =
          MethodSignatureUtil.createMethodSignature(
              "contains", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY);
      PsiMethod contains =
          MethodSignatureUtil.findMethodBySignature(collectionClass, containsSignature, false);
      addMethod(contains, 0, patternMethods, indices);

      if (PsiUtil.isLanguageLevel5OrHigher(collectionClass)) {
        PsiClassType wildcardCollection =
            javaPsiFacade
                .getElementFactory()
                .createType(collectionClass, PsiWildcardType.createUnbounded(manager));
        MethodSignature removeAllSignature =
            MethodSignatureUtil.createMethodSignature(
                "removeAll",
                new PsiType[] {wildcardCollection},
                PsiTypeParameter.EMPTY_ARRAY,
                PsiSubstitutor.EMPTY);
        PsiMethod removeAll =
            MethodSignatureUtil.findMethodBySignature(collectionClass, removeAllSignature, false);
        addMethod(removeAll, 0, patternMethods, indices);
      }
    }

    final PsiClass listClass =
        javaPsiFacade.findClass(CommonClassNames.JAVA_UTIL_LIST, searchScope);
    if (listClass != null) {
      MethodSignature indexofSignature =
          MethodSignatureUtil.createMethodSignature(
              "indexOf", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY);
      PsiMethod indexof =
          MethodSignatureUtil.findMethodBySignature(listClass, indexofSignature, false);
      addMethod(indexof, 0, patternMethods, indices);
      MethodSignature lastindexofSignature =
          MethodSignatureUtil.createMethodSignature(
              "lastIndexOf", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY);
      PsiMethod lastindexof =
          MethodSignatureUtil.findMethodBySignature(listClass, lastindexofSignature, false);
      addMethod(lastindexof, 0, patternMethods, indices);
    }

    final PsiClass mapClass = javaPsiFacade.findClass(CommonClassNames.JAVA_UTIL_MAP, searchScope);
    if (mapClass != null) {
      PsiMethod remove =
          MethodSignatureUtil.findMethodBySignature(mapClass, removeSignature, false);
      addMethod(remove, 0, patternMethods, indices);
      MethodSignature getSignature =
          MethodSignatureUtil.createMethodSignature(
              "get", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY);
      PsiMethod get = MethodSignatureUtil.findMethodBySignature(mapClass, getSignature, false);
      addMethod(get, 0, patternMethods, indices);
      MethodSignature containsKeySignature =
          MethodSignatureUtil.createMethodSignature(
              "containsKey", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY);
      PsiMethod containsKey =
          MethodSignatureUtil.findMethodBySignature(mapClass, containsKeySignature, false);
      addMethod(containsKey, 0, patternMethods, indices);
      MethodSignature containsValueSignature =
          MethodSignatureUtil.createMethodSignature(
              "containsValue", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY);
      PsiMethod containsValue =
          MethodSignatureUtil.findMethodBySignature(mapClass, containsValueSignature, false);
      addMethod(containsValue, 1, patternMethods, indices);
    }

    final PsiClass concurrentMapClass =
        javaPsiFacade.findClass(CommonClassNames.JAVA_UTIL_CONCURRENT_HASH_MAP, searchScope);
    if (concurrentMapClass != null) {
      MethodSignature containsSignature =
          MethodSignatureUtil.createMethodSignature(
              "contains", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY);
      PsiMethod contains =
          MethodSignatureUtil.findMethodBySignature(concurrentMapClass, containsSignature, false);
      addMethod(contains, 1, patternMethods, indices);
    }
  }
Пример #17
0
  public LinkedList<Pair<PsiType, Binding>> intersect(final PsiType x, final PsiType y) {
    final LinkedList<Pair<PsiType, Binding>> list = new LinkedList<Pair<PsiType, Binding>>();

    new Object() {
      void intersect(
          final PsiType x, final PsiType y, final LinkedList<Pair<PsiType, Binding>> list) {
        if (x instanceof PsiWildcardType || y instanceof PsiWildcardType) {
          final PsiType xType = x instanceof PsiWildcardType ? ((PsiWildcardType) x).getBound() : x;
          final PsiType yType = y instanceof PsiWildcardType ? ((PsiWildcardType) y).getBound() : y;

          intersect(xType, yType, list);
        }
        if (x instanceof PsiArrayType || y instanceof PsiArrayType) {
          if (x instanceof PsiClassType || y instanceof PsiClassType) {
            try {
              final PsiElementFactory f = JavaPsiFacade.getInstance(myProject).getElementFactory();
              final PsiType keyType = x instanceof PsiClassType ? x : y;

              final PsiType object = f.createTypeFromText("java.lang.Object", null);
              final PsiType cloneable = f.createTypeFromText("java.lang.Cloneable", null);
              final PsiType serializable = f.createTypeFromText("java.io.Serializable", null);

              intersect(keyType, object, list);
              intersect(keyType, cloneable, list);
              intersect(keyType, serializable, list);
            } catch (IncorrectOperationException e) {
              LOG.error("Exception " + e);
            }
          } else if (x instanceof PsiArrayType && y instanceof PsiArrayType) {
            intersect(
                ((PsiArrayType) x).getComponentType(), ((PsiArrayType) y).getComponentType(), list);
          }
        } else if (x instanceof PsiClassType && y instanceof PsiClassType) {
          final PsiClassType.ClassResolveResult xResult = Util.resolveType(x);
          final PsiClassType.ClassResolveResult yResult = Util.resolveType(y);

          final PsiClass xClass = xResult.getElement();
          final PsiClass yClass = yResult.getElement();

          final PsiSubstitutor xSubst = xResult.getSubstitutor();
          final PsiSubstitutor ySubst = yResult.getSubstitutor();

          if (xClass == null || yClass == null) {
            return;
          }

          if (xClass.equals(yClass)) {
            final Binding risen = rise(x, y, null);

            if (risen == null) {
              final PsiElementFactory factory =
                  JavaPsiFacade.getInstance(xClass.getProject()).getElementFactory();

              list.addFirst(
                  new Pair<PsiType, Binding>(
                      Util.banalize(
                          factory.createType(xClass, factory.createRawSubstitutor(xClass))),
                      create()));
            } else {
              list.addFirst(new Pair<PsiType, Binding>(risen.apply(x), risen));
            }
          } else {
            final PsiClass[] ancestors = GenericsUtil.getLeastUpperClasses(xClass, yClass);

            for (final PsiClass ancestor : ancestors) {
              if ("java.lang.Object".equals(ancestor.getQualifiedName()) && ancestors.length > 1) {
                continue;
              }

              final PsiSubstitutor x2aSubst =
                  TypeConversionUtil.getSuperClassSubstitutor(ancestor, xClass, xSubst);
              final PsiSubstitutor y2aSubst =
                  TypeConversionUtil.getSuperClassSubstitutor(ancestor, yClass, ySubst);

              final PsiElementFactory factory =
                  JavaPsiFacade.getInstance(xClass.getProject()).getElementFactory();

              intersect(
                  factory.createType(ancestor, x2aSubst),
                  factory.createType(ancestor, y2aSubst),
                  list);
            }
          }
        }
      }
    }.intersect(x, y, list);

    return list;
  }