Xtext链接服务和派生状态

时间:2015-06-23 00:37:21

标签: eclipse xtext emf eclipse-emf-ecore ecore

我有这个语法:

Feature returns ecore::EStructuralFeature:
{Feature} name=ID ':' (fp_many?='*')? eType=[ecore::EClassifier];

和EClass:

Class returns ecore::EClass:
{EClassClass}
name=ID (interface?=':Api')?
(BEGIN
(eStructuralFeatures+=Feature)*
(eOperations+=Operation)*
END)?;

我的目标是使用类似YAML语法的文本Ecore mm的DSL,因此我需要根据其EType将Feature对象转换为EAttribute或EReference。

我试图将afterModelLinked挂钩LazyLinker,如下所示:

Queue<Feature> ftrs = Queues.newArrayDeque(features);
Feature f = null;
while ((f = ftrs.poll()) != null) {
    if (f.getEType() == null)
     continue;
    if (f.getEType() instanceof EDataType) {
    createEAttribute(eClazz, f);
    } else if (f.getEType() instanceof EClass) {
    createEReference(eClazz, f);
    }
    eClazz.getEStructuralFeatures().remove(f);
}

此代码确实将该功能转换为适当的类型,但我在验证服务中遇到错误,此处是堆栈跟踪:

org.eclipse.emf.common.util.WrappedException: java.lang.NullPointerException
at org.eclipse.xtext.linking.lazy.LazyLinkingResource.getEObject(LazyLinkingResource.java:233)
at org.eclipse.xtext.resource.persistence.StorageAwareResource.getEObject(StorageAwareResource.java:124)
at org.eclipse.xtext.linking.lazy.LazyLinkingResource.doResolveLazyCrossReference(LazyLinkingResource.java:192)
at org.eclipse.xtext.linking.lazy.LazyLinkingResource.resolveLazyCrossReference(LazyLinkingResource.java:151)
at org.eclipse.xtext.linking.lazy.LazyLinkingResource.resolveLazyCrossReferences(LazyLinkingResource.java:137)
at org.eclipse.xtext.EcoreUtil2.resolveLazyCrossReferences(EcoreUtil2.java:528)
at org.eclipse.xtext.validation.ResourceValidatorImpl.resolveProxies(ResourceValidatorImpl.java:163)
at org.eclipse.xtext.validation.ResourceValidatorImpl.validate(ResourceValidatorImpl.java:75)
at org.eclipse.xtext.ui.editor.validation.ValidationJob$1.exec(ValidationJob.java:91)
at org.eclipse.xtext.ui.editor.validation.ValidationJob$1.exec(ValidationJob.java:1)
at org.eclipse.xtext.util.concurrent.CancelableUnitOfWork.exec(CancelableUnitOfWork.java:26)
at org.eclipse.xtext.resource.OutdatedStateManager.exec(OutdatedStateManager.java:121)
at org.eclipse.xtext.ui.editor.model.XtextDocument$XtextDocumentLocker.internalReadOnly(XtextDocument.java:520)
at org.eclipse.xtext.ui.editor.model.XtextDocument$XtextDocumentLocker.readOnly(XtextDocument.java:492)
at org.eclipse.xtext.ui.editor.model.XtextDocument.readOnly(XtextDocument.java:133)
at org.eclipse.xtext.ui.editor.validation.ValidationJob.createIssues(ValidationJob.java:86)
at org.eclipse.xtext.ui.editor.validation.ValidationJob.run(ValidationJob.java:67)
at org.eclipse.core.internal.jobs.Worker.run(Worker.java:54)
Caused by: java.lang.NullPointerException
at org.eclipse.xtext.linking.impl.ImportedNamesAdapter.find(ImportedNamesAdapter.java:34)
at org.eclipse.xtext.linking.impl.DefaultLinkingService.getImportedNamesAdapter(DefaultLinkingService.java:95)
at com.eacg.dsl.faml.linker.FamlLinkingService.getImportedNamesAdapter(FamlLinkingService.java:53)
at org.eclipse.xtext.linking.impl.DefaultLinkingService.registerImportedNamesAdapter(DefaultLinkingService.java:86)
at org.eclipse.xtext.linking.impl.DefaultLinkingService.registerImportedNamesAdapter(DefaultLinkingService.java:90)
at org.eclipse.xtext.linking.impl.DefaultLinkingService.registerImportedNamesAdapter(DefaultLinkingService.java:80)
at org.eclipse.xtext.linking.impl.DefaultLinkingService.getScope(DefaultLinkingService.java:58)
at com.eacg.dsl.faml.linker.FamlLinkingService.getScope(FamlLinkingService.java:47)
at org.eclipse.xtext.linking.impl.DefaultLinkingService.getLinkedObjects(DefaultLinkingService.java:119)
at org.eclipse.xtext.linking.lazy.LazyLinkingResource.getEObject(LazyLinkingResource.java:250)
at org.eclipse.xtext.linking.lazy.LazyLinkingResource.getEObject(LazyLinkingResource.java:225)

调试时,我发现即使我在创建映射时删除了对象Feature,它仍在上下文中使用。

我的问题是:如何在不破坏我的模型的情况下安全地替换对象Feature。我也尝试过实施IDerivedStateComputer,但遇到了一些错误。

1 个答案:

答案 0 :(得分:2)

我认为这里的根本问题是EMF是一种基于图形的格式;类可以是其他类的特征,操作的参数等。通常,这个关系图可以包含循环,循环和节点。因此,任何试图就地修改内容的东西都会变得棘手,需要一个完整的图形遍历算法来确保你不会改变你尚未处理的东西所依赖的东西。

另一种方法是让模型以其原生形式加载和链接,然后将其转换为单次传递。这是xcore实现事物的方式;等效声明是:

XClass:
{XClass}
(annotations+=XAnnotation)*
((abstract?='abstract'? 'class') | interface?= 'interface') name = ID
('<' typeParameters+=XTypeParameter (',' typeParameters+=XTypeParameter)* '>')?
('extends' superTypes+=XGenericType (',' superTypes+=XGenericType)*)?
('wraps' instanceType=JvmTypeReference) ?
'{'
   (members+=XMember)*
'}'

注意所有的X,那些是本地模型类。然后,只有一个功能:

protected EClass getEClass(final XClass xClass)