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 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 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());
      }
    }
  private static void addExceptions(PsiClassType[] exceptionsToAdd, PsiTryStatement tryStatement)
      throws IncorrectOperationException {
    for (PsiClassType type : exceptionsToAdd) {
      final JavaCodeStyleManager styleManager =
          JavaCodeStyleManager.getInstance(tryStatement.getProject());
      String name =
          styleManager.suggestVariableName(VariableKind.PARAMETER, null, null, type).names[0];
      name = styleManager.suggestUniqueVariableName(name, tryStatement, false);

      PsiCatchSection catchSection =
          JavaPsiFacade.getInstance(tryStatement.getProject())
              .getElementFactory()
              .createCatchSection(type, name, tryStatement);
      tryStatement.add(catchSection);
    }
  }
  @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());
  }
 @Override
 public void visitTryStatement(@NotNull PsiTryStatement statement) {
   super.visitTryStatement(statement);
   if (JspPsiUtil.isInJspFile(statement.getContainingFile())) {
     return;
   }
   if (m_ignoreTestCases) {
     if (TestUtils.isPartOfJUnitTestMethod(statement)) {
       return;
     }
     final PsiClass containingClass = PsiTreeUtil.getParentOfType(statement, PsiClass.class);
     if (containingClass != null && TestFrameworks.getInstance().isTestClass(containingClass)) {
       return;
     }
   }
   final PsiCatchSection[] catchSections = statement.getCatchSections();
   for (final PsiCatchSection section : catchSections) {
     checkCatchSection(section);
   }
 }
  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
      }
    }
  }
  public void fillCompletions(
      CompletionParameters parameters, final Consumer<LookupElement> result) {
    final PsiElement position = parameters.getPosition();
    if (PsiTreeUtil.getParentOfType(position, PsiComment.class, false) != null) {
      return;
    }

    PsiStatement statement = PsiTreeUtil.getParentOfType(position, PsiExpressionStatement.class);
    if (statement == null) {
      statement = PsiTreeUtil.getParentOfType(position, PsiDeclarationStatement.class);
    }
    PsiElement prevLeaf = PsiTreeUtil.prevVisibleLeaf(position);
    if (statement != null
        && statement.getTextRange().getStartOffset() == position.getTextRange().getStartOffset()) {
      if (!psiElement()
          .withSuperParent(2, PsiSwitchStatement.class)
          .afterLeaf("{")
          .accepts(statement)) {
        PsiTryStatement tryStatement = PsiTreeUtil.getParentOfType(prevLeaf, PsiTryStatement.class);
        if (tryStatement == null
            || tryStatement.getCatchSections().length > 0
            || tryStatement.getFinallyBlock() != null) {
          result.consume(
              new OverrideableSpace(
                  createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE_BEFORE_WORD));
        }
      }
    }

    if (isStatementPosition(position)) {
      if (PsiTreeUtil.getParentOfType(position, PsiSwitchStatement.class, false, PsiMember.class)
          != null) {
        result.consume(
            new OverrideableSpace(createKeyword(position, PsiKeyword.CASE), TailType.INSERT_SPACE));
        result.consume(
            new OverrideableSpace(
                createKeyword(position, PsiKeyword.DEFAULT), TailType.CASE_COLON));
        if (START_SWITCH.accepts(position)) {
          return;
        }
      }

      addBreakContinue(result, position);
      addStatementKeywords(result, position);
    }

    if (SUPER_OR_THIS_PATTERN.accepts(position)) {
      final boolean afterDot = AFTER_DOT.accepts(position);
      final boolean insideQualifierClass = isInsideQualifierClass(position);
      final boolean insideInheritorClass =
          PsiUtil.isLanguageLevel8OrHigher(position) && isInsideInheritorClass(position);
      if (!afterDot || insideQualifierClass || insideInheritorClass) {
        if (!afterDot || insideQualifierClass) {
          result.consume(createKeyword(position, PsiKeyword.THIS));
        }

        final LookupItem superItem = (LookupItem) createKeyword(position, PsiKeyword.SUPER);
        if (psiElement()
            .afterLeaf(psiElement().withText("{").withSuperParent(2, psiMethod().constructor(true)))
            .accepts(position)) {
          final PsiMethod method =
              PsiTreeUtil.getParentOfType(position, PsiMethod.class, false, PsiClass.class);
          assert method != null;
          final boolean hasParams = superConstructorHasParameters(method);
          superItem.setInsertHandler(
              new ParenthesesInsertHandler<LookupElement>() {
                @Override
                protected boolean placeCaretInsideParentheses(
                    InsertionContext context, LookupElement item) {
                  return hasParams;
                }

                @Override
                public void handleInsert(InsertionContext context, LookupElement item) {
                  super.handleInsert(context, item);
                  TailType.insertChar(context.getEditor(), context.getTailOffset(), ';');
                }
              });
        }

        result.consume(superItem);
      }
    }

    if (isExpressionPosition(position)) {
      if (PsiTreeUtil.getParentOfType(position, PsiAnnotation.class) == null) {
        result.consume(
            TailTypeDecorator.withTail(
                createKeyword(position, PsiKeyword.NEW), TailType.INSERT_SPACE));
        result.consume(createKeyword(position, PsiKeyword.NULL));
      }
      if (mayExpectBoolean(parameters)) {
        result.consume(createKeyword(position, PsiKeyword.TRUE));
        result.consume(createKeyword(position, PsiKeyword.FALSE));
      }
    }

    PsiFile file = position.getContainingFile();
    if (!(file instanceof PsiExpressionCodeFragment)
        && !(file instanceof PsiJavaCodeReferenceCodeFragment)
        && !(file instanceof PsiTypeCodeFragment)) {
      if (prevLeaf == null) {
        result.consume(
            new OverrideableSpace(
                createKeyword(position, PsiKeyword.PACKAGE), TailType.HUMBLE_SPACE_BEFORE_WORD));
        result.consume(
            new OverrideableSpace(
                createKeyword(position, PsiKeyword.IMPORT), TailType.HUMBLE_SPACE_BEFORE_WORD));
      } else if (END_OF_BLOCK.getValue().isAcceptable(position, position)
          && PsiTreeUtil.getParentOfType(position, PsiMember.class) == null) {
        result.consume(
            new OverrideableSpace(
                createKeyword(position, PsiKeyword.IMPORT), TailType.HUMBLE_SPACE_BEFORE_WORD));
      }
    }

    if ((isInsideParameterList(position)
            || isAtResourceVariableStart(position)
            || isAtCatchVariableStart(position))
        && !psiElement().afterLeaf(PsiKeyword.FINAL).accepts(position)
        && !AFTER_DOT.accepts(position)) {
      result.consume(
          TailTypeDecorator.withTail(
              createKeyword(position, PsiKeyword.FINAL), TailType.HUMBLE_SPACE_BEFORE_WORD));
    }

    if (isInstanceofPlace(position)) {
      result.consume(
          LookupElementDecorator.withInsertHandler(
              createKeyword(position, PsiKeyword.INSTANCEOF),
              new InsertHandler<LookupElementDecorator<LookupElement>>() {
                @Override
                public void handleInsert(
                    InsertionContext context, LookupElementDecorator<LookupElement> item) {
                  TailType tailType = TailType.HUMBLE_SPACE_BEFORE_WORD;
                  if (tailType.isApplicable(context)) {
                    tailType.processTail(context.getEditor(), context.getTailOffset());
                  }

                  if ('!' == context.getCompletionChar()) {
                    context.setAddCompletionChar(false);
                    context.commitDocument();
                    PsiInstanceOfExpression expr =
                        PsiTreeUtil.findElementOfClassAtOffset(
                            context.getFile(),
                            context.getStartOffset(),
                            PsiInstanceOfExpression.class,
                            false);
                    if (expr != null) {
                      String space =
                          context.getCodeStyleSettings().SPACE_WITHIN_PARENTHESES ? " " : "";
                      context
                          .getDocument()
                          .insertString(expr.getTextRange().getStartOffset(), "!(" + space);
                      context.getDocument().insertString(context.getTailOffset(), space + ")");
                    }
                  }
                }
              }));
    }

    if (isSuitableForClass(position)) {
      for (String s : ModifierChooser.getKeywords(position)) {
        result.consume(
            new OverrideableSpace(createKeyword(position, s), TailType.HUMBLE_SPACE_BEFORE_WORD));
      }
      result.consume(
          new OverrideableSpace(
              createKeyword(position, PsiKeyword.CLASS), TailType.HUMBLE_SPACE_BEFORE_WORD));
      if (PsiTreeUtil.getParentOfType(position, PsiCodeBlock.class, true, PsiMember.class)
          == null) {
        result.consume(
            new OverrideableSpace(
                createKeyword(position, PsiKeyword.INTERFACE), TailType.HUMBLE_SPACE_BEFORE_WORD));
        if (PsiUtil.getLanguageLevel(position).isAtLeast(LanguageLevel.JDK_1_5)) {
          result.consume(
              new OverrideableSpace(
                  createKeyword(position, PsiKeyword.ENUM), TailType.INSERT_SPACE));
        }
      }
    }

    addPrimitiveTypes(result, position);

    if (isAfterTypeDot(position)) {
      result.consume(createKeyword(position, PsiKeyword.CLASS));
    }

    addUnfinishedMethodTypeParameters(position, result);

    if (JavaMemberNameCompletionContributor.INSIDE_TYPE_PARAMS_PATTERN.accepts(position)) {
      result.consume(
          new OverrideableSpace(
              createKeyword(position, PsiKeyword.EXTENDS), TailType.HUMBLE_SPACE_BEFORE_WORD));
      result.consume(
          new OverrideableSpace(
              createKeyword(position, PsiKeyword.SUPER), TailType.HUMBLE_SPACE_BEFORE_WORD));
    }
  }