Tuesday, June 22, 2010

How to Deploy Xtext to a Headless Plain-Java Environment?

Yesterday, Sven and I were at the Eclipse Democamp in Hannover which was organized by brox IT-Solutions and Bredex - thanks for the nice event. I met interesting people and we discussed various topics. One particular question about Xtext was raised several times from different sides: How do I use my language in an environment without Eclipse, e.g. on a build server? As this was already possible from the first minute even with the former oAW version of Xtext and with Xtext 0.7.0, too, I was kind of suprised. In fact, any execution of the generator workflow uses Xtext in a standalone environment - without OSGi, Equinox or any dependency on Eclipse UI. The problem seems to be another one: How can I determine all the required libraries to deploy my Xtext-driven generator?

It turns out that this task is suprisingly easy with Eclipse. We'll use a minor trick to simplify the necessary steps. First of all, we have to create a new Run Configuration for a Java Application. Actually this one will never be executed, but we need to refer to this one in the next step. Just create a new configuration for your generator-project and use the org.eclipse.emf.mwe2.launch.runtime.Mwe2Launcher as the main class:
Now that we have a run configuration for the generator project, let's export the project as a runnable jar. Choose Export... -> Runnable JAR file from the context menu of the generator project. The wizard will ask for a launch configuration and that's where we use the one that we created a second ago:
Select the options of your choice, point to a target file and hit the Finish-button. Eclipse will collect required libraries and add the necessary entries to the MANIFEST.MF in the runnable JAR file. As I already said, it's suprisingly simple.

Last but not least, I recommend to create a batch file or shell script that starts a virtual machine, points to the exported archive and refers to the module name of the generator workflow, e.g.:
java -jar exported.jar workflow.MyDslGenerator
It's probably a good idea to wrap the invocation of the Mwe2Launcher in a custom main class to encapsulate the name of the generator workflow and pass additional arguments to the workflow.

Sunday, June 20, 2010

New In Xtext: Case Insensitive Languages

A quick glimpse at the New and Noteworthy features of Xtext 1.0 reveals that the framework allows to develop languages that are case insensitive.
To mark upper and lower cases meaningless for keywords or cross references, you just have to replace two default fragments in the MWE2 workflow, add an option and hit the Run button:

The o.e.x.g.parser.antlr.ex.rt.AntlrGeneratorFragment and o.e.x.g.parser.antlr.ex.ca.ContentAssistParserGeneratorFragment replace the two fragments, that are configured by default: o.e.x.g.parser.antlr.XtextAntlrGeneratorFragment and o.e.x.g.parser.antlr.XtextAntlrUiGeneratorFragment.

Xtext provides an API that allows to define custom, local scopes that are ignore case as well. Have a look at the utility class o.e.x.resource.ignorecase.IgnoreCaseScopes to learn more about it. The configured generator fragments will take care of the rest, e.g. the default bindings for the global scopes, the parser and the serializer.

As you can see it is possible to define case insensitivity independently for keywords and cross-links. And if you want to keep your workflow short and concise instead of adding this flag for each and every fragment that accepts this option, you are free to introduce a new property and use this one directly or via the auto-inject option. Please refer to the updated documentation if you want to learn more about the MWE2 language.

Thursday, June 17, 2010

Customizing Error Messages in Xtext 1.0

As the Eclipse Helios Release is around the corner I'll use the chance to describe some nice odds and ends in Xtext 1.0. One of which is a newly introduced API that allows to customize the default messages for parse errors and linking diagnostics.

If you try to read erroneous models, you'll get annotations for syntax errors and linking problems in the editor by default. These error messages are not always the most meaningful ones from a user's point of view. Furthermore it was not possible to i18n them. This was changed with Xtext 1.0 by means of two newly introduced customization hooks.

Users who want to alter the default messages that the parser produces may implement a so called ISyntaxErrorMessageProvider which allows to change the wording of syntax errors and messages from the value converter.

The implementor has the current state of the parser at hand to produce a meaningful message for the user. Basically any information is available to compute the SyntaxErrorMessage. She is free to use the intermediate semantic model, the attached node model that reflects the parsed tokens, or the really low level stream that the parser works with.

Especially handy is the option to assign an issue code to a syntax error message. This is the constant that a quick fix refers to, to solve your models syntactic problems easily. Assuming you evolve the syntax of your language, you may want to define such quick fixes that migrate old files to the new notation. Of course there are more use cases such as mandatory keyword sequences at the end of an element.

There is another component that produces default error messages: If the linker cannot resolve an EMF proxy when navigating a cross reference, it will create an error diagnostic, too. We used the same pattern to allow clients to customize this message.

Again, every piece of information is available in the context, that is passed to the message provider and of course it is possible to assign an issue code to the linking diagnostic. Even more, clients may choose to reduce the severity of the linking problem to a warning. Languages that support a kind of dynamic invoke like C# may establish real links for the statically bound features but ignore unresolved references for dynamic parts.

Both APIs may come quite handy if you want to i18n your applicaton or tailor the error messages that are presented to the user.