All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.vertx.codetrans.lang.groovy.GroovyWriter Maven / Gradle / Ivy

package io.vertx.codetrans.lang.groovy;

import com.sun.source.tree.LambdaExpressionTree;
import io.vertx.codegen.type.ApiTypeInfo;
import io.vertx.codegen.type.ClassTypeInfo;
import io.vertx.codegen.type.EnumTypeInfo;
import io.vertx.codegen.type.TypeInfo;
import io.vertx.codetrans.CodeModel;
import io.vertx.codetrans.CodeWriter;
import io.vertx.codetrans.MethodSignature;
import io.vertx.codetrans.expression.*;
import io.vertx.codetrans.statement.StatementModel;

import javax.lang.model.element.TypeElement;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
* @author Julien Viet
*/
class GroovyWriter extends CodeWriter {

  final GroovyCodeBuilder builder;

  GroovyWriter(GroovyCodeBuilder builder) {
    super(builder);
    this.builder = builder;
  }

  @Override
  public void renderCharLiteral(char value) {
    append('\'');
    renderChars(Character.toString(value));
    append("\' as char");
  }

  @Override
  public void renderStringLiteral(List parts) {
    append('"');
    for (Object part : parts) {
      if (part instanceof ExpressionModel) {
        append("${");
        ExpressionModel ex = (ExpressionModel) part;
        ex.render(this);
        append("}");
      } else {
        renderChars(part.toString());
      }
    }
    append('"');
  }

  @Override
  public void renderStatement(StatementModel statement) {
    statement.render(this);
    append("\n");
  }

  @Override
  public void renderTryCatch(StatementModel tryBlock, StatementModel catchBlock) {
    append("try {\n");
    indent();
    tryBlock.render(this);
    unindent();
    append("} catch(Exception e) {\n");
    indent();
    catchBlock.render(this);
    unindent();
    append("}\n");
  }

  @Override
  public void renderLongLiteral(String value) {
    renderChars(value);
    append('L');
  }

  @Override
  public void renderFloatLiteral(String value) {
    renderChars(value);
    append('f');
  }

  @Override
  public void renderDoubleLiteral(String value) {
    renderChars(value);
    append('d');
  }

  @Override
  public void renderThis() {
    append("this");
  }

  @Override
  public void renderLambda(LambdaExpressionTree.BodyKind bodyKind, List parameterTypes, List parameterNames, CodeModel body) {
    append("{");
    for (int i = 0; i < parameterNames.size(); i++) {
      if (i == 0) {
        append(" ");
      } else {
        append(", ");
      }
      append(parameterNames.get(i));
    }
    append(" ->\n");
    indent();
    body.render(this);
    if (bodyKind == LambdaExpressionTree.BodyKind.EXPRESSION) {
      append("\n");
    }
    unindent();
    append("}");
  }

  @Override
  public void renderApiType(ApiTypeInfo apiType) {
    append(apiType.getSimpleName());
  }

  @Override
  public void renderJavaType(ClassTypeInfo javaType) {
    append(javaType.getName());
  }

  @Override
  public void renderAsyncResultSucceeded(TypeInfo resultType, String name) {
    append(name).append(".succeeded()");
  }

  @Override
  public void renderAsyncResultFailed(TypeInfo resultType, String name) {
    append(name).append(".failed()");
  }

  @Override
  public void renderAsyncResultCause(TypeInfo resultType, String name) {
    append(name).append(".cause()");
  }

  @Override
  public void renderAsyncResultValue(TypeInfo resultType, String name) {
    append(name).append(".result()");
  }

  @Override
  public void renderEnumConstant(EnumTypeInfo type, String constant) {
    append(type.getSimpleName()).append('.').append(constant);
  }

  @Override
  public void renderThrow(String throwableType, ExpressionModel reason) {
    if (reason == null) {
      append("throw new ").append(throwableType).append("()");
    } else {
      append("throw new ").append(throwableType).append("(");
      reason.render(this);
      append(")");
    }
  }

  @Override
  public void renderSystemOutPrintln(ExpressionModel expression) {
    append("println(");
    expression.render(this);
    append(")");
  }

  @Override
  public void renderSystemErrPrintln(ExpressionModel expression) {
    append("System.err.println(");
    expression.render(this);
    append(")");
  }

  @Override
  public void renderToDataObject(JsonObjectModel model, ClassTypeInfo type) {
    model.render(this);
  }

  @Override
  public void renderNewMap() {
    append("[:]");
  }

  @Override
  public void renderNewList() {
    append("[]");
  }

  public void renderDataObject(DataObjectLiteralModel model) {
    renderJsonObject(model.getMembers());
  }

  @Override
  public void renderDataObjectToJson(IdentifierModel model) {
    model.render(this);
  }

  public void renderJsonObject(JsonObjectLiteralModel jsonObject) {
    renderJsonObject(jsonObject.getMembers());
  }

  public void renderJsonArray(JsonArrayLiteralModel jsonArray) {
    renderJsonArray(jsonArray.getValues());
  }

