S-JIS[2013-08-18] 変更履歴

Xtextバリデーション

Xtextのバリデーション(精査)のメモ。


概要

xtextファイルに書いた文法以外のバリデーション(入力値が正しいかどうかを精査する判定ロジック)を実装することが出来る。

xtextファイルをビルドすると、Validatorクラスの空実装が作られる。
例えばDMDL.xtextの場合、DMDLValidator.xtendというファイルが作られる。(Xtext 2.4.2)
これはXtendという(Javaに似た)言語であり、ここにアウトラインページのカスタマイズを実装していく。


Javaソースへの変換

Xtext 2.4.2では、ソース整形クラスとして生成されるファイルはXtend用である。
個人的には新しい言語を覚えるよりJavaの方が分かり易いので、Javaで実装したい。

XtendはJavaに似ているので、Javaに変換するのも難しくない。

元のxtendファイルは、ファイル自体は削除せずに、中身を空にしておく。
中身が残っていると同じクラスがJavaとXtendの両方で定義されることになり、コンパイルエラーになる。
xtendファイル自体を消してしまうと、次にxtextファイルをビルドしたときにまた生成されてしまうので、ファイル自体は残しておく必要がある。

AbstractDMDLValidatorというクラスも生成されているが、こちらは修正する必要は無い。

DMDLValidator.java(DMDLの例):

package jp.hishidama.xtext.dmdl_editor.validation;
import org.eclipse.xtext.validation.Check;
public class DMDLValidator extends AbstractDMDLValidator {
}

警告を出す例

DMDLの場合、データモデル名は英小文字と数字とアンダースコアだけ使用できる(つまりsnake_caseだ)が、
アンダースコアで区切られた各部分は数字で始まるのは非推奨となっている。

xtextファイルの文法上はsnake_caseのみ満たすよう定義したので、非推奨のチェックをValidatorで行う。

DMDL.xtext:

ModelDefinition:
	〜
	name = Name
	〜
	';';

Name:
	NAME_TOKEN | 'projective' | 'joined' | 'summarized';

terminal NAME_TOKEN:
	('a'..'z') ('a'..'z' | '0'..'9')* ('_' ('a'..'z' | '0'..'9')+)*;

DMDLValidator.java:

import jp.hishidama.xtext.dmdl_editor.dmdl.DmdlPackage;
import jp.hishidama.xtext.dmdl_editor.dmdl.ModelDefinition;

import org.eclipse.emf.ecore.EStructuralFeature;
public class DMDLValidator extends AbstractDMDLValidator {

	// エラーコード
	public static final String INVALID_NAME = "invalidName";
	@Check
	public void checkModelName(ModelDefinition model) {
		String name = model.getName();

		String[] ss = name.split("_");
		for (String s : ss) {
			char c = s.charAt(0);
			if ('0' <= c && c <= '9') {
				String message = "アンダースコアで区切られた各部分は英字から始めることが推奨されています。";
				EStructuralFeature feature = DmdlPackage.Literals.MODEL_DEFINITION__NAME;
				String code = INVALID_NAME;
				warning(message,	//エラーメッセージ
					feature,	//エラーのあった場所
					code,	//エラーコード
					s	//問題のあったデータ
				);
				return;
			}
		}
	}
}

チェックを行うメソッドのメソッド名は何でもよい。@Checkアノテーションを付け、引数にルールクラスを指定する。

警告を出すときはwarning()メソッドを呼び出す。
場所を示すオブジェクトがDmdlPackage.Literalsというクラスに生成されているので、それを使う。
エラーコードと問題のあったデータ(issueData)を渡すようになっているが、何に使われるかは不明(爆)


Xtext目次へ戻る / Eclipseへ戻る / 技術メモへ戻る
メールの送信先:ひしだま