Sunday, June 20, 2010

Semantic Model Access in Xtext

In Xtext, the parser creates the EMF-based semantic model or abstract syntax tree from the textual representation of the model. Many components, e.g. validation or outline, but also an interpreter or code generator work on this semantic model rather than on the textual representation. In this post, I want to introduce you to Xtext's APIs to safely read and modify the semantic model of an Xtext document.

Why do we need model synchronization at all?

In a running Xtext Workbench, there are a number of components which access the semantic model, i.e. the parser, the linker, the validator, the outline, the index builder etc. While some of these components are executed by the display thread, others like the parser or the indexer use different concurrent threads to not deteriorate the editing experience. If you for example want to have a consistent outline of your model, it is essential to keep other threads from modifying the model while the outline component reads it.

Why not use EMF Transaction?

Editors that use EMF Transaction usually employ a so called TransactionalEditingDomain that shields a ResourceSet with a lock and manages a transactional command stack. The Resources in the ResourceSet can be read safely - i.e. excluding any concurrent write operation - inside a Runnable that is passed to the TransactionalEditingDomain.runExclusive() method. Write access is only possible by issuing a command. A change listener throws an Exception if write operations are executed outside of write command.

This quite heavy-weight mechanism can be appropriate for pure model editors, i.e. editors modifying the model directly like the generated EMF tree editor, but experience shows that it is not easily integrated with other command frameworks. (If you don't believe this, just look at the way GMF deals with EMF Transactions, GEF commands and the Eclipse Operation history.)

Architecturally, an Xtext editor is a text editor in the first place. The commands on its undo/redo stack are the usual commands used in text editors. So instead of inventing yet another adapter technology, we headed for an easier synchronization mechanism.

How do I read a model safely?

Each XtextEditor uses an IXtextDocument to store its model. The IXtextDocument allows reentrant read/write access to the underlying semantic model by means of the two methods
readOnly() and modify(). Both take an argument of type IUnitOfWork(<T>, IXtextResource) which defines a method <T> exec(IXtextResource) that contains what you want to do with the model and allows to deliver a result of arbitrary type.

So here is an example of safely reading a model:
IXtextDocument myDocument = ...;
String rootElementName = myDocument.readOnly(
new IUnitOfWork(){
public String exec(IXtextResource resource) {
MyType type = (MyType)resource.getContents().get(0);
return myType.getName();
}
});

How do I modify a model safely?

Direct write-access on the document is usually only performed inside the framework. If you want to change a document by means of its semantic model, you should rather use an IDocumentEditor which uses the modify() method internally but takes care of synchronizing the node model, too:
@Inject
private IDocumentEditor documentEditor;

public void setRootName(IXtextDocument myDocument,
final String newName) {
documentEditor.process(
new IUnitOfWork.Void() {
public void process(IXtextResource resource) {
MyType type = (MyType)resource.getContents().get(0);
myType.setName(newName);
}
}, myDocument);
}

BTW, the QuickFix-API internally uses an IDocumentEditor, too.

PS:

In Xtext 2.0 we have changed the semantics of XtextDocument.modify() to use the former IDocumentEditor functionality. So the model write example now symmetrically becomes
public void setRootName(IXtextDocument myDocument,
final String newName) {
myDocument.modify(
new IUnitOfWork.Void(){
public void process(IXtextResource resource) {
MyType type = (MyType)resource.getContents().get(0);
myType.setName(newName);
}
});
}

Monday, June 7, 2010

Xtext: Webinar and Eclipse Demo Camp

Tomorrow (Tue, 8th of June) will be my Xtext presentation day ;-)

At 5pm CEST I will jump in for Sebastian in the Xtext Webinar. Sven and me will give a free one hour live seminar on Xtext introducing the framework and demonstrating its new fancy features in Helios. Moritz will assist us in answering your questions on the live chat. It's free and it's broadcast live via internet. Why not join?

If you're based in Germany's Ruhr area, you might want to visit the Eclipse Demo Camp in Dortmund. I will give another 20min demo of Xtext and - guess what - its new amazing features! But even for non-Xtext enthusiasts there will be nice demos, e.g on SAP's new graphical modeling framework "Graphiti", on developing Android apps with Eclipse and a lot more intriguing topics.

Finally, I plan to have my hopefully well-earned after-work pint in the Eclipse Stammtisch.