我很难搞清楚,我做错了什么。一个简单的例子,我正在尝试做的事情:
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))
}
}
所以我的问题是:
在一个明显更复杂的语法中,我是否需要编写所有单独的范围提供程序,以使序列化工作?或者是否有一些我缺少的配置选项?
答案 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)