private static PsiElement fixCatchBlock(GrTryCatchStatement tryCatch, PsiClassType[] exceptions) {
    if (exceptions.length == 0) return tryCatch;
    final GroovyPsiElementFactory factory =
        GroovyPsiElementFactory.getInstance(tryCatch.getProject());

    final GrCatchClause[] clauses = tryCatch.getCatchClauses();
    List<String> restricted =
        ContainerUtil.map(
            clauses,
            new Function<GrCatchClause, String>() {
              @Override
              @Nullable
              public String fun(GrCatchClause grCatchClause) {
                final GrParameter grParameter = grCatchClause.getParameter();
                return grParameter != null ? grParameter.getName() : null;
              }
            });

    restricted = ContainerUtil.skipNulls(restricted);
    final DefaultGroovyVariableNameValidator nameValidator =
        new DefaultGroovyVariableNameValidator(tryCatch, restricted);

    GrCatchClause anchor = clauses.length == 0 ? null : clauses[clauses.length - 1];
    for (PsiClassType type : exceptions) {
      final String[] names =
          GroovyNameSuggestionUtil.suggestVariableNameByType(type, nameValidator);
      final GrCatchClause catchClause = factory.createCatchClause(type, names[0]);
      final GrStatement printStackTrace =
          factory.createStatementFromText(names[0] + ".printStackTrace()");
      catchClause.getBody().addStatementBefore(printStackTrace, null);
      anchor = tryCatch.addCatchClause(catchClause, anchor);
      JavaCodeStyleManager.getInstance(anchor.getProject()).shortenClassReferences(anchor);
    }
    return tryCatch;
  }
 @Override
 public void visitTryStatement(GrTryCatchStatement tryCatchStatement) {
   final GrOpenBlock tryBlock = tryCatchStatement.getTryBlock();
   final GrCatchClause[] catchClauses = tryCatchStatement.getCatchClauses();
   final GrFinallyClause finallyClause = tryCatchStatement.getFinallyClause();
   builder.append("try");
   tryBlock.accept(this);
   for (GrCatchClause catchClause : catchClauses) {
     catchClause.accept(this);
   }
   if (finallyClause != null) {
     finallyClause.accept(this);
   }
 }
 private static PsiElement generateTryCatch(PsiElement element, PsiClassType[] exceptions) {
   if (exceptions.length == 0) return element;
   GrTryCatchStatement tryCatch =
       (GrTryCatchStatement)
           GroovyPsiElementFactory.getInstance(element.getProject())
               .createStatementFromText("try{} catch (Exception e){}");
   final GrStatement statement = PsiTreeUtil.getParentOfType(element, GrStatement.class);
   assert statement != null;
   tryCatch.getTryBlock().addStatementBefore(statement, null);
   tryCatch = (GrTryCatchStatement) statement.replace(tryCatch);
   tryCatch.getCatchClauses()[0].delete();
   fixCatchBlock(tryCatch, exceptions);
   return tryCatch;
 }
 private static boolean tryStatementsAreEquivalent(
     @NotNull GrTryCatchStatement statement1, @NotNull GrTryCatchStatement statement2) {
   final GrOpenBlock tryBlock1 = statement1.getTryBlock();
   final GrOpenBlock tryBlock2 = statement2.getTryBlock();
   if (!openBlocksAreEquivalent(tryBlock1, tryBlock2)) {
     return false;
   }
   final GrFinallyClause finallyBlock1 = statement1.getFinallyClause();
   final GrFinallyClause finallyBlock2 = statement2.getFinallyClause();
   if (finallyBlock1 != null) {
     if (finallyBlock2 == null
         || !openBlocksAreEquivalent(finallyBlock1.getBody(), finallyBlock2.getBody())) {
       return false;
     }
   } else if (finallyBlock2 != null) {
     return false;
   }
   final GrCatchClause[] catchBlocks1 = statement1.getCatchClauses();
   final GrCatchClause[] catchBlocks2 = statement2.getCatchClauses();
   if (catchBlocks1.length != catchBlocks2.length) {
     return false;
   }
   for (int i = 0; i < catchBlocks2.length; i++) {
     if (!catchClausesAreEquivalent(catchBlocks1[i], catchBlocks2[i])) {
       return false;
     }
   }
   return true;
 }
  public void visitTryStatement(GrTryCatchStatement tryCatchStatement) {
    final GrOpenBlock tryBlock = tryCatchStatement.getTryBlock();
    final GrCatchClause[] catchClauses = tryCatchStatement.getCatchClauses();
    final GrFinallyClause finallyClause = tryCatchStatement.getFinallyClause();

    for (int i = catchClauses.length - 1; i >= 0; i--) {
      myCaughtExceptionInfos.push(new ExceptionInfo(catchClauses[i]));
    }

    if (finallyClause != null) myFinallyCount++;

    List<Pair<InstructionImpl, GroovyPsiElement>> oldPending = null;
    if (finallyClause != null) {
      oldPending = myPending;
      myPending = new ArrayList<Pair<InstructionImpl, GroovyPsiElement>>();
    }

    InstructionImpl tryBegin = startNode(tryBlock);
    tryBlock.accept(this);
    InstructionImpl tryEnd = myHead;
    finishNode(tryBegin);

    Set<Pair<InstructionImpl, GroovyPsiElement>> pendingAfterTry =
        new LinkedHashSet<Pair<InstructionImpl, GroovyPsiElement>>(myPending);

    @SuppressWarnings("unchecked")
    List<InstructionImpl>[] throwers = new List[catchClauses.length];

    for (int i = 0; i < catchClauses.length; i++) {
      throwers[i] = myCaughtExceptionInfos.pop().myThrowers;
    }

    InstructionImpl[] catches = new InstructionImpl[catchClauses.length];

    for (int i = 0; i < catchClauses.length; i++) {
      interruptFlow();
      final InstructionImpl catchBeg = startNode(catchClauses[i]);
      for (InstructionImpl thrower : throwers[i]) {
        addEdge(thrower, catchBeg);
      }

      final GrParameter parameter = catchClauses[i].getParameter();
      if (parameter != null && myPolicy.isVariableInitialized(parameter)) {
        addNode(new ReadWriteVariableInstruction(parameter.getName(), parameter, WRITE));
      }
      catchClauses[i].accept(this);
      catches[i] = myHead;
      finishNode(catchBeg);
    }

    pendingAfterTry.addAll(myPending);
    myPending = new ArrayList<Pair<InstructionImpl, GroovyPsiElement>>(pendingAfterTry);

    if (finallyClause != null) {
      myFinallyCount--;
      interruptFlow();
      final InstructionImpl finallyInstruction = startNode(finallyClause, false);
      Set<AfterCallInstruction> postCalls = new LinkedHashSet<AfterCallInstruction>();

      final List<Pair<InstructionImpl, GroovyPsiElement>> copy = myPending;
      myPending = new ArrayList<Pair<InstructionImpl, GroovyPsiElement>>();
      for (Pair<InstructionImpl, GroovyPsiElement> pair : copy) {
        postCalls.add(addCallNode(finallyInstruction, pair.getSecond(), pair.getFirst()));
      }

      if (tryEnd != null) {
        postCalls.add(addCallNode(finallyInstruction, tryCatchStatement, tryEnd));
      }

      for (InstructionImpl catchEnd : catches) {
        if (catchEnd != null) {
          postCalls.add(addCallNode(finallyInstruction, tryCatchStatement, catchEnd));
        }
      }

      // save added postcalls into separate list because we don't want returnInstruction grabbed
      // their pending edges
      List<Pair<InstructionImpl, GroovyPsiElement>> pendingPostCalls = myPending;
      myPending = new ArrayList<Pair<InstructionImpl, GroovyPsiElement>>();

      myHead = finallyInstruction;
      finallyClause.accept(this);
      final ReturnInstruction returnInstruction = new ReturnInstruction(finallyClause);
      for (AfterCallInstruction postCall : postCalls) {
        postCall.setReturnInstruction(returnInstruction);
        addEdge(returnInstruction, postCall);
      }
      addNodeAndCheckPending(returnInstruction);
      interruptFlow();
      finishNode(finallyInstruction);

      if (oldPending == null) {
        error();
      }
      oldPending.addAll(pendingPostCalls);
      myPending = oldPending;
    } else {
      if (tryEnd != null) {
        addPendingEdge(tryCatchStatement, tryEnd);
      }
      for (InstructionImpl catchEnd : catches) {
        addPendingEdge(tryBlock, catchEnd);
      }
    }
  }