private static String genIteratorVar(
      GrVariableDeclaration variableDeclaration,
      StringBuilder builder,
      ExpressionContext expressionContext,
      @NotNull GrExpression tupleInitializer,
      PsiType iteratorType,
      GroovyResolveResult iteratorMethodResult) {

    final String iteratorName =
        suggestVarName(iteratorType, variableDeclaration, expressionContext);
    builder.append("final ");
    writeType(builder, iteratorType, variableDeclaration);
    builder.append(' ').append(iteratorName).append(" = ");

    invokeMethodByResolveResult(
        tupleInitializer,
        iteratorMethodResult,
        "iterator",
        GrExpression.EMPTY_ARRAY,
        GrNamedArgument.EMPTY_ARRAY,
        GrClosableBlock.EMPTY_ARRAY,
        new ExpressionGenerator(builder, expressionContext),
        variableDeclaration);
    builder.append(";\n");
    return iteratorName;
  }
 private static void genForPart(
     StringBuilder builder, GroovyPsiElement part, final Generator visitor) {
   part.accept(visitor);
   for (String statement : visitor.getContext().myStatements) {
     builder.append(statement).append(", ");
   }
   builder.append(visitor.getBuilder());
 }
  @Override
  protected void processIntention(@NotNull PsiElement element, Project project, Editor editor)
      throws IncorrectOperationException {
    final GrMethodCallExpression expression = (GrMethodCallExpression) element;
    final GrClosableBlock block = expression.getClosureArguments()[0];
    final GrParameterList parameterList = block.getParameterList();
    final GrParameter[] parameters = parameterList.getParameters();

    String var;
    if (parameters.length == 1) {
      var = parameters[0].getText();
      var = StringUtil.replace(var, GrModifier.DEF, "");
    } else {
      var = "it";
    }

    final GrExpression invokedExpression = expression.getInvokedExpression();
    GrExpression qualifier = ((GrReferenceExpression) invokedExpression).getQualifierExpression();
    final GroovyPsiElementFactory elementFactory =
        GroovyPsiElementFactory.getInstance(element.getProject());
    if (qualifier == null) {
      qualifier = elementFactory.createExpressionFromText("this");
    }

    StringBuilder builder = new StringBuilder();
    builder.append("for (").append(var).append(" in ").append(qualifier.getText()).append(") {\n");
    String text = block.getText();
    final PsiElement blockArrow = block.getArrow();
    int index;
    if (blockArrow != null) {
      index = blockArrow.getStartOffsetInParent() + blockArrow.getTextLength();
    } else {
      index = 1;
    }
    while (index < text.length() && Character.isWhitespace(text.charAt(index))) index++;
    text = text.substring(index, text.length() - 1);
    builder.append(text);
    builder.append("}");

    final GrStatement statement = elementFactory.createStatementFromText(builder.toString());
    GrForStatement forStatement = (GrForStatement) expression.replaceWithStatement(statement);
    final GrForClause clause = forStatement.getClause();
    GrVariable variable = clause.getDeclaredVariable();

    forStatement = updateReturnStatements(forStatement);

    if (variable == null) return;

    if (ApplicationManager.getApplication().isUnitTestMode()) return;

    final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
    final Document doc = documentManager.getDocument(element.getContainingFile());
    if (doc == null) return;

    documentManager.doPostponedOperationsAndUnblockDocument(doc);
    editor.getCaretModel().moveToOffset(variable.getTextOffset());
    new VariableInplaceRenamer(variable, editor).performInplaceRename();
  }
 @Override
 public void visitFlowInterruptStatement(GrFlowInterruptingStatement statement) {
   builder.append(statement.getStatementText());
   final String name = statement.getLabelName();
   if (name != null) {
     builder.append(' ').append(name); // todo check incorrect labels
   }
   builder.append(';');
 }
 @Override
 public void visitCatchClause(GrCatchClause catchClause) {
   final GrParameter parameter = catchClause.getParameter();
   builder.append("catch (");
   writeVariableWithoutSemicolonAndInitializer(builder, parameter, context);
   builder.append(") ");
   final GrOpenBlock body = catchClause.getBody();
   if (body != null) {
     body.accept(this);
   }
 }
 @Override
 public void visitAssertStatement(final GrAssertStatement assertStatement) {
   final GrExpression assertion = assertStatement.getAssertion();
   final GrExpression message = assertStatement.getErrorMessage();
   if (assertion != null) {
     writeStatement(
         assertStatement,
         new StatementWriter() {
           @Override
           public void writeStatement(StringBuilder builder, ExpressionContext context) {
             builder.append("assert ");
             writeExpression(assertion, builder, context);
             if (message != null) {
               builder.append(" : ");
               writeExpression(message, builder, context);
             }
             builder.append(';');
           }
         });
   } else if (message != null) {
     writeStatement(
         assertStatement,
         new StatementWriter() {
           @Override
           public void writeStatement(StringBuilder builder, ExpressionContext context) {
             builder.append("assert : ");
             writeExpression(message, builder, context);
             builder.append(';');
           }
         });
   } else {
     builder.append("assert;");
   }
 }
 @Override
 public void visitFinallyClause(GrFinallyClause finallyClause) {
   builder.append("finally ");
   final GrOpenBlock body = finallyClause.getBody();
   if (body != null) {
     body.accept(this);
   }
 }
  private static void generateParametersForDelegateCall(
      GrChangeInfoImpl grInfo, GrMethod method, StringBuilder buffer) {
    buffer.append("(");

    final GrParameter[] oldParameters = method.getParameterList().getParameters();
    final JavaParameterInfo[] parameters = grInfo.getNewParameters();

    String[] params = new String[parameters.length];
    for (int i = 0; i < parameters.length; i++) {
      JavaParameterInfo parameter = parameters[i];
      final int oldIndex = parameter.getOldIndex();
      if (oldIndex >= 0) {
        params[i] = oldParameters[oldIndex].getName();
      } else {
        params[i] = parameter.getDefaultValue();
      }
    }
    buffer.append(StringUtil.join(params, ","));
    buffer.append(");");
  }
  private static boolean generateDelegate(GrChangeInfoImpl grInfo) {
    final GrMethod method = grInfo.getMethod();
    final PsiClass psiClass = method.getContainingClass();
    GrMethod newMethod = (GrMethod) method.copy();
    newMethod = (GrMethod) psiClass.addAfter(newMethod, method);
    StringBuilder buffer = new StringBuilder();
    buffer.append("\n");
    if (method.isConstructor()) {
      buffer.append("this");
    } else {
      if (!PsiType.VOID.equals(method.getReturnType())) {
        buffer.append("return ");
      }
      buffer.append(
          GrChangeSignatureUtil.getNameWithQuotesIfNeeded(
              grInfo.getNewName(), method.getProject()));
    }

    generateParametersForDelegateCall(grInfo, method, buffer);

    final GrCodeBlock codeBlock =
        GroovyPsiElementFactory.getInstance(method.getProject())
            .createMethodBodyFromText(buffer.toString());
    newMethod.setBlock(codeBlock);
    newMethod.getModifierList().setModifierProperty(PsiModifier.ABSTRACT, false);

    CodeStyleManager.getInstance(method.getProject()).reformat(newMethod);
    return processPrimaryMethodInner(grInfo, method, null);
  }
 @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 void writeReturn(
      StringBuilder builder, ExpressionContext context, final GrExpression expression) {
    builder.append("return ");

    final PsiType expectedReturnType = PsiImplUtil.inferReturnType(expression);
    final PsiType nnReturnType =
        expectedReturnType == null || expectedReturnType == PsiType.VOID
            ? TypesUtil.getJavaLangObject(expression)
            : expectedReturnType;
    wrapInCastIfNeeded(
        builder,
        nnReturnType,
        expression.getNominalType(),
        expression,
        context,
        new StatementWriter() {
          @Override
          public void writeStatement(StringBuilder builder, ExpressionContext context) {
            writeExpression(expression, builder, context);
          }
        });
    builder.append(';');
  }
  public void generateCodeBlock(GrCodeBlock block, boolean shouldInsertReturnNull) {
    builder.append("{");
    GrParameter[] parameters;
    if (block.getParent() instanceof GrMethod) {
      GrMethod method = (GrMethod) block.getParent();
      parameters = method.getParameters();
    } else if (block instanceof GrClosableBlock) {
      parameters = ((GrClosableBlock) block).getAllParameters();
    } else {
      parameters = GrParameter.EMPTY_ARRAY;
    }

    for (GrParameter parameter : parameters) {
      if (context.analyzedVars.toWrap(parameter)) {
        StringBuilder typeText =
            new StringBuilder().append(GroovyCommonClassNames.GROOVY_LANG_REFERENCE);
        writeTypeParameters(
            typeText,
            new PsiType[] {context.typeProvider.getParameterType(parameter)},
            parameter,
            new GeneratorClassNameProvider());
        builder
            .append("final ")
            .append(typeText)
            .append(' ')
            .append(context.analyzedVars.toVarName(parameter))
            .append(" = new ")
            .append(typeText)
            .append('(')
            .append(parameter.getName())
            .append(");\n");
      }
    }
    visitStatementOwner(block, shouldInsertReturnNull);
    builder.append("}\n");
  }
 public void visitStatementOwner(GrStatementOwner owner, boolean shouldInsertReturnNull) {
   boolean hasLineFeed = false;
   for (PsiElement e = owner.getFirstChild(); e != null; e = e.getNextSibling()) {
     if (e instanceof GrStatement) {
       ((GrStatement) e).accept(this);
       hasLineFeed = false;
     } else if (TokenSets.COMMENT_SET.contains(e.getNode().getElementType())) {
       builder.append(e.getText());
     } else if (org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.isLineFeed(e)) {
       hasLineFeed = true;
       if (IN_TEST) {
         builder.append(genSameLineFeed(e.getText()));
       } else {
         builder.append(e.getText());
       }
     }
   }
   if (shouldInsertReturnNull) {
     if (!hasLineFeed) {
       builder.append('\n');
     }
     builder.append("return null;\n");
   }
 }
  @Override
  public void visitReturnStatement(final GrReturnStatement returnStatement) {
    final GrExpression returnValue = returnStatement.getReturnValue();
    if (returnValue == null) {
      builder.append("return;\n");
      return;
    }

    writeStatement(
        returnStatement,
        new StatementWriter() {
          @Override
          public void writeStatement(StringBuilder builder, ExpressionContext context) {
            writeReturn(builder, context, returnValue);
          }
        });
  }
 @Override
 public void visitThrowStatement(GrThrowStatement throwStatement) {
   final GrExpression exception = throwStatement.getException();
   if (exception == null) {
     builder.append("throw ;");
     return;
   }
   writeStatement(
       throwStatement,
       new StatementWriter() {
         @Override
         public void writeStatement(StringBuilder builder, ExpressionContext context) {
           builder.append("throw ");
           writeExpression(
               exception, builder, context); // todo add exception to method 'throws' list
           builder.append(';');
         }
       });
 }
  private void writeTupleDeclaration(
      GrVariableDeclaration variableDeclaration,
      StringBuilder builder,
      ExpressionContext expressionContext) {
    GrVariable[] variables = variableDeclaration.getVariables();
    final GrExpression tupleInitializer = variableDeclaration.getTupleInitializer();
    if (tupleInitializer instanceof GrListOrMap) {
      for (GrVariable variable : variables) {
        writeVariableSeparately(variable, builder, expressionContext);
        builder.append(";\n");
      }
    } else if (tupleInitializer != null) {

      GroovyResolveResult iteratorMethodResult =
          resolveMethod(
              tupleInitializer,
              "iterator",
              GrExpression.EMPTY_ARRAY,
              GrNamedArgument.EMPTY_ARRAY,
              GrClosableBlock.EMPTY_ARRAY,
              variableDeclaration);

      final PsiType iteratorType = inferIteratorType(iteratorMethodResult, tupleInitializer);

      final String iteratorName =
          genIteratorVar(
              variableDeclaration,
              builder,
              expressionContext,
              tupleInitializer,
              iteratorType,
              iteratorMethodResult);

      final GrModifierList modifierList = variableDeclaration.getModifierList();

      PsiType iterableTypeParameter = PsiUtil.extractIterableTypeParameter(iteratorType, false);

      for (final GrVariable v : variables) {
        ModifierListGenerator.writeModifiers(builder, modifierList);
        final PsiType type = context.typeProvider.getVarType(v);
        writeType(builder, type, variableDeclaration);
        builder.append(' ').append(v.getName());

        builder.append(" = ");
        wrapInCastIfNeeded(
            builder,
            type,
            iterableTypeParameter,
            tupleInitializer,
            expressionContext,
            new StatementWriter() {
              @Override
              public void writeStatement(StringBuilder builder, ExpressionContext context) {
                builder
                    .append(iteratorName)
                    .append(".hasNext() ? ")
                    .append(iteratorName)
                    .append(".next() : null");
              }
            });
        builder.append(";\n");
      }
    } else {
      writeSimpleVarDeclaration(variableDeclaration, builder, expressionContext);
    }
  }
 private static void writeVariableWithoutSemicolonAndInitializer(
     StringBuilder builder, GrVariable var, ExpressionContext context) {
   ModifierListGenerator.writeModifiers(builder, var.getModifierList());
   writeType(builder, context.typeProvider.getVarType(var), var);
   builder.append(' ').append(var.getName());
 }
  @Override
  public void visitForStatement(GrForStatement forStatement) {
    // final StringBuilder builder = new StringBuilder();
    builder.append("for(");

    final GrForClause clause = forStatement.getClause();
    ExpressionContext forContext = context.extend();
    if (clause instanceof GrForInClause) {
      final GrExpression expression = ((GrForInClause) clause).getIteratedExpression();
      final GrVariable declaredVariable = clause.getDeclaredVariable();
      LOG.assertTrue(declaredVariable != null);

      writeVariableWithoutSemicolonAndInitializer(builder, declaredVariable, context);
      builder.append(" : ");
      if (expression != null) {
        final ExpressionContext context = forContext.copy();
        writeExpression(expression, builder, context);
      }
    } else if (clause instanceof GrTraditionalForClause) {
      final GrTraditionalForClause cl = (GrTraditionalForClause) clause;
      final GrCondition initialization = cl.getInitialization();
      final GrExpression condition = cl.getCondition();
      final GrExpression update = cl.getUpdate();

      if (initialization instanceof GrParameter) {
        StringBuilder partBuilder = new StringBuilder();
        writeVariableWithoutSemicolonAndInitializer(
            partBuilder, (GrParameter) initialization, context);
        final GrExpression initializer = ((GrParameter) initialization).getInitializerGroovy();
        if (initializer != null) {
          final ExpressionContext partContext = forContext.copy();
          partBuilder.append(" = ");
          writeExpression(initializer, partBuilder, partContext);
          for (String statement : partContext.myStatements) {
            builder.append(statement).append(", ");
          }
          builder.append(partBuilder);
        }
      } else if (initialization != null) {
        StringBuilder partBuilder = new StringBuilder();
        final ExpressionContext partContext = forContext.copy();
        genForPart(builder, initialization, new CodeBlockGenerator(partBuilder, partContext, null));
      }

      builder.append(';');
      if (condition != null) {
        genForPart(builder, condition, forContext.copy()); // todo???
      }

      builder.append(';');
      if (update != null) {
        genForPart(builder, update, forContext.copy());
      }
    }
    builder.append(')');

    final GrStatement body = forStatement.getBody();
    if (body != null) {
      body.accept(new CodeBlockGenerator(builder, forContext, null));
    }
  }