Eclipse内からStringTemplateを使用してコードを生成する場合:
DSLのランタイムプロジェクトでジェネレータスタブを見つけます。IGeneratorインターフェースを実装するクラスが必要です。メソッド#doGeneratorは、リソースとIFileSystemAccessのインスタンスを使用して呼び出されます。リソースはEMFの概念であり、基本的にはオブジェクトの物理的な場所を抽象化したものです。getContentsを提供し、VocSpecのインスタンスのリストへのアクセスを提供します(文法スニペットが完了している場合)。これらのインスタンスは、出力を生成する文字列テンプレートに渡すことができます。出力は、IFileSystemAccess#generateFileを使用して書き込む必要があります
これをスタンドアロンプロセスとして実行する場合は、XtextFAQの手順に従う必要があります。EMFリソースをロードする方法を説明します。その後、Eclipseベースのソリューションとほぼ同じように実行できます。つまり、IGeneratorを実装し、結果をIFileSystemAccessに渡します。
簡単な例を挙げると、これは数分で開始するために実行する必要があることです。
まず、「GenerateMyDsl.mwe2」ワークフローファイルで次のコードスニペットを有効にして、ワークフローを実行する必要があります。
fragment = generator.GeneratorFragment {
generateMwe = false
generateJavaMain = true
}
ランタイムプロジェクトのパッケージに、接尾辞.generatorが付いた新しいアーティファクトがあります。つまり、「Main.java」ファイルです。
2番目のステップは、ジェネレーターを実装することです。次のスニペットは、「MyDslGenerator.xtend」クラスで使用できます。
package org.xtext.example.mydsl.generator
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.xtext.generator.IGenerator
import org.eclipse.xtext.generator.IFileSystemAccess
import org.antlr.stringtemplate.StringTemplate
import org.antlr.stringtemplate.language.DefaultTemplateLexer
import org.xtext.example.mydsl.myDsl.Model
class MyDslGenerator implements IGenerator {
override void doGenerate(Resource resource, IFileSystemAccess fsa) {
val hello = new StringTemplate("Generated with StringTemplate, $greeting.name$!", typeof(DefaultTemplateLexer))
val model = resource.contents.head as Model
hello.setAttribute("greeting", model.greetings.head)
fsa.generateFile("Sample.txt", hello.toString())
}
}
Javaに相当するものは、次のようなものになります。
package org.xtext.example.mydsl.generator;
import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.language.DefaultTemplateLexer;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.generator.IFileSystemAccess;
import org.eclipse.xtext.generator.IGenerator;
import org.xtext.example.mydsl.myDsl.Model;
public class StringTemplateGenerator implements IGenerator {
public void doGenerate(Resource input, IFileSystemAccess fsa) {
StringTemplate hello = new StringTemplate("Generated with StringTemplate, $greeting.name$!", DefaultTemplateLexer.class);
Model model = (Model) input.getContents().get(0);
hello.setAttribute("greeting", model.getGreetings().get(0));
fsa.generateFile("Sample.txt", hello.toString());
}
}
次に、入力ファイルの場所と予想される出力パスを反映するように、スタブ「Main.java」の内容を変更する必要があります。
package org.xtext.example.mydsl.generator;
import java.util.List;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.xtext.generator.IGenerator;
import org.eclipse.xtext.generator.JavaIoFileSystemAccess;
import org.eclipse.xtext.util.CancelIndicator;
import org.eclipse.xtext.validation.CheckMode;
import org.eclipse.xtext.validation.IResourceValidator;
import org.eclipse.xtext.validation.Issue;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;
public class Main {
public static void main(String[] args) {
Injector injector = new MyDslStandaloneSetupGenerated().createInjectorAndDoEMFRegistration();
Main main = injector.getInstance(Main.class);
main.runGenerator("input/Sample.mydsl");
}
@Inject
private Provider<ResourceSet> resourceSetProvider;
@Inject
private IResourceValidator validator;
@Inject
private IGenerator generator;
@Inject
private JavaIoFileSystemAccess fileAccess;
protected void runGenerator(String string) {
// load the resource
ResourceSet set = resourceSetProvider.get();
Resource resource = set.getResource(URI.createURI(string), true);
// validate the resource
List<Issue> list = validator.validate(resource, CheckMode.ALL, CancelIndicator.NullImpl);
if (!list.isEmpty()) {
for (Issue issue : list) {
System.err.println(issue);
}
return;
}
// configure and start the generator
fileAccess.setOutputPath("output/");
generator.doGenerate(resource, fileAccess);
System.out.println("Code generation finished.");
}
}
入力ファイルは、ランタイムプロジェクトの新しく作成されたフォルダ「input」にあります。ファイル'Sample.mydsl'の内容は次のとおりです。
Hello Pankesh!
これでメインクラスを実行でき、Eclipseですばやく更新した後、ランタイムプロジェクトに単一のファイル「Sample.txt」を含む新しい「output」フォルダーが見つかります。
Generated with StringTemplate, Pankesh!
ところで:Xtextのドキュメントには、 Xtendを使用してコードを生成する方法に関するチュートリアルが含まれています-Eclipseや既存のJavaユーティリティと一見統合されていないため、StringTemplateよりも優れています。
package org.xtext.example.mydsl.generator
import org.eclipse.emf.ecore.resource.Resource
import org.eclipse.xtext.generator.IFileSystemAccess
import org.eclipse.xtext.generator.IGenerator
import org.xtext.example.mydsl.myDsl.Model
class MyDslGenerator implements IGenerator {
override void doGenerate(Resource resource, IFileSystemAccess fsa) {
val model = resource.contents.head as Model
fsa.generateFile("Sample.txt", '''
Generated with Xtend, «model.greetings.head»!
''')
}
}