tag:blogger.com,1999:blog-16462550218421690382024-03-02T02:06:25.966+01:00Dietmar Stoll's BlogDietmar Stollhttp://www.blogger.com/profile/10428546280407453804noreply@blogger.comBlogger10125tag:blogger.com,1999:blog-1646255021842169038.post-1012669266727764692015-11-18T20:08:00.005+01:002020-12-28T20:10:25.865+01:00Convert Java snippets to Xtend with Ctrl-Shift-V<a href="http://www.eclipse.org/xtend/" target="_blank">Xtend</a> is a dialect of Java which compiles into Java source code. The Xtend-integration in the Eclipse IDE allows developers to work simultaneously with Java and Xtend. As the syntax of both is similar, converting from Java to Xtend is not too hard, but it usually needs manual adjustments. Using the neat shortcut <i>Ctrl-Shift-V (Ctrl+Shift+V/</i><i>Cmd-Shift-V/</i><i>Cmd+Shift+V)</i> to paste Java code into Xtend files substantially reduces the manual editing. It helps to quickly get compilable Xtend code. Here are some examples of the automatic conversions.<br />
<br />
Java type access:<br />
<pre style="background-color: white; color: #080808; font-family: monospace;">EcoreUtil2.getContainerOfType(context, Model.<span style="color: #0033b3;">class</span>);</pre>
Pasted into an Xtend file:<br />
<pre style="background-color: white; color: #080808; font-family: monospace;">EcoreUtil2.getContainerOfType(context, Model) </pre>
The converter used the simpler Xtend syntax for accessing the type of Model and omitted the semicolon.<br />
<br />
Java field with visibility: <br />
<pre style="background-color: white; color: #080808; font-family: monospace;"><span style="color: #0033b3;">private static final </span>Logger <span style="color: #871094; font-style: italic;">logger </span>= Logger.getLogger(<br /> CompositeEValidator.<span style="color: #0033b3;">class</span>);</pre>
Converted to Xtend:<br />
<pre style="background-color: white; color: #080808; font-family: monospace;"><span style="color: #0033b3;">static final </span>Logger <span style="color: #871094; font-style: italic;">logger </span>= Logger.getLogger(<br /> CompositeEValidator)</pre>
The default visibility for fields is private so the converter omitted it. Again, the short Xtend type access syntax was used.<br />
<br />
Java name that is an Xtend keyword:<br />
<pre style="background-color: white; color: #080808; font-family: monospace;"><span style="color: #0033b3;">private </span><span style="color: black;">String </span><span style="color: #871094;">val</span>;</pre>
Converted to Xtend:<br />
<pre style="background-color: white; color: #080808; font-family: monospace;"><span style="color: black;">String </span>^val</pre>
The Xtend keyword was automatically escaped. <br />
<br />
Variable and cast in Java:<br />
<pre style="background-color: white; color: #080808; font-family: monospace;">Model <span style="color: #871094;">model </span>= (Model) object;</pre>
Converted to Xtend:<br />
<pre style="background-color: white; color: #080808; font-family: monospace;"><span style="color: #0033b3;">var </span><span style="color: #871094;">Model </span>model = <span style="color: #0033b3;">object as </span>Model</pre>
The <span style="font-family: "courier new" , "courier" , monospace;">var</span>/<span style="font-family: "courier new" , "courier" , monospace;">val</span> keywords were added for mutable/final local variables and the Xtend type cast syntax was used (by the way, the type declaration of <span style="font-family: "courier new" , "courier" , monospace;">Model</span> could be omitted due to Xtend's type inference).<br />
<br />
Method in Java:<br />
<pre style="background-color: white; color: #080808; font-family: monospace;"><span style="color: #0033b3;">public void </span><span style="color: #00627a;">foo</span>() { <span style="color: #8c8c8c; font-style: italic;">//...</span></pre>
Converted to Xtend:<br />
<pre style="background-color: white; color: #080808; font-family: monospace;">def void foo() { <span style="color: #8c8c8c; font-style: italic;">//...</span></pre>
The default visibility for methods is public so it was omitted and the <span style="font-family: "courier new" , "courier" , monospace;">def</span> keyword for method definitions was added.<br />
<br />
Method overriding in Java:<br />
<pre style="background-color: white; color: #080808; font-family: monospace;"><span style="color: #0033b3;">public </span><span style="color: black;">String </span><span style="color: #00627a;">toString</span>() {</pre>
Converted to Xtend:<br />
<pre style="background-color: white; color: #080808; font-family: monospace;"><span style="color: #0033b3;">override </span>String toString() {</pre>
As Xtend explicitly states overrides, the keyword was added (instead of <span style="font-family: "courier new" , "courier" , monospace;">def</span>). Again, the visibility was omitted.Dietmar Stollhttp://www.blogger.com/profile/10428546280407453804noreply@blogger.com1tag:blogger.com,1999:blog-1646255021842169038.post-53578793776990278592013-11-09T16:35:00.002+01:002013-11-09T16:35:26.291+01:00Default enum literals for Xtext generated EMF modelsXtext allows to easily build fully-fledged editors for domain specific languages (DSL) which are based on the Eclipse Modeling Framework (EMF). While existing Ecore models may be used, Xtext is also able to infer an Ecore model from the Xtext grammar. For complex Ecore models, it should certainly be considered to manage them independently, e.g. with <a href="http://wiki.eclipse.org/Xcore">Xcore</a>. However, a few simple tweaks of grammar rules can influence the automatically generated Ecore model quite remarkably (e.g. the inheritance hierarchy) and may delay the point in time where it may be better to manage them independently. This example shows how to influence the generation of enumerators (enums) and default literals with grammar rules.<p/>
The code example below assumes that there's a model element with an optional "visibility" attribute of type enum and that the DSL must be able to capture the case where no visibility enum at all was given.<p/>
As the default literal of a generated enum is the first literal, an enum rule is added to the grammar which uses, say, "unspecified" for that. However, the user of the DSL editor should simply be able to enter nothing at all instead of "unspecified" which would look odd in the editor. This can be achieved by adding a second rule which returns the aforementioned enum, but only contains the literals allowed for the user. Please note that the order of the enum rules is important for generated models.
<pre class="prettyprint">
MyModelElement:
// ...
// user may specify enum or nothing at all
visibility=Visibility?
// ...
;
// rule for the generated Ecore model
enum VisibilityEnum:
unspecified | // first literal is the default
public |
private
;
// rule for the DSL editor
enum Visibility returns VisibilityEnum:
public |
private
;</pre>
Dietmar Stollhttp://www.blogger.com/profile/10428546280407453804noreply@blogger.com10tag:blogger.com,1999:blog-1646255021842169038.post-10891576509893008542013-04-11T19:47:00.001+02:002020-12-28T19:59:29.243+01:00Multiple Validators in Xtext
Early validation of domain specific languages (DSLs) and suggestions on how to fix these errors ('quickfixes') are key for a good end user experience and for avoiding problems in the toolchain, for instance in generators that use DSL models: The more editor validations, the better. This description shows how to improve the maintainability and modularity of validation code for Xtext DSLs by simply splitting them.
In the generated [MyDsl]JavaValidator, an annotation referring to other custom validators has to be added as shown below:
<pre class="prettyprint">@ComposedChecks(validators =<br /> {MyCustomValidator.<span style="color: #0033b3;">class</span>, MyOthercustomValidator.<span style="color: #0033b3;">class</span>})<br /><span style="color: #0033b3;">public class </span><span style="color: black;">MyDslJavaValidator </span><span style="color: #0033b3;">extends </span>AbstractMyDslJavaValidator {<br /><br /> <span style="color: #8c8c8c; font-style: italic;">// check method as usual inside the generated Java Validator<br /></span><span style="color: #8c8c8c; font-style: italic;"> </span>@Check<br /> <span style="color: #0033b3;">public void </span><span style="color: #00627a;">checkMyDslElement</span>(MyEntity myEntity) { <span style="color: #8c8c8c; font-style: italic;">// ...</span>
</pre>
Please note that the custom validator has to override the register()-method. Apart from that, the checks look exactly as they would if they were in the generated validator.
<pre class="prettyprint"><span style="color: #8c8c8c; font-style: italic;">// Example for a split custom validator written in Xtend<br /></span><span style="color: #0033b3;">public class </span><span style="color: black;">MyCustomValidator </span><span style="color: #0033b3;">extends </span>AbstractDeclarativeValidator {<br /><br /> override <span style="color: #00627a;">register</span>(EValidatorRegistrar registrar) {<br /> <span style="color: #8c8c8c; font-style: italic;">//not needed for classes used as ComposedCheck<br /></span><span style="color: #8c8c8c; font-style: italic;"> </span>}<br /><br /> <span style="color: #8c8c8c; font-style: italic;">// additional check method in separate validator<br /></span><span style="color: #8c8c8c; font-style: italic;"> </span>@Check<br /> def <span style="color: #0033b3;">void </span><span style="color: #00627a;">checkMyDslElement</span>(MyEntity myEntity) {<br /> [...] <span style="color: #8c8c8c; font-style: italic;">// validation code</span>
</pre>Dietmar Stollhttp://www.blogger.com/profile/10428546280407453804noreply@blogger.com1tag:blogger.com,1999:blog-1646255021842169038.post-18466381981807001962012-10-09T21:23:00.002+02:002020-12-28T19:57:08.170+01:00Clean Eclipse Preferences Tree with Multiple DSLsAs it is easy to build new domain specific languages (DSLs) with Xtext for Eclipse, enterprise projects may have multiple languages, which are usually related. Each language comes with its own Eclipse preference page, which are by default mixed with other preference pages. A simple way to keep the Eclipse preferences tree clean is to add a root page which aggregates the preference pages for individual (but possibly related) Xtext languages. This can be done by adding the snippet below to a <i>plugin.xml</i> file, for instance to the one of the base DSL's UI project.<br />
<br />
<pre class="prettyprint"><<span style="color: #0033b3;">extension<br /></span><span style="color: #0033b3;"> </span><span style="color: #174ad4;">point</span><span style="color: #067d17;">="org.eclipse.ui.preferencePages"</span>><br /> <<span style="color: #0033b3;">page<br /></span><span style="color: #0033b3;"> </span><span style="color: #174ad4;">class</span><span style="color: #067d17;">="my.dsl.ui.MyDslExecutableExtensionFactory:org.eclipse.xtext.ui.editor.preferences.LanguageRootPreferencePage"<br /></span><span style="color: #067d17;"> </span><span style="color: #174ad4;">id</span><span style="color: #067d17;">="my.id.root.ui"<br /></span><span style="color: #067d17;"> </span><span style="color: #174ad4;">name</span><span style="color: #067d17;">="My DSLs"</span>><br /> <<span style="color: #0033b3;">keywordReference </span><span style="color: #174ad4;">id</span><span style="color: #067d17;">="my.id.root.ui.keyword_root_pref"</span>/><br /> </<span style="color: #0033b3;">page</span>><br /></<span style="color: #0033b3;">extension</span>><br /><br /><span style="color: #8c8c8c; font-style: italic;"><!-- add keywords for the search in the preferences page --><br /></span><<span style="color: #0033b3;">extension<br /></span><span style="color: #174ad4;">point</span><span style="color: #067d17;">="org.eclipse.ui.keywords"</span>><br /><<span style="color: #0033b3;">keyword<br /></span><span style="color: #0033b3;"> </span><span style="color: #174ad4;">id</span><span style="color: #067d17;">="my.id.root.ui.keyword_root_pref"<br /></span><span style="color: #067d17;"> </span><span style="color: #174ad4;">label</span><span style="color: #067d17;">="other keywords"</span>/><br /></<span style="color: #0033b3;">extension</span>>
</pre>
<br />
<span style="font-family: inherit;">Now, the id of the root page, in this case <i>my.id.root.ui</i> just has to be added to the <i>plugin.xml</i> files of the UI projects of the languages whose preferences should be aggregated. This can also be done in the graphical <i>plugin.xml</i> editor of the DSL's UI projects by navigating to the tab <i>Extensions</i>, selecting the first child node under <i>org.eclipse.ui.preferencePages</i> (which should be the DSL preference page) and pasting <i>my.id.root.ui</i> into the <i>category</i> text box.</span>Dietmar Stollhttp://www.blogger.com/profile/10428546280407453804noreply@blogger.com0tag:blogger.com,1999:blog-1646255021842169038.post-43582919626481913492012-07-18T20:10:00.002+02:002020-12-28T20:11:26.617+01:00Custom Syntax Error Messages with Quick Fix<p>Xtext editors for domain specific languages (DSLs) provide many error messages out of the box, such as syntactical errors, duplicate name errors or unresolvable references. For an improved user experience, some technical error messages from the editor (or, more
specifically, from the <a href="http://www.antlr.org/" target="_blank">Antlr</a> parser that is used by the editor) may be customized. In many DSLs, identifiers (for DSL concepts like packages, entities and so on) are expected to conform to the regular expression of the terminal rule <tt>ID</tt>:<br />
</p><pre style="background-color: white; color: #080808; font-family: monospace;">terminal ID : <span style="color: #067d17;">'^'</span>?(<span style="color: #067d17;">'a'</span>..<span style="color: #067d17;">'z'</span>|<span style="color: #067d17;">'A'</span>..<span style="color: #067d17;">'Z'</span>|<span style="color: #067d17;">'_'</span>) (<span style="color: #067d17;">'a'</span>..<span style="color: #067d17;">'z'</span>|<span style="color: #067d17;">'A'</span>..<span style="color: #067d17;">'Z'</span>|<span style="color: #067d17;">'_'</span>|<span style="color: #067d17;">'0'</span>..<span style="color: #067d17;">'9'</span>)*;</pre><p>In addition, any keyword that is defined in other rules of the DSL grammar may not be used as an identifier<code class="java plain"></code>. Keywords may be escaped with the caret (^) symbol, which is certainly arguable. This would be similar to using "class" as a
name for a class in Java (if that would be possible). Here are some snippets of a DSL with a package concept:<br />
<br />
</p><pre style="background-color: white; color: #080808; font-family: monospace;"><span style="color: #0033b3;">package package </span><span style="color: #8c8c8c; font-style: italic;">// the second word is a reserved keyword and therefore not be valid as identifier<br /></span><span style="color: #0033b3;">package </span>^<span style="color: #0033b3;">package </span><span style="color: #8c8c8c; font-style: italic;">// okay, the keyword was escaped<br /></span><span style="color: #0033b3;">package </span>myPackage <span style="color: #8c8c8c; font-style: italic;">// okay unless 'myPackage' is a grammar keyword<br /></span></pre><br />
The default
error message when using a reserved keyword where an identifier is
expected looks like this.<br />
<br />
<div style="color: red;">
<b><tt>mismatched input 'package' expecting RULE_ID</tt></b></div>
<br />
<br />
This message can be customized using Xtext's <tt>SyntaxErrorMessageProvider</tt> (written in <a href="http://www.eclipse.org/xtend/" target="_blank">Xtend</a>):<br />
<br />
<div class="code panel" style="border-width: 1px;">
<div class="codeContent panelContent">
<div>
<div class="syntaxhighlighter nogutter java" id="highlighter_179583">
<table border="0" cellpadding="0" cellspacing="0"><tbody>
<tr><td class="code"><pre style="background-color: white; color: #080808; font-family: monospace;"><span style="color: #0033b3;">class </span><span style="color: black;">SyntaxErrorMessageProviderCustom </span><span style="color: #0033b3;">extends </span>SyntaxErrorMessageProvider {<br /><br /> <span style="color: #0033b3;">public static </span>val String USED_RESERVED_KEYWORD = <span style="color: #067d17;">"USED_RESERVED_KEYWORD"<br /></span><span style="color: #067d17;"><br /></span><span style="color: #067d17;"> </span>@Inject IGrammarAccess grammarAccess<br /> <span style="color: #8c8c8c; font-style: italic;">/**<br /></span><span style="color: #8c8c8c; font-style: italic;"> * Customized error message for reserved keywords<br /></span><span style="color: #8c8c8c; font-style: italic;"> */<br /></span><span style="color: #8c8c8c; font-style: italic;"> </span>override <span style="color: #00627a;">getSyntaxErrorMessage</span>(IParserErrorContext context) {<br /> val <span style="color: black;">unexpectedText </span>= context?.recognitionException?.token?.text<br /> <span style="color: #0033b3;">if </span>(GrammarUtil::getAllKeywords(<span style="color: #871094;">grammarAccess</span>.getGrammar()).contains(<span style="color: black;">unexpectedText</span>)) {<br /> println(context.defaultMessage)<br /> <span style="color: #0033b3;">return new </span>SyntaxErrorMessage(<span style="color: #067d17;">'''<br /></span><span style="color: #067d17;"> "«unexpectedText»" </span>is a reserved keyword which is not allowed as Identifier.<br /> Please choose another word or alternatively confuse your co-workers by escaping it with the caret (^) character like <span style="color: #0033b3;">this</span>: <span style="color: #067d17;">"^«unexpectedText»"</span>.<span style="color: #067d17;">''',<br /></span><span style="color: #067d17;"> </span>USED_RESERVED_KEYWORD)<br /> }<br /> <span style="color: #0033b3;">super</span>.getSyntaxErrorMessage(context)<br /> }<br />}<br /></pre></td></tr>
</tbody></table>
</div>
</div>
</div>
</div>
<br />
The customized error message provider has to be bound in <tt><mydsl>MyDslRuntimeModule.java</mydsl></tt> like this<code>:</code><br />
<div class="code panel" style="border-width: 1px;">
<div class="codeContent panelContent">
<div>
<div class="syntaxhighlighter nogutter java" id="highlighter_781131">
<table border="0" cellpadding="0" cellspacing="0"><tbody>
<tr><td class="code"><div class="container" title="Hint: double-click to select code"><pre style="background-color: white; color: #080808; font-family: monospace;"><span style="color: #8c8c8c; font-style: italic;">/**<br /></span><span style="color: #8c8c8c; font-style: italic;"> * custom error messages for syntax errors<br /></span><span style="color: #8c8c8c; font-style: italic;"> */<br /></span><span style="color: #0033b3;">public </span>Class<<span style="color: #007e8a;">X </span><span style="color: #0033b3;">extends </span>ISyntaxErrorMessageProvider> bindISyntaxErrorMessageProvider() {<br /> <span style="color: #0033b3;">return </span>SyntaxErrorMessageProviderCustom.<span style="color: #0033b3;">class</span>;<br />}</pre><div class="line number6 index5 alt1">
</div>
</div>
</td></tr>
</tbody></table>
</div>
</div>
</div>
</div>
<br />
A simple quickfix in <tt>MyDslQuickfixProvider</tt> could look like this:<br />
<div class="code panel" style="border-width: 1px;">
<div class="codeContent panelContent">
<div>
<div class="syntaxhighlighter nogutter java" id="highlighter_475104">
<table border="0" cellpadding="0" cellspacing="0"><tbody>
<tr><td class="code"><div class="container" title="Hint: double-click to select code">
<div class="line number1 index0 alt2">
</div><pre style="background-color: white; color: #080808; font-family: monospace;"><span style="color: #8c8c8c; font-style: italic;">/**<br /></span><span style="color: #8c8c8c; font-style: italic;"> * Provide a fix when reserved keywords are used as identifiers<br /></span><span style="color: #8c8c8c; font-style: italic;"> */<br /></span>@Fix(SyntaxErrorMessageProviderCustom::USED_RESERVED_KEYWORD)<br />def <span style="color: #0033b3;">public </span>void reservedKeywordUsed(Issue issue, IssueResolutionAcceptor acceptor) {<br /> <span style="color: #0033b3;">val </span><span style="color: black;">unexpectedText </span>= issue.data?.get(<span style="color: #1750eb;">0</span>)<br /> acceptor.accept(issue, <span style="color: #067d17;">'''Change '</span>«unexpectedText»<span style="color: #067d17;">' to '</span>«unexpectedText.generateUniqueIdentifier».<span style="color: #067d17;">' '''</span>, <span style="color: #067d17;">'''<br /></span><span style="color: #067d17;"> </span>Change <span style="color: #067d17;">'«unexpectedText»' </span>to <span style="color: #067d17;">'«unexpectedText.generateUniqueIdentifier»'</span>,<br /> which <span style="color: #0033b3;">is </span>not a reserved keyword.<span style="color: #067d17;">''', <br /></span><span style="color: #067d17;"> "correction_linked_rename.gif"</span>,<br /> [ IModificationContext context |<br /> <span style="color: #0033b3;">val </span><span style="color: black;">xtextDocument </span>= context.getXtextDocument<br /> <span style="color: black;">xtextDocument</span>.replace(issue.offset, issue.length, <span style="color: black;">unexpectedText</span>.generateUniqueIdentifier)<br /> ])<br />}<br /><br />def String generateUniqueIdentifier(String it) {<br /> <span style="color: #0033b3;">val </span>candidate = <span style="color: #067d17;">'my' </span>+ it?.toFirstUpper?:<span style="color: #067d17;">'Name'<br /></span><span style="color: #067d17;"> </span><span style="color: #0033b3;">var </span>count = <span style="color: #1750eb;">1<br /></span><span style="color: #1750eb;"> </span><span style="color: #0033b3;">val </span>reserved = GrammarUtil::getAllKeywords(grammarAccess.getGrammar())<br /> <span style="color: #0033b3;">if </span>(reserved.contains(candidate)) {<br /> <span style="color: #0033b3;">while </span>(reserved.contains(candidate + count)) {<br /> count = count + <span style="color: #1750eb;">1<br /></span><span style="color: #1750eb;"> </span>}<br /> <span style="color: #0033b3;">return </span>candidate + count<br /> }<br /> <span style="color: #0033b3;">return </span>candidate<br />}</pre><div class="line number28 index27 alt1">
</div>
</div>
</td></tr>
</tbody></table>
</div>
</div>
</div>
</div>
<br />
This kind of customization has been available for a long time now. For more information, see <a class="external-link" href="http://zarnekow.blogspot.ch/2010/06/customizing-error-messages-in-xtext-10.html" rel="nofollow">Customizing error messages</a> from Sebastian Zarnekow.Dietmar Stollhttp://www.blogger.com/profile/10428546280407453804noreply@blogger.com0tag:blogger.com,1999:blog-1646255021842169038.post-21573378052725022732011-08-14T15:24:00.008+02:002018-01-20T18:47:06.561+01:00Xtext Grammar VisualizationWhen developing EBNF-style grammars, e.g. for Xtext, syntax graphs can be a great help. One of the new <a href="http://www.eclipse.org/Xtext/#features">features</a> in Xtext 2 is the <a href="http://www.eclipse.org/Xtext/documentation/indigo/new_and_noteworthy.php#M3">Xtext Syntax Graph</a> which can be selected in the Eclipse menu under <span style="font-style: italic;">Views</span> - <span style="font-style: italic;">Xtext</span> - <span style="font-style: italic;">Xtext Syntax Graph</span>. In case the grammar has ambiguities, users get an error message similar to the following when trying to generate the code for the grammar by running the MWE2 workflow file.
<br />
<br />
<span style="color: rgb(255 , 0 , 0); font-size: 100%; font-weight: bold;">Decision can match input such as [...] using multiple alternatives 1,2</span>
<br />
<br />
If the error isn't obvious, the alternatives can be displayed graphically with ANTLRWorks (the graph analysis can be expensive and thus is not included in the standard Xtext Syntax Graph). Here is an example of an Eclipse Xtext project with a simple, <span class="ev" id="11.sc" role="menuitem" tabindex="-1">ambiguous</span> grammar and the Xtext Syntax Graph.
<br />
<br />
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEga7Rk5qfaRJD86HVbfO0gifQGOsSSZnX_fQb20uRPSr2JkcewfM-ykc01kvpE8AuuXd8Dm0_hvV_cmOdznswD98d2CG1KslhwqnB21LRCFnZzVbCF8erNx0jndxj4upuG5VOEk40Cfx50/s1600/antlr-grammar.png"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5640710023611859586" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEga7Rk5qfaRJD86HVbfO0gifQGOsSSZnX_fQb20uRPSr2JkcewfM-ykc01kvpE8AuuXd8Dm0_hvV_cmOdznswD98d2CG1KslhwqnB21LRCFnZzVbCF8erNx0jndxj4upuG5VOEk40Cfx50/s400/antlr-grammar.png" style="cursor: hand; cursor: pointer;" /></a>
<br />
<div style="text-align: left;">
<br />
To analyze the grammar in ANTLRWorks, the executable jar file from the <a href="http://www.antlr.org/works/index.html">ANTLR website</a> can be downloaded and run using the JRE (<span style="font-style: italic;">java -jar antlrworks-1.x.x.jar</span>). ANTLRWorks expects the ANTLR grammar file from the Xtext project, which is called <span style="font-style: italic;">Internal[...].g</span>. A debug-friendly version of this file may be generated by adding <i>fragment = parser.antlr.DebugAntlrGeneratorFragment {
} </i>to your MWE2 workflow file and running it again<i>. </i>The file is located in the Eclipse Xtext project in the <span style="font-style: italic;">src-gen</span> folder in the <span style="font-style: italic;">[...].antlr.internal</span> package (see first screenshot). <br />
<i></i>After opening it, the grammar can be checked by selecting <span style="font-style: italic;">Grammar</span> - <span style="font-style: italic;">Check Grammar (Ctrl-R)</span> from the menu. It will show an error message. Selecting the incorrect rule <span style="font-style: italic;">ruleModel</span> and ticking both checkboxes for the alternatives (on the lower right on the screenshot) shows the ambiguity graphically.
<br />
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKTw69f3EcL5QNldppP_QtRnV1ZfZ1S1N9h8vKoVigTaeGEZQqXLS9ayvKeV24GZ0h4kQJq7j5LuZYSqIlEI4WhfLYZnwc8ZVrLHDFiIQKhsXUZB16Y_uDRw8y6mKTFAk5SiP99pCHStk/s1600/antlworks-2-alt.png"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5640710842274692274" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhKTw69f3EcL5QNldppP_QtRnV1ZfZ1S1N9h8vKoVigTaeGEZQqXLS9ayvKeV24GZ0h4kQJq7j5LuZYSqIlEI4WhfLYZnwc8ZVrLHDFiIQKhsXUZB16Y_uDRw8y6mKTFAk5SiP99pCHStk/s400/antlworks-2-alt.png" style="cursor: hand; cursor: pointer; display: block; height: 357px; margin: 0px auto 10px; text-align: center; width: 400px;" /></a>
<br />
<br /></div>
</div>
</div>
Dietmar Stollhttp://www.blogger.com/profile/10428546280407453804noreply@blogger.com0tag:blogger.com,1999:blog-1646255021842169038.post-37351119123028722362011-02-07T18:23:00.011+01:002020-12-28T19:45:07.376+01:00Quickly formatting DSLs with XtextOne typical task of developing new domain specific languages with Xtext is to customize the formatting in order to have a nice text layout. If the majority of grammar keywords should be formatted in the same way and only a few in a specific way, a generic formatter could be used. As an example, for DSLs with many key-value pairs (e.g. domain models), one might want to indent everything between curly braces and start a new line before each keyword. Instead of manually listing the keywords for the <span style="font-style: italic;">findKeywords()</span>-method of the <span style="font-style: italic;">IGrammarAccess</span>, <span style="font-style: italic;">GrammarUtil</span>.<span style="font-style: italic;">getAllKeywords()</span> can be used to get all the keywords, so a generic formatting method could look like this:
<pre class="brush: java"><span style="color: #0033b3;">public class </span><span style="color: black;">GenericFormatter </span>{<br /><br /> <span style="color: #8c8c8c; font-style: italic;">/**<br /></span><span style="color: #8c8c8c; font-style: italic;"> * In your implementation of<br /></span><span style="color: #8c8c8c; font-style: italic;"> * {@link </span><span style="color: black; font-style: italic;">org.</span><span style="color: #8c8c8c; font-style: italic;">eclipse.xtext.formatting.impl.AbstractDeclarativeFormatter#configureFormatting(</span><span style="color: black; font-style: italic;">org.</span><span style="color: #8c8c8c; font-style: italic;">eclipse.xtext.formatting.impl.FormattingConfig)}<br /></span><span style="color: #8c8c8c; font-style: italic;"> * you may call this generic formatting method first. It indents blocks between curly braces and sets a linewrap<br /></span><span style="color: #8c8c8c; font-style: italic;"> * before each keyword. Add your own behavior afterwards, e.g.<br /></span><span style="color: #8c8c8c; font-style: italic;"> * </span><span style="color: #8c8c8c; font-style: italic;"><br /></span><span style="color: #8c8c8c; font-style: italic;"> * keywords = grammar.findKeywords(...);<br /></span><span style="color: #8c8c8c; font-style: italic;"> * for (final Keyword keyword : keywords) {<br /></span><span style="color: #8c8c8c; font-style: italic;"> * config.setNoLinewrap().before(keyword);<br /></span><span style="color: #8c8c8c; font-style: italic;"> * }<br /></span><span style="color: #8c8c8c; font-style: italic;"> */<br /></span><span style="color: #8c8c8c; font-style: italic;"> </span><span style="color: #0033b3;">public static void </span><span style="color: #00627a;">genericFormatting</span>(<span style="color: #0033b3;">final </span>FormattingConfig config, <span style="color: #0033b3;">final </span>IGrammarAccess grammar) {<br /> <span style="color: #0033b3;">for </span>(<span style="color: #0033b3;">final </span>Pair <span style="color: black;">pair </span>: grammar.findKeywordPairs(<span style="color: #067d17;">"{"</span>, <span style="color: #067d17;">"}"</span>)) { <span style="color: #8c8c8c; font-style: italic;">//$NON-NLS-1$ //$NON-NLS-2$<br /></span><span style="color: #8c8c8c; font-style: italic;"> // a space before the first '{'<br /></span><span style="color: #8c8c8c; font-style: italic;"> </span>config.setSpace(<span style="color: #067d17;">" "</span>).before(<span style="color: black;">pair</span>.getFirst()); <span style="color: #8c8c8c; font-style: italic;">//$NON-NLS-1$<br /></span><span style="color: #8c8c8c; font-style: italic;"> // indentation between<br /></span><span style="color: #8c8c8c; font-style: italic;"> </span>config.setIndentation(<span style="color: black;">pair</span>.getFirst(), <span style="color: black;">pair</span>.getSecond());<br /> <span style="color: #8c8c8c; font-style: italic;">// and a linewrap before the last '{'<br /></span><span style="color: #8c8c8c; font-style: italic;"> </span>config.setLinewrap(<span style="color: #1750eb;">1</span>).before(<span style="color: black;">pair</span>.getSecond());<br /> }<br /><br /> <span style="color: #8c8c8c; font-style: italic;">// linewrap before all keywords<br /></span><span style="color: #8c8c8c; font-style: italic;"> </span><span style="color: #0033b3;">final </span>Set <span style="color: black;">allKeywords </span>= GrammarUtil.getAllKeywords(grammar.getGrammar());<br /> <span style="color: #0033b3;">final </span>List <span style="color: black;">keywords </span>= grammar.findKeywords(<span style="color: black;">allKeywords</span>.toArray(<span style="color: #0033b3;">new </span>String[<span style="color: black;">allKeywords</span>.size()]));<br /> <span style="color: #0033b3;">for </span>(<span style="color: #0033b3;">final </span>Keyword <span style="color: black;">keyword </span>: <span style="color: black;">keywords</span>) {<br /> config.setLinewrap().before(<span style="color: black;">keyword</span>);<br /> }<br /><br /> }<br />}<keyword keyword=""><string><keyword>
</keyword></string></keyword></pre>
It could be called inside the <span style="font-style: italic;">configureFormatting()</span>-method in <span style="font-style: italic;">[NameOfTheDSL]Formatter</span>. Formatting code that overrides this behavior for specific keywords can be added after the call to the generic method like this:
<pre class="brush: java"><span style="color: black;">keywords </span>= grammar.findKeywords([<span style="color: black;">keywords </span>w/o wrap before]);<br /><span style="color: #0033b3;">for </span>(<span style="color: #0033b3;">final </span>Keyword <span style="color: black;">keyword </span>: <span style="color: black;">keywords</span>) {<br /> config.setNoLinewrap().before(<span style="color: black;">keyword</span>);<br />}
</pre>Dietmar Stollhttp://www.blogger.com/profile/10428546280407453804noreply@blogger.com0tag:blogger.com,1999:blog-1646255021842169038.post-45160763095719485032010-09-24T17:20:00.008+02:002010-09-24T20:05:48.873+02:00Migrating from Xtext 0.7.x to Xtext 1.0 in Eclipse Galileo (3.5)Are you stuck with Eclipse Galileo in your project but still like to use the new features of Xtext 1.0? Xtext 1.0 works fine not only in the newest Eclipse Helios (3.6), but also in Eclipse Galileo (3.5). Galileo users can also benefit from <a href="http://www.eclipse.org/Xtext/documentation/helios/new_and_noteworthy.php">Xtext 1.0 features</a>. The eclipse plugins can be updated by using the Eclipse update mechanism and adding the Xtext update site <a href="http://download.itemis.com/updates/releases/">http://download.itemis.com/updates/releases/</a> to the update manager.<br /><br />After the update of the Xtext plugins, developers may refer to the <a href="http://www.eclipse.org/Xtext/documentation/">Xtext documentation</a> (Chapter 11. <a href="http://www.eclipse.org/Xtext/documentation/1_0_1/xtext.html#migrating_from_0_7">Migrating from Xtext 0.7.x to 1.0</a>) for a manual on what has to be changed. If projects are heavily customized, the cleanest way to migrate, which is starting a new Xtext project and moving the artifacts from the old to the new projects, might not be desired and developers may prefer following the <a href="http://www.eclipse.org/Xtext/documentation/1_0_1/xtext.html#MigratingStepByStep">Migrating Step by Step</a> guidelines. Before follwing these guidelines, I recommend to quickly create a sample project (New|Project...|Xtext Project) with the default settings and running the workflow (GenerateMyDsl.mwe2). This can be a handy reference, e.g. on the new folder structure for the recommended "Rename Package" refactoring. I also recommend to read section 11.2.5. <a href="http://www.eclipse.org/Xtext/documentation/1_0_1/xtext.html#NoteworthyAPIChanges">Noteworthy API Changes</a> before fixing compilation errors.<br /><br />Grammars are backwards compatible. With Xtext 1.0, working on the grammar as a developer has become more convenient. Among other improvements, the content assist was enhanced and more hints for developers were added to prevent grammars with potentially unintended side-effects, e.g. if a rule contains only optional elements and may be consumed from the parser without object instantiation, the developer is given a hint to add an action that creates an object (see <a href="http://www.eclipse.org/Xtext/documentation/1_0_1/xtext.html#SimpleActions">Actions</a> in the Xtext documentation).<br /><br />I was doing this migration for a heavily customized Xtext modeling project, and it turned out it took less effort than expected. The customer is happy with the new features of Xtext 1.0 and the complex project now loads in a bit more than half of the time it took before.Dietmar Stollhttp://www.blogger.com/profile/10428546280407453804noreply@blogger.com0tag:blogger.com,1999:blog-1646255021842169038.post-80655336791166807622010-07-16T09:26:00.048+02:002020-12-28T19:18:41.046+01:00Xtext Quick Fix VariantsOne of my favorite Eclipse features is the quick fix functionality. When there is an error in your source code, Eclipse may have a quick fix available - it shows up with a bulb symbol on the left editor margin and may offer you several actions to fix it. You can also use the shortcut [Ctrl-1] to activate it. Xtext ships with a quick fix API which makes it easy to provide quick fixes for your own DSL, so you can provide quick fixes for your customized validation errors and warnings, which is really nice.
<div style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSvLMkdN615Ral7Jqpjt8_JlIKLF6pZ-7E667g1q4OF14te2spuVjrFe19LWOeXfEQuIfIggXDTRwBfZNj0FGL98R0qyoYL47A32JqCmm2gAt2MPytvFvINJ-sWrwdm4JY11ryLmnQ7H4/s1600/2010-07+Eclipse+Xtext+Quick+Fix+Example.png" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"><img alt="" border="0" id="BLOGGER_PHOTO_ID_5494436421382433346" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSvLMkdN615Ral7Jqpjt8_JlIKLF6pZ-7E667g1q4OF14te2spuVjrFe19LWOeXfEQuIfIggXDTRwBfZNj0FGL98R0qyoYL47A32JqCmm2gAt2MPytvFvINJ-sWrwdm4JY11ryLmnQ7H4/s400/2010-07+Eclipse+Xtext+Quick+Fix+Example.png" style="cursor: pointer; height: 124px; width: 400px;" /></a>
</div>
Quick fix actions in Xtext may either manipulate the Xtext document directly, or modify the underlying semantic model, and Xtext takes care of changing the document. Isn't that neat? For pure text manipulation, the <span style="font-style: italic;">IModification</span> interface can be used, while for working on the model you may implement <span style="font-style: italic;">ISemanticModification</span>.
The example below shows you how to use those two variants. In the example, we use a simple domain specific language for a tourist guide. The model may contain an arbitrary number of cities, and each city may contain zero or more sights, where a sight has a name and a description.
We implemented two validation warnings: One checks whether the city's name starts with a capital letter, the other warns the user when a city doesn't have any sights. Quick fixes could be to capitalize the first letter (by changing the Xtext document) and, for the sake of the example, just add a generic sight, but this time by modifying the semantic model.
To associate a quick fix with a certain validation, an identification code is used, so you have to define one for your validation like this:
<pre class="brush: java"><span style="color: #0033b3;">public static final </span><span style="color: black;">String </span><span style="color: #871094; font-style: italic;">INVALID_NAME </span>= <span style="color: #067d17;">"xtext.workshop.advanced.quickfix.InvalidTypeName"</span>;
</pre>
The check could look like this:
<pre class="brush: java"><span style="color: #0033b3;">public class </span><span style="color: black;">TouristguideDslJavaValidator </span><span style="color: #0033b3;">extends<br /></span><span style="color: #0033b3;"> </span>AbstractTouristguideDslJavaValidator {<br />[...]<br /><br /> @Check<br /> <span style="color: #0033b3;">public void </span><span style="color: #00627a;">checkTypeNameStartsWithCapital</span>(City city) {<br /> <span style="color: #0033b3;">if </span>(city.getName() == <span style="color: #0033b3;">null </span>|| city.getName().length() == <span style="color: #1750eb;">0</span>)<br /> <span style="color: #0033b3;">return</span>;<br /> <span style="color: #0033b3;">if </span>(!<span style="color: black;">Character</span>.isUpperCase(city.getName().charAt(<span style="color: #1750eb;">0</span>))) {<br /> warning(<span style="color: #067d17;">"Name should start with a capital letter."</span>,<br /> TouristguideDslPackage.CITY__NAME, INVALID_NAME,<br /> city.getName());<br /> }<br /> }<br />}
</pre>
Note that the warning takes additional parameters (in the example only one is supplied) with "user data". Here you can supply an arbitrary number of Strings with user data that may be useful for the quick fix.
Here is a step-by-step guide:
<ol><li>Import the plug-ins with the Touristguide Language (<a href="http://www.dietmar-stoll.de/dl/quickfix-eclipse-projects-2010-07-ex.zip">download examples</a>). If you only want to try the quick fix but not implement it yourself, just download the <a href="http://www.dietmar-stoll.de/dl/quickfix-eclipse-projects-2010-07-sol.zip">finished projects</a> where quick fixes are already implemented. Have a quick look at the Touristguide.xtext file in to understand how a valid .guide-file looks like.</li><li>Launch an Eclipse runtime application, create an new project, a new .guide-file and test if you get two validation warnings in the Problems view (Shift-Alt-Q X) for the following text:
<pre>city "bonn" { }</pre></li><li>Switch back to the Eclipse development environment workbench and review the validator <span style="font-style: italic;">TouristguideDslJavaValidator.java</span> (you may cf. section <span style="font-style: italic;">7.3 Quick Fixes</span> of the <a href="http://www.eclipse.org/Xtext/documentation/">Xtext 1.0.0 documentation</a>)</li><li>Open the file <span style="font-style: italic;">TouristguideDslQuickfixProvider.java</span> in the ui-Project. To implement the quick fix for the capital letters, you may implement methods like the ones below.</li></ol>
<pre class="brush: java"><span style="color: #0033b3;">public class </span><span style="color: black;">TouristguideDslQuickfixProvider </span><span style="color: #0033b3;">extends </span>DefaultQuickfixProvider {<br /><br /> @Fix(TouristguideDslJavaValidator.INVALID_NAME)<br /> <span style="color: #0033b3;">public void </span><span style="color: #00627a;">capitalizeName</span>(<span style="color: #0033b3;">final </span>Issue issue,<br /> IssueResolutionAcceptor acceptor) {<br /> <span style="color: #8c8c8c; font-style: italic;">// retrieve the 'user data' from the validation warning<br /></span><span style="color: #8c8c8c; font-style: italic;"> // upcase.png ... icon to display (in the icons folder)<br /></span><span style="color: #8c8c8c; font-style: italic;"> </span>acceptor.accept(issue, <span style="color: #067d17;">"Capitalize name"</span>, <span style="color: #067d17;">"Capitalize the name </span><span style="color: #0037a6;">\"</span><span style="color: #067d17;">"<br /></span><span style="color: #067d17;"> </span>+ issue.getData()[<span style="color: #1750eb;">0</span>] + <span style="color: #067d17;">"</span><span style="color: #0037a6;">\"</span><span style="color: #067d17;">."</span>,<br /> <span style="color: #067d17;">"upcase.png"</span>, <span style="color: #0033b3;">new </span>IModification() {<br /> <span style="color: #0033b3;">public void </span><span style="color: #00627a;">apply</span>(IModificationContext context)<br /> <span style="color: #0033b3;">throws </span>BadLocationException {<br /> IXtextDocument <span style="color: black;">xtextDocument </span>= context<br /> .getXtextDocument();<br /> <span style="color: black;">String firstLetter </span>= <span style="color: black;">xtextDocument</span>.get(<br /> <span style="color: #851691;">issue</span>.getOffset() + <span style="color: #1750eb;">1</span>, <span style="color: #1750eb;">1</span>);<br /> <span style="color: black;">xtextDocument</span>.replace(<span style="color: #851691;">issue</span>.getOffset() + <span style="color: #1750eb;">1</span>, <span style="color: #1750eb;">1</span>,<br /> <span style="color: black;">firstLetter</span>.toUpperCase());<br /> }<br /> });<br /> }<br /><br /> @Fix(TouristguideDslJavaValidator.CITY_NOT_INTERESTING)<br /> <span style="color: #0033b3;">public void </span><span style="color: #00627a;">addSightToCity</span>(<span style="color: #0033b3;">final </span>Issue issue,<br /> IssueResolutionAcceptor acceptor) {<br /> acceptor.accept(issue, <span style="color: #067d17;">"Add sight to make city more interesting"</span>,<br /> <span style="color: #067d17;">"Add a random sight, to make the city look more interesting."</span>,<br /> <br /> <span style="color: #8c8c8c; font-style: italic;">// providing null for the icon name makes Eclipse use the<br /></span><span style="color: #8c8c8c; font-style: italic;"> // standard quick fix icon<br /></span><span style="color: #8c8c8c; font-style: italic;"> </span><span style="color: #0033b3;">null</span>, <span style="color: #0033b3;">new </span>ISemanticModification() {<br /> <span style="color: #0033b3;">public void </span><span style="color: #00627a;">apply</span>(EObject element,<br /> IModificationContext context) <span style="color: #0033b3;">throws </span><span style="color: black;">Exception </span>{<br /> <span style="color: #8c8c8c; font-style: italic;">// we know that the warning applies to cities<br /></span><span style="color: #8c8c8c; font-style: italic;"> </span>City <span style="color: black;">c </span>= (City) element;<br /> <span style="color: #8c8c8c; font-style: italic;">// programmatic modification of the model<br /></span><span style="color: #8c8c8c; font-style: italic;"> </span>Sight <span style="color: black;">sight </span>= TouristguideDslFactory.eINSTANCE<br /> .createSight();<br /> <span style="color: black;">sight</span>.setName(<span style="color: #067d17;">"Central Station"</span>);<br /> <span style="color: black;">sight</span>.setDescription(<span style="color: #067d17;">"The famous central station of "<br /></span><span style="color: #067d17;"> </span>+ Strings.toFirstUpper(<span style="color: black;">c</span>.getName()) + <span style="color: #067d17;">"."</span>);<br /> <span style="color: black;">c</span>.getSights().add(<span style="color: black;">sight</span>);<br /> <span style="color: #8c8c8c; font-style: italic;">// Xtext automatically inserts text for the above<br /></span><span style="color: #8c8c8c; font-style: italic;"> </span>}<br /> });<br /> }<br />}</pre>
<ol start="5"><li>Restart the runtime workbench and have fun testing your new quick fixes :-)</li></ol>Dietmar Stollhttp://www.blogger.com/profile/10428546280407453804noreply@blogger.com3tag:blogger.com,1999:blog-1646255021842169038.post-55708604123420465772010-06-01T10:31:00.014+02:002010-06-02T09:37:30.855+02:00Bonner Vortragsreihe von itemis: Nach der WM ist vor der WM<p>Im Rahmen der Bonner Vortragsreihe, die gerade von Hanno Wendt (<a href="http://www.itemis.com/">itemis</a>) organisiert wird (siehe auch die allgemeinen itemis <a href="http://www.itemis.de/veranstaltungen">Veranstaltungen</a>), erzählte gestern Thomas Fricke (viadee) von seinen Erlebnissen als Mitarbeiter von Franz Beckenbauer im Organisationskomitee der WM 2006 und davon, wie man die Erkenntnisse aus Projektmanagementsicht auf seine eigenen Projekte übertragen kann. Der Vortrag war, wie der Untertitel versprach, tatsächlich ein spannender Blick hinter die Kulissen einer Fußballweltmeisterschaft. Es wurden auch einige Zahlen genannt, die belegten, dass heutzutage der Ticketverkauf bei den Einnahmen kaum noch eine Rolle spielt, da der Löwenanteil durch Medienrechte und Sponsoren erzielt wird.</p><p>Der Vortrag war auch für Nicht-Fußballenthusiasten wie mich sehr unterhaltsam und mit lustigen Fußballer-Kommentaren gewürzt wie etwa "Fußball ist wie Schach - nur ohne Würfel." Neben der Unterhaltung wurden auch einige Parallelen zum IT-Geschäft gezogen. Nicht nur die Organisation alleine, sondern auch die Einbeziehung von Emotionen haben wohl dazu geführt, dass die WM als "Sommermärchen" anstatt nur als "gut organisiert" bezeichnet wird. Beispiele dafür sind der vorherige Besuch der Teilnehmerländer von hochrangigen Vertretern des Organisationskomitees, alternative Sicherheitskonzepte anstelle von Zäunen in Stadien, mehrsprachige Freiwillige für die ausländischen Fans und die "Freundlichkeitskampagne" mit der Deutschen Zentrale für Tourismus<span></span>. Eine offene Hierarchie mit transparenter Kommunikation und aufrichtigem Lob (was in Deutschland generell viel zu kurz käme) hat laut Fricke ebenfalls wesentlich zum Gelingen beigetragen. </p><p>Beruhigend war für mich zu hören, dass dort bezüglich Methoden und Werkzeugen offenbar auch nur mit Wasser gekocht wurde. Diese Einfachheit sei aber konsequent durchgezogen worden. Es seien beispielsweise keine Ausnahmen bei den regelmäßigen Treffen gemacht worden, auch wenn man versucht war, diese zu streichen, "weil es doch gerade prima läuft". Auch wurden oftmals Office-Dokumente anstelle komplizierter Werkzeuge verwendet. Im Wesentlichen wurden also einfache und altbekannte Methoden eingesetzt. Fricke nannte das "die Perfektion des Naheliegenden".</p>Dietmar Stollhttp://www.blogger.com/profile/10428546280407453804noreply@blogger.com0