public static boolean methodMatches(@NotNull PsiMethod firstMethod, @NotNull PsiSubstitutor firstSubstitutor,
                                      @NotNull PsiMethod secondMethod, @NotNull PsiSubstitutor secondSubstitutor) {
    if (!firstMethod.getName().equals(secondMethod.getName())) {
      return false;
    }

    PsiParameterList firstMethodParameterList = firstMethod.getParameterList();
    PsiParameterList secondMethodParameterList = secondMethod.getParameterList();
    if (firstMethodParameterList.getParametersCount() != secondMethodParameterList.getParametersCount()) {
      return false;
    }

    PsiParameter[] firstMethodParameters = firstMethodParameterList.getParameters();
    PsiParameter[] secondMethodParameters = secondMethodParameterList.getParameters();
    for (int i = 0; i < firstMethodParameters.length; i++) {
      final PsiType firstMethodParameterListParameterType = firstSubstitutor.substitute(firstMethodParameters[i].getType());
      final PsiType secondMethodParameterListParameterType = secondSubstitutor.substitute(secondMethodParameters[i].getType());

      final PsiType firstParameterType = TypeConversionUtil.erasure(firstMethodParameterListParameterType, firstSubstitutor);
      final PsiType secondParameterType = TypeConversionUtil.erasure(secondMethodParameterListParameterType, secondSubstitutor);

      if (!PsiElementUtil.typesAreEquivalent(firstParameterType, secondParameterType)) {
        return false;
      }
    }

    return true;
  }
public static boolean methodMatches(@NotNull PsiMethod firstMethod, @NotNull PsiSubstitutor firstSubstitutor,
                                      @NotNull PsiMethod secondMethod, @NotNull PsiSubstitutor secondSubstitutor)