0
votes

I have created a little program that reads in a Java file and feeds it to the ASTParser from the Eclipse JDT to build an Abstract Syntax Tree (AST). The root node is a CompilationUnit which I am able to access. I then iterate over the Types collection which contains the class(es) from the Java file. In my case, there is only one (the public class). This class is represented as an object that is of the type TypeDeclaration. I know I have successfully accessed this object because I am able to get its SimpleName and print it to the console.

TypeDeclaration has many methods including getFields() and getMethods(). However, when I call these methods, they return collections that are empty. The Java class that I am reading certainly has both Fields and Methods, so I don't understand why it is coming up as empty. Any ideas what is causing this? Am I misusing this API in some way or have I not initialized something?

Here is a reduced version of my code for accessing the AST:

// char array to store the file in
char[] contents = null;
BufferedReader br = new BufferedReader(new FileReader(this.file));
StringBuffer sb = new StringBuffer();
String line = "";
while((line = br.readLine()) != null) {
    sb.append(line);
}
contents = new char[sb.length()];
sb.getChars(0, sb.length()-1, contents, 0);

// Create the ASTParser
ASTParser parser = ASTParser.newParser(AST.JLS4);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setSource(contents);
parser.setResolveBindings(true);
CompilationUnit parse = (CompilationUnit) parser.createAST(null);

// look at each of the classes in the compilation unit
for(Object type : parse.types()) {
    TypeDeclaration td = (TypeDeclaration) type;
    // Print out the name of the td
    System.out.println(td.getName().toString()); // this works
    FieldDeclaration[] fds = td.getFields();
    MethodDeclaration[] mds = td.getMethods();
    System.out.println("Fields: " + fds.size()); // returns 0???
    System.out.println("Methods: " + mds.size()); // returns 0???
}

Here is the Java file that I am reading in:

public class Vector {

    // x, the first int value of this vector
    private int x;

    // y, the second int value of this vector
    private int y;

    public Vector(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public String toString() {
        return "Vector( " + this.x + " , " + this.y + " )";
    }

    public int getX() {
        return x;
}

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}

So, as expected, the first print in my AST code results in Vector, but then the subsequent prints result in Fields: 0 and Methods: 0, when I would actually expect Fields: 2 and Methods: 6.

1

1 Answers

1
votes

The problem with the above code is that the newline characters (\n) are being lost. Each time the contents of the BufferedReader are appended to the StringBuffer (sb), the \n isn't being included. The result is that from line 3 of the sample program on, everything gets commented out because the program is read in as:

public class Vector { // x, the first int value of this vector private int x; ...

No worries though because there is a simple solution. Inside of the while loop of your parsing program, simple append \n to the end of each line of input read. Like follows:

...
while((line = br.readLine()) != null) {
    sb.append(line + "\n");
}
...

The program should now be read in correctly and the output should be, as expected, 2 fields and 6 methods!