10

Eclipse 的 JDT 编译器提供了一个INameEnvironment定义方法的接口,findType(...)使您可以进行级联编译。奇怪的是,我想知道是否有任何方法可以使用标准 JDK 编译器工具包来做到这一点?

请注意,该场景是一个模板引擎,它在内存中编译模板文件生成的具有相互依赖关系的类,它无法预测您遇到模板文件的顺序,因此Foo可能需要先编译,然后再编译它的父级Bar,因此您需要一种机制来进行级联编译,这意味着在编译过程中Foo您需要生成另一个源Bar并首先对其进行编译才能继续Foo编译:一些代码如下:

private NameEnvironmentAnswer findType(final String name) {
    try {
        if (!name.contains(TemplateClass.CN_SUFFIX)) {
            return findStandType(name);
        }

        char[] fileName = name.toCharArray();
        TemplateClass templateClass = classCache.getByClassName(name);

        // TemplateClass exists
        if (templateClass != null) {

            if (templateClass.javaByteCode != null) {
                ClassFileReader classFileReader = new ClassFileReader(templateClass.javaByteCode, fileName, true);
                return new NameEnvironmentAnswer(classFileReader, null);
            }
            // Cascade compilation
            ICompilationUnit compilationUnit = new CompilationUnit(name);
            return new NameEnvironmentAnswer(compilationUnit, null);
        }

        // So it's a standard class
        return findStandType(name);
    } catch (ClassFormatException e) {
        // Something very very bad
        throw new RuntimeException(e);
    }
}
4

2 回答 2

2

根据我们的评论对话,我认为答案很明确:不,你不能用 JDK 编译器做到这一点。它在请求包时确实给了你一个钩子,但不是特定的类依赖项。

据我所知,尽可能接近:

这是一篇不错的带有代码的文章,尽管需要对其进行调整以在内存类中处理。具体来说,您描述的问题是由该JavaFileManager.list(...)方法处理的。您必须在此处返回已缓存在内存中的 JavaFileObjects。您很可能需要创建ForwardingJavaFileManager文章中描述的子类——尽管经过修改以处理您正在使用的缓存类。

你可以用它来编译一些东西。如果它返回错误,请使用正则表达式找出缺少的内容。在为丢失的东西生成/编译代码后,重试编译原始代码。

注意:它确实要求依赖类的 FQN 作为 ForwardingFileManager.list(...) 中的 packageName 参数。那时我还没有尝试返回课程。它可能不起作用,因为包会不匹配,但也许会。

于 2012-11-27T20:27:32.477 回答
1

尝试通读这个HelloWorld示例,看看它是否能解决您的问题。如果不发布代码,很难说出您的具体问题是什么。

于 2012-01-17T00:51:53.120 回答