Xtext Tip: Adding importedNamespace support
If you look at Xtext’s documentation here, there is a mention of the possibility of adding import name space support to your DSLs. This allows your DSL to have Java like imports. For example, in our block language, it should be possible to import the name space from another Block and then use in our alias. We can for example define Block3 in file Block3.block
block Block3 {
field myField1
field myField2
}
And then use it in the file Block1.block
as follows:
block Block1 {
import Block3.*
alias myAlias1 aliases myField1
alias myAlias2 aliases myField2
}
block Block2 {
import Block3.myField2
alias myAlias2 aliases myField2
}
The block language with import name space support
The first step is to modify the MWE file to enable the ImportNameSpaceScopeProvider
, this is done as follows:
module com.idiomaticsoft.dsl.block.GenerateBlock
import org.eclipse.xtext.xtext.generator.*
import org.eclipse.xtext.xtext.generator.model.project.*
var rootPath = ".."
Workflow {
component = XtextGenerator {
configuration = {
project = StandardProjectConfig {
baseName = "com.idiomaticsoft.dsl.block"
rootPath = rootPath
runtimeTest = {
enabled = true
}
eclipsePlugin = {
enabled = true
}
eclipsePluginTest = {
enabled = true
}
createEclipseMetaData = true
}
code = {
encoding = "UTF-8"
lineDelimiter = "\n"
fileHeader = "/*\n * generated by Xtext \${version}\n */"
preferXtendStubs = false
}
}
language = StandardLanguage {
name = "com.idiomaticsoft.dsl.block.Block"
fileExtensions = "block"
serializer = {
generateStub = false
}
validator = {
composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"// Generates checks for @Deprecated grammar annotations, an IssueProvider and a corresponding PropertyPage
generateDeprecationValidation = true
}
generator = {
generateXtendStub = true
}
scopeProvider = scoping.ImportNamespacesScopingFragment2 {
generateXtendStub = false
}
junitSupport = {
junitVersion = "5"
}
}
}
}
Once we have that, we need to modify the grammar. A new grammar would look like this:
grammar com.idiomaticsoft.dsl.block.Block with org.eclipse.xtext.common.Terminals
generate block "http://www.idiomaticsoft.com/dsl/block/Block"
Model:
blocks+=Block*;
Import:
'import' importedNamespace=ImportFQN;
Block:
'block' name=ID '{'
(imports+=Import)*
(members+=Member)*
'}';
Member:
Block | Field | Alias;
Field:
'field' name=ID;
Alias:
'alias' name=ID 'aliases' alias=[Member|MemberFQN];
MemberFQN:
ID ("." ID)*;
ImportFQN:
ID ("." ID)* ('.' (ID | '*'));
This grammar includes a new Import
rule that has importedNamespace
attribute. This attribute is one of those Xtext defaults, and to make the infrastructure work, you need to name your attribute like that. You can see that the new grammar supports both importing an FQN and a wildcard, without much more effor from the user.
Things to consider
The default for this feature are the following:
- If you want to have several
importedNamespace
, then you need to use severalImport
rules. You cannot have a rule likeimportedNamespace+=ImportFQN
. The default implementation expects this attribute to be a string. - The imports of the rules are valid for all elements in the container and its children.
The full code for this example can be found here.