Редактирование/изменение файла .java программно? (не файл .class)

Итак, вот фрагмент кода, использующий CodeModel, который генерирует Java-код:

    JCodeModel cm = new JCodeModel();
    JDefinedClass dc = cm._class("foo.Bar");
    JMethod m = dc.method(0, int.class, "foo"); 
    m.body()._return(JExpr.lit(5));
    File f = new File("C:/target/classes");
    f.mkdirs();
    cm.build(f);

Этот код генерирует .java файл:

package foo;
public class Bar {

       int foo() {
        return  5;
    }
}

Однако, я НЕ хочу, хочу, чтобы CodeModel создавал для меня новый java файл. У меня уже есть .java файл и хотел бы добавить несколько строк кода в метод внутри него. Поэтому я хотел бы, чтобы API напрямую изменял файл java/создавал измененную копию. Есть ли способ сделать это?

Ответ 1

Я знаю, что прошло некоторое время с момента публикации, но одна из наиболее доступных для поиска библиотек преобразования Java выглядит Spoon.

Из Spoon Homepage:

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

Обновление: Square также создала библиотеку генерации исходного кода JavaPoet, свободный API выглядит достаточно простым, чтобы понять.

Ответ 2

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

Eclipse IDE делает что-то подобное для поддержки рефакторинга кода. Этот article может быть полезен.

Ответ 3

... Я бы хотел, чтобы API напрямую изменял файл java/создавал измененную копию. Есть ли способ сделать это?

JavaParser - это API, который позволяет вам читать файлы Java, изменять их и получать результаты в виде строки.

Более конкретно, JavaParser анализирует файл и создает AST (абстрактное синтаксическое дерево). Затем вы можете изменить JavaParser AST, представляющий ваш исходный код, используя API и получить строковое представление AST.

У меня уже есть .java файл и хотел бы добавить несколько строк кода в метод внутри него.

Вот пример использования JavaParser для добавления строки в конец тела метода и печати результата:

class MyClass {
    public static void someMethod() {
        /* ... */
        // Lines will be added here:
    }

    public static void main(String[] args) {
        String newStatement = "System.out.println(\"Hello world!\");"
        File myClassSourceFile = new File("MyClass.java");
        CompilationUnit cu = JavaParser.parse(myClassSourceFile);
        ClassOrInterfaceDeclaration classDeclaration = cu.getClassByName("MyClass").get();
        MethodDeclaration method = classDeclaration.getMethodsByName().get(0);
        method.getBody().get().addStatement(newStatement);

        // Print out the resulting Java source code.
        System.out.println(cu.toString());
    }
}

CompilationUnit. Из JavaParser javadoc: "Этот класс представляет собой весь блок компиляции. Каждый java файл обозначает компилятор".

ПРИМЕЧАНИЕ. В вашем коде вы захотите заменить вызовы Option.get() правильной дополнительной обработкой.

Ответ 4

Что вам нужно, это система преобразования программ. Это инструмент, который анализирует ваш исходный файл и может применять преобразования для его модификации, восстанавливает исходный код с изменениями.

Система преобразования источника в источник принимает правила вида:

lhs -> rhs  if cond

где lhs и rhs являются шаблонами suce для действительных фрагментов языка, а cond проверяет правильность этого правила. (Рассмотрим "? X/? X → 1, если? X ~ = 0", вам нужно условие, чтобы убедиться, что деление действительно).

Одним из таких инструментов является наш DMS Software Reengineering Toolkit. У DMS есть полные парсеры C, С++, С#, Java, COBOL, Python, PHP и ECMAScript (как и многие менее известные языки) и могут применять такие правила напрямую. DMS также обеспечивает сбор и контроль таблиц символов и анализ потока данных, поскольку они часто полезны при определении cond для сложных правил. Если вы хотите, вы также можете вернуться к "стандартным" процедурным интерфейсам, чтобы посещать узлы дерева и изменять АСТ.