#5 Debug Support
Jul 03, 2012 |
13 minutes |
Debug
Demonstration of the the Xtext 2.3 debug support feature. Debug an Xbase expression and a custom DSL.
- Download:
- source code Project Files in Zip (1.79 MB)
- mp4 Full Size H.264 Video (32.7 MB)
- m4v Smaller H.264 Video (18.7 MB)
- webm Full Size VP8 Video (19.4 MB)
- ogv Full Size Theora Video (45.1 MB)
What's new in Xtext 2.3: http://www.eclipse.org/Xtext/releasenotes/2.3.0/new_and_noteworthy.php
A very good tutorial about integrating Xbase expressions into a custom DSL using TDD and enabling the debugger support: http://www.rcp-vision.com/?p=4089&lang=en
DomainmodelJvmModelInferrer:
xtend
XmlGenerator : {
members += f.toMethod(f.name + "XmlGenerator", f.newTypeRef(typeof(String))) [
documentation = f.documentation
body = [
val varName = declareVariable(this, "sb")
var t = trace(f, true)
f.newTypeRef(typeof(StringBuilder)).serialize(f, t)
t.append(''' «varName» = new ''')
f.newTypeRef(typeof(StringBuilder)).serialize(f, t)
t.append(''' ();''').newLine
inferXml(f.block, 0)
trace(f).append('''return «varName».toString();''').newLine
]
]
}
XmlGenerator : { members += f.toMethod(f.name + "XmlGenerator", f.newTypeRef(typeof(String))) [ documentation = f.documentation body = [ val varName = declareVariable(this, "sb") var t = trace(f, true) f.newTypeRef(typeof(StringBuilder)).serialize(f, t) t.append(''' «varName» = new ''') f.newTypeRef(typeof(StringBuilder)).serialize(f, t) t.append(''' ();''').newLine inferXml(f.block, 0) trace(f).append('''return «varName».toString();''').newLine ] ] }
xtend
def dispatch inferXml(ITreeAppendable it, XmlTags tags, int indentation) {
for (tag : tags.tags) {
var t =trace(tag, true)
t.indent(indentation)
t.outputln('''"<«tag.name»>"''')
inferXml(tag.block, indentation + 1)
trace(tag).indent(indentation)
trace(tag).outputln('''"</«tag.name»>"''')
}
}
def dispatch void inferXml(ITreeAppendable it, XmlContent content, int indentation) {
val t = trace(content, true)
t.indent(indentation)
t.outputln('''this.«content.property.name»''')
}
def indent(ITreeAppendable it, int indentation) {
val spaces = (0..indentation).map [""].reduce [ result, next |
result + " "
]
output('''"«spaces»"''')
}
def outputln(ITreeAppendable it, String content) {
val varName = getName(this)
append('''«varName».append(«content»);''').newLine
append('''«varName».append("\n");''').newLine
append('''System.out.println(«content»);''').newLine
}
def output(ITreeAppendable it, String content) {
val varName = getName(this)
append('''«varName».append(«content»);''').newLine
append('''System.out.print(«content»);''').newLine
}
def dispatch inferXml(ITreeAppendable it, XmlTags tags, int indentation) { for (tag : tags.tags) { var t =trace(tag, true) t.indent(indentation) t.outputln('''"<«tag.name»>"''') inferXml(tag.block, indentation + 1) trace(tag).indent(indentation) trace(tag).outputln('''"</«tag.name»>"''') } } def dispatch void inferXml(ITreeAppendable it, XmlContent content, int indentation) { val t = trace(content, true) t.indent(indentation) t.outputln('''this.«content.property.name»''') } def indent(ITreeAppendable it, int indentation) { val spaces = (0..indentation).map [""].reduce [ result, next | result + " " ] output('''"«spaces»"''') } def outputln(ITreeAppendable it, String content) { val varName = getName(this) append('''«varName».append(«content»);''').newLine append('''«varName».append("\n");''').newLine append('''System.out.println(«content»);''').newLine } def output(ITreeAppendable it, String content) { val varName = getName(this) append('''«varName».append(«content»);''').newLine append('''System.out.print(«content»);''').newLine }
Enabling breakpoints:
DomainmodelRuntimeModule.java
@Override
public Class<? extends IStratumBreakpointSupport> bindIStratumBreakpointSupport() {
return MyStratumBreakpointSupport.class;
}
@Override public Class<? extends IStratumBreakpointSupport> bindIStratumBreakpointSupport() { return MyStratumBreakpointSupport.class; }
MyStratumBreakpointSupport.java
public class MyStratumBreakpointSupport implements IStratumBreakpointSupport {
public boolean isValidLineForBreakPoint(XtextResource resource, int line) {
IParseResult parseResult = resource.getParseResult();
if (parseResult == null)
return false;
ICompositeNode node = parseResult.getRootNode();
return isValidLineForBreakpoint(node, line);
}
protected boolean isValidLineForBreakpoint(ICompositeNode node, int line) {
for (INode n : node.getChildren()) {
if (n.getStartLine()<= line && n.getEndLine() >= line) {
EObject eObject = n.getSemanticElement();
if (eObject instanceof XExpression && !(eObject.eClass() == XbasePackage.Literals.XBLOCK_EXPRESSION)) {
return true;
}
if (n instanceof ICompositeNode && isValidLineForBreakpoint((ICompositeNode) n, line)) {
return true;
}
if (eObject instanceof XmlGenerator) {
return true;
}
}
if (n.getStartLine() > line) {
return false;
}
}
return false;
}
}
public class MyStratumBreakpointSupport implements IStratumBreakpointSupport { public boolean isValidLineForBreakPoint(XtextResource resource, int line) { IParseResult parseResult = resource.getParseResult(); if (parseResult == null) return false; ICompositeNode node = parseResult.getRootNode(); return isValidLineForBreakpoint(node, line); } protected boolean isValidLineForBreakpoint(ICompositeNode node, int line) { for (INode n : node.getChildren()) { if (n.getStartLine()<= line && n.getEndLine() >= line) { EObject eObject = n.getSemanticElement(); if (eObject instanceof XExpression && !(eObject.eClass() == XbasePackage.Literals.XBLOCK_EXPRESSION)) { return true; } if (n instanceof ICompositeNode && isValidLineForBreakpoint((ICompositeNode) n, line)) { return true; } if (eObject instanceof XmlGenerator) { return true; } } if (n.getStartLine() > line) { return false; } } return false; } }