private PsiType rawTypeForTypeParameter(final PsiTypeParameter typeParameter) {
   final PsiClassType[] extendsTypes = typeParameter.getExtendsListTypes();
   if (extendsTypes.length > 0) {
     // First bound
     return substitute(extendsTypes[0]);
   }
   // Object
   return PsiType.getJavaLangObject(typeParameter.getManager(), typeParameter.getResolveScope());
 }
  /**
   * @param methodSignature method signature
   * @param superMethodSignature super method signature
   * @return null if signatures do not match
   */
  @Nullable
  public static PsiSubstitutor getSuperMethodSignatureSubstitutor(
      @NotNull MethodSignature methodSignature, @NotNull MethodSignature superMethodSignature) {
    PsiSubstitutor result =
        getSuperMethodSignatureSubstitutorImpl(methodSignature, superMethodSignature);
    if (result == null) return null;

    PsiTypeParameter[] methodTypeParameters = methodSignature.getTypeParameters();
    PsiTypeParameter[] superTypeParameters = superMethodSignature.getTypeParameters();
    PsiSubstitutor methodSubstitutor = methodSignature.getSubstitutor();

    // check bounds
    for (int i = 0; i < methodTypeParameters.length; i++) {
      PsiTypeParameter methodTypeParameter = methodTypeParameters[i];
      PsiTypeParameter superTypeParameter = superTypeParameters[i];
      final Set<PsiType> methodSupers = new HashSet<PsiType>();
      for (PsiClassType methodSuper : methodTypeParameter.getSuperTypes()) {
        methodSupers.add(methodSubstitutor.substitute(methodSuper));
      }

      final Set<PsiType> superSupers = new HashSet<PsiType>();
      for (PsiClassType superSuper : superTypeParameter.getSuperTypes()) {
        superSupers.add(
            methodSubstitutor.substitute(
                PsiUtil.captureToplevelWildcards(
                    result.substitute(superSuper), methodTypeParameter)));
      }
      methodSupers.remove(
          PsiType.getJavaLangObject(
              methodTypeParameter.getManager(), methodTypeParameter.getResolveScope()));
      superSupers.remove(
          PsiType.getJavaLangObject(
              superTypeParameter.getManager(), superTypeParameter.getResolveScope()));
      if (!methodSupers.equals(superSupers)) return null;
    }

    return result;
  }