Xtext is a great technology. I really mean it. After 15-30 minutes (depending on your previous domain knowledge) you can get a really fancy textual editor, that parses your text into an EMF model. Xbase is even better: you can simply include Java-like expressions into your language, that can be easily translated into pure Java code.
However, while using Xtext I found some minor “paper-cuts”. One of the most problematic of them was the fact that I cannot open my textual models using the Sample Reflective Ecore Model editor, as I get an exception: java.net.MalformedURLException: unknown protocol: java.
A similar exception occurred if I tried to open the files programatically (but without the help of the generated Xtext editor). When I asked in the Eclipse forums how to open Xtext model files programatically, I was answered (btw. very quickly – kudos for that 🙂 ) that a specific ResourceSet implementation is needed that refers to model files and classes available in a Java project.
This gave me the idea to create an Xtext extension that allows opening an EMF tree editor, the Xtext Reflective Tree Editor. The plug-in consists of two parts:
- An extended version of the org.eclipse.emf.ecore.presentation.EcoreEditor class, that opens its ResourceSet using the Xtext API (more specifically, uses an injected ResourceSet);
- And an Xtext generator fragment, that can be used to generate a new editor extension to the ui project (with the corresponding dependency added to the reflective editor plug-in).
Usage
To use the plug-in, just follow the following simple steps:
- Add
hu.cubussapiens.xtext.reflectiveeditor
as a dependency to your language project. - Extend your editor generation workflow:
- Import the generator package:
import hu.cubussapiens.xtext.reflectiveeditor.generator.*
- Add the new generator fragment at the end of the generator (file.extensions is the list of file extensions defined in the default workflow):
fragment = ReflectiveXtextEditorFragment {
fileExtensions = file.extensions
} - Regenerate your language.
- Unless the plugin.xml files are updated automatically, you have to copy the newly generated editor extension from the end of the plugin.xml_gen file of the ui plug-in to the plugin.xml file. The simplest way to do this is to select both files, and open the compare editor from the popup menu (Compare with/Each other…), the copy the changes manually.
- Finally, open the runtime workbench, and open your textual model files from the popup menu using Open with/«LanguageName» Reflective Editor. The result should be similar to the screenshot below.
In my case, the editor shows both the domain model generated from the file directly (the Pattern Model element), the inferred JVM model classes (the various JVM Generic Type instances), and also the referred Java classes as external resources (the resources beginning with the java:/ URIs).
Download
If you are interested in the plug-in in action, download it from our update site: http://eclipse.cubussapiens.hu, or take a look at the repository on Github: https://github.com/ujhelyiz/xtext-reflective
Version 0.5.3 is already available, and hopefully works well for all languages.
Wow! Very cool!
However, it begs the question.. Why would someone, like you, want to use the reflective editor instead of a text-based editor? Isn’t editing textually much faster and efficient ?
Basically, editing is much effective in the text-based editor. However, when developing the language or the tooling, it is often nice that you could view the textual and the EMF version side by side (think writing code generators for example).
Yeah, I know, for end-users this feature is less appealing, but during development we missed it. Its possible to develop without such a view, but makes coding often easier.
Thank you!
It’s indeed very cool
I believe that both text representations and tree representations have their role (and a third, which is more graph-like). You can easily create many tree representations from the same source, for example, including some implicit grouping nodes, and when you drag-drop items, you get to preserve the source and destination a lot more effectively than in a text editor where you would generally copy paste. Also, text is more likely to become inconsistent due to parsing errors while editing, and a tree editor with a properties view allows you to easily glance at all the properties you could add for that certain element.
If we look at program source code, I like to say that when it comes to static elements like projects, packages, types, fields and methods, I like to work in trees, but when it comes to the dynamic stuff, the statements and expressions, then I definitely prefer a text editor.
I’m sceptical about the end-user use cases of the tree editor (but it is not prohibited to use it there). However during development I think, it is useful, so there is no reason not to have it.
About a more graph-like view you could have a look at Jan Köhnlein’s Generic graph viewer component (e.g. see the following blog post: http://koehnlein.blogspot.com/2012/01/multitouch-gestures-in-generic-graph.html).
However, that view is not inferrable automatically from a grammar, it needs help. Tree editor needs only to be written once, so it is cheaper to use – making it much more useful during development, when even the language changes.
Why changes on Reflective Tree Editor don’t produce anything on real file?
Thanks!
Thanks for the interest in the reflective editor.
Changes in the reflective editor should appear. I will look into the issue shortly (but not today).
Cheers,
Zoltán
@Tommaso De Sica: I have check the reflective editor now, and I could update the textual representation using the Reflective editor – however, only after saving the changes. As long as the changes are not saved, they do not appear in the Xtext editor.
This behavior is by design, as the internal modification steps of a textual editor and a tree editor are really different, and I would like to keep this plug-in as simple as possible by avoiding really complicated cases. For more information about these issue check the GMF integration part of the Xtext manual – the same issues apply here as well.
However, if you have experienced a different issue, feel free to report back, either here or in the issue tracker section of the repository.
It’s not explicitly stated in your post, but I’d like to add here that it is only necessary to use this specific reflective editor when one is developing an Xtext editor which uses Xbase. For most of the simple cases (i.e. languages based purely on metamodels), the normal reflective editor and the generated editor work just fine for me.
Thanks for the clarification. I wanted to add that information to the post, but somehow it was left out. I will add it later.