带引用的Xtext序列化模型

时间:2014-11-29 15:16:11

标签: serialization xtext scoping

我很难搞清楚,我做错了什么。一个简单的例子,我正在尝试做的事情:

DSL:

Model: elements += ModelElement*;
ModelElement: Greeting | Person;
Person: 'person' name = ID;
Greeting: 'hello' person = [Person];

序列化模型的代码:

val factory = MyDslFactory.eINSTANCE

val model = factory.createModel

val bob = factory.createPerson
bob.name = "Bob"

val greetBob = factory.createGreeting
greetBob.person = bob

model.elements += bob
model.elements += greetBob

val injector = Guice.createInjector(new MyDslRuntimeModule)
val serializer = injector.getInstance(ISerializer)
// Error happens here:
val result = serializer.serialize(model)

现在,当此代码运行时,ImportedNamespaceAwareLocalScopeProvider启动,并抛出以下异常:

java.lang.NullPointerException
    at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.getResourceScope(ImportedNamespaceAwareLocalScopeProvider.java:95)
    at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.getScope(ImportedNamespaceAwareLocalScopeProvider.java:89)
    at org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider.getScope(ImportedNamespaceAwareLocalScopeProvider.java:87)
    at org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider.delegateGetScope(AbstractDeclarativeScopeProvider.java:72)
    at org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider.getScope(AbstractDeclarativeScopeProvider.java:102)
    at org.eclipse.xtext.serializer.tokens.CrossReferenceSerializer.serializeCrossRef(CrossReferenceSerializer.java:84)
    at org.eclipse.xtext.serializer.acceptor.SequenceFeeder.getToken(SequenceFeeder.java:454)
    at org.eclipse.xtext.serializer.acceptor.SequenceFeeder.accept(SequenceFeeder.java:214)
    at test.serializer.MyDslSemanticSequencer.sequence_Greeting(MyDslSemanticSequencer.java:65)
    at test.serializer.MyDslSemanticSequencer.createSequence(MyDslSemanticSequencer.java:33)
    at org.eclipse.xtext.serializer.acceptor.SequenceFeeder.acceptEObjectRuleCall(SequenceFeeder.java:299)
    at org.eclipse.xtext.serializer.acceptor.SequenceFeeder.acceptRuleCall(SequenceFeeder.java:325)
    at org.eclipse.xtext.serializer.acceptor.SequenceFeeder.accept(SequenceFeeder.java:239)
    at org.eclipse.xtext.serializer.sequencer.BacktrackingSemanticSequencer.accept(BacktrackingSemanticSequencer.java:400)
    at org.eclipse.xtext.serializer.sequencer.BacktrackingSemanticSequencer.createSequence(BacktrackingSemanticSequencer.java:449)
    at test.serializer.MyDslSemanticSequencer.sequence_Model(MyDslSemanticSequencer.java:75)
    at test.serializer.MyDslSemanticSequencer.createSequence(MyDslSemanticSequencer.java:39)
    at org.eclipse.xtext.serializer.impl.Serializer.serialize(Serializer.java:85)
    at org.eclipse.xtext.serializer.impl.Serializer.serialize(Serializer.java:108)
    at org.eclipse.xtext.serializer.impl.Serializer.serialize(Serializer.java:122)
    at org.eclipse.xtext.serializer.impl.Serializer.serialize(Serializer.java:51)
    at test.generator.MyDslGenerator.doGenerate(MyDslGenerator.java:42)
    at org.eclipse.xtext.builder.BuilderParticipant.handleChangedContents(BuilderParticipant.java:515)
    at org.eclipse.xtext.builder.BuilderParticipant.handleChangedContents(BuilderParticipant.java:505)
    at org.eclipse.xtext.builder.BuilderParticipant.doGenerate(BuilderParticipant.java:490)
    at org.eclipse.xtext.builder.BuilderParticipant.doBuild(BuilderParticipant.java:259)
    at org.eclipse.xtext.builder.BuilderParticipant.build(BuilderParticipant.java:217)
    at org.eclipse.xtext.builder.impl.RegistryBuilderParticipant$DeferredBuilderParticipant.build(RegistryBuilderParticipant.java:158)
    at org.eclipse.xtext.builder.impl.RegistryBuilderParticipant.build(RegistryBuilderParticipant.java:68)
    at org.eclipse.xtext.builder.impl.XtextBuilder.doBuild(XtextBuilder.java:189)
    at org.eclipse.xtext.builder.impl.XtextBuilder.incrementalBuild(XtextBuilder.java:167)
    at org.eclipse.xtext.builder.impl.XtextBuilder.build(XtextBuilder.java:95)
    at org.eclipse.core.internal.events.BuildManager$2.run(BuildManager.java:734)
    at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
    at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:206)
    at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:246)
    at org.eclipse.core.internal.events.BuildManager$1.run(BuildManager.java:299)
    at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
    at org.eclipse.core.internal.events.BuildManager.basicBuild(BuildManager.java:302)
    at org.eclipse.core.internal.events.BuildManager.basicBuildLoop(BuildManager.java:358)
    at org.eclipse.core.internal.events.BuildManager.build(BuildManager.java:381)
    at org.eclipse.core.internal.events.AutoBuildJob.doBuild(AutoBuildJob.java:143)
    at org.eclipse.core.internal.events.AutoBuildJob.run(AutoBuildJob.java:241)
    at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)

意思,(我认为),它无法解析范围,唯一可能发生这种情况的地方是Greeting规则的person引用。

现在,如果我手动编写范围提供程序,则引用会在没有问题的情况下得到解决,并且序列化很好。

class MyDslScopeProvider extends AbstractDeclarativeScopeProvider {
    //A dummy scope provider
    def scope_Greeting_person(Greeting g, EReference ref) {
        val model = g.eContainer as Model
        return Scopes.scopeFor(model.elements.filter(Person))
    }
}

所以我的问题是:

在一个明显更复杂的语法中,我是否需要编写所有单独的范围提供程序,以使序列化工作?或者是否有一些我缺少的配置选项?

2 个答案:

答案 0 :(得分:0)

如何将模型添加到虚拟资源

va rs = injector.getInstance(ResourceSet)
val resource = rs.createResource(URI.createURI("dummy/test.mydsl"))
resource.contents += model

答案 1 :(得分:0)

我无法直接回复@Balazs Edes,但是@Christian Dietrich给出的解决方案是正确的;这是有关实现方法的示例:

注入资源集:

@Inject Provider<XtextResourceSet> rsProvider

然后创建资源:

val rs = rsProvider.get

val resource = rs.createResource(URI.createURI("dummy/test.dmodel"))

在随后的步骤中,在运行serialize()之前,将模型添加到资源中:

resource.getContents.add(model)