自动生成Java源代码

时间:2011-04-21 14:47:51

标签: java code-generation

我正在寻找一种方法,根据类中定义的字段,自动为现有Java源代码文件中的新方法生成源代码。

实质上,我希望执行以下步骤:

  1. 阅读并解析SomeClass.java
  2. 遍历源代码中定义的所有字段
  3. 添加源代码方法someMethod()
  4. 保存SomeClass.java(理想情况下,保留现有代码的格式)
  5. 哪种工具和技术最适合实现这一目标?

    修改

    我不想在运行时生成代码;我想扩充现有的Java 源代码

7 个答案:

答案 0 :(得分:11)

你想要的是一个Program Transformation系统。

好的对你的关心,建立代表的解析代码程序AST的语言解析器,为您提供访问的AST和江苏实际修改,并且可以重新从AST源文本。你关于“扫描字段”的评论只是代表程序的AST的一种遍历。对于您生成的每个有趣的分析结果,您希望对AST进行更改,可能在其他位置,但仍然在AST中。 在完成所有chagnes之后,您需要使用注释(最初输入或在新代码中构建)重新生成文本。

有几种工具专门针对Java执行此操作。

Jackpot提供了一个解析器,构建了AST,并允许您编写Java过程来对树进行所需的操作。好处:简单概念。缺点:你写了很多Java代码来爬树/砍伐树木而不是你期望的。 Jackpot仅适用于Java。

StrategoTXL解析您的代码,生成的AST,让你写“surce - 源”转换(使用目标语言的语法,例如,Java在这种情况下),以表达模式和修复。其他好消息:您可以定义您喜欢的任何编程语言,作为要处理的目标语言,并且这两种语言都具有Java定义。 但他们在分析方面很薄弱:通常需要符号表和数据流分析才能真正进行所需的分析和更改。并且他们坚持所有是一个重写规则,无论这有助于你;这有点像坚持你只需要工具箱中的锤子;毕竟,一切都可以像钉子一样对待,对吗?

我们的DMS Software Reengineering Toolkit允许abitrary目标语言的定义(和已many predefined langauges including Java),包括西洋陆军棋,TXL,累积奖金的程序能力的所有的源极 - 到 - 源极转换功能, 并另外提供符号表,控制和数据流分析信息。编译人员告诉我们,这些东西对于构建强大的编译器(=“分析+优化+优化”)是必要的,并且由于完全相同的原因,它也适用于代码生成系统。使用此方法,您可以生成代码并在您具备相关知识的范围内对其进行优化。类似于序列化思想的一个例子是为指定的XML DTD生成快速的XML读取器和编写器;我们已经使用DMS for Java和COBOL完成了这项工作。

DMS已被用于读取/修改/写入多种源文件。可以在本技术论文中找到一个很好的例子,使这些想法变得清晰,该技术论文展示了如何修改代码以插入检测探针:Branch Coverage Made Easy。 可以在How to transform Algebra使用相同的想法找到一个更简单但更完整的定义任意语言和变换以应用于它的示例。

答案 1 :(得分:4)

查看 Java Emitter模板。它们允许您使用标记语言创建Java源文件。它类似于如何使用脚本语言来吐出HTML,除非您吐出可编译的源代码。 JET的语法与JSP非常相似,因此不太难以接受。然而,对于你想要完成的事情,这可能是一种过度杀伤力。如果您决定沿着这条路走下去,这里有一些资源:

答案 2 :(得分:2)

您可以使用cglib在运行时生成代码。

答案 3 :(得分:2)

使用自动生成的代码修改相同的java源文件是维护噩梦。考虑生成一个扩展当前类的新类,并添加所需的方法。使用反射从用户定义的类中读取并为自动生成类创建速度模板。然后为每个用户定义的类生成其扩展类。在构建生命周期中集成代码生成阶段。

或者您可以使用'字节码增强'技术来增强类,而无需修改源代码。

更新:

  1. 混合自动生成的代码总是会冒着将来修改它的风险,只是为了调整一个小的行为。这只是下一次构建的问题,而这种变化将会丢失。
  2. 您必须完全依赖自动生成源代码之上的注释来阻止开发人员这样做。
  3. 版本控制 - 假设您更新了someMethod()的模板,现在您的所有源文件版本都将更新,即使源更新是自动生成的。你会看到多余的历史。

答案 4 :(得分:1)

迭代字段并定义someMethod是一个非常模糊的问题陈述,因此很难给出一个非常有用的答案,但Eclipse的重构支持提供了一些很好的工具。它将为您提供初始化一组已定义成员的构造函数,并且它还将为您定义toString方法。

我不知道你想要考虑的其他someMethod(),但是有一个开始。

答案 5 :(得分:1)

我非常警惕将生成的代码注入包含手写代码的文件中。应该将手写代码检入修订控制,但生成的代码不应该;代码生成应该作为构建过程的一部分完成。您必须构建构建过程,以便为每个文件创建临时副本,将生成的源代码注入其中,然后编译结果,而不触及开发人员处理的原始源文件。

答案 6 :(得分:1)

Antlr是一个非常棒的工具,可以非常轻松地将Java源代码转换为Java源代码。