Question

Eclipse's JDT compiler provide an interface INameEnvironment which defines method findType(...) enable you to do cascade compilation. Curiously I would like to know if there are any means to do it using standard JDK compiler toolkit?

Note, the scenario is a template engine which do in memory compilation for template file generated classes which have inter-dependencies, and it cannot forecast the order you encountered a template file, thus Foo might needs to be compiled first before it's parent Bar compiled already, therefore you need a mechanism to do cascade compilation, meaning during compilation of Foo you need to generate another source Bar and compile it first in order to continue Foo's compilation: some code like the follows:

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);
    }
}
Was it helpful?

Solution

Based on our comment conversation, I think the answer is a clear: no, you can't do that with the JDK compiler. It does give you a hook when it requests the package, but not the specific class dependency.

About as close as you can get so far as I know is:

Here's a nice article with code though it needs to be adapted to handle in memory classes. Specifically the issue you're describing is handled by the JavaFileManager.list(...) method. You have to return back JavaFileObjects here that you have cached in memory. You'll most likely need to create a subclass of ForwardingJavaFileManager as described in the article--though modified to handle the cached classes you are working with.

You can use that to compile something. If it returns errors, use regex to find out what is missing. After generating/compiling the code for the missing thing, retry compiling the original code.

NOTE: It does ask for the FQN of the dependent class as the packageName argument in ForwardingFileManager.list(...) at some point. I haven't tried to return the class at that point. It might not work because the package would mismatch, but maybe it would.

OTHER TIPS

Try reading through this HelloWorld example to see if it solves your problem. Without posting the code, it's hard to say what your specific issue is.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top