blob: 0e84b4bb007ce8b5f32357660dd9a36199be4019 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Xtext - Eclipse Support</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description"
content="The website of Eclipse Xtext, an open-source framework for development of programming languages and domain-specific languages">
<meta name="author" content="Sven Efftinge">
<meta name="author" content="Miro Spoenemann">
<!-- styles -->
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<!-- Le fav and touch icons -->
<link rel="shortcut icon" href="/Xtext/images/favicon.png">
<link href="/Xtext/css/bootstrap.css" rel="stylesheet" type='text/css'>
<link href="/Xtext/css/bootstrap-responsive.css" rel="stylesheet" type='text/css'>
<link href="/Xtext/css/shield-responsive.css" rel="stylesheet" type='text/css'>
<link href='/Xtext/css/fonts.css' rel='stylesheet' type='text/css'>
<link href="/Xtext/css/prettyPhoto.css" rel="stylesheet" media="screen" type='text/css'>
<link href="/Xtext/css/prettify.css" type="text/css" rel="stylesheet"/>
<link href="/Xtext/css/style.css" rel="stylesheet" type='text/css'>
<!-- cover flow -->
<link href="/Xtext/css/coverflow.css" rel="stylesheet" type='text/css'>
<!--[if lt IE 9]>
<link href="/css/iebugs.css" rel="stylesheet" type='text/css'>
<![endif]-->
<!-- BEGIN Cookie Consent
<link rel="stylesheet" type="text/css" href="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.0.3/cookieconsent.min.css" />
<script src="//cdnjs.cloudflare.com/ajax/libs/cookieconsent2/3.0.3/cookieconsent.min.js"></script>
<script>
window.addEventListener("load", function(){
window.cookieconsent.initialise({
"palette": {
"popup": {
"background": "#000"
},
"button": {
"background": "#f1d600"
}
},
"theme": "edgeless",
"type": "opt-in",
onInitialise: function (status) {
var type = this.options.type;
var didConsent = this.hasConsented();
if (type == 'opt-in' && didConsent) {
// TODO: enable cookies
}
if (type == 'opt-out' && !didConsent) {
// TODO: disable cookies
}
},
onStatusChange: function(status, chosenBefore) {
var type = this.options.type;
var didConsent = this.hasConsented();
if (type == 'opt-in' && didConsent) {
// TODO: enable cookies
}
if (type == 'opt-out' && !didConsent) {
// TODO: disable cookies
}
},
onRevokeChoice: function() {
var type = this.options.type;
if (type == 'opt-in') {
// TODO: disable cookies
}
if (type == 'opt-out') {
// TODO: enable cookies
}
},
"content": {
"href": "http://www.eclipse.org/legal/privacy.php"
}
})});
</script>
END Cookie Consent -->
</head>
<body>
<header class="site-header">
<!-- Navbar -->
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse"
data-target=".nav-collapse"> <span class="icon-bar"></span> <span
class="icon-bar"></span> <span class="icon-bar"></span>
</a> <a class="brand" href="/Xtext/index.html"></a>
<div class="nav-collapse collapse" style="height: 0px;">
<ul class="nav">
<!--li ><a href="/Xtext/news.html">News</a></li-->
<li ><a href="/Xtext/download.html">Download</a></li>
<li ><a href="/Xtext/documentation/index.html">Documentation</a></li>
<li ><a href="/Xtext/community.html">Community</a></li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Support &amp; Trainings<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="https://www.itemis.com/en/xtext/support-and-team/" target="_blank">itemis</a></li>
<li><a href="https://www.typefox.io/language-engineering/" target="_blank">TypeFox</a></li>
</ul>
</li>
<li ><a href="http://xtend-lang.org">Xtend</a></li>
</ul>
<!--div class="nav pull-right">
<li ><a><iframe src="https://ghbtns.com/github-btn.html?user=eclipse&repo=xtext&type=star&count=true" frameborder="0" scrolling="0" width="170px" height="20px"></iframe></a></li>
</div-->
</div>
<!--/.nav-collapse -->
</div>
</div>
</div>
<!-- Navbar End -->
</header>
<div class="page-content">
<script>
function startSearch(event) {
if (event.keyCode == 13) {
var q = 'site:eclipse.org/Xtext/documentation+' + event.target.value;
window.open('https://www.google.com/search?q=' + q, "_self");
}
}
</script>
<div class="wrapper">
<div id="page">
<div class="inner">
<div id="maincontainer" class="container">
<span class="edit-on-github pull-right">
<a href="https://github.com/eclipse/xtext/edit/website-published/xtext-website/documentation/310_eclipse_support.md">Edit on Github</a>
</span>
<div class="span3" style="margin-left: 0px;">
<div class="search-bar">
<img src="/Xtext/images/search-gray.png"/>
<input type="search" id="google-search" onkeyup="startSearch(event);"/>
</div>
<ul id="nav-outline" style="margin-left: 0px;">
<li class="nav-part">Getting Started</li>
<li><a href="102_domainmodelwalkthrough.html">15 Minutes Tutorial</a></li>
<li><a href="103_domainmodelnextsteps.html">15 Minutes Tutorial - Extended</a></li>
<li><a href="104_jvmdomainmodel.html">Five simple steps to your JVM language</a></li>
<li class="nav-part">Reference Documentation</li>
<li><a href="301_grammarlanguage.html">The Grammar Language</a></li>
<li><a href="302_configuration.html">Configuration</a></li>
<li><a href="303_runtime_concepts.html">Language Implementation</a></li>
<li><a href="305_xbase.html">Integration with Java</a></li>
<li><a href="307_special_languages.html">Typical Language Configurations</a></li>
<li><a href="308_emf_integration.html">Integration with EMF</a></li>
<li><a href="310_eclipse_support.html">Eclipse Support</a></li>
<li><a href="330_web_support.html">Web Editor Support</a></li>
<li><a href="340_lsp_support.html">LSP Support</a></li>
<li><a href="350_continuous_integration.html">Continuous Integration</a></li>
</ul>
</div>
<div class="span8 doc-contents">
<h1 id="ide-concepts">Eclipse Support</h1>
<p>For the following part we will refer to the Xtext Examples shipped with the Xtext framework to describe the different aspects of Xtext’s UI features.</p>
<h2 id="label-provider">Label Provider</h2>
<p>There are various places in the UI in which model elements have to be presented to the user: In the <a href="#outline">outline view</a>, in <a href="#hyperlinking">hyperlinks</a>, in <a href="#content-assist">content proposals</a>, find dialogs etc. Xtext allows to customize each of these appearances by individual implementation of the <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ILabelProvider.html">ILabelProvider</a> interface.</p>
<p>An <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ILabelProvider.html">ILabelProvider</a> has two methods: <code>getText(Object)</code> returns the text in an object’s label, while <code>getImage(Object)</code> returns the icon. In addition, the Eclipse UI framework offers the <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/DelegatingStyledCellLabelProvider.IStyledLabelProvider.html">IStyledLabelProvider</a>, which returns a <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/StyledString.html">StyledString</a> (i.e. with custom fonts, colors etc.) in the <code>getStyledText(Object)</code> method.</p>
<p>Almost all label providers in the Xtext framework inherit from the base class <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/label/AbstractLabelProvider.java">AbstractLabelProvider</a> which unifies both approaches. Subclasses can either return a styled string or a string in the <code>doGetText(Object)</code> method. The framework will automatically convert it to a styled text (with default styles) or to a plain text in the respective methods.</p>
<p>Dealing with images can be cumbersome, too, as image handles tend to be scarce system resources. The <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/label/AbstractLabelProvider.java">AbstractLabelProvider</a> helps you managing the images: In your implementation of <code>doGetImage(Object)</code> you can as well return an <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/swt/graphics/Image.html">Image</a>, an <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/resource/ImageDescriptor.html">ImageDescriptor</a> or a string, representing a path in the <em>icons/</em> folder of the containing plug-in. This path is actually configurable by Google Guice. Have a look at the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/PluginImageHelper.java">PluginImageHelper</a> to learn about the customizing possibilities.</p>
<p>If you have the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/ui/labeling/LabelProviderFragment2.xtend">LabelProviderFragment2</a> in the list of generator fragments in the MWE2 workflow of your language, it will automatically create stubs and bindings for an <a href="#eobject-label-provider"><code>{MyLang}EObjectLabelProvider</code></a> and an <a href="#description-label-provider"><code>{MyLang}DescriptionLabelProvider</code></a> which you can implement manually.</p>
<h3 id="eobject-label-provider">Label Providers For EObjects</h3>
<p>The EObject label provider refers to actually loaded and thereby available model elements. By default, Xtext binds the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/label/DefaultEObjectLabelProvider.java">DefaultEObjectLabelProvider</a> to all use cases, but you can change the binding individually for the Outline, Content Assist or other places. For that purpose, there is a so called <em>binding annotation</em> for each use case. For example, to use a custom <em>MyContentAssistLabelProvider</em> to display elements in the content assist, you have to override <code>configureContentProposalLabelProvider(..)</code> in your language’s UI module:</p>
<pre><code class="language-java">@Override
public void configureContentProposalLabelProvider(Binder binder) {
binder.bind(ILabelProvider.class)
.annotatedWith(ContentProposalLabelProvider.class)
.to(MyContentAssistLabelProvider.class);
}
</code></pre>
<p>If your grammar uses an imported <a href="https://git.eclipse.org/r/plugins/gitiles/emf/org.eclipse.emf/+/refs/tags/R2_20_0/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/EPackage.java">EPackage</a>, there may be an existing <em>edit</em>-plug-in generated by EMF that also provides label providers for model elements. To use this as a fallback, your label provider should call the constructor with the delegate parameter and use dependency injection for its initialization, e.g.</p>
<pre><code class="language-java">public class MyLabelProvider {
@Inject
public MyLabelProvider(AdapterFactoryLabelProvider delegate) {
super(delegate);
}
}
</code></pre>
<h4 id="default-eobject-label-provider">DefaultEObjectLabelProvider</h4>
<p>The default implementation of the <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/ILabelProvider.html">ILabelProvider</a> interface utilizes the polymorphic dispatcher idiom to implement an external visitor as the requirements of the label provider are kind of a best match for this pattern. It boils down to the fact that the only thing you need to do is to implement a method that matches a specific signature. It either provides an image filename or the text to be used to represent your model element. Have a look at the following example to get a more detailed idea about the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/label/DefaultEObjectLabelProvider.java">DefaultEObjectLabelProvider</a>.</p>
<pre><code class="language-java">public class StatemachineLabelProvider
extends DefaultLabelProvider {
public String text(Event event) {
return event.getName() + " (" + event.getCode() + ")";
}
public String image(Event event) {
return "event.gif";
}
public String image(State state) {
return "state.gif";
}
}
</code></pre>
<p>What is especially nice about the default implementation is the actual reason for its class name: It provides very reasonable defaults. To compute the label for a certain model element, it will first look for an <a href="https://git.eclipse.org/r/plugins/gitiles/emf/org.eclipse.emf/+/refs/tags/R2_20_0/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/EAttribute.java">EAttribute</a> <em>name</em> and try to use this one. If it cannot find such a feature, it will try to use the first feature that can be used best as a label. At worst it will return the class name of the model element, which is kind of unlikely to happen.</p>
<p>You can also customize error handling by overriding the methods <code>handleTextError()</code> or <code>handleImageError()</code>.</p>
<h3 id="description-label-provider">Label Providers For Index Entries</h3>
<p>Xtext maintains an index of all model elements to allow quick searching and linking without loading the referenced resource (see the chapter on <a href="303_runtime_concepts.html#index-based">index-based scopes</a> for details). The elements from this index also appear in some UI contexts, e.g. in the <em>Find model elements</em> dialog or in the <em>Find references</em> view. For reasons of scalability, the UI should not automatically load resources, so we need another implementation of a label provider that works with the elements from the index, i.e. <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/resource/IResourceDescription.java">IResourceDescription</a>, <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/resource/IEObjectDescription.java">IEObjectDescription</a>, and <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/resource/IReferenceDescription.java">IReferenceDescription</a>.</p>
<p>The default implementation of this service is the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/label/DefaultDescriptionLabelProvider.java">DefaultDescriptionLabelProvider</a>. It employs the same polymorphic dispatch mechanism as the <a href="#default-eobject-label-provider">DefaultEObjectLabelProvider</a>. The default text of an <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/resource/IEObjectDescription.java">IEObjectDescription</a> is its indexed name. The image is resolved by dispatching to <code>image(EClass)</code> with the <a href="https://git.eclipse.org/r/plugins/gitiles/emf/org.eclipse.emf/+/refs/tags/R2_20_0/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/EClass.java">EClass</a> of the described object. This is likely the only method you want to override. Instances of <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/resource/IResourceDescription.java">IResourceDescription</a> will be represented with their path and the icon registered for your language’s editor.</p>
<p>To have a custom description label provider, make sure it is bound in your UI module:</p>
<pre><code class="language-java">public void configureResourceUIServiceLabelProvider(Binder binder) {
binder.bind(ILabelProvider.class)
.annotatedWith(ResourceServiceDescriptionLabelProvider.class)
.to(StatemachineDescriptionLabelProvider.class);
}
</code></pre>
<h2 id="content-assist">Content Assist</h2>
<p>The Xtext generator, amongst other things, generates the following two content assist related artifacts:</p>
<ul>
<li>An abstract proposal provider class named <code>Abstract{MyLang}ProposalProvider</code> generated into the <em>src-gen</em> folder within the <em>ui</em> project, and</li>
<li>a concrete subclass in the <em>src</em>-folder of the <em>ui</em> project called <code>{MyLang}ProposalProvider</code></li>
</ul>
<p>First we will investigate the generated <code>Abstract{MyLang}ProposalProvider</code> with methods that look like this:</p>
<pre><code class="language-java">public void complete{TypeName}_{FeatureName}(
EObject model, Assignment assignment,
ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
// subclasses may override
}
public void complete_{RuleName}(
EObject model, RuleCall ruleCall,
ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
// subclasses may override
}
</code></pre>
<p>The snippet above indicates that the generated class contains a <em>complete*</em>-method for each assigned feature in the grammar and for each rule. The braces in the snippet are place-holders that should give a clue about the naming scheme used to create the various entry points for implementors. The generated proposal provider falls back to some default behavior for cross-references and keywords. Furthermore it inherits the logic that was introduced in grammars that were mixed into the current language.</p>
<p>Clients who want to customize the behavior may override the methods from the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/contentassist/AbstractJavaBasedContentProposalProvider.java">AbstractJavaBasedContentProposalProvider</a> or introduce new methods with a specialized first parameter. The framework inspects the type of the model object and dispatches method calls to the most concrete implementation that can be found.</p>
<p>It is important to know that, for a given offset in a model file, many possible grammar elements exist. The framework dispatches to the method declarations for any valid element. This means that a bunch of <em>complete*</em> methods may be called.</p>
<p>To provide a dummy proposal for the code of an <code>event</code> instance, you may introduce a specialization of the generated method and implement it as follows. This will propose <code>ZonkID</code> for an event with the name <code>Zonk</code>.</p>
<pre><code class="language-java">@Override
public void completeEvent_Code(
Event event, Assignment assignment,
ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
// call implementation of superclass
super.completeEvent_Code(model, assignment, context, acceptor);
// compute the plain proposal
String proposal = event.getName() + "ID";
// Create and register the completion proposal:
// The proposal may be null as the createCompletionProposal(..)
// methods check for valid prefixes and terminal token conflicts.
// The acceptor handles null-values gracefully.
acceptor.accept(createCompletionProposal(proposal, context));
}
</code></pre>
<h2 id="quick-fixes">Quick Fixes</h2>
<p>For validations written using the <a href="303_runtime_concepts.html#custom-validation">AbstractDeclarativeValidator</a> it is possible to provide corresponding quick fixes in the editor. To be able to implement a quick fix for a given diagnostic (a warning or error) the underlying <em>cause</em> of the diagnostic must be known (i.e. what actual problem does the diagnostic represent), otherwise the fix doesn’t know what needs to be done. As we don’t want to deduce this from the diagnostic’s error message we associate a problem specific <em>code</em> with the diagnostic.</p>
<p>In the following example taken from the <em>DomainmodelValidator</em> the diagnostic’s <em>code</em> is given by the third argument to the <code>warning()</code> method and it is a reference to the static <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/String.html">String</a> field <code>INVALID_TYPE_NAME</code> in the <code>IssueCodes</code> interface.</p>
<pre><code class="language-java">warning("Name should start with a capital",
DomainmodelPackage.TYPE__NAME, IssueCodes.INVALID_TYPE_NAME, type.getName());
</code></pre>
<p>Now that the validation has a unique code identifying the problem we can register quick fixes for it. We start by adding the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/ui/quickfix/QuickfixProviderFragment2.xtend">QuickfixProviderFragment2</a> to our workflow and after regenerating the code we should find an empty class <em>MyDslQuickfixProvider</em> in our DSL’s UI project and new entries in the <em>plugin.xml_gen</em> file.</p>
<p>Continuing with the <code>INVALID_TYPE_NAME</code> problem from the domain model example we add a method with which the problem can be fixed (have a look at the <em>DomainmodelQuickfixProvider</em> for details):</p>
<pre><code class="language-java">@Fix(IssueCodes.INVALID_TYPE_NAME)
public void fixTypeName(Issue issue, IssueResolutionAcceptor acceptor) {
acceptor.accept(issue,
"Capitalize name", // quick fix label
"Capitalize name of '" + issue.getData()[0] + "'", // description
"upcase.png", // quick fix icon
(IModificationContext context) -&gt; {
IXtextDocument xtextDocument = context.getXtextDocument();
String firstLetter = xtextDocument.get(issue.getOffset(), 1);
xtextDocument.replace(issue.getOffset(), 1, Strings.toFirstUpper(firstLetter));
});
);
}
</code></pre>
<p>By using the correct signature (see below) and annotating the method with the @<a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/quickfix/Fix.java">Fix</a> annotation referencing the previously specified issue code from the validator, Xtext knows that this method implements a fix for the problem. This also allows us to annotate multiple methods as fixes for the same problem.</p>
<p>The first three parameters given to the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/quickfix/IssueResolutionAcceptor.java">IssueResolutionAcceptor</a> define the UI representation of the quick fix. As the document is not necessarily loaded when the quick fix is offered, we need to provide any additional data from the model that we want to refer to in the UI when creating the issue in the validator above. In this case, we provided the existing type name. The additional data is available as <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/validation/Issue.java">Issue.getData()</a>. As it is persisted in markers, only strings are allowed.</p>
<p>The actual model modification is implemented in the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/model/edit/IModification.java">IModification</a>. The <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/model/edit/IModificationContext.java">IModificationContext</a> provides access to the erroneous document. In this case, we’re using Eclipse’s <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/IDocument.html">IDocument</a> API to replace a text region.</p>
<p>If you prefer to implement the quick fix in terms of the semantic model use an <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/model/edit/ISemanticModification.java">ISemanticModification</a> instead. Its <code>apply(EObject, IModificationContext)</code> method will be invoked inside a modify-transaction and the first argument will be the erroneous semantic element. This makes it very easy for the fix method to modify the model as necessary. After the method returns the model as well as the Xtext editor’s content will be updated accordingly. If the method fails (throws an exception) the change will not be committed. The following snippet shows a semantic quick fix for a similar problem.</p>
<pre><code class="language-java">@Fix(IssueCodes.INVALID_FEATURE_NAME)
public void fixFeatureName(final Issue issue,
IssueResolutionAcceptor acceptor) {
acceptor.accept(issue,
"Uncapitalize name", // label
"Uncapitalize name of '" + issue.getData()[0] + "'", // description
"upcase.png", // icon
(EObject element, IModificationContext context) -&gt; ((Feature) element).setName(Strings.toFirstLower(issue.getData()[0])));
}
</code></pre>
<p>The <code>@Fix</code> annotation is repeatable so you can specify it multiple times if a method offers a quickfix for multiple issue codes.</p>
<pre><code class="language-java">@Fix(IssueCodes.INVALID_TYPE_NAME)
@Fix(IssueCodes.OTHER_ISSUE)
public void fixName(final Issue issue,
IssueResolutionAcceptor acceptor) {
...
}
</code></pre>
<p>Alternatively you can wrap it in a <code>@Fixes</code> container.</p>
<pre><code class="language-java">@Fixes(@Fix(IssueCodes.INVALID_TYPE_NAME),@Fix(IssueCodes.OTHER_ISSUE))
public void fixName(final Issue issue,
IssueResolutionAcceptor acceptor) {
...
}
</code></pre>
<h3 id="multi-quickfixes">Multi-Quickfixes</h3>
<p>Xtext also provides a Quickfix API for the definition of multi-quickfixes. Its implementation is similar to the quick fix above, but you need to call <code>acceptor.acceptMulti()</code> instead of <code>acceptor.accept()</code>.</p>
<pre><code class="language-java">@Fix(IssueCodes.INVALID_FEATURE_NAME)
public void fixFeatureName(Issue issue,
IssueResolutionAcceptor acceptor) {
acceptor.acceptMulti(issue,
"Uncapitalize name", // label
"Uncapitalize name", // description
"upcase.png", // icon
(EObject element) -&gt; ((Feature) element).setName(Strings.toFirstLower(issue.getData()[0])));
}
</code></pre>
<p>In such cases, you can select all the <code>Invalid Feature Name</code> warnings on the Problems view and use the Quick Fix dialog (either via the context menu or the keyboard shortcut <code>Ctrl + 1</code>) to convert all uppercase feature names into lowercase at once in a single quickfix action.</p>
<h3 id="quick-fixes-for-linking-errors-and-syntax-errors">Quick Fixes for Linking Errors and Syntax Errors</h3>
<p>You can even define quick fixes for linking errors. The issue codes are assigned by the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/linking/ILinkingDiagnosticMessageProvider.java">ILinkingDiagnosticMessageProvider</a>. Have a look at the domain model example how to add quick fixes for these errors:</p>
<pre><code class="language-java">@Fix(IssueCodes.MISSING_TYPE)
public void createReferenceType(Issue issue, IssueResolutionAcceptor acceptor) {
createLinkingIssueResolutions(issue, acceptor);
}
</code></pre>
<p>Hence, there is the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/parser/antlr/ISyntaxErrorMessageProvider.java">ISyntaxErrorMessageProvider</a> to assign issue codes to syntactical errors.</p>
<h2 id="autoediting">Auto Editing</h2>
<p>Xtext-based editors automatically assist the user by inserting/deleting certain text at typetime, e.g. inserting/removing closing single quotes, double quotes, parenthesis, square brackets or curly braces when the user inserts/removes the opening ones. Moreover, the auto-indentation functionality ensures the indentation-awareness of new lines: after hitting the <code>ENTER</code> key e.g. in a block enclosed by curly braces the cursor is automatically placed on the indented position in the subsequent new line.</p>
<p>This default behaviour can be customized by extending the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/autoedit/DefaultAutoEditStrategyProvider.java">DefaultAutoEditStrategyProvider</a> class. The Xtext Simple Arithmetics example provides an interactive interpreter as an auto editing strategy by binding the customized <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.xtext.ui.examples/projects/arithmetics/org.eclipse.xtext.example.arithmetics.ui/src/org/eclipse/xtext/example/arithmetics/ui/autoedit/AutoEditStrategy.java">AutoEditStrategy</a> class in the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.xtext.ui.examples/projects/arithmetics/org.eclipse.xtext.example.arithmetics.ui/src/org/eclipse/xtext/example/arithmetics/ui/ArithmeticsUiModule.java">ArithmeticsUiModule</a>.</p>
<p><img src="images/autoediting.gif" alt="" /></p>
<h2 id="templates">Template Proposals</h2>
<p>Xtext-based editors automatically support code templates. That means that you get the corresponding preference page where users can add and change template proposals. If you want to ship a couple of default templates, you have to put a file named <em>templates.xml</em> inside the <em>templates</em> directory of the generated UI-plug-in. This file contains templates in a format as described in the <a href="http://help.eclipse.org/luna/topic/org.eclipse.cdt.doc.user/tasks/cdt_t_imp_code_temp.htm">Eclipse online help</a>.</p>
<p><img src="images/preferences_templates.png" alt="" /></p>
<p>By default Xtext registers <em>context types</em> that follow certain patterns. A context type will be created</p>
<ol>
<li>for each rule (<code>{languageName}.{RuleName}</code>) and</li>
<li>for each keyword (<code>{languageName}.kw_{keyword}</code>).</li>
</ol>
<p>If you don’t like these defaults you’ll have to subclass <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/templates/XtextTemplateContextTypeRegistry.java">XtextTemplateContextTypeRegistry</a> and configure it via <a href="302_configuration.html#guicemodules">Guice</a>.</p>
<p>In addition to the standard template proposal extension mechanism, Xtext ships with a predefined set of <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/templates/TemplateVariableResolver.html">TemplateVariableResolvers</a> to resolve special variable types in templates. Besides the standard template variables available in <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/templates/GlobalTemplateVariables.html">GlobalTemplateVariables</a> like <code>${user}</code>, <code>${date}</code>, <code>${time}</code>, <code>${cursor}</code>, etc., these <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/templates/TemplateVariableResolver.html">TemplateVariableResolvers</a> support the automatic resolution of cross references enumeration values. Both resolvers are explained in the following sections.</p>
<p>It is best practice to edit the templates in the preferences page, export them into the <em>templates.xml</em> file and put the file into the <em>templates</em> folder of your UI-plug-in. However, these templates will not be visible by default. To fix it, you have to manually edit the xml-file and insert an <code>id</code> attribute for each template element. Note that the attribute name is case sensitive. As always in Eclipse Plug-In development, if the folder <em>templates</em> did not exist before, you have to add it to the <em>bin.includes</em> in the <em>build.properties</em> file.</p>
<h3 id="cross-reference-template-variable-resolver">Cross Reference Template Variable Resolver</h3>
<p>Xtext comes with a specific template variable resolver called <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/templates/CrossReferenceTemplateVariableResolver.java">CrossReferenceTemplateVariableResolver</a>, which can be used to pre-populate placeholders for cross-references within a template. The respective template variable is called <em>CrossReference</em> and its syntax is as follows:</p>
<p><code>${&lt;displayText&gt;:CrossReference([&lt;MyPackageName&gt;.]&lt;MyType&gt;.&lt;myRef&gt;)}</code></p>
<p>Where “displayText” is the initial value that is shown in the editor. It is also the identifier for a place holder so that multiple place holders with the same name will be updated at once by the user using linked editing.</p>
<p>This small example (taken from the Xtext Statemachine example) yields the text <em>event =&gt; state</em> and allows selecting any events and states using a drop down:</p>
<pre><code class="language-xml">&lt;template
name="Transition"
description="Template for a Transition"
id="org.eclipse.xtext.example.fowlerdsl.Statemachine.Transition"
context="org.eclipse.xtext.example.fowlerdsl.Statemachine.Transition"
enabled="true"
&gt;${event:CrossReference('Transition.event')} =&gt; ${state:CrossReference('Transition.state')}&lt;/template&gt;
&lt;/template&gt;
</code></pre>
<p><img src="images/templates_crossref.png" alt="" /></p>
<h3 id="enumeration-template-variable-resolver">Enumeration Template Variable Resolver</h3>
<p>The <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/templates/EnumTemplateVariableResolver.java">EnumTemplateVariableResolver</a> resolves a template variable to <a href="https://git.eclipse.org/r/plugins/gitiles/emf/org.eclipse.emf/+/refs/tags/R2_20_0/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/EEnumLiteral.java">EEnumLiterals</a> which are assignment-compatible to the enumeration type declared as the first parameter of the <em>Enum</em> template variable.</p>
<p>The syntax is as follows:</p>
<p><code>${&lt;displayText&gt;:Enum([&lt;MyPackage&gt;.]&lt;EnumType&gt;)}</code></p>
<p>For example the following template (taken from the Xtext Domainmodel example):</p>
<pre><code class="language-domainexample">&lt;template
name="Entity"
description="template for an Entity"
id="entity"
context="org.eclipse.xtext.example.Domainmodel.Entity"
enabled="true"&gt;
${public:Enum('Visibility')} entity ${Name} {
${cursor}
}
&lt;/template&gt;
</code></pre>
<p>yields the text <code>public entity Name {}</code> where the text <code>public</code> is the default value of the <code>Visibility</code>. The editor provides a drop down that is populated with the other literal values as defined in the <a href="https://git.eclipse.org/r/plugins/gitiles/emf/org.eclipse.emf/+/refs/tags/R2_20_0/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/EEnum.java">EEnum</a>.</p>
<h2 id="outline">Outline View</h2>
<p>Xtext provides an outline view to help you navigate your models. By default, it provides a hierarchical view on your model and allows you to sort tree elements alphabetically. Selecting an element in the outline will highlight the corresponding element in the text editor. Users can choose to synchronize the outline with the editor selection by clicking the <em>Link with Editor</em> button.</p>
<p><img src="images/sample_outline.png" alt="" /></p>
<p>In its default implementation, the outline view shows the containment hierarchy of your model. This should be sufficient in most cases. If you want to adjust the structure of the outline, i.e. by omitting a certain kind of node or by introducing additional nodes, you can customize the outline by implementing your own <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/IOutlineTreeProvider.java">IOutlineTreeProvider</a>.</p>
<p>If your workflow defines the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/ui/outline/OutlineTreeProviderFragment2.xtend">OutlineTreeProviderFragment2</a>, Xtext generates a stub for your own <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/IOutlineTreeProvider.java">IOutlineTreeProvider</a> that allows you to customize every aspect of the outline by inheriting the powerful customization methods of <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/impl/DefaultOutlineTreeProvider.java">DefaultOutlineTreeProvider</a>. The following sections show how to fill this stub with life.</p>
<h3 id="influencing-the-outline-structure">Influencing the outline structure</h3>
<p>Each node in the outline tree is an instance of <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/IOutlineNode.java">IOutlineNode</a>. The outline tree is always rooted in a <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/impl/DocumentRootNode.java">DocumentRootNode</a>. This node is automatically created for you. Its children are the root nodes in the displayed view.</p>
<p>An <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/impl/EObjectNode.java">EObjectNode</a> represents a model element. By default, Xtext creates an <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/impl/EObjectNode.java">EObjectNode</a> for each model element in the node of its container. Nodes are created by calling the method <code>createNode(parentNode, modelElement)</code> which delegates to <code>createEObjectNode(..)</code> if not specified differently.</p>
<p>To change the children of specific nodes, you have to implement the method</p>
<pre><code class="language-java">_createChildren(parentNode,
parentModelElement)
</code></pre>
<p>with the appropriate types. The following snippet shows you how to skip the root model element of type <code>Domainmodel</code> in the outline of our domain model example:</p>
<pre><code class="language-java">protected void _createChildren(DocumentRootNode parentNode,
Domainmodel domainModel) {
for (AbstractElement element : domainModel.getElements()) {
createNode(parentNode, element);
}
}
</code></pre>
<p>You can choose not to create any node in the <code>_createChildren()</code> method. Because the outline nodes are calculated on demand, the UI will show you an expandable node that doesn’t reveal any children even if it is expanded. This might be confuse your users a bit. To overcome this shortcoming, you have to implement the method <code>_isLeaf(modelElement)</code> with the appropriate argument type, e.g.</p>
<pre><code class="language-java">// feature nodes are leafs and not expandable
protected boolean _isLeaf(Feature feature) {
return true;
}
</code></pre>
<p>Xtext provides a third type of node: <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/impl/EStructuralFeatureNode.java">EStructuralFeatureNode</a>. It is used to represent a feature of a model element rather than the element itself. The following simplified snippet from Xtend2 illustrates how to use it:</p>
<pre><code class="language-java">protected void _createChildren(DocumentRootNode parentNode,
XtendFile xtendFile) {
// show a node for the attribute XtendFile.package
createEStructuralFeatureNode(parentNode,
xtendFile,
Xtend2Package.Literals.XTEND_FILE__PACKAGE,
getImageForPackage(),
xtendFile.getPackage(),
true);
// show a container node for the list reference XtendFile.imports
// the imports will be shown as individual child nodes automatically
createEStructuralFeatureNode(parentNode,
xtendFile,
Xtend2Package.Literals.XTEND_FILE__IMPORTS,
getImageForImportContainer(),
"import declarations",
false);
createEObjectNode(parentNode, xtendFile.getXtendClass());
}
</code></pre>
<p>Of course you can add further custom types of nodes. For consistency, make sure to inherit from <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/impl/AbstractOutlineNode.java">AbstractOutlineNode</a>. To instantiate these, you have to implement <code>_createNode(parentNode, semanticElement)</code> with the appropriate parameter types.</p>
<h3 id="styling-the-outline">Styling the outline</h3>
<p>You can also customize the icons and texts for an outline node. By default, Xtext uses the <a href="#label-provider">label provider</a> of your language. If you want the labels to be specific to the outline, you can override the methods <code>_text(modelElement)</code> and <code>_image(modelElement)</code> in your <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/impl/DefaultOutlineTreeProvider.java">DefaultOutlineTreeProvider</a>.</p>
<p>Note that the method <code>_text(modelElement)</code> can return a <a href="http://docs.oracle.com/javase/8/docs/api/java/lang/String.html">String</a> or a <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/StyledString.html">StyledString</a>. The <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/label/StylerFactory.java">StylerFactory</a> can be used to create <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/viewers/StyledString.html">StyledStrings</a>, like in the following example:</p>
<pre><code class="language-java">@Inject
private StylerFactory stylerFactory;
public Object _text(Entity entity) {
if(entity.isAbstract()) {
return new StyledString(entity.getName(),
stylerFactory
.createXtextStyleAdapterStyler(getTypeTextStyle())));
else
return entity.getName();
}
protected TextStyle getTypeTextStyle() {
TextStyle textStyle = new TextStyle();
textStyle.setColor(new RGB(149, 125, 71));
textStyle.setStyle(SWT.ITALIC);
return textStyle;
}
</code></pre>
<p>To access images we recommend to use the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/PluginImageHelper.java">PluginImageHelper</a>.</p>
<h3 id="filtering-actions">Filtering actions</h3>
<p>Often, you want to allow users to filter the contents of the outline to make it easier to concentrate on the relevant aspects of the model. To add filtering capabilities to your outline, you need to add a filter action to your outline. Filter actions must extend <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/actions/AbstractFilterOutlineContribution.java">AbstractFilterOutlineContribution</a> to ensure that the action toggle state is handled correctly. Here is an example from the Xtext Domainmodel example:</p>
<pre><code class="language-java">public class FilterOperationsContribution
extends AbstractFilterOutlineContribution {
public static final String PREFERENCE_KEY =
"ui.outline.filterEntities";
@Inject
private PluginImageHelper imageHelper;
@Override
protected boolean apply(IOutlineNode node) {
return !(node instanceof EObjectNode)
|| !((EObjectNode) node).getEClass()
.equals(DomainmodelPackage.Literals.OPERATION);
}
@Override
public String getPreferenceKey() {
return PREFERENCE_KEY;
}
@Override
protected void configureAction(Action action) {
action.setText("Hide operations");
action.setDescription("Hide operations");
action.setToolTipText("Hide operations");
action.setImageDescriptor(imageHelper.getImageDescriptor("Operation.gif"));
}
}
</code></pre>
<p>The contribution must be bound in the <em>DomainmodelUiModule</em> like this</p>
<pre><code class="language-java">public void configureFilterOperationsContribution(Binder binder) {
binder
.bind(IOutlineContribution.class).annotatedWith(
Names.named("FilterOperationsContribution"))
.to(FilterOperationsContribution.class);
}
</code></pre>
<h3 id="sorting-actions">Sorting actions</h3>
<p>Xtext already adds a sorting action to your outline. By default, nodes are sorted lexically by their text. You can change this behavior by binding your own <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/impl/OutlineFilterAndSorter.java">IComparator</a>.</p>
<p>A very common use case is to group the children by categories first, e.g. show the imports before the types in a package declaration, and sort the categories separately. That is why the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/outline/actions/SortOutlineContribution.java">DefaultComparator</a> has a method <code>getCategory(IOutlineNode)</code> that allows to specify such categories. The example shows how to use such categories:</p>
<pre><code class="language-java">public class MydslOutlineNodeComparator extends DefaultComparator {
@Override
public int getCategory(IOutlineNode node) {
if (node instanceof EObjectNode)
switch((EObjectNode) node).getEClass().getClassifierID())) {
case MydslPackage.TYPE0:
return -10;
case MydslPackage.TYPE1:
return -20;
}
return Integer.MIN_VALUE;
}
}
</code></pre>
<p>As always, you have to declare a binding for your custom implementation in your <em>MyDslUiModule</em>:</p>
<pre><code class="language-java">@Override
public Class&lt;? extends IComparator&gt;
bindOutlineFilterAndSorter$IComparator() {
return MydslOutlineNodeComparator.class;
}
</code></pre>
<h3 id="quick-outline">Quick Outline</h3>
<p>Xtext also provides a quick outline: If you press CTRL-O in an Xtext editor, the outline of the model is shown in a popup window. The quick outline also supports drill-down search with wildcards. To enable the quick outline, you have to put the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/ui/outline/QuickOutlineFragment2.xtend">QuickOutlineFragment2</a> into your workflow.</p>
<h2 id="folding">Folding</h2>
<p>Xtext calculates the editor folding regions based on the grammar out-of-the-box. Although it comes with good defaults, sometimes they do not satisfy the needs and have to be customized.</p>
<p>Considering e.g the Xtext Statemachine example, the framework provides folding capabilities for the <code>state</code> regions:</p>
<p><img src="images/folding_default.png" alt="" /></p>
<p>In order to make <code>events</code>, <code>resetEvents</code> and <code>commands</code> foldable too, a custom implementation of the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/folding/DefaultFoldingRegionProvider.java">DefaultFoldingRegionProvider</a> is necessary:</p>
<pre><code class="language-java">public class StatemachineFoldingRegionProvider extends DefaultFoldingRegionProvider {
@Override
protected void computeObjectFolding(
EObject o,
IFoldingRegionAcceptor&lt;ITextRegion&gt; foldingRegionAcceptor) {
if (o instanceof Statemachine) {
XtextResource res = (XtextResource) o.eResource();
computeEventsFolding(res, foldingRegionAcceptor);
computeResetEventsFolding(res, foldingRegionAcceptor);
computeCommandsFolding(res, foldingRegionAcceptor);
} else {
super.computeObjectFolding(o, foldingRegionAcceptor);
}
}
private void computeEventsFolding(
XtextResource res,
IFoldingRegionAcceptor&lt;ITextRegion&gt; foldingRegionAcceptor) {
...
}
private void computeResetEventsFolding(
XtextResource res,
IFoldingRegionAcceptor&lt;ITextRegion&gt; foldingRegionAcceptor) {
...
}
private void computeCommandsFolding(
XtextResource res,
IFoldingRegionAcceptor&lt;ITextRegion&gt; foldingRegionAcceptor) {
...
}
...
}
</code></pre>
<p>Additionally, the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.xtext.ui.examples/projects/fowlerdsl/org.eclipse.xtext.example.fowlerdsl.ui/src/org/eclipse/xtext/example/fowlerdsl/ui/folding/StatemachineFoldingRegionProvider.java">StatemachineFoldingRegionProvider</a> class has to be bound in the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.xtext.ui.examples/projects/fowlerdsl/org.eclipse.xtext.example.fowlerdsl.ui/src/org/eclipse/xtext/example/fowlerdsl/ui/StatemachineUiModule.java">StatemachineUiModule</a>:</p>
<pre><code class="language-java">public class StatemachineUiModule extends AbstractStatemachineUiModule {
...
public Class&lt;? extends IFoldingRegionProvider&gt; bindIFoldingRegionProvider() {
return StatemachineFoldingRegionProvider.class;
}
}
</code></pre>
<p>As a result, not only the <code>state</code>, but also the <code>events</code>, <code>resetEvents</code> and <code>commands</code> regions become foldable:<br />
<img src="images/folding_customized.png" alt="" /></p>
<h2 id="hyperlinking">Hyperlinking</h2>
<p>The Xtext editor provides hyperlinking support for any tokens corresponding to cross-references in your grammar definition. You can either <em>CTRL-click</em> on any of these tokens or hit <em>F3</em> while the cursor position is at the token in question and this will take you to the referenced model element. As you’d expect this works for references to elements in the same resource as well as for references to elements in other resources. In the latter case the referenced resource will first be opened using the corresponding editor.</p>
<h3 id="location-provider">Location Provider</h3>
<p>When navigating a hyperlink, Xtext will also select the text region corresponding to the referenced model element. Determining this text region is the responsibility of the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/resource/ILocationInFileProvider.java">ILocationInFileProvider</a>. The <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/resource/DefaultLocationInFileProvider.java">default implementation</a> implements a best effort strategy which can be summarized as:</p>
<ol>
<li>If the model element’s <a href="https://git.eclipse.org/r/plugins/gitiles/emf/org.eclipse.emf/+/refs/tags/R2_20_0/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/EClass.java">type</a> declares a feature <em>name</em> then return the region of the corresponding token(s). As a fallback also check for a feature <em>id</em>.</li>
<li>If the model element’s node model contains any top-level tokens corresponding to invocations of the rule <em>ID</em> in the grammar then return a region spanning all those tokens.</li>
<li>As a last resort return the region corresponding to the first keyword token of the referenced model element.</li>
</ol>
<p>The location service offers different methods to obtain the region of interest for special use cases. You can either obtain the complete region for an object or only the identifying string which is usually the name of the instance (see <code>getSignificantTextRegion(EObject)</code>). You can also query for the text region of a specific <a href="https://git.eclipse.org/r/plugins/gitiles/emf/org.eclipse.emf/+/refs/tags/R2_20_0/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/EStructuralFeature.java">EStructuralFeature</a> by means of <code>getFullTextRegion(EObject, EStructuralFeature, int)</code>.</p>
<p>As the default strategy is a best effort it may not always result in the selection you want. If that’s the case you can <a href="302_configuration.html#guicemodules">override</a> the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/resource/ILocationInFileProvider.java">ILocationInFileProvider</a> binding in the UI module as in the following example:</p>
<pre><code class="language-java">public class MyDslUiModule extends AbstractMyDslUiModule {
@Override
public Class&lt;? extends ILocationInFileProvider&gt;
bindILocationInFileProvider() {
return MyDslLocationInFileProvider.class;
}
}
</code></pre>
<p>Often the default strategy only needs some guidance (e.g. selecting the text corresponding to another feature than <em>name</em>). In that case you can simply subclass the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/resource/DefaultLocationInFileProvider.java">DefaultLocationInFileProvider</a> and override the methods <code>getIdentifierFeature()</code> or <code>useKeyword()</code> to guide the first and last steps of the strategy as described above (see <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/xtext/XtextLocationInFileProvider.java">XtextLocationInFileProvider</a> for an example).</p>
<h3 id="customizing-available-hyperlinks">Customizing Available Hyperlinks</h3>
<p>The hyperlinks are provided by the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/hyperlinking/HyperlinkHelper.java">HyperlinkHelper</a> which will create links for cross-referenced objects by default. Clients may want to override <code>createHyperlinksByOffset(XtextResource, int, IHyperlinkAcceptor)</code> to provide additional links or supersede the default implementation.</p>
<h2 id="hovering">Hovering</h2>
<p>Similar to <a href="#hyperlinking">hyperlinking</a>, Xtext-based editors provide hovering support on certain tokens: e.g. hovering over a cross-reference token, the Xtext framework shows the documentation of the element the cross-reference is referring to. Considering the Xtext Simple Arithmetics example, when hovering over a function call, a popup window displays the documentation of the called function:</p>
<p><img src="images/hovering.png" alt="" /></p>
<p>This functionality is implemented in the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/hover/html/DefaultEObjectHoverProvider.java">DefaultEObjectHoverProvider</a> that delegates to the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/documentation/impl/MultiLineCommentDocumentationProvider.java">MultiLineCommentDocumentationProvider</a> class via the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/documentation/IEObjectDocumentationProvider.java">IEObjectDocumentationProvider</a> interface by default. Customization can happen e.g. by extending the <code>DefaultEObjectHoverProvider</code> class, overriding the <code>getHoverInfoAsHtml(EObject o)</code> method and binding the custom implementation in the corresponding UI module:</p>
<pre><code class="language-java">public class MyDslHoverProvider extends DefaultEObjectHoverProvider {
@Override
protected String getHoverInfoAsHtml(EObject o) {
...
}
}
</code></pre>
<pre><code class="language-java">public class MyDslUiModule extends AbstractMyDslUiModule {
public Class&lt;? extends IEObjectHoverProvider&gt; bindIEObjectHoverProvider() {
return MyDslHoverProvider.class;
}
}
</code></pre>
<h2 id="maroccurrences">Mark Occurrences</h2>
<p>Xtext-based editors are able to highlight all occurrences of a certain element in the opened DSL file. Once the user selects an element while the <code>Toggle Mark Occurrences</code> button is enabled, all occurrences are highlighted with corresponding markers on the right side of the editor.</p>
<p><img src="images/mark_occurrences.png" alt="" /></p>
<p>Customization can happen by either extending the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/occurrences/DefaultOccurrenceComputer.java">DefaultOccurrenceComputer</a> class or even providing a complete implementation of the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/occurrences/IOccurrenceComputer.java">IOccurrenceComputer</a> interface.</p>
<pre><code class="language-java">public class MyDslOccurrenceComputer extends DefaultOccurrenceComputer {
...
}
</code></pre>
<pre><code class="language-java">public class MyDslUiModule extends AbstractMyDslUiModule {
public Class&lt;? extends IOccurrenceComputer&gt; bindIOccurrenceComputer() {
return MyDslOccurrenceComputer.class;
}
}
</code></pre>
<h2 id="findreferences">Find References</h2>
<p>Xtext-based editors are able to locate all references in the entire workspace where a certain element is referred to. Invoking the <code>Find References</code> context menu or using the keyboard shortcut <code>Ctlr+Shift+G</code> (<code>Cmd+Shift+G</code> on Mac) on the selected element lists all the references in the <code>Search</code> view.</p>
<p><img src="images/find_references.gif" alt="" /></p>
<p>The <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/findReferences/IReferenceFinder.java">org.eclipse.xtext.findReferences.IReferenceFinder</a> and the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/findrefs/IReferenceFinder.java">org.eclipse.xtext.ui.editor.findrefs.IReferenceFinder</a> interfaces are responsible for this functionality. These interfaces are implemented by the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/findReferences/ReferenceFinder.java">ReferenceFinder</a> and the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/findrefs/DelegatingReferenceFinder.java">DelegatingReferenceFinder</a> classes. As almost everything in the Xtext framework, these components can also be customized if the default implementations do not satisfy your needs.</p>
<h2 id="highlighting">Syntax Coloring</h2>
<p>Besides the already mentioned advanced features like <a href="#content-assist">content assist</a> and <a href="303_runtime_concepts.html#formatting">code formatting</a> the powerful editor for your DSL is capable to mark up your model-code to improve the overall readability. It is possible to use different colors and fonts according to the meaning of the different parts of your input file. One may want to use some unintrusive colors for large blocks of comments while identifiers, keywords and strings should be colored differently to make it easier to distinguish between them. This kind of text decorating markup does not influence the semantics of the various sections but helps to understand the meaning and to find errors in the source code.</p>
<p><img src="images/highlighting.png" alt="" /></p>
<p>The highlighting is done in two stages. This allows for sophisticated algorithms that are executed asynchronously to provide advanced coloring while simple pattern matching may be used to highlight parts of the text instantaneously. The latter is called lexical highlighting while the first is based on the meaning of your different model elements and therefore called semantic highlighting.</p>
<p>When you introduce new highlighting styles, the preference page for your DSL is automatically configured and allows the customization of any registered highlighting setting. They are automatically persisted and reloaded on startup.</p>
<p><img src="images/preferences_syntax.png" alt="" /></p>
<h3 id="lexical-highlighting">Lexical Highlighting</h3>
<p>The lexical highlighting can be customized by providing implementations of the interface <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/syntaxcoloring/IHighlightingConfiguration.java">IHighlightingConfiguration</a> and the abstract class <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/syntaxcoloring/AbstractTokenScanner.java">AbstractTokenScanner</a>. The latter fulfills the interface <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/rules/ITokenScanner.html">ITokenScanner</a> from the underlying JFace framework, which may be implemented by clients directly.</p>
<p>The <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/syntaxcoloring/IHighlightingConfiguration.java">IHighlightingConfiguration</a> is used to register any default style without a specific binding to a pattern in the model file. It is used to populate the preferences page and to initialize the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/syntaxcoloring/ITextAttributeProvider.java">ITextAttributeProvider</a>, which in turn is the component that is used to obtain the actual settings for a style’s id. An implementation will usually be very similar to the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/syntaxcoloring/DefaultHighlightingConfiguration.java">DefaultHighlightingConfiguration</a> and read like this:</p>
<pre><code class="language-java">public class DefaultHighlightingConfiguration
implements IHighlightingConfiguration {
public static final String KEYWORD_ID = "keyword";
public static final String COMMENT_ID = "comment";
public void configure(IHighlightingConfigurationAcceptor acceptor) {
acceptor.acceptDefaultHighlighting(
KEYWORD_ID, "Keyword", keywordTextStyle());
acceptor.acceptDefaultHighlighting(COMMENT_ID, "Comment", commentTextStyle();
}
public TextStyle keywordTextStyle() {
TextStyle textStyle = new TextStyle();
textStyle.setColor(new RGB(127, 0, 85));
textStyle.setStyle(SWT.BOLD);
return textStyle;
}
}
</code></pre>
<p>Implementations of the <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/jface/text/rules/ITokenScanner.html">ITokenScanner</a> are responsible for splitting the content of a document into various parts, the so called tokens, and return the highlighting information for each identified range. It is critical that this is done very fast because this component is used on each keystroke. Xtext ships with a default implementation that is based on the lexer that is generated by ANTLR which is very lightweight and fast. This default implementation can be customized by clients easily. They simply have to bind another implementation of the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/syntaxcoloring/AbstractAntlrTokenToAttributeIdMapper.java">AbstractAntlrTokenToAttributeIdMapper</a>. To get an idea about it, have a look at the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/syntaxcoloring/DefaultAntlrTokenToAttributeIdMapper.java">DefaultAntlrTokenToAttributeIdMapper</a>.</p>
<h3 id="semantic-highlighting">Semantic Highlighting</h3>
<p>The semantic highlighting stage is executed asynchronously in the background and can be used to calculate highlighting states based on the meaning of the different model elements. Users of the editor will notice a very short delay after they have edited the text until the styles are actually applied to the document. This keeps the editor responsive while providing aid when reading and writing your model.</p>
<p>As for the lexical highlighting the interface to register the available styles is the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/syntaxcoloring/IHighlightingConfiguration.java">IHighlightingConfiguration</a>. The <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/syntaxcoloring/ISemanticHighlightingCalculator.java">ISemanticHighlightingCalculator</a> is the primary hook to implement the logic that will compute the to-be-highlighted ranges based on the model elements.</p>
<p>The framework will pass the current <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/resource/XtextResource.java">XtextResource</a> and an <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/syntaxcoloring/IHighlightedPositionAcceptor.java">IHighlightedPositionAcceptor</a> to the calculator. It is ensured that the resource will not be altered externally until the called method <code>provideHighlightingFor()</code> returns. However, the resource may be <code>null</code> in case of errors in the model. The implementor’s task is to navigate the semantic model and compute various ranges based on the attached node information and associate styles with them. This may read similar to the following snippet:</p>
<pre><code class="language-java">public void provideHighlightingFor(XtextResource resource,
IHighlightedPositionAcceptor acceptor) {
if (resource == null || resource.getParseResult() == null)
return;
INode root = resource.getParseResult().getRootNode();
for (INode node : root.getAsTreeIterable()) {
if (node.getGrammarElement() instanceof CrossReference) {
acceptor.addPosition(node.getOffset(), node.getLength(),
MyHighlightingConfiguration.CROSS_REF);
}
}
}
</code></pre>
<p>This example refers to an implementation of the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/syntaxcoloring/IHighlightingConfiguration.java">IHighlightingConfiguration</a> that registers an own style for each cross-reference. It is pretty much the same implementation as for the previously mentioned sample of a lexical <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/editor/syntaxcoloring/IHighlightingConfiguration.java">IHighlightingConfiguration</a>.</p>
<pre><code class="language-java">public class HighlightingConfiguration
implements IHighlightingConfiguration {
// lexical stuff goes here
// ..
public final static String CROSS_REF = "CrossReference";
public void configure(IHighlightingConfigurationAcceptor acceptor) {
// lexical stuff goes here
// ..
acceptor.acceptDefaultHighlighting(CROSS_REF,
"Cross-References", crossReferenceTextStyle());
}
public TextStyle crossReferenceTextStyle() {
TextStyle textStyle = new TextStyle();
textStyle.setStyle(SWT.ITALIC);
return textStyle;
}
}
</code></pre>
<p>The implementor of an <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.ide/src/org/eclipse/xtext/ide/editor/syntaxcoloring/ISemanticHighlightingCalculator.java">ISemanticHighlightingCalculator</a> should be aware of performance to ensure a good user experience. It is probably not a good idea to traverse everything of your model when you will only register a few highlighted ranges that can be found easier with some typed method calls. It is strongly advised to use purposeful ways to navigate your model. The parts of Xtext’s core that are responsible for the semantic highlighting are pretty optimized in this regard as well. The framework will only update the ranges that actually have been altered, for example. This speeds up the redraw process. It will even move, shrink or enlarge previously announced regions based on a best guess before the next semantic highlighting pass has been triggered after the user has changed the document.</p>
<h2 id="refactoring">Rename Refactoring</h2>
<p>Xtext provides rename refactoring of the elements in your language. That includes</p>
<ul>
<li>a command, handlers and keybindings on both declarations and references,</li>
<li>in-place linked editing for the new name,</li>
<li>validation and preview,</li>
<li>renaming of declaration and all references even across language boundaries.</li>
</ul>
<p>To enable refactoring support make sure the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext.xtext.generator/src/org/eclipse/xtext/xtext/generator/ui/refactoring/RefactorElementNameFragment2.xtend">RefactorElementNameFragment2</a> is enabled in the fragment section of the MWE workflow of your language, e.g.</p>
<pre><code class="language-mwe2">// rename refactoring
fragment = refactoring.RefactorElementNameFragment2 {}
</code></pre>
<p>The fragment has an additional flag <code>useJdtRefactoring</code> which can be used to delegate to JDT’s refactoring infrastructure for languages using <a href="305_xbase.html">Xbase</a> and an <a href="305_xbase.html#xbase-inferred-type">inferred JVM model</a> (i.e. the Xtext domain model example or Xtend).</p>
<p>If you have stuck to the defaults with regard to naming, cross-referencing, and indexing, the rename refactoring should not need any customization. Give it a try.</p>
<h3 id="customizing">Customizing</h3>
<p>The most likely component you want to customize is the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/refactoring/IRenameStrategy.java">IRenameStrategy</a>. This component defines how the declaration of the target element is performed. It has two major responsibilities:</p>
<ul>
<li>Apply and revert the declaration change on the semantic model (methods <code>applyDeclarationChange</code> and <code>revertDeclarationChange</code>). The default is to look for an <a href="https://git.eclipse.org/r/plugins/gitiles/emf/org.eclipse.emf/+/refs/tags/R2_20_0/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/EAttribute.java">EAttribute</a> <code>name</code> on the target object and set its value using EMFs reflective API.</li>
<li>Create the LTK <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ltk/core/refactoring/Change.html">Change</a> objects of the declaration change. These changes will be aggregated, checked for overlaps, presented to you in the preview and finally executed if you apply the refactoring. The default is to use the <a href="https://github.com/eclipse/xtext-core/blob/master/org.eclipse.xtext/src/org/eclipse/xtext/resource/ILocationInFileProvider.java">ILocationInFileProvider</a> to locate the text range representing the name and create a <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/text/edits/ReplaceEdit.html">ReplaceEdit</a> for it.</li>
</ul>
<p>As the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/refactoring/IRenameStrategy.java">IRenameStrategy</a> is a stateful object, you have to bind a custom <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/refactoring/IRenameStrategy.java">Provider</a> to create it.</p>
<p>The second component you might want to customize is the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/refactoring/IDependentElementsCalculator.java">IDependentElementsCalculator</a>. Dependent elements are those elements whose name change when the target element is renamed. For example, when you rename a Java class the qualified names of its inner classes change, too, thus references to these have to be updated as well. This calculation is performed by the <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/refactoring/IDependentElementsCalculator.java">IDependentElementsCalculator</a>. By default, all elements contained in the target element are added. This matches Xtext’s default strategy of qualified name computation.</p>
<h3 id="rename-participants">Rename Participants</h3>
<p>One refactoring can trigger another: When renaming a rule in an Xtext grammar, the returned <a href="https://git.eclipse.org/r/plugins/gitiles/emf/org.eclipse.emf/+/refs/tags/R2_20_0/plugins/org.eclipse.emf.ecore/src/org/eclipse/emf/ecore/EClass.java">EClass</a> should be renamed, too. For these cases, you can register a <a href="http://help.eclipse.org/luna/topic/org.eclipse.platform.doc.isv/reference/api/org/eclipse/ltk/core/refactoring/participants/RenameParticipant.html">RenameParticipant</a> by the common means of LTK. If the target of the participant is Xtext based, you can use a <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/refactoring/impl/AbstractProcessorBasedRenameParticipant.java">AbstractProcessorBasedRenameParticipant</a>.</p>
<h2 id="projectwizard">Project Wizard</h2>
<p>The MWE2 workflow can generate a wizard that clients of your language can use to create model projects. This will be generated in the <code>.ui</code> project. If the language was generated before the <code>plugin.xml</code> will have to be manually merged with the <code>plugin.xml_gen</code>.</p>
<p>This must be explicitly specified in the MWE2 file in the <code>language</code> section as follows</p>
<pre><code class="language-mwe2">projectWizard = {
generate = true
}
</code></pre>
<p>By default, the generated wizard will create a Plug-in project. If you want a General project you need to set the following property to false: <code>pluginProject=false</code>, for example</p>
<pre><code class="language-mwe2">projectWizard = {
generate = true
pluginProject = false
}
</code></pre>
<p>In the <code>src</code> folder of the <code>ui</code> project a <code>MyDslProjectTemplateProvider</code> Xtend file will be generated, where you can specify the templates the user can select from to generate new projects.</p>
<p>The templates define two things. On the one hand they define how the template is presented to the user. A name, a description and the layout of the widgets the user gets presented to select values for the parameters of the template. On the other hand the content of the projects that the template generates is defined. The wizard is able to generate any number and kind of projects with any number and kind of files as content.</p>
<p>The templates are contributed to the wizard by the extension point <code>org.eclipse.xtext.ui.projectTemplate</code>. An implementor of <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/wizard/template/IProjectTemplateProvider.java">IProjectTemplateProvider</a> is registered for the language it provides templates to. The method of this interface returns instances of <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/wizard/template/AbstractProjectTemplate.java">AbstractProjectTemplate</a>. Each of these instances defines one template.</p>
<p>To create a subclass of <code>AbstractProjectTemplate</code> it is advisable to annotate a class with the active annotation <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/wizard/template/ProjectTemplate.java">ProjectTemplate</a>. With this annotation the name and description can be defined and will be made available to the user interface. Also the extension of <code>AbstractProjectTemplate</code> will be done for you.</p>
<p>In a project template the method <code>generateProjects(IProjectGenerator)</code> needs to be overridden. The parameter instance offers a single <code>generate</code> method that takes an instance of <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/util/ProjectFactory.java">ProjectFactory</a>. Using this class, or available subclasses, all kind of projects can be generated by the template. The following illustrates a simple example to generate a plugin project with a template:</p>
<pre><code class="language-xtend">generator.generate(new PluginProjectFactory =&gt; [
projectName = projectInfo.projectName
location = projectInfo.locationPath
projectNatures += #[JavaCore.NATURE_ID, "org.eclipse.pde.PluginNature", XtextProjectHelper.NATURE_ID]
builderIds += JavaCore.BUILDER_ID
folders += "src"
addFile('''src/Model.mydsl''', '''
Hello World!
''')
])
</code></pre>
<p>The <code>AbstractProjectTemplate</code> offers methods to create check boxes, text fields and combo boxes. These will be made available to the user in the wizard to configure the selected template. The values inserted by the user can then be used to configure the templates. In the following example a check box is used to control if a file is generated or not.</p>
<pre><code class="language-xtend">@ProjectTemplate(label="Test", icon="project_template.png", description="&lt;p&gt;&lt;b&gt;Test&lt;/b&gt;&lt;/p&gt;&lt;p&gt;This is a test project.&lt;/p&gt;")
final class TestProject {
val generateHello = check("Generate Hello", true)
override generateProjects(IProjectGenerator generator) {
if (generateHello.value) {
generator.generate(new PluginProjectFactory =&gt; [
projectName = projectInfo.projectName
location = projectInfo.locationPath
projectNatures += #[JavaCore.NATURE_ID, "org.eclipse.pde.PluginNature", XtextProjectHelper.NATURE_ID]
builderIds += JavaCore.BUILDER_ID
folders += "src"
addFile('''src/Model.mydsl''', '''
Hello World!
''')
])
}
}
}
</code></pre>
<p>For more elaborate templates it is also possible to group parameters together, enable/disable parameters, have parameter values be changed in response of the change of a different parameter and add validations to the wizard if the selected parameters are correct. This can be done by implementing the provided methods <code>updateVariables</code> and <code>validate</code>. The Xtext Statemachine example contains a more sophisticated implementation of the new project wizard.</p>
<h2 id="file-wizard">File Wizard</h2>
<p>Similar to the <a href="#projectwizard">Project Wizard</a> it is possible to generate a wizard for new dsl files with the MWE2 workflow. The wizard will be generated in the <code>.ui</code> project. If the language was generated before the <code>plugin.xml</code> will have to be manually merged with the <code>plugin.xml_gen</code>.</p>
<p>This must be explicitly specified in the MWE2 file in the <code>language</code> section as follows</p>
<pre><code class="language-mwe2">fileWizard = {
generate = true
}
</code></pre>
<p>The API for the file wizard is very similar to the one of the project wizard. The templates are defined with the same widgets/parameters but instead of generating whole projects one or many files are generated. To add new template providers there is the extension point <code>org.eclipse.xtext.ui.fileTemplate</code> to register a <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/wizard/template/IFileTemplateProvider.java">IFileTemplateProvider</a>. To create instances of <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/wizard/template/AbstractFileTemplate.java">AbstractFileTemplate</a> one should use the active annotation <a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui/src/org/eclipse/xtext/ui/wizard/template/FileTemplate.java">FileTemplate</a>.</p>
<p>An simple example template might look like this:</p>
<pre><code class="language-xtend">@FileTemplate(label="Hello World", icon="file_template.png", description="Create a hello world for MyDsl.")
final class HelloWorldFile {
val helloName = combo("Hello Name:", #["Xtext", "World", "Foo", "Bar"], "The name to say 'Hello' to")
override generateFiles(IFileGenerator generator) {
generator.generate('''«folder»/«name».mydsl''', '''
Hello «helloName»!
''')
}
}
</code></pre>
<p>The Xtext Statemachine example contains a more sophisticated implementation of the new file wizard.</p>
<h2 id="code-mining">Code Mining</h2>
<p>Code Mining shows inline annotations in the text editor that are not part of the text itself, but derived from its contents. It can be very helpful to leverage code minings for example to show inferred types, parameter names for literals and other kind of meta information.</p>
<p>Code minings come in two flavors: “header annotations” are printed in a separate line above the mined text, “inline annotations” are shown in-line. The following screenshot shows both flavors:</p>
<p><img src="images/code_mining.png" alt="" /></p>
<p>To enable code mining, the <code>org.eclipse.xtext.xtext.generator.ui.codemining.CodeMiningFragment</code> has to be integrated in the <code>language</code> section of the MWE2 file as follows:</p>
<pre><code class="language-mwe2">fragment = org.eclipse.xtext.xtext.generator.ui.codemining.CodeMiningFragment {}
</code></pre>
<p>With execution of the generator a stub class <code>&lt;LanguageName&gt;CodeMiningProvider</code> is created in the <code>.codemining</code> sub-package of the UI plugin. Furthermore the provider is registered to the <code>org.eclipse.ui.workbench.texteditor.codeMiningProviders</code> extension point in the <code>plugin.xml</code>.</p>
<p>The following class <code>MyDslCodeMiningProvider</code> shows a simple example:</p>
<pre><code class="language-java">public class MyDslCodeMiningProvider extends AbstractXtextCodeMiningProvider {
@Override
protected void createCodeMinings(IDocument document, XtextResource resource, CancelIndicator indicator,
IAcceptor&lt;ICodeMining&gt; acceptor) throws BadLocationException {
acceptor.accept(createNewLineHeaderCodeMining(1, document, "header annotation"));
acceptor.accept(createNewLineContentCodeMining(5, " inline annotation "));
}
}
</code></pre>
<p>Clients have to implement the <code>createCodeMinings()</code> method, compute text and position of meta information that should be presented in the text editor. Finally instances of <code>ICodeMining</code> are created with that information and passed to the <code>acceptor</code>.</p>
<p>The base class <code>AbstractXtextCodeMiningProvider</code> provides some factory methods for creating <code>ICodeMining</code> instances for convenience. Use <code>createNewLineHeaderCodeMining()</code> and <code>createNewLineContentCodeMining()</code> for that purpose.</p>
<p>For an implementation reference, have a look at the Xtext Domainmodel example.</p>
<h2 id="ui-testing">UI Testing</h2>
<p>Automated UI tests are crucial for the maintainability and the quality of a software product. That’s why it is strongly recommended to write not only automated unit tests for your language, but also automated UI tests for your language editor. The <code>org.eclipse.xtext.ui.testing</code> package contains some base classes that come in handy when implementing automated UI tests:</p>
<ul>
<li><a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui.testing/src/org/eclipse/xtext/ui/testing/AbstractAutoEditTest.java">AbstractAutoEditTest</a>: base class for testing the auto editing functionality</li>
<li><a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui.testing/src/org/eclipse/xtext/ui/testing/AbstractCodeMiningTest.java">AbstractCodeMiningTest</a>: base class for testing the code mining capabilities</li>
<li><a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui.testing/src/org/eclipse/xtext/ui/testing/AbstractContentAssistTest.java">AbstractContentAssistTest</a>: base class for testing the content assistant and template proposals</li>
<li><a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui.testing/src/org/eclipse/xtext/ui/testing/AbstractFoldingTest.java">AbstractFoldingTest</a>: base class for testing the folding capabilities</li>
<li><a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui.testing/src/org/eclipse/xtext/ui/testing/AbstractHighlightingTest.java">AbstractHighlightingTest</a>: base class for testing the syntactical and semantic coloring</li>
<li><a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui.testing/src/org/eclipse/xtext/ui/testing/AbstractHoverTest.java">AbstractHoverTest</a>: base class for testing the hovering functionality</li>
<li><a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui.testing/src/org/eclipse/xtext/ui/testing/AbstractHyperlinkingTest.java">AbstractHyperlinkingTest</a>: base class for testing the hyperlinking functionality</li>
<li><a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui.testing/src/org/eclipse/xtext/ui/testing/AbstractMultiQuickfixTest.java">AbstractMultiQuickfixTest</a>: base class for testing the multi quick fixes</li>
<li><a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui.testing/src/org/eclipse/xtext/ui/testing/AbstractOutlineTest.java">AbstractOutlineTest</a>: base class for testing the structure of the outline view</li>
<li><a href="https://github.com/eclipse/xtext-eclipse/blob/master/org.eclipse.xtext.ui.testing/src/org/eclipse/xtext/ui/testing/AbstractQuickfixTest.java">AbstractQuickfixTest</a>: base class for testing the quick fixes</li>
<li></li>
</ul>
<p>The Xtext example projects (<em>File → New → Example → Xtext Examples</em>) contain UI test cases that make use of these framework classes. Feel free to study the corresponding <code>org.eclipse.xtext.example.&lt;language&gt;.ui.tests</code> projects to get some inspirations on how to implement automated UI test cases for your Xtext-based language editor.</p>
<hr />
<p><strong><a href="330_web_support.html">Next Chapter: Web Editor Support</a></strong></p>
</div>
</div>
</div>
</div>
</div>
</div>
<footer class="site-footer">
<div id="extra">
<div class="inner">
<div class="container">
<div class="row">
<div class="span6">
<h3 class="footer-links-header">Quick Links</h3>
<ul class="footer-links clearfix">
<li><a href="http://www.eclipse.org/legal/privacy.php">Privacy Policy</a></li>
<li><a href="http://www.eclipse.org/legal/termsofuse.php">Terms of Use</a></li>
<li><a href="http://www.eclipse.org/legal/copyright.php">Copyright Agent</a></li>
<li><a href="http://www.eclipse.org/legal/">Legal</a></li>
</ul>
<ul class="footer-links clearfix">
<li><a href="http://www.eclipse.org">Eclipse Home</a></li>
<li><a href="http://marketplace.eclipse.org/">Market Place</a></li>
<li><a href="http://www.planeteclipse.org/">Eclipse Planet</a></li>
<li><a href="https://www.eclipse.org/forums/index.php/f/27/">Xtext Forum</a></li>
</ul>
</div>
<div class="span6">
<!-- Social Media Links -->
<h3 class="footer-links-header"">Social Media</h3>
<ul class="footer-links clearfix">
<li>
<a href="https://twitter.com/xtext"><img src="/Xtext/images/Twitter-bird-darkgray.png" class="img-responsive" style="margin-right: 5px;height: 1em;" alt="Twitter icon">@xtext on Twitter</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<a href="#" class="scrollup fadeOutRight animated" style="display: none;">ScrollUp</a>
<!-- Le javascript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="/Xtext/js/jquery-1.11.3.min.js"></script>
<script src="/Xtext/js/bootstrap.min.js"></script>
<script src="/Xtext/js/jquery.easing.1.3.js" type="text/javascript"></script>
<script src="/Xtext/js/jquery.prettyPhoto.js" type="text/javascript"></script>
<script src="/Xtext/js/prettify.js" type="text/javascript"></script>
<script src="/Xtext/js/lang-xtend.js" type="text/javascript"></script>
<script src="/Xtext/js/lang-common.js" type="text/javascript"></script>
<script src="/Xtext/js/custom.js" type="text/javascript"></script>
<!--script src="https://apis.google.com/js/platform.js" async defer></script-->
<!--script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push([ '_setAccount', 'UA-2429174-3' ]);
_gaq.push([ '_trackPageview' ]);
(function() {
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl'
: 'http://www')
+ '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script-->
<script src="/Xtext/js/coverflow.min.js" type="text/javascript"></script>
<script>
$(function() {
$('#coverflow').coverflow({
active : 1,
visibleAside: 2,
overlap : 0.5,
scale : 0.9,
angle : 20,
trigger : {
"itemfocus" : true,
"swipe" : true,
"mousewheel" : false
}
});
$('#coverflow :hidden').toggle();
$(window).resize(function() {
$('#coverflow').coverflow();
});
});
</script>
</footer>
</body>
</html>