Using the Eclipse AST

后端 未结 2 1741
一整个雨季
一整个雨季 2021-02-03 14:10

I have recently come into the need of modifying some Java code (adding methods, changing the signatures of some fields and removing methods) and I think that all of this can be

相关标签:
2条回答
  • 2021-02-03 14:44

    You can do this with Eclipse by calling APIs that let you manipulate the ASTs.

    Or you can apply program transformations to achieve your effect in way that doesn't depend on the microscopic details of the AST.

    As an example you might write the following program transformation:

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

    to add an integer parameter with an arbitrary name to a parameter list. This achieves the same effect as a whole set of API calls but it is a lot more readable because it is in the surface syntax of your language (in this case, Java).

    Our DMS Software Reengineering Toolkit can accept such program transformations and apply them to many languages, including Java.

    0 讨论(0)
  • 2021-02-03 14:55

    I will not post the whole source code to this problem here because it is quite long but I will get people started.

    All the docs that you will need are here: 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();
    

    That will create a compilation unit for you from the source code that you pass in.

    Now this is a simple function that prints out all of the methods inside the class definitions in what you have passed:

    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());
                }
            }
        }
    }
    

    This should get you all started.

    It does take some time to get used to this (a lot in my case). But it does work and is the best method I could get my hands on.

    Good luck ;)

    ExtremeCoder


    Edit:

    Before I forget, these are the imports that I used to get this working (I took quite a bit of time to get these organized):

    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
    

    Where xxxx represents a version number.

    0 讨论(0)
提交回复
热议问题