java - 使用JET生成代码: Indenting code

标签 java eclipse code-generation eclipse-m2t-jet

我正在尝试执行以下操作:

Write a JET template that receives an object of type Class as argument. The object should represent a Java interface. The template generates a class that implements the interface, i.e. provides methods for all the method signatures it defines. The name of the generated class should be XImplementation where X is the name of the argument interface. The methods in the generated class do nothing or only return constant values: 0 for int and double, false for boolean, and null for reference types. You do not need to consider any other return types. E.g. for the following interface A, class AImplementation would be generated:

interface A {  
    void m1(int x, int y);  
    int m2(Object a);  
    Object m3();  
}  

class AImplementation implements A {  
    public void m1(int p1, int p2) { }  
    public int m2(Object p1) { return 0; }  
    public Object m3() { return null; }  
}  

Hint: the unqualified (simple) name of a type can be acquired by using the getSimpleName() method on the corresponding Class object.

我已经阅读了在 eclipse.org 上找到的关于 JET 的教程,但我仍然无法理解我需要做什么。

当我制作要翻译的 .txtjet 文件时,我是否试图让 .txtjet 文件的实现写入一个巨大的字符串,其中包含我想在 generate 中生成的代码方法?这是正确的概念吗?

如果是这种情况,我在某​​一特定方面遇到了麻烦。这是我到目前为止提出的 JET 模板:

<%@ jet imports="java.lang.reflect.*" class="Q2Generator" %>
<%Object o = (Object) argument;%>
<%Class c = o.getClass();%>

public class <%=c.getName()%>Implementation implements <%=c.getName()%> {
<%for (Method m : c.getDeclaredMethods()) {%>
<%  Class type = m.getReturnType();%>
<%  if (!type.isPrimitive()) {%>
public <%=type.getSimpleName()%> <%=m.getName()%> { return null; } // this line is the problem
<%  }%>
<%}%>       
}

此模板在 generate 方法中生成以下代码:

  public final String NL = nl == null ? (System.getProperties().getProperty("line.separator")) : nl;
  protected final String TEXT_1 = NL + "public class ";
  protected final String TEXT_2 = "Implementation implements ";
  protected final String TEXT_3 = " {";
  protected final String TEXT_4 = NL + "public ";
  protected final String TEXT_5 = " ";
  protected final String TEXT_6 = " { return null; }";
  protected final String TEXT_7 = NL + "\t\t" + NL + "}";
  protected final String TEXT_8 = NL;

  public String generate(Object argument)
  {
    final StringBuffer stringBuffer = new StringBuffer();
    Object o = (Object) argument;
    Class c = o.getClass();
    stringBuffer.append(TEXT_1);
    stringBuffer.append(c.getName());
    stringBuffer.append(TEXT_2);
    stringBuffer.append(c.getName());
    stringBuffer.append(TEXT_3);
    for (Method m : c.getDeclaredMethods()) {
        Class type = m.getReturnType();
        if (!type.isPrimitive()) {
    stringBuffer.append(TEXT_4);
    stringBuffer.append(type.getSimpleName());
    stringBuffer.append(TEXT_5);
    stringBuffer.append(m.getName());
    stringBuffer.append(TEXT_6);
        }
    }
    stringBuffer.append(TEXT_7);
    stringBuffer.append(TEXT_8);
    return stringBuffer.toString();
  }

有没有办法缩进 if 语句中的 stringBuffer.append() 行?字符串方式是否是完成此任务的正确方式?

谢谢。

最佳答案

我会使用较新的 JET2 语法。您应该能够使用新建 -> 其他创建新的 JET 转换。

至于高层发生的事情,您将有一个名为 main.jet 的模板,它将充当 Controller 。它本身不创建任何文本内容,但会管理项目、文件夹和文件的生成。

我知道您想使用类对象作为输入,但我建议您构建模板以使用 XML 文件作为输入。像这样:

<root>
    <object name="A">
        <method name="m1" returns="void">
            <arg name="x" type="int" />
            <arg name="y" type="int" />
        </method>
        <method name="m2" returns="int">
            <arg name="a" type="Object" />
        </method>
        <method name="m3" returns="Object">
        </method>
    </object>
</root>

您可以看到,给定一个类,我们可以“轻松”地创建这样一个 XML 文档。

所以 main.jet 看起来像这样:

<%@taglib prefix="ws" id="org.eclipse.jet.workspaceTags" %>

<c:iterate select="/root/object" var="object"

    <c:set select="$object" name="impl" ><c:get select="$object/@name"/>Implementation</c:set>
    <c:set select="$object" name="interface" ><c:get select="$object/@name"/></c:set>

</c:iterate>


<c:iterate select="/root/object" var="object">

    <ws:file path="my project/src/a/b/c/{$object/@interface}.java" template="interface.jet" />
    <ws:file path="my project/src/a/b/c/{$object/@impl}.java" template="impl.jet" />

</c:iterate>

基本上,您是在遍历每个对象(您可以定义任意多个对象),构建实现和接口(interface)名称并将这些名称存储回模型中。
完成所有命名约定后,您将遍历对象元素并使用 ws:file 标记将模板应用于模型。该标签告诉使用哪个模板,然后指定要使用生成结果创建的文件名。

interface.jet 文件可能看起来像这样:

package a.b.c;

interface <c:get select="$object/@interface"/> { 
<c:iterate select="$object/method" var="method" > 
    <c:get select="$method/@returns"/> <c:get select="$method/@name"/>(int x, int y);  
</c:iterate>
}  

请注意,我已将包硬编码为 a.b.c。您可以通过将属性添加到 XML 文件(可能是对象元素)并使用 c:get 标记将其插入到源中来创建该变量。我还对 args 进行了硬编码,但您可以使用另一个迭代标记来迭代模型中的嵌套元素以写出方法签名。

所以我会停在那里看看这是否是您要找的东西。您可能想在评论中提出更多问题或发布更多问题。

关于java - 使用JET生成代码: Indenting code,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7762304/

相关文章:

Java:寻找最快的方法来检查字符串是否存在特定范围内的 Unicode 字符

java - SonarLint 2.2.1 Eclipse 没有发现大部分问题(与在线示例不同)

java - 如何从网页监控互联网带宽?

java - 构建项目时的 Maven 配置

java - 如何在 Mac 上恢复已删除的 java 文件?

c# - 使用 C# 实现代码模板

java - 在运行时创建带有注释字段的 java 类

java - 如何从 IntelliJ getter/setter 生成中删除 `get` 和 `set`

java - 从列表中对象的特定字段创建数组

eclipse - [eclipse]访问存储库条目时发生错误