|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: "Inspecting an AST" |
| 4 | +date: 2018-03-03 09:58:46 +0100 |
| 5 | +categories: [blog] |
| 6 | +tags: [guide, danny] |
| 7 | +permalink: /inspecting-an-ast/ |
| 8 | +--- |
| 9 | + |
| 10 | +## Inspecting an AST |
| 11 | + |
| 12 | +Two of the more common questions on JavaParser are: |
| 13 | + |
| 14 | +* If I have this piece of code, how do I access that part of it? |
| 15 | +* If I want this piece of code, how do I create the AST for it? |
| 16 | + |
| 17 | +and both can be answered the same way: by looking at the AST that is generated when you parse the code you have or want. We offer several ways to do this. |
| 18 | + |
| 19 | +### First: parse the code |
| 20 | + |
| 21 | +This is something like: |
| 22 | + |
| 23 | + package com.github.javaparser; |
| 24 | + |
| 25 | + import com.github.javaparser.ast.CompilationUnit; |
| 26 | + |
| 27 | + public class Inspect { |
| 28 | + public static void main(String[] args) { |
| 29 | + // Parse the code you want to inspect: |
| 30 | + CompilationUnit cu = StaticJavaParser.parse("class X { int x; }"); |
| 31 | + // Now comes the inspection code: |
| 32 | + System.out.println(cu); |
| 33 | + } |
| 34 | + } |
| 35 | + |
| 36 | +### Option 1: your IDE's debugger |
| 37 | + |
| 38 | +You'll need to figure out how your IDE works to get this to work. Put a breakpoint on `System.out.println(cu);` and run the program in debug mode. When it stops at the breakpoint, you should be able to see the known variables. Look for `cu` and you can click it open, and now you can inspect the whole generated AST. |
| 39 | + |
| 40 | +### Option 2: use one the structure printers |
| 41 | + |
| 42 | +Thanks to [Ryan Beckett](https://www.linkedin.com/in/ryanbeckett/) there are a few printers that will output the structure of the AST with only one purpose: for you to look at. My favourite one outputs Yaml: |
| 43 | + |
| 44 | + // Now comes the inspection code: |
| 45 | + YamlPrinter printer = new YamlPrinter(true); |
| 46 | + System.out.println(printer.output(cu)); |
| 47 | + |
| 48 | +Here's the output. You can see property names (`isInterface`, `identifier`, ...) node types (`Type=CompilationUnit`) and values (`"false"`, `"x"`). You can see how a type has members, how `int x;` is one of those members, that it has type `FieldDeclaration` and can contain multiple variables, but there is only one now: `"x"`. |
| 49 | + |
| 50 | + root(Type=CompilationUnit): |
| 51 | + types: |
| 52 | + - type(Type=ClassOrInterfaceDeclaration): |
| 53 | + isInterface: "false" |
| 54 | + name(Type=SimpleName): |
| 55 | + identifier: "X" |
| 56 | + members: |
| 57 | + - member(Type=FieldDeclaration): |
| 58 | + variables: |
| 59 | + - variable(Type=VariableDeclarator): |
| 60 | + name(Type=SimpleName): |
| 61 | + identifier: "x" |
| 62 | + type(Type=PrimitiveType): |
| 63 | + type: "INT" |
| 64 | + |
| 65 | +If you like looking at XML, try: |
| 66 | + |
| 67 | + // Now comes the inspection code: |
| 68 | + XmlPrinter printer = new XmlPrinter(true); |
| 69 | + System.out.println(printer.output(cu)); |
| 70 | + |
| 71 | +You will need to load this into an editor that can format XML. Finally an extra cool one - it outputs the AST as a dot file which can be visualized as a graph with [Graphviz](http://graphviz.org/)! |
| 72 | + |
| 73 | + // Now comes the inspection code: |
| 74 | + DotPrinter printer = new DotPrinter(true); |
| 75 | + try (FileWriter fileWriter = new FileWriter("ast.dot"); |
| 76 | + PrintWriter printWriter = new PrintWriter(fileWriter)) { |
| 77 | + printWriter.print(printer.output(cu)); |
| 78 | + } |
| 79 | + |
| 80 | +I've sent the output to Graphiz this way: |
| 81 | + |
| 82 | + dot -Tpng ast.dot > ast.png |
| 83 | + |
| 84 | + |
0 commit comments