public static void performInline(Project project, Editor editor, PsiMethod method, boolean allowInlineThisOnly) {
    PsiReference reference = editor != null ? TargetElementUtil.findReference(editor, editor.getCaretModel().getOffset()) : null;

    PsiCodeBlock methodBody = method.getBody();
    Supplier<PsiCodeBlock> specialization = InlineMethodSpecialization.forReference(reference);
    if (specialization != null) {
      allowInlineThisOnly = true;
      methodBody = specialization.get();
    }

    if (methodBody == null){
      String message;
      if (method.hasModifierProperty(PsiModifier.ABSTRACT)) {
        message = JavaRefactoringBundle.message("refactoring.cannot.be.applied.to.abstract.methods", getRefactoringName());
      }
      else if (method.hasModifierProperty(PsiModifier.NATIVE)) {
        message = JavaRefactoringBundle.message("refactoring.cannot.be.applied.to.native.methods", getRefactoringName());
      }
      else {
        message = JavaRefactoringBundle.message("refactoring.cannot.be.applied.no.sources.attached", getRefactoringName());
      }
      CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringName(), HelpID.INLINE_METHOD);
      return;
    }

    if (reference == null && checkRecursive(method)) {
      String message = RefactoringBundle.message("refactoring.is.not.supported.for.recursive.methods", getRefactoringName());
      CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringName(), HelpID.INLINE_METHOD);
      return;
    }

    if (reference != null) {
      final String errorMessage = InlineMethodProcessor.checkUnableToInsertCodeBlock(methodBody, reference.getElement());
      if (errorMessage != null) {
        CommonRefactoringUtil.showErrorHint(project, editor, errorMessage, getRefactoringName(), HelpID.INLINE_METHOD);
        return;
      }
    }

    if (method.isConstructor()) {
      if (method.isVarArgs()) {
        String message = JavaRefactoringBundle.message("refactoring.cannot.be.applied.to.vararg.constructors", getRefactoringName());
        CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringName(), HelpID.INLINE_CONSTRUCTOR);
        return;
      }
      final boolean chainingConstructor = InlineUtil.isChainingConstructor(method);
      if (!chainingConstructor) {
        InlineObjectProcessor processor = InlineObjectProcessor.create(reference, method);
        if (processor != null) {
          if (Messages.showOkCancelDialog(JavaRefactoringBundle.message("inline.method.object.suggestion.message"),
                                          JavaRefactoringBundle.message("inline.method.object.action.name"),
                                          JavaRefactoringBundle.message("inline.action.name"), CommonBundle.getCancelButtonText(),
                                          Messages.getQuestionIcon()) == Messages.OK) {
            processor.setPrepareSuccessfulSwingThreadCallback(() -> {});
            processor.run();
          }
          return;
        }
        if (!isThisReference(reference)) {
          String message = JavaRefactoringBundle.message("refactoring.cannot.be.applied.to.inline.non.chaining.constructors",
                                                     getRefactoringName());
          CommonRefactoringUtil.showErrorHint(project, editor, message, getRefactoringName(), HelpID.INLINE_CONSTRUCTOR);
          return;
        }
        allowInlineThisOnly = true;
      }
      if (reference != null) {
        final PsiElement refElement = reference.getElement();
        PsiCall constructorCall = refElement instanceof PsiJavaCodeReferenceElement ? RefactoringUtil.getEnclosingConstructorCall((PsiJavaCodeReferenceElement)refElement) : null;
        if (constructorCall == null || !method.equals(constructorCall.resolveMethod())) reference = null;
      }
    }
    else {
      if (reference != null && !method.getManager().areElementsEquivalent(method, reference.resolve())) {
        reference = null;
      }
    }

    if (reference != null && PsiTreeUtil.getParentOfType(reference.getElement(), PsiImportStaticStatement.class) != null) {
      reference = null;
    }

    final boolean invokedOnReference = reference != null;
    if (!invokedOnReference) {
      final VirtualFile vFile = method.getContainingFile().getVirtualFile();
      ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(Collections.singletonList(vFile));
    }

    if (reference != null) {
      final PsiElement referenceElement = reference.getElement();
      if (referenceElement.getLanguage() == JavaLanguage.INSTANCE && 
          !(referenceElement instanceof PsiJavaCodeReferenceElement)) {
        reference = null;
      }
    }
    InlineMethodDialog dialog = new InlineMethodDialog(project, method, reference, editor, allowInlineThisOnly);
    if (ApplicationManager.getApplication().isUnitTestMode()) {
      try {
        dialog.doAction();
      } finally {
        dialog.close(DialogWrapper.OK_EXIT_CODE, true);
      }
    }
    else {
      dialog.show();
    }
  }
public static void performInline(Project project, Editor editor, PsiMethod method, boolean allowInlineThisOnly)