eclipse-emf / org.eclipse.emf

Eclipse Public License 2.0
10 stars 13 forks source link

Default values (EDEFAULT) for EAttributes that use EDataTypes with EType paramters (generics) is not generated #23

Closed claesrosell closed 7 months ago

claesrosell commented 7 months ago

Discussed in https://github.com/eclipse-emf/org.eclipse.emf/discussions/22

Originally posted by **claesrosell** January 18, 2024 Hi. I do not know if this is a bug or not. Hence, I started a discussion first. "default value literal"'s on EAttribute:s which uses an EDateType with EType parameters (generics) does not seem to be fully supported. To explain the problem I am using this simple meta model ``` ``` A simple EClass called ``MyClass`` with one single EAttribute ``myAttribute`` which uses the EDataType ``EMyDataType`` which in turn has a type parameter. The EAttribute is given the default value literal "1" The generated code for MyClassImpl will miss a MY_ATTRIBUTE_EDEFAULT declaration and eIsSet() and eUnset() methods of MyClassImpl switch/case statement for the EAttribute will be generated to handle "null" as the default value. ``` @Override public void eUnset(int featureID) { switch (featureID) { case MyModelPackage.MY_CLASS__MY_ATTRIBUTE: setMyAttribute((MyDataType)null); return; } super.eUnset(featureID); } ``` So if something like this is done: ``` MyClass myObject = MyModelFactory.eINSTANCE.createMyClass(); Object myValue= myObject.getMyAttribute(); ``` ``myValue`` will have the value ``null`` However, the `initializePackageContents` method of the generated MyModelPackageImpl class will be generated to support default value of the EAttribute. ``` initEAttribute(getMyClass_MyAttribute(), g1, "MyAttribute", "1", 0, 1, MyClass.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_UNSETTABLE, !IS_ID, IS_UNIQUE, !IS_DERIVED, IS_ORDERED); ``` So if I call: ``` Object defaultValue = MyModelPackage.Literals.MY_CLASS__MY_ATTRIBUTE.getDefaultValue(); ``` ... the default value will be an instance of MyDataType ( created from the string "1" via ``MyModelFactoryImpl.createEMyDataTypeFromString()`` ) I have looked into the jet templates and the genmodel and the ``.hasEDefault()`` method of GenFeatureImpl.java explicitly checks if there are type parameters defined and if so, it returns false: ``` public boolean hasEDefault() { return getEcoreFeature() instanceof EAttribute && (getEffectiveComplianceLevel().getValue() < GenJDKLevel.JDK50 || (getEcoreFeature().getEType() != null && getEcoreFeature().getEType().getETypeParameters().isEmpty() && getEcoreFeature().getEGenericType().getETypeParameter() == null && getEcoreFeature().getEType().getInstanceTypeName() == getEcoreFeature().getEType().getInstanceClassName())); } ```
merks commented 7 months ago

You're the third person with a PR on GitHub for EMF. 🥳

claesrosell commented 6 months ago

@merks, this needs more work. I do not know why I didn't find the issues that I encountered today when I tested this over the weekend, but the generated code for these new default values does not always compile. I am sorry that missed this.

I will open a new issue to explain the problem.

merks commented 6 months ago

I should have insisted that I wanted to see how that actually works for an actual concrete example of a real Java org.example.types.MyDataType class because it was kind of hard to imagine how you can create a typed value MyDataType for arbitrary T from such a generic EDataType given only a string literal. I also don't understand how serialization/deserializations works for such a datatype, and that's why the code generally assumed that's not possible. But then I figured if someone specifies a default value literal, they can shoot themselves in the foot if they so choose, or I assume they know what they are doing better than I do...