eclipse-diffmerge / org.eclipse.emf.diffmerge.core

Eclipse Public License 2.0
3 stars 7 forks source link

Default comparison doesent handle EClass::eSuperTypes references correctly #119

Open eclipse-diffmerge-bot opened 3 years ago

eclipse-diffmerge-bot commented 3 years ago

Due to the fact that the behavior of the EClass::eSuperTypes reference is not like other references it has to be treatet differently since in the current version it duplicates all the supertypes if you try to merge two ecore-models.

A specific and reproducable example together with some more detailed explanation can be found in the emf forums:

https://www.eclipse.org/forums/index.php/t/1084618/

🆔 ECLIPSE-512806 👷 simon.bbbbbbb 📅 2017-02-28 🔎 0.7.0

eclipse-diffmerge-bot commented 3 years ago

olivier.constant commented on 2017-02-28

The specific cases I have found in Ecore (Neon release) are:

  1. ETypedElement.eType : EClassifier [0..1] vs ETypedElement.eGenericType : EGenericType [0..1, containment]

In ETypedElementImpl::setEType(...), a call is always made to setEGenericType(...). If the eType is set to null then so is the eGenericType, otherwise a new eGenericType is created whose eClassifier is set to the eType. ETypedElementImpl::setEGenericType(...), on the other hand, has nothing specific.

  1. EClass.eSuperTypes : EClass [] vs EClass.eGenericSuperTypes : EGenericType [, containment]

In EClassImpl::getESuperTypes(), a DelegatingEcoreEList is used that refers most of the time to getEGenericSuperTypes() including for element addition, removal, and position. Local methods wrap/unwrap handle the eType/eGenericType correspondence by [creating a new eGenericType as above] / [making a call to EGenericTypeImpl::basicGetERawType() and substituting EcorePackage.Literals.EOBJECT to the result if not an EClass].

As a side note, we have:

  • EGenericType.eClassifier : EClassifier [0..1]
  • EGenericType.eRawType : EClassifier [1, derived] In EGenericTypeImpl::setEClassifier(...), a call to setERawType(...) is made if feature eTypeParameter is null, which is the case if the eGenericType has been created as in 1. and 2.

EClassImpl::getEGenericSuperTypes(), on the other hand, has nothing specific except that it puts a ESuperAdapter in the game and it hasShadow(), so that it also sends notifications about eSuperTypes when it is changed. These additional notifications are based on an unwrap(...) method that has the same behavior as the one above.

  1. EOperation.eExceptions : EClassifier [] vs EOperation.eGenericExceptions : EGenericType [, containment]

At first sight it looks exactly like case 2., except that there is nothing like the ESuperAdapter.