我正在尝试评估不同的方法,以在构建项目时从特定于域的语言中自动生成的Java项目中的某些代码。过去,我已经手动编写了一个或两个代码生成器,但是我没有现有代码生成框架的经验。我们尚未决定是使用这种框架还是手工构建发电机。
我需要一个概念问题的帮助;我想了解如何构建代码生成器,这使DSL可以参考现有(手写的)Java类,方法和字段。应该可以参考与生成的Java类中相同的编译单元(例如Maven项目)中的类。这意味着在运行代码生成器之前无法编译这些手写类,并且代码生成器除了在 classpath上所需的所有内容以外的所有内容以外,必须查看Java源文件用于编译这些类。
现有框架如何处理此类情况(如果有的话)?他们是自己解析Java源文件还是重新使用Java编译器的某些机器?
我认为,如果允许其自己的代码来引用同一汇编单元中的任何(非动态)非Java语言(非动态)非Java语言,则它是同一问题。看这些编译器的工作方式也许很有帮助,除非它们本身还包括Java编译器,除非它们绕过javac
。
有多种原因为什么代码生成器需要访问同一汇编单元的Java文件中的类:
- 我想提供与Java类似的语义,我可以在这里使用
import <package>.*
,然后使用这些类的名称,而无需完全限定每个类的名称。 - 如果它指的是不存在或不符合某些必需条件的符号,我想拒绝代码。
- 在某些情况下,我要生成取决于类的成员或方法签名的代码。一个示例是自动生成装饰器或构建器或实现接口,而在代码生成器不会生成基类或接口的情况下。
- 我可能想使用生成代码中引用的符号的类型信息。例如根据方法的签名生成不同的代码。
我们的项目使用Maven。我对解决这些问题的一般方法感兴趣,但是非常感谢适用于Maven的信息或示例。
如何使用DSL扩展Java,该DSL允许DSL编译器参考外部Java元素(类,方法,字段)?
实际上不清楚您在问什么,此外,这个问题比编程更重要。
无论如何,从我自己的DSL实现的经验来看,使用java
classloaders
可以动态访问新生成和编译的Java类。另外,如果您使用的是maven
,则必须将带有生产范围的所有依赖项加载到Main Class Loader中,并可以使用reflection
加载它们。
这是一些有用的链接:
- http://www.javaworld.com/article/2077260/learn-java/the-basics-of-java-class-loaders.html
- http://tutorials.jenkov.com/java-reflection/dynamic-class-loading-reloading.html
- http://docs.oracle.com/javase/tutorial/reflect/
不要解析Java程序,而是使用编译的类。参考类可以用不同的语言编写,包括其他DSL-唯一的共同点是类文件格式。
这会导致循环依赖性问题,Java程序是指DSL程序,而DSL程序则引用Java程序。可能的解决方案是:
-
在将DSL转换为Java时,请勿分析任何其他程序。所有可能的错误都将在编译生成的Java代码
时报告 将引用重定向到公共接口,从而破坏依赖性循环