如果您想在 Eclipse 中使用 StringTemplate 生成代码:
在 DSL 的运行时项目中找到生成器存根。应该有一个实现 IGenerator 接口的类。将使用资源和 IFileSystemAccess 实例调用方法#doGenerator。资源是一个 EMF 概念——基本上是对对象物理位置的抽象。它提供 getContents ,这反过来将提供对 VocSpec 实例列表的访问(如果语法片段完整)。这些实例可以传递给将产生输出的字符串模板事物。输出应通过 IFileSystemAccess#generateFile 写入
如果您想将其作为一个独立的过程来执行,您应该按照Xtext FAQ中的步骤进行操作。他们解释了如何加载 EMF 资源。之后,您可以执行与基于 Eclipse 的解决方案几乎相同的操作。也就是说,实现 IGenerator 并将结果传递给 IFileSystemAccess。
给你一个简短的例子,这是在几分钟内开始应该做的事情:
首先,您应该在“GenerateMyDsl.mwe2”工作流文件中启用以下代码片段并运行工作流。
fragment = generator.GeneratorFragment {
generateMwe = false
generateJavaMain = true
}
您将在运行时项目的包中找到一个带有后缀 .generator 的新工件。即“Main.java”文件。
第二步是实现生成器。以下片段可用于“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”:
Generated with StringTemplate, Pankesh!
顺便说一句:Xtext 文档包含一个关于如何使用 Xtend 生成代码的教程——它比 StringTemplate 好,因为它与 Eclipse 和现有的 Java 实用程序无缝集成:
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»!
''')
}
}