public static void createTemplateForMethod(ChooseTypeExpression[] paramTypesExpressions,
                                             ParameterNameExpression[] paramNameExpressions,
                                             PsiMethod method,
                                             PsiClass owner,
                                             ChooseTypeExpression returnTypeExpression,
                                             boolean isConstructor,
                                             boolean isScrollToTemplate,
                                             @Nullable final PsiElement context) {

    final Project project = owner.getProject();
    PsiTypeElement typeElement = method.getReturnTypeElement();

    TemplateBuilderImpl builder = new TemplateBuilderImpl(method);
    builder.setScrollToTemplate(isScrollToTemplate);
    if (!isConstructor) {
      assert typeElement != null;
      builder.replaceElement(typeElement, returnTypeExpression);
    }
    PsiParameter[] parameters = method.getParameterList().getParameters();
    for (int i = 0; i < parameters.length; i++) {
      PsiParameter parameter = parameters[i];
      PsiTypeElement parameterTypeElement = parameter.getTypeElement();
      builder.replaceElement(parameterTypeElement, paramTypesExpressions[i]);
      builder.replaceElement(parameter.getNameIdentifier(), paramNameExpressions[i]);
    }

    PsiCodeBlock body = method.getBody();
    if (body != null) {
      PsiElement lbrace = body.getLBrace();
      assert lbrace != null;
      builder.setEndVariableAfter(lbrace);
    }
    else {
      builder.setEndVariableAfter(method.getParameterList());
    }

    method = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(method);
    Template template = builder.buildTemplate();

    final PsiFile targetFile = owner.getContainingFile();
    final Editor newEditor = positionCursor(project, targetFile, method);
    TextRange range = method.getTextRange();
    newEditor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset());

    TemplateManager manager = TemplateManager.getInstance(project);


    TemplateEditingListener templateListener = new TemplateEditingAdapter() {
      @Override
      public void templateFinished(@NotNull Template template, boolean brokenOff) {
        ApplicationManager.getApplication().runWriteAction(() -> {
          PsiDocumentManager.getInstance(project).commitDocument(newEditor.getDocument());
          final int offset = newEditor.getCaretModel().getOffset();
          PsiMethod method1 = PsiTreeUtil.findElementOfClassAtOffset(targetFile, offset - 1, PsiMethod.class, false);
          if (context instanceof PsiMethod) {
            final PsiTypeParameter[] typeParameters = ((PsiMethod)context).getTypeParameters();
            for (PsiTypeParameter typeParameter : typeParameters) {
              if (CreateMethodFromUsageFix.checkTypeParam(method1, typeParameter)) {
                final JVMElementFactory factory = JVMElementFactories.getFactory(method1.getLanguage(), method1.getProject());
                PsiTypeParameterList list = method1.getTypeParameterList();
                if (list == null) {
                  PsiTypeParameterList newList = factory.createTypeParameterList();
                  list = (PsiTypeParameterList)method1.addAfter(newList, method1.getModifierList());
                }
                list.add(factory.createTypeParameter(typeParameter.getName(), typeParameter.getExtendsList().getReferencedTypes()));
              }
            }
          }
          if (method1 != null) {
            try {
              final boolean hasNoReturnType = method1.getReturnTypeElement() == null && method1 instanceof GrMethod;
              if (hasNoReturnType) {
                ((GrMethod)method1).setReturnType(PsiTypes.voidType());
              }
              if (method1.getBody() != null) {
                FileTemplateManager templateManager = FileTemplateManager.getInstance(project);
                FileTemplate fileTemplate = templateManager.getCodeTemplate(GroovyTemplates.GROOVY_FROM_USAGE_METHOD_BODY);

                PsiClass containingClass = method1.getContainingClass();
                LOG.assertTrue(!containingClass.isInterface() || GrTraitUtil.isTrait(containingClass), "Interface bodies should be already set up");
                CreateFromUsageUtils.setupMethodBody(method1, containingClass, fileTemplate);
              }
              if (hasNoReturnType) {
                ((GrMethod)method1).setReturnType(null);
              }

              if (method1 instanceof GrMethod && GroovyModifiersUtil.isDefUnnecessary((GrMethod)method1)) {
                ((GrMethod)method1).getModifierList().setModifierProperty(GrModifier.DEF, false);
              }
            }
            catch (IncorrectOperationException e) {
              LOG.error(e);
            }

            CreateFromUsageUtils.setupEditor(method1, newEditor);
          }
        });
      }
    };
    manager.startTemplate(newEditor, template, templateListener);
  }
public static void createTemplateForMethod(ChooseTypeExpression[] paramTypesExpressions,
                                             ParameterNameExpression[] paramNameExpressions,
                                             PsiMethod method,
                                             PsiClass owner,
                                             ChooseTypeExpression returnTypeExpression,
                                             boolean isConstructor,
                                             boolean isScrollToTemplate,
                                             @Nullable final PsiElement context)