Validation

Validation (a.k.a Static Analysis) is one of the most interesting aspects when developing a programming language. The users of your languages will be grateful if they get informative feedback as they type. In Xtext there are basically three different kinds of validation

Syntactical Validation

The syntactical correctness of any textual input is validated automatically by the parser. The error messages are generated by the underlying parser technology and cannot be customized using a general hook. Any syntax errors can be retrieved from the Resource using the common EMF API:

Cross-link Validation

Any broken cross-links can be checked generically. As cross-link resolution is done lazily (see linking), any broken links are resolved lazy as well. If you want to validate whether all links are valid, you’ll have to navigate through the model so that all proxies get resolved. This is done automatically in the editor.

Any unresolvable cross-links will be reported through:

Custom Validation

In addition to the afore mentioned kinds of validations, which are more or less done automatically, you can specify additional constraints specific for your ecore model. We leverage existing EMF API (mainly EValidator) and have put some convenience stuff on top. Basically all you need to do is to make sure that an EValidator is registered for your EPackage. The registry for EValidators ( org.eclipse.emf.ecore.EValidator.Registry.INSTANCE) can only be filled programatically, that means that there’s no equinox extension point similar to the EPackage- and ResourceFactory registries.

For Xtext we provide a generator fragment for the convenient java-based EValidator API. Just add the following fragment to your generator configuration and you’re good to go:

<fragment class="org.eclipse.xtext.generator.validation.JavaValidatorFragment"/>

The generator will provide you with two Java classes. An abstract class generated to src-gen/ which extends the library class AbstractDeclarativeValidator. This one just registers the EPackages for which this validator contains constraints. The other class is a subclass of that abstract class and is generated to the src/ folder in order to be edited by you. That’s where you put the constraints in.

The purpose of the AbstractDeclarativeValidator is to allow you to write constraints in a (the name says it) declarative way. That is instead of writing exhaustive if else constructs or extending the generated EMF switch you just have to add the @Check annotation to any method and it will be invoked automatically when validation takes place. Moreover you can state for what type the respective constraints method is, just by declaring a typed parameter. This also let’s you avoid any castings. In addition to the reflective invocation of test methods the AbstractDeclarative provides a couple of convenience assertions.

All in all this is very similar to how Junit work. Example:


  public class DomainmodelJavaValidator extends AbstractDomainmodelJavaValidator {
    
    @Check
    public void checkTypeNameStartsWithCapital(Type type) {
      if (!Character.isUpperCase(type.getName().charAt(0)))
       warning("Name should start with a capital", DomainmodelPackage.TYPE__NAME);
    }
  }