public static boolean performExtractMethod(
      boolean doRefactor,
      boolean replaceAllDuplicates,
      Editor editor,
      PsiFile file,
      Project project,
      final boolean extractChainedConstructor,
      int... disabledParams)
      throws PrepareFailedException, IncorrectOperationException {
    int startOffset = editor.getSelectionModel().getSelectionStart();
    int endOffset = editor.getSelectionModel().getSelectionEnd();

    PsiElement[] elements;
    PsiExpression expr = CodeInsightUtil.findExpressionInRange(file, startOffset, endOffset);
    if (expr != null) {
      elements = new PsiElement[] {expr};
    } else {
      elements = CodeInsightUtil.findStatementsInRange(file, startOffset, endOffset);
    }
    if (elements.length == 0) {
      final PsiExpression expression =
          IntroduceVariableBase.getSelectedExpression(project, file, startOffset, endOffset);
      if (expression != null) {
        elements = new PsiElement[] {expression};
      }
    }
    assertTrue(elements.length > 0);

    final ExtractMethodProcessor processor =
        new ExtractMethodProcessor(
            project, editor, elements, null, "Extract Method", "newMethod", null);
    processor.setShowErrorDialogs(false);
    processor.setChainedConstructor(extractChainedConstructor);

    if (!processor.prepare()) {
      return false;
    }

    if (doRefactor) {
      processor.testPrepare();
      if (disabledParams != null) {
        for (int param : disabledParams) {
          processor.doNotPassParameter(param);
        }
      }
      ExtractMethodHandler.run(project, editor, processor);
    }

    if (replaceAllDuplicates) {
      final List<Match> duplicates = processor.getDuplicates();
      for (final Match match : duplicates) {
        if (!match.getMatchStart().isValid() || !match.getMatchEnd().isValid()) continue;
        processor.processMatch(match);
      }
    }

    return true;
  }
 public void invoke(
     @NotNull final Project project,
     final Editor editor,
     final PsiFile file,
     final DataContext dataContext) {
   ExtractMethodHandler.selectAndPass(
       project,
       editor,
       file,
       new Pass<PsiElement[]>() {
         public void pass(final PsiElement[] selectedValue) {
           invokeOnElements(project, editor, file, selectedValue);
         }
       });
 }
  private void invokeOnElements(
      @NotNull final Project project,
      @NotNull final Editor editor,
      @NotNull PsiFile file,
      @NotNull PsiElement[] elements) {
    if (elements.length == 0) {
      String message =
          RefactoringBundle.getCannotRefactorMessage(
              RefactoringBundle.message(
                  "selected.block.should.represent.a.set.of.statements.or.an.expression"));
      CommonRefactoringUtil.showErrorHint(
          project,
          editor,
          message,
          ExtractMethodObjectProcessor.REFACTORING_NAME,
          HelpID.EXTRACT_METHOD_OBJECT);
      return;
    }

    final ExtractMethodObjectProcessor processor =
        new ExtractMethodObjectProcessor(project, editor, elements, "");
    final ExtractMethodObjectProcessor.MyExtractMethodProcessor extractProcessor =
        processor.getExtractProcessor();
    try {
      if (!extractProcessor.prepare()) return;
    } catch (PrepareFailedException e) {
      CommonRefactoringUtil.showErrorHint(
          project,
          editor,
          e.getMessage(),
          ExtractMethodObjectProcessor.REFACTORING_NAME,
          HelpID.EXTRACT_METHOD_OBJECT);
      ExtractMethodHandler.highlightPrepareError(e, file, editor, project);
      return;
    }

    if (!CommonRefactoringUtil.checkReadOnlyStatus(
        project, extractProcessor.getTargetClass().getContainingFile())) return;
    if (extractProcessor.showDialog()) {
      run(project, editor, processor, extractProcessor);
    }
  }