Community
Participate
Working Groups
The method 'ensureModelLinked(...)' in 'Linker' clears all references of an EObject regardless the fact that those reference represent eOpposite of others. This way reference of already linked EObjects may be cleared again, since those eOpposites are usually not mentioned in the grammar. Instead of: protected void ensureModelLinked(EObject model, final IDiagnosticProducer producer) { boolean clearAllReferencesRequired = isClearAllReferencesRequired(model.eResource()); TreeIterator<EObject> iterator = getAllLinkableContents(model); while(iterator.hasNext()) { EObject next = iterator.next(); if (clearAllReferencesRequired) { clearReferences(next); } ensureLinked(next, producer); } } we suggest: protected void ensureModelLinked(EObject model, final IDiagnosticProducer producer) { boolean clearAllReferencesRequired = isClearAllReferencesRequired(model.eResource()); TreeIterator<EObject> iterator = getAllLinkableContents(model); // first clear all (possibly invalid) references if (clearAllReferencesRequired) { while (iterator.hasNext()) { clearReferences(iterator.next()); } } // re-link iterator = getAllLinkableContents(model); while (iterator.hasNext()) { ensureLinked(iterator.next(), producer); } }
That would mean iterate over the tree twice for everyone although eOpposites are rarely used with Xtext (as it is problematic anyway). Can't you just subclass and override ensureModelLinked for your specific language?
Of course we could do that, right now we've overriden 'isClearAllReferencesRequired(...)' like you did for the Xtext language. However, in order to improve this situation in general, what do you think about adding a further check in 'AbstractCleaningLinker#cleareReference(EObject, EReference)' like '(ref.getEOpposite == null || !<<isAssignedInGrammar>>(ref.getEOpposite))' <<isAssignedInGrammar>> denotes a function that checks the assignment of the given EReference in the current grammar. Btw. you can discuss this with Miro as some of his main artifacts are affected by this change ;-)
Reducing the severity as subclassing the linking solves your problem. I don't like adding specific code to make bi-directional references work a "bit better", as there seem to be other issues anyway. At least when they go across two resources. Also see https://bugs.eclipse.org/bugs/show_bug.cgi?id=282486 What is the reason you are having bi-directional references? Do you reuse an existing ecore model?