private static boolean tryStatementsAreEquivalent(
     @NotNull PsiTryStatement statement1, @NotNull PsiTryStatement statement2) {
   final PsiCodeBlock tryBlock1 = statement1.getTryBlock();
   final PsiCodeBlock tryBlock2 = statement2.getTryBlock();
   if (!codeBlocksAreEquivalent(tryBlock1, tryBlock2)) {
     return false;
   }
   final PsiCodeBlock finallyBlock1 = statement1.getFinallyBlock();
   final PsiCodeBlock finallyBlock2 = statement2.getFinallyBlock();
   if (!codeBlocksAreEquivalent(finallyBlock1, finallyBlock2)) {
     return false;
   }
   final PsiCodeBlock[] catchBlocks1 = statement1.getCatchBlocks();
   final PsiCodeBlock[] catchBlocks2 = statement2.getCatchBlocks();
   if (catchBlocks1.length != catchBlocks2.length) {
     return false;
   }
   for (int i = 0; i < catchBlocks2.length; i++) {
     if (!codeBlocksAreEquivalent(catchBlocks1[i], catchBlocks2[i])) {
       return false;
     }
   }
   final PsiParameter[] catchParameters1 = statement1.getCatchBlockParameters();
   final PsiParameter[] catchParameters2 = statement2.getCatchBlockParameters();
   if (catchParameters1.length != catchParameters2.length) {
     return false;
   }
   for (int i = 0; i < catchParameters2.length; i++) {
     if (!parametersAreEquivalent(catchParameters2[i], catchParameters1[i])) {
       return false;
     }
   }
   return true;
 }
 private static boolean tryStatementsAreEquivalent(
     @NotNull PsiTryStatement statement1, @NotNull PsiTryStatement statement2) {
   final PsiCodeBlock tryBlock1 = statement1.getTryBlock();
   final PsiCodeBlock tryBlock2 = statement2.getTryBlock();
   if (!codeBlocksAreEquivalent(tryBlock1, tryBlock2)) {
     return false;
   }
   final PsiCodeBlock finallyBlock1 = statement1.getFinallyBlock();
   final PsiCodeBlock finallyBlock2 = statement2.getFinallyBlock();
   if (!codeBlocksAreEquivalent(finallyBlock1, finallyBlock2)) {
     return false;
   }
   final PsiCodeBlock[] catchBlocks1 = statement1.getCatchBlocks();
   final PsiCodeBlock[] catchBlocks2 = statement2.getCatchBlocks();
   if (catchBlocks1.length != catchBlocks2.length) {
     return false;
   }
   for (int i = 0; i < catchBlocks2.length; i++) {
     if (!codeBlocksAreEquivalent(catchBlocks1[i], catchBlocks2[i])) {
       return false;
     }
   }
   final PsiResourceList resourceList1 = statement1.getResourceList();
   final PsiResourceList resourceList2 = statement2.getResourceList();
   if (resourceList1 != null) {
     if (resourceList2 == null) {
       return false;
     }
     if (resourceList1.getResourceVariablesCount() != resourceList2.getResourceVariablesCount()) {
       return false;
     }
     final List<PsiResourceVariable> resourceVariables1 = resourceList1.getResourceVariables();
     final List<PsiResourceVariable> resourceVariables2 = resourceList2.getResourceVariables();
     for (int i1 = 0, size = resourceVariables1.size(); i1 < size; i1++) {
       final PsiResourceVariable variable1 = resourceVariables1.get(i1);
       final PsiResourceVariable variable2 = resourceVariables2.get(i1);
       if (!localVariablesAreEquivalent(variable1, variable2)) {
         return false;
       }
     }
   } else if (resourceList2 != null) {
     return false;
   }
   final PsiParameter[] catchParameters1 = statement1.getCatchBlockParameters();
   final PsiParameter[] catchParameters2 = statement2.getCatchBlockParameters();
   if (catchParameters1.length != catchParameters2.length) {
     return false;
   }
   for (int i = 0; i < catchParameters2.length; i++) {
     if (!parametersAreEquivalent(catchParameters2[i], catchParameters1[i])) {
       return false;
     }
   }
   return true;
 }
  private static void fixExceptions(PsiElement ref, PsiClassType[] newExceptions)
      throws IncorrectOperationException {
    // methods' throws lists are already modified, may use ExceptionUtil.collectUnhandledExceptions
    newExceptions = filterCheckedExceptions(newExceptions);

    PsiElement context = PsiTreeUtil.getParentOfType(ref, PsiTryStatement.class, PsiMethod.class);
    if (context instanceof PsiTryStatement) {
      PsiTryStatement tryStatement = (PsiTryStatement) context;
      PsiCodeBlock tryBlock = tryStatement.getTryBlock();

      // Remove unused catches
      Collection<PsiClassType> classes =
          ExceptionUtil.collectUnhandledExceptions(tryBlock, tryBlock);
      PsiParameter[] catchParameters = tryStatement.getCatchBlockParameters();
      for (PsiParameter parameter : catchParameters) {
        final PsiType caughtType = parameter.getType();

        if (!(caughtType instanceof PsiClassType)) continue;
        if (ExceptionUtil.isUncheckedExceptionOrSuperclass((PsiClassType) caughtType)) continue;

        if (!isCatchParameterRedundant((PsiClassType) caughtType, classes)) continue;
        parameter.getParent().delete(); // delete catch section
      }

      PsiClassType[] exceptionsToAdd = filterUnhandledExceptions(newExceptions, tryBlock);
      addExceptions(exceptionsToAdd, tryStatement);

      adjustPossibleEmptyTryStatement(tryStatement);
    } else {
      newExceptions = filterUnhandledExceptions(newExceptions, ref);
      if (newExceptions.length > 0) {
        // Add new try statement
        PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(ref.getProject());
        PsiTryStatement tryStatement =
            (PsiTryStatement)
                elementFactory.createStatementFromText("try {} catch (Exception e) {}", null);
        PsiStatement anchor = PsiTreeUtil.getParentOfType(ref, PsiStatement.class);
        LOG.assertTrue(anchor != null);
        tryStatement.getTryBlock().add(anchor);
        tryStatement = (PsiTryStatement) anchor.getParent().addAfter(tryStatement, anchor);

        addExceptions(newExceptions, tryStatement);
        anchor.delete();
        tryStatement.getCatchSections()[0].delete(); // Delete dummy catch section
      }
    }
  }
 private static void adjustPossibleEmptyTryStatement(PsiTryStatement tryStatement)
     throws IncorrectOperationException {
   PsiCodeBlock tryBlock = tryStatement.getTryBlock();
   if (tryBlock != null) {
     if (tryStatement.getCatchSections().length == 0 && tryStatement.getFinallyBlock() == null) {
       PsiElement firstBodyElement = tryBlock.getFirstBodyElement();
       if (firstBodyElement != null) {
         tryStatement
             .getParent()
             .addRangeAfter(firstBodyElement, tryBlock.getLastBodyElement(), tryStatement);
       }
       tryStatement.delete();
     }
   }
 }
    @Override
    protected void doFix(Project project, ProblemDescriptor descriptor)
        throws IncorrectOperationException {
      final PsiType thrownType = myThrown.getType();
      if (thrownType == null) {
        return;
      }
      final PsiElement typeElement = descriptor.getPsiElement();
      if (typeElement == null) {
        return;
      }
      final PsiElement catchParameter = typeElement.getParent();
      if (!(catchParameter instanceof PsiParameter)) {
        return;
      }
      final PsiElement catchBlock = ((PsiParameter) catchParameter).getDeclarationScope();
      if (!(catchBlock instanceof PsiCatchSection)) {
        return;
      }
      final PsiCatchSection myBeforeCatchSection = (PsiCatchSection) catchBlock;
      final PsiTryStatement myTryStatement = myBeforeCatchSection.getTryStatement();
      final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
      final String name =
          codeStyleManager.suggestUniqueVariableName("e", myTryStatement.getTryBlock(), false);
      final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
      final PsiCatchSection section = factory.createCatchSection(thrownType, name, myTryStatement);
      final PsiCatchSection element =
          (PsiCatchSection) myTryStatement.addBefore(section, myBeforeCatchSection);
      codeStyleManager.shortenClassReferences(element);

      if (isOnTheFly()) {
        final PsiCodeBlock newBlock = element.getCatchBlock();
        assert newBlock != null;
        final TextRange range = SurroundWithUtil.getRangeToSelect(newBlock);
        final PsiFile file = element.getContainingFile();
        final Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor();
        if (editor == null) {
          return;
        }
        final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
        if (editor.getDocument() != document) {
          return;
        }
        editor.getCaretModel().moveToOffset(range.getStartOffset());
        editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
        editor.getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset());
      }
    }
  @Override
  public TextRange surroundStatements(
      Project project, Editor editor, PsiElement container, PsiElement[] statements)
      throws IncorrectOperationException {
    PsiManager manager = PsiManager.getInstance(project);
    PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
    CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);

    statements = SurroundWithUtil.moveDeclarationsOut(container, statements, false);
    if (statements.length == 0) {
      return null;
    }

    @NonNls String text = "try{\n}finally{\n\n}";
    PsiTryStatement tryStatement = (PsiTryStatement) factory.createStatementFromText(text, null);
    tryStatement = (PsiTryStatement) codeStyleManager.reformat(tryStatement);

    tryStatement =
        (PsiTryStatement) container.addAfter(tryStatement, statements[statements.length - 1]);

    PsiCodeBlock tryBlock = tryStatement.getTryBlock();
    if (tryBlock == null) {
      return null;
    }
    SurroundWithUtil.indentCommentIfNecessary(tryBlock, statements);
    tryBlock.addRange(statements[0], statements[statements.length - 1]);
    container.deleteChildRange(statements[0], statements[statements.length - 1]);

    PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock();
    if (finallyBlock == null) {
      return null;
    }
    int offset = finallyBlock.getTextRange().getStartOffset() + 2;
    editor.getCaretModel().moveToOffset(offset);
    final Document document = editor.getDocument();
    PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(document);
    editor.getSelectionModel().removeSelection();
    final PsiStatement firstTryStmt = tryBlock.getStatements()[0];
    final int indent =
        firstTryStmt.getTextOffset()
            - document.getLineStartOffset(document.getLineNumber(firstTryStmt.getTextOffset()));
    EditorModificationUtil.insertStringAtCaret(editor, StringUtil.repeat(" ", indent), false, true);
    return new TextRange(editor.getCaretModel().getOffset(), editor.getCaretModel().getOffset());
  }