  private boolean isValidMapLiteralKey(String s) {
    int len = s.length();
    if (len == 0) {
      return false;
    }
    if (!Character.isJavaIdentifierStart(s.charAt(0))) {
      return false;
    }
    for (int i = 1;i < len;i++) {
      if (!Character.isJavaIdentifierPart(s.charAt(i))) {
        return false;
      }
    }
    return true;
  }

  private void renderJsonObject(Iterable members) {
    Iterator iterator = members.iterator();
    if (iterator.hasNext()) {
      append("[\n").indent();
      while (iterator.hasNext()) {
        Member member = iterator.next();
        String name = member.getName();
        if (isValidMapLiteralKey(name)) {
          append(name);
        } else {
          append("'");
          renderChars(name);
          append("'");
        }
        append(":");
        if (member instanceof Member.Single) {
          ((Member.Single) member).getValue().render(this);
        } else if (member instanceof Member.Sequence) {
          renderJsonArray(((Member.Sequence) member).getValues());
        } else if (member instanceof Member.Entries) {
          renderJsonObject(((Member.Entries) member).entries());
        }
        if (iterator.hasNext()) {
          append(',');
        }
        append('\n');
      }
      unindent().append("]");
    } else {
      append("[:]");
    }
  }

  private void renderJsonArray(List values) {
    append("[\n").indent();
    for (int i = 0;i < values.size();i++) {
      values.get(i).render(this);
      if (i < values.size() - 1) {
        append(',');
      }
      append('\n');
    }
    unindent().append(']');
  }

  @Override
  public void renderJsonObjectAssign(ExpressionModel expression, String name, ExpressionModel value) {
    expression.render(this);
    append('.');
    append(name);
    append(" = ");
    value.render(this);
  }

  @Override
  public void renderJsonArrayAdd(ExpressionModel expression, ExpressionModel value) {
    expression.render(this);
    append(".add(");
    value.render(this);
    append(")");
  }

  @Override
  public void renderDataObjectAssign(ExpressionModel expression, String name, ExpressionModel value) {
    renderJsonObjectAssign(expression, name, value);
  }

  @Override
  public void renderJsonObjectMemberSelect(ExpressionModel expression, Class type, String name) {
    expression.render(this);
    append('.');
    append(name);
  }

  @Override
  public void renderJsonObjectToString(ExpressionModel expression) {
    append("groovy.json.JsonOutput.toJson(");
    expression.render(this);
    append(")");
  }

  @Override
  public void renderJsonArrayToString(ExpressionModel expression) {
    append("groovy.json.JsonOutput.toJson(");
    expression.render(this);
    append(")");
  }

  @Override
  public void renderDataObjectMemberSelect(ExpressionModel expression, String name) {
    renderJsonObjectMemberSelect(expression, Object.class, name);
  }

  @Override
  public void renderJsonObjectSize(ExpressionModel expression) {
    expression.render(this);
    append(".size()");
  }

  @Override
  public void renderJsonArraySize(ExpressionModel expression) {
    expression.render(this);
    append(".size()");
  }

  @Override
  public void renderListAdd(ExpressionModel list, ExpressionModel value) {
    list.render(this);
    append(".add(");
    value.render(this);
    append(")");
  }

  @Override
  public void renderListSize(ExpressionModel list) {
    list.render(this);
    append(".size()");
  }

  @Override
  public void renderListGet(ExpressionModel list, ExpressionModel index) {
    list.render(this);
    append("[");
    index.render(this);
    append("]");
  }

  @Override
  public void renderListLiteral(List arguments) {
    append("[");
    for (Iterator it = arguments.iterator();it.hasNext();) {
      it.next().render(this);
      if (it.hasNext()) {
        append(", ");
      }
    }
    append("]");
  }

  @Override
  public void renderMapGet(ExpressionModel map, ExpressionModel key) {
    map.render(this);
    append('[');
    key.render(this);
    append(']');
  }

  @Override
  public void renderMapPut(ExpressionModel map, ExpressionModel key, ExpressionModel value) {
    map.render(this);
    append('[');
    key.render(this);
    append("] = ");
    value.render(this);
  }

  @Override
  public void renderMapForEach(ExpressionModel map, String keyName, TypeInfo keyType, String valueName, TypeInfo valueType, LambdaExpressionTree.BodyKind bodyKind, CodeModel block) {
    map.render(this);
    append(".each ");
    renderLambda(bodyKind, Arrays.asList(keyType, valueType), Arrays.asList(keyName, valueName), block);
  }

  @Override
  public void renderMethodReference(ExpressionModel expression, MethodSignature signature) {
    expression.render(this);
    append(".&").append(signature.getName());
  }

  @Override
  public void renderNew(ExpressionModel expression, TypeInfo type, List argumentModels) {
    append("new ");
    expression.render(this);
    append('(');
    for (int i = 0; i < argumentModels.size(); i++) {
      if (i > 0) {
        append(", ");
      }
      argumentModels.get(i).render(this);
    }
    append(')');
  }

  @Override
  public void renderInstanceOf(ExpressionModel expression, TypeElement type) {
    expression.render(this);
    append(" instanceof ");
    append(type.getQualifiedName());
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy