public static @NotNull PsiMethod substituteGenericMethod(@NotNull PsiMethod sourceMethod,
                                                           @NotNull PsiSubstitutor substitutor,
                                                           @Nullable PsiElement target) {
    final Project project = sourceMethod.getProject();
    final JVMElementFactory factory = getFactory(sourceMethod.getProject(), target);
    final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);

    try {
      PsiMethod resultMethod = createMethod(factory, sourceMethod, target);
      copyModifiers(sourceMethod.getModifierList(), resultMethod.getModifierList());
      PsiSubstitutor collisionResolvedSubstitutor =
        substituteTypeParameters(factory, target, sourceMethod.getTypeParameterList(), resultMethod.getTypeParameterList(), substitutor, sourceMethod);
      substituteReturnType(PsiManager.getInstance(project), resultMethod, sourceMethod.getReturnType(), collisionResolvedSubstitutor);
      PsiTypeElement typeElement = resultMethod.getReturnTypeElement();
      if (typeElement != null && typeElement.getText().startsWith("@")) {
        // If return type is annotated, substituteReturnType will add the annotation into type element,
        // so the method should be reparsed to move it to the modifier list
        resultMethod = factory.createMethodFromText(resultMethod.getText(), target);
      }
      substituteParameters(factory, codeStyleManager, sourceMethod.getParameterList(), resultMethod.getParameterList(), collisionResolvedSubstitutor, target);
      copyDocComment(sourceMethod, resultMethod, factory);
      GlobalSearchScope scope = sourceMethod.getResolveScope();
      List<PsiClassType> thrownTypes = ExceptionUtil.collectSubstituted(collisionResolvedSubstitutor, sourceMethod.getThrowsList().getReferencedTypes(), scope);
      if (target instanceof PsiClass) {
        for (PsiMethod psiMethod : ((PsiClass)target).findMethodsBySignature(sourceMethod, true)) {
          if (psiMethod != null && psiMethod != sourceMethod && !MethodSignatureUtil.isSuperMethod(psiMethod, sourceMethod)) {
            PsiClass aSuper = psiMethod.getContainingClass();
            if (aSuper != null && aSuper != target) {
              PsiSubstitutor superClassSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(aSuper, (PsiClass)target, PsiSubstitutor.EMPTY);
              ExceptionUtil.retainExceptions(thrownTypes, ExceptionUtil.collectSubstituted(superClassSubstitutor, psiMethod.getThrowsList().getReferencedTypes(), scope));
            }
          }
        }
      }
      substituteThrows(factory, resultMethod.getThrowsList(), collisionResolvedSubstitutor, sourceMethod, thrownTypes);
      sortModifiers(resultMethod, sourceMethod);
      return resultMethod;
    }
    catch (IncorrectOperationException e) {
      LOG.error(e);
      return sourceMethod;
    }
  }
public static @NotNull PsiMethod substituteGenericMethod(@NotNull PsiMethod sourceMethod,
                                                           @NotNull PsiSubstitutor substitutor,
                                                           @Nullable PsiElement target)