assumes ST 4.0.1
One of the frustrations with ST v3 was that it was sometimes hard to debug the templates. For v4, everything is a lot cleaner and I can present for you a nice GUI that tells you everything about a template and any nested templates. There are some key bits of information you need when debugging a template:
The GUI frame answers these questions and provides extra information including the generated bytecodes compiled from the original template as well as an execution trace through the interpreter.
To use the GUI inspector, you don't need to do anything except call ST.inspect() on the root of your template hierarchy. If you also want to track template creation events and attribute injection events, turn on the static STGroup.trackCreationEvents flag. The interpretation of templates is totally side effect free so you can render and inspect templates as you wish and in any order.
STGroup.trackCreationEvents = true;
STGroup group = new STGroupFile("t.stg");
ST st = group.getInstanceOf("test");
st.add("attrname", value);
...
st.inspect();
|
Here's basic view when you start up:

Clicking on one of the templates in the upper left quadrant resets the display so that the output from that template instance is highlighted in the output pane. The stack of templates in the lower left pane also changes. Opening up the template names in that pane shows the attributes injected into that template.
Also notice that the location in the source code where the template was created to show and also the place in the source where the attribute was added is shown. The main outputFile template was created at location CodeGenerator.java line 296. In the attributes pane you can see that rewriteMode was injected at line 343, and so on. If there is no location, that means that the template was automatically created by StringTemplate internally or the attribute was not set.

Sometimes it's helpful to figure out how ST interprets the syntax of your source code. When looking at the template source, the right subpane next to it shows the AST. If you click on an element in the AST, it highlights the place in the source code for which it was created.
![]()
If you'd like to see what the bytecode looks like, you can click on that pane.
![]()
Finally, you can also see the interpreter in action (mostly of educational value). The trace shows the stack of the byte code interpreter, the call stack, and the number of output characters.
![]()
When you reference an attribute, say, x within your template, ST tries to resolve x within the injected attributes of that template. If you can't find it, ST looks up the enclosing template change towards the root of the overall template hierarchy. This dynamic scoping allows deeply nested templates to refer to attributes injected into the root template. You might, for example, want to know the overall file name in some deeply nested template. Or, you might want to know the surrounding method name when you're generating code in nested template for the various statements.
Sometimes, though, it can be hard figuring out why an attribute as the wrong value. You can look at the lower left pane for the stack of templates to see the scope context. Simply start at the bottom and look upwards until you find the first definition of your attribute. Here's an example where the output shows "CommonTree" because the ruleLabelPropertyRef_start references attribute labelType:
(<scope>!=null?((<labelType>)<scope>.start):null) |
labelType happens to be a default attribute of a template above in the hierarchy that references <ASTLabelType>. The ASTLabelType value is set as an argument of genericParser template way up the hierarchy, almost at the root.
