Xtext et JUnit

Le projet XText de la fondation Eclipse permet de facilement mettre en place des éditeurs de texte pour les langages dédiés (DSLs). Cependant, il est rapidement assez complexe de manipuler l'API de Xtext afin de l'intégrer à une batterie de tests unitaires.

Je vais donc ici fournir un extrait de code pour faciliter la prise en main et l'utilisation, depuis une application externe (JUnit), des moteurs de validation. L'intérêt est donc de pouvoir exécuter les contrôles de Xtext sur nos données et récupérer les éventuels erreurs et/ou warning remontés :

// On parse le texte extrait de l'éditeur
Injector injector = new MyStandaloneSetup().createInjectorAndDoEMFRegistration();
MyParser parser = injector.getInstance(MyParser.class);
InputStream  input = new ByteArrayInputStream(texte.getBytes());
IParseResult result = parser.doParse(input);

// On execute la validation Xtext
Diagnostic diagnostic = Diagnostician.INSTANCE.validate(parseResult.getRootNode().getElement());

// On récupère les erreurs/warning levés
boolean success = true;
String errorMessage = "Message(s) : \n";
switch (diagnostic.getSeverity()) {
case Diagnostic.ERROR:
 success = false;
 if (diagnostic.getException() != null) {
  diagnostic.getException().printStackTrace();
  errorMessage += diagnostic.getException().getMessage();
 } else if (diagnostic.getChildren().size() > 0) {
  for (Diagnostic d : diagnostic.getChildren()) {
   if (d.getException() != null) {
    d.getException().printStackTrace();
    errorMessage += d.getException().getMessage() + "\n";
   } else {
    errorMessage += d.getMessage() + "\n";
   }
  }
 } else {
  errorMessage += diagnostic.getMessage();
 }
 break;
case Diagnostic.WARNING:
 // No warning thrown
}

A partir de ces résultats, il est donc possible de contrôler simplement, avec les assertions JUnit, les retours des validations. Ce code s'inspire du paragraphe Validating Manually de la document XText.

De la même façon, il est possible de lancer l'exécution des switch qui parsent le contenu de l'éditeur afin de le traiter spécifiquement :

// Voir le parseResult instancié plus haut
MySwitch mySwitch = new MySwitch();
mySwitch.doSwitch(parseResult.getRootNode().getElement());

Enjoy!


Fichier(s) joint(s) :

3 commentaires:

François a dit…

Ah! Enfin des posts sur Xtext !

Paul-Emmanuel Faidherbe a dit…

Héhé. Mais je me suis rendu compte que la difficulté avec Xtext réside essentiellement dans l'aspect métier... La mise en places des switch et autres n'est finalement pas si ardue. Donc pour le moment je ne sais pas trop quels points particuliers aborder sur Xtext

Anonyme a dit…

XText est un outil très intéressant. Je cherche un tutoriel sur comment analyser la grammaire (le code permettant de créer le PCODE ou du code source à partir de la grammaire créée). Surtout sur la v2.

Autant, le projet XCode me paraît vraiment excellent, autant il me paraît difficile d'accès sur la deuxième partie, c'est à dire avoir du code généré (la création de la grammaire en ell-même est assez bien décrite). Peut-être s'agit-il d'un projet récent et réservé à une audience limitée (peu de gens s'intéresse à la théorie des compilateurs et à la création de nouveaux langages).

En tout cas, nous sommes en cours d'évaluation de la solution proposée par itemis (à savoir le projet applause, encore en v1 et disponible sur GitHub).