Xtext Tip: How to change the default delimiter of your FQNs
In a previous tip I showed how to add FQN support to your Xtext DSL. In this tip, we are going to customize our FQN to have a different separator. The full code for this example can be found here.
The basic block language
I am using the block language of the previous tip, but this time we are using the characters ->
as separator
block Block1 {
field field1
field field2
block SubBlock {
field field2
}
alias field3 aliases field2
}
block Block2 {
alias field1 aliases Block1->SubBlock->field2 // this is an FQN with a -> as separator
}
Customize the FQN separator
First we change the grammar. The new grammar looks 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*;
Block:
'block' name=ID '{' (members+=Member)* '}';
Member:
Block | Field | Alias;
Field:
'field' name=ID;
Alias:
'alias' name=ID 'aliases' alias=[Member|MemberFQN];
MemberFQN: // This rule describes the new form of the FQN
ID ("->" ID)*;
The next step is to customize the delimiter itself. This modification is so common that it is enough to override one method to make it happen. First, we extend the default implementation IQualifiedNameConverter
and override the method getDelimiter
:
package com.idiomaticsoft.dsl.block.scoping;
import org.eclipse.xtext.naming.IQualifiedNameConverter.DefaultImpl;
public class BlockQualifiedNameConververImpl extends DefaultImpl {
@Override
public String getDelimiter() {
return "->";
}
}
Second, we create configure Xtext to use this class instead of the default one. This is done in the RuntimeModule
:
package com.idiomaticsoft.dsl.block;
import org.eclipse.xtext.naming.IQualifiedNameConverter;
import com.google.inject.Binder;
import com.idiomaticsoft.dsl.block.scoping.BlockQualifiedNameConververImpl;
/**
* Use this class to register components to be used at runtime / without the
* Equinox extension registry.
*/
public class BlockRuntimeModule extends AbstractBlockRuntimeModule {
@Override
public void configure(Binder binder) {
binder.bind(IQualifiedNameConverter.class).to(BlockQualifiedNameConververImpl.class);
super.configure(binder);
}
}
Once we have this, we can enjoy our new delimiter.