How to debug a Java Emitter template

This is a tricky task. The generation of a piece of code – let’s assume that it is a Java class – is based on a java emitter template that defines with literal constants and JSP like syntax the code of the resulting class. To create a source file a Java generator class is generated from the template. This generator class produces dour output Java source file.

Setting a break point in the template and start the JET generator in debug will not work, since the actual errors occur in the class that is generated from the template and there are no breakpoints set.
So let us assume your call of the JET generator looks something like this:

monitor = createIfNull(_monitor);
Config config = getConfig();
String templateURI=config.getTemplateFullUri();
JETEmitter emitter = new JETEmitter(templateURI, getClass().getClassLoader());
Monitor sub = new BasicMonitor.EclipseSubProgress(monitor, 1);
emitter.addVariable("model", ModelPlugin.getPluginID());
jetEmiterProjectName=emitter.getProjectName();
String result = emitter.generate(sub, new Object []{ config.getModel() });
return result;

Listing from the class ch.sahits.codegen.java.generator.JETGatway from the Eclipse plug-in ch.sahits.codegen.java
If you have the sources of the EMF available you can put a breakpoint at the second to last line of the above listing and step into the emitter. Work your way through until you reach this code fragment:

IMarker [] markers = targetFile.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE);
boolean errors = false;
for (int i = 0; i < markers.length; ++i) { IMarker marker = markers[i]; if (marker.getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_INFO) == IMarker.SEVERITY_ERROR) { errors = true; subProgressMonitor.subTask (marker.getAttribute(IMarker.MESSAGE) + " : " + (CodeGenPlugin.getPlugin().getString ("jet.mark.file.line", new Object [] { targetFile.getLocation(), marker.getAttribute(IMarker.LINE_NUMBER) }))); } }

Belongs to org.eclipse.emf.codegen.jet.JETEmitter.EclipseHelper.initialize(Monitor,JETEmitter)
There you see a concrete error message is sent to the monitor, but since use the set up you do you won't see it.
The above method may work fine if you have access to the source whenever you need it and the debugging is no regular occurrence (since this is a nuisance).
The initialize method is called from the JETEmitter.generate(Monitor,Object[]) method if the initialisation did not already occur. So you can provide your own implementation of the initialize method and explicitly call it before generating the code.
I did this by coping the EclipseHelper class and changing the above code:

IMarker [] markers = targetFile.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE);
boolean errors = false;
for (int i = 0; i < markers.length; ++i) { IMarker marker = markers[i]; if (marker.getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_INFO) == IMarker.SEVERITY_ERROR) { errors = true; String errorMessage = marker.getAttribute(IMarker.MESSAGE) + " : " + (CodeGenPlugin.getPlugin().getString ("jet.mark.file.line", new Object [] { targetFile.getLocation(), marker.getAttribute(IMarker.LINE_NUMBER) })); Logging.addMessage(getClass(), errorMessage); Logging.log(new RuntimeException(errorMessage)); subProgressMonitor.subTask(errorMessage); } }

Listening from ch.sahits.codegen.java.internal.generator.jet.JETEmitterInitializer
The above code results in logging an error. Alternatively you can just put it out on the console.
Before you call the generate method you have to call the initialize method.

JETEmitter emitter = new JETEmitter(templateURI, getClass().getClassLoader());
Monitor sub = new BasicMonitor.EclipseSubProgress(monitor, 1);
emitter.addVariable("model", ModelPlugin.getPluginID());
jetEmiterProjectName=emitter.getProjectName();
new JETEmitterInitializer(emitter).initialize(monitor);
String result = emitter.generate(sub, new Object []{ config.getModel() });

Mentioned Resources:
ch.sahits.codegen.java.generator.JETGateway
org.eclipse.emf.codegen.jet.JETEmitter
ch.sahits.codegen.java.internal.generator.jet.JETEmitterInitializer

Schreibe einen Kommentar