Каскадная компиляция в памяти с помощью javax.tool - PullRequest
10 голосов
/ 17 января 2012

Jcl-компилятор Eclipse предоставляет интерфейс 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);
    }
}

Ответы [ 2 ]

2 голосов
/ 28 ноября 2012

Исходя из нашего комментария, я думаю, что ответ ясен: нет, вы не можете сделать это с помощью компилятора JDK. Он запрашивает пакет при запросе пакета, но не конкретную зависимость от класса.

Примерно настолько близко, насколько вы можете понять, насколько я знаю:

Вот хорошая статья с кодом, хотя она должна быть адаптирована для обработки в классах памяти. В частности, проблема, которую вы описываете, решается методом JavaFileManager.list(...). Вы должны вернуть обратно JavaFileObjects здесь, которые вы кэшировали в памяти. Скорее всего, вам потребуется создать подкласс ForwardingJavaFileManager, как описано в этой статье, хотя и модифицированный для обработки кэшированных классов, с которыми вы работаете.

Вы можете использовать это для компиляции чего-либо. Если он возвращает ошибки, используйте регулярное выражение, чтобы выяснить, чего не хватает. После генерации / компиляции кода для отсутствующей вещи повторите попытку компиляции исходного кода.

ПРИМЕЧАНИЕ. В какой-то момент он запрашивает FQN зависимого класса в качестве аргумента packageName в ForwardingFileManager.list (...). Я не пытался вернуть класс в тот момент. Это может не сработать, потому что пакет не будет соответствовать, но, возможно, будет.

1 голос
/ 17 января 2012

Попробуйте прочитать этот HelloWorld пример, чтобы увидеть, решит ли он вашу проблему. Без публикации кода сложно сказать, в чем заключается ваша конкретная проблема.

...