Подтвердить что ты не робот

Замена кода с помощью обработчика аннотации

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

Среда обработки предоставляет объект Filer, который имеет удобные методы для создания новых файлов источника и класса. Они отлично работают, но затем я попытался выяснить, как читать существующие исходные файлы, и все, что он предоставляет, - это "getResource". Поэтому в моей реализации процессора я сделал это:

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    try {
        for (TypeElement te : annotations) {
            for (Element element : roundEnv.getElementsAnnotatedWith(te)) {
                FileObject in_file = processingEnv.getFiler().getResource(
                    StandardLocation.SOURCE_PATH, "",
                    element.asType().toString().replace(".", "/") + ".java");

                FileObject out_file = processingEnv.getFiler().getResource(
                    StandardLocation.SOURCE_OUTPUT, "",
                    element.asType().toString().replace(".", "/") + ".java");

                //if (out_file.getLastModified() >= in_file.getLastModified()) continue;

                CharSequence data = in_file.getCharContent(false);

                data = transform(data); // run the macro processor

                JavaFileObject out_file2 = processingEnv.getFiler().createSourceFile(
                    element.asType().toString(), element);
                Writer w = out_file2.openWriter();
                w.append(data);
                w.close();
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, e.getMessage());
    }
    return true;
}

Мое первое затруднительное положение: я не могу не чувствовать, что element.asType().toString().replace(".", "/") + ".java" (чтобы получить квалифицированное имя типа и преобразовать его в путь пакета и исходного файла) не является хорошим способом подойти к проблеме. Остальная часть API настолько переработана, но, похоже, нет удобного метода для извлечения исходного исходного кода.

Реальная проблема заключается в том, что тогда компилятор становится спонтанно нарушен вторым исходным файлом в выходном каталоге ( "error: duplicate class" ), и теперь я застрял.

Я уже написал оставшуюся часть - макро-лексер и парсер и многое другое для вычисления некоторых данных и вставки значений полей и методов - но он работает как начальный шаг вне компилятора. За исключением того факта, что исходные файлы не могут иметь расширение .java(чтобы предотвратить их просмотр компилятором), это работает хорошо. Затем я услышал, что аннотации могут генерировать код, который, я полагаю, будет более правильным и удобным, но я не могу найти много рекомендаций по нему.

4b9b3361

Ответ 1

Цель обработчика аннотаций - позволить разработчику добавлять новые классы, а не заменять существующие классы. При этом есть ошибка, которая позволяет добавлять код в существующие классы. Проект Lombok использовал, чтобы добавить геттер и сеттер (среди другие вещи) для ваших скомпилированных классов Java.

Подход, который я использовал для "замены" методов/полей, либо расширяется, либо передается в класс ввода. Это позволяет вам переопределять/переадресовывать вызовы в целевой класс.

Итак, если это ваш класс ввода:

InputImpl.java:

public class InputImpl implmements Input{
    public void foo(){
        System.out.println("foo");
    }
    public void bar(){
        System.out.println("bar");
    }
}

Вы можете создать следующее, чтобы заменить его:

InputReplacementImpl.java:

public class InputReplacementImpl implmements Input{

    private Input delegate;

    //setup delegate....

    public void foo(){
        System.out.println("foo replacement");
    }
    public void bar(){
        delegate.bar();
    }
}

Это вызывает вопрос, как вы ссылаетесь на InputReplacementImpl вместо InputImpl. Вы можете создать еще один код для выполнения обертывания или просто вызвать конструктор кода, который должен быть сгенерирован.

Я не уверен, в чем ваш вопрос, но я надеюсь, что это проливает свет на ваши проблемы.