This is a blog post on Inter-Language-Cross-References in Xtext. Let us asume we have a DSL that contains Definitions. Now we want to create another DSL that references (uses) the Definitions defined in the the first DSL.
So let us start with the first DSL: We create a new Xtext Project
And here is the (for demonstration purpose oversimplyfied) Grammar
grammar org.xtext.example.definitions.Definitions with org.eclipse.xtext.common.Terminals
generate definitions "http://www.xtext.org/example/definitions/Definitions"
Model:
definitions+=Definition*;
Definition:
'define' name=ID;
We run GenerateDefinitions.mwe2 to generate the language. This is all for the first DSL.
Now let us create a project for the second DSL.
To be able to reference the first DSL from the second we add a bundle dependency to the Manifest of the second
Here the resulting manifest
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: org.xtext.example.usages
Bundle-Vendor: My Company
Bundle-Version: 1.0.0.qualifier
Bundle-SymbolicName: org.xtext.example.usages; singleton:=true
Bundle-ActivationPolicy: lazy
Require-Bundle: org.eclipse.xtext;visibility:=reexport,
org.eclipse.xtext.xbase;resolution:=optional;visibility:=reexport,
org.eclipse.xtext.generator;resolution:=optional,
org.apache.commons.logging;bundle-version="1.0.4";resolution:=optional,
org.eclipse.emf.codegen.ecore;resolution:=optional,
org.eclipse.emf.mwe.utils;resolution:=optional,
org.eclipse.emf.mwe2.launch;resolution:=optional,
org.xtext.example.definitions;bundle-version="1.0.0"
Import-Package: org.apache.log4j
Bundle-RequiredExecutionEnvironment: J2SE-1.5
Now we can create the Grammar from the Usage DSL
grammar org.xtext.example.usages.Usages with org.eclipse.xtext.common.Terminals
generate usages "http://www.xtext.org/example/usages/Usages"
import "http://www.xtext.org/example/definitions/Definitions" as def
Model:
usages+=Usage*;
Usage:
'use' definition=[def::Definition];
With "http://www.xtext.org/example/definitions/Definitions"
as def we import the metamodel of our Define DSL to our Usage DSL.
Thus the Type Definition is available and can be used to define the cross reference definition=[def::Definition]
To get the thing running we have to do some adjustments to the workflow of the Usages language.
module org.xtext.example.usages.GenerateUsages
import org.eclipse.emf.mwe.utils.*
import org.eclipse.xtext.generator.*
import org.eclipse.xtext.ui.generator.*
var grammarURI = "classpath:/org/xtext/example/usages/Usages.xtext"
var file.extensions = "use"
var projectName = "org.xtext.example.usages"
var runtimeProject = "../${projectName}"
Workflow {
bean = StandaloneSetup {
scanClassPath = true
platformUri = "${runtimeProject}/..";
registerGeneratedEPackage = "org.xtext.example.definitions.definitions.DefinitionsPackage"
registerGenModelFile = "platform:/resource/org.xtext.example.definitions/src-gen/org/xtext/example/definitions/Definitions.genmodel"
}
...
}
we generate our Usage DSL GenerateUsages.mwe2
finally we start a new runtime eclipse and give it a try
Update Xtext 2.9.2+:
Here is how the workflow looks like with the new Xtext 2.9.x generator
module org.xtext.example.usages.GenerateUsages
import org.eclipse.xtext.xtext.generator.*
import org.eclipse.xtext.xtext.generator.model.project.*
var rootPath = ".."
Workflow {
component = XtextGenerator {
configuration = {
project = StandardProjectConfig {
baseName = "org.xtext.example.usages"
rootPath = rootPath
runtimeTest = {
enabled = true
}
eclipsePlugin = {
enabled = true
}
eclipsePluginTest = {
enabled = true
}
createEclipseMetaData = true
}
code = {
encoding = "UTF-8"
fileHeader = "/*\n * generated by Xtext \${version}\n */"
}
}
language = StandardLanguage {
name = "org.xtext.example.usages.Usages"
referencedResource = "platform:/resource/org.xtext.example.definitions/model/generated/Definitions.genmodel"
fileExtensions = "use"
serializer = {
generateStub = false
}
validator = {
}
}
}
}