Использование Eclipse AST - PullRequest
6 голосов
/ 28 июля 2010

Недавно я стал нуждаться в изменении некоторого кода Java (добавление методов, изменение сигнатур некоторых полей и удаление методов), и я думаю, что все это может быть достигнуто с помощью AST Eclipse SDK.

Из некоторых исследований я знаю, как анализировать исходный файл, но я не знаю, как делать вещи, упомянутые выше. Кто-нибудь знает хороший учебник или кто-то может дать мне краткое объяснение, как решить эти проблемы?

Большое спасибо,

ExtremeCoder


Edit:

Теперь я начал больше изучать JCodeModel, и я думаю, что это может быть намного проще в использовании, но я не знаю, можно ли в него загрузить существующий документ?

Если это может сработать, дайте мне знать;)

Еще раз спасибо.

Ответы [ 2 ]

4 голосов
/ 28 июля 2010

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

Все документы, которые вам понадобятся, находятся здесь: http://publib.boulder.ibm.com/infocenter/iadthelp/v6r0/index.jsp?topic=/org.eclipse.jdt.doc.isv/reference/api/org/eclipse/jdt/core/dom/package-summary.html

Document document = new Document("import java.util.List;\n\nclass X\n{\n\n\tpublic void deleteme()\n\t{\n\t}\n\n}\n");
ASTParser parser = ASTParser.newParser(AST.JLS3);
parser.setSource(document.get().toCharArray());
CompilationUnit cu = (CompilationUnit)parser.createAST(null);
cu.recordModifications();

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

Теперь это простая функция, которая печатает все методы внутри определений классов в том, что вы передали:

List<AbstractTypeDeclaration> types = cu.types();
for(AbstractTypeDeclaration type : types) {
    if(type.getNodeType() == ASTNode.TYPE_DECLARATION) {
        // Class def found
        List<BodyDeclaration> bodies = type.bodyDeclarations();
        for(BodyDeclaration body : bodies) {
            if(body.getNodeType() == ASTNode.METHOD_DECLARATION) {
                MethodDeclaration method = (MethodDeclaration)body;
                System.out.println("method declaration: ");
                System.out.println("name: " + method.getName().getFullyQualifiedName());
                System.out.println("modifiers: " + method.getModifiers());
                System.out.println("return type: " + method.getReturnType2().toString());
            }
        }
    }
}

Это должно привести вас в порядок.

Требуется некоторое время, чтобы привыкнуть к этому (много в моем случае). Но это работает, и это лучший метод, который я мог получить в свои руки.

Удачи;)

ExtremeCoder


Edit:

Прежде чем я забуду, это импорт, который я использовал, чтобы заставить это работать (я потратил довольно много времени, чтобы организовать их):

org.eclipse.jdt.core_xxxx.jar
org.eclipse.core.resources_xxxx.jar
org.eclipse.core.jobs_xxxx.jar
org.eclipse.core.runtime_xxxx.jar
org.eclipse.core.contenttype_xxxx.jar
org.eclipse.equinox.common_xxxx.jar
org.eclipse.equinox.preferences_xxxx.jar
org.eclipse.osgi_xxxx.jar
org.eclipse.text_xxxx.jar

Где xxxx представляет номер версии.

1 голос
/ 31 июля 2010

Вы можете сделать это с Eclipse, вызывая API, которые позволяют вам манипулировать AST.

Или вы можете применить программные преобразования для достижения эффекта, который не зависит от микроскопических деталей AST.

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

add_int_parameter(p:parameter_list, i: identifier): parameters -> parameters
  " \p " -> " \p , int \i";

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

Наш инструментарий реинжиниринга программного обеспечения DMS может принимать такие программные преобразования и применять их ко многим языкам, включая Java.

...