Xtext
provides various mechanism for validating the models. It as well provides some
default implementation for recurring issues. One such implementation is NamesAreUniqueValidator, which validates the model names for uniqueness
in the given scope. One can use this default validation by configuring the DSL
workflow (*.mwe2) as shown below.
// Xtend-based API for validation
fragment = validation.ValidatorFragment auto-inject {
composedCheck = "org.eclipse.xtext.validation.ImportUriValidator"
composedCheck = "org.eclipse.xtext.validation.NamesAreUniqueValidator"
}
The
above validator works great within any given scope. But the validator by
default considers the super type as a context during validation. In the below
example, Type is a super class of DataType, Entity, Enumeration
grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.common.Terminals
generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"
Domainmodel:
(elements+=Type)*;
Type:
DataType |
Entity | Enumeration;
DataType:
'datatype' name=ID;
Entity:
'entity' name=ID ('extends' superType=[Entity])? '{'
(features+=Feature)*
'}';
Enumeration:
'enum' name=ID '{'
literals+=Literal* '}';
Literal:
'literal' name=ID;
Feature:
(many?='many')? name=ID ':' type=[Type];
Which
means, we will not be able to create a Type with same name. Precisely, I cannot
have a same name for Enumeration and Entity. The editor will be marked with red
ink as shown below.
The above behavior is perfectly normal, but this can be changed to check Entity, Enumeration and DataType separately within a scope. NamesAreUniqueValidator uses a helper NamesAreUniqueValidationHelper, which indeed does this classification of types. By default the above helper returns a base class as a type for context. So using XText binding mechanism, one can bind the custom helper
1. Custom Helper Implementation
package org.xtext.example.mydsl.validation;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.xtext.validation.NamesAreUniqueValidationHelper;
import org.xtext.example.mydsl.myDsl.MyDslPackage;
public class CustomNamesAreUniqueValidationHelper extends NamesAreUniqueValidationHelper {
@Override
protected EClass
getAssociatedClusterType(EClass eClass) {
if (MyDslPackage.Literals.TYPE.isSuperTypeOf(eClass)) {
// you can check for
entity, enumeration ,separately as well
return eClass;
}
return super.getAssociatedClusterType(eClass);
}
}
2. Binding in RuntimeModule
Now bind the new Custom helper in your *RuntimeModule.java a
shown below
public Class<? extends INamesAreUniqueValidationHelper>
bindINamesAreUniqueValidationHelper(){
return CustomNamesAreUniqueValidationHelper.class;
}
No comments:
Post a Comment