diff --git a/src/lib/eolian_cxx/grammar/klass_def.hpp b/src/lib/eolian_cxx/grammar/klass_def.hpp index 3356a6ff77..d6969315e7 100644 --- a/src/lib/eolian_cxx/grammar/klass_def.hpp +++ b/src/lib/eolian_cxx/grammar/klass_def.hpp @@ -778,16 +778,35 @@ enum class member_scope struct function_def { - klass_name klass; // Klass information for function_def as method - type_def return_type; + // Klass information for function_def as method + klass_name klass; + // Eolian name of the function std::string name; + + // Actual return type as expected in the C version of this function. + // For property getters, this could be the type of the single + // value it holds + type_def return_type; + // Parameters of this function as the C implementation of it std::vector parameters; + + // Original return type as declared in the Eo. + type_def explicit_return_type; + // Original Eolian keys of this function. Used only for properties + std::vector keys; + // Original Eolian values of this function. Used only for properties + std::vector values; + + // Name of this function in the C api std::string c_name; std::string filename; - std::vector namespaces; // Namespaces for top-level function pointers + // Namespaces for top-level function pointers + std::vector namespaces; + documentation_def documentation; documentation_def return_documentation; documentation_def property_documentation; + function_type type; member_scope scope; bool is_beta; @@ -801,6 +820,8 @@ struct function_def && lhs.return_type == rhs.return_type && lhs.name == rhs.name && lhs.parameters == rhs.parameters + && lhs.keys == rhs.keys + && lhs.values == rhs.values && lhs.c_name == rhs.c_name && lhs.filename == rhs.filename && lhs.namespaces == rhs.namespaces @@ -818,46 +839,25 @@ struct function_def return !(lhs == rhs); } function_def() = default; - function_def(klass_name _klass, - type_def _return_type, std::string const& _name, - std::vector const& _parameters, - std::string const& _c_name, - std::string _filename, - std::vector const& _namespaces, - documentation_def _documentation, - documentation_def _return_documentation, - documentation_def _property_documentation, - function_type _type, - member_scope _scope, - bool _is_beta = false, - bool _is_protected = false, - bool _is_static = false, - Eolian_Unit const* unit = nullptr) - : klass(_klass), return_type(_return_type), name(_name), - parameters(_parameters), c_name(_c_name), filename(_filename), - namespaces(_namespaces), - documentation(_documentation), - return_documentation(_return_documentation), - property_documentation(_property_documentation), - type(_type), - scope(_scope), - is_beta(_is_beta), is_protected(_is_protected), - is_static(_is_static), - unit(unit) {} function_def( ::Eolian_Function const* function, Eolian_Function_Type type, Eolian_Typedecl const* tp, Eolian_Unit const* unit) - : return_type(void_), unit(unit) + : return_type(void_), explicit_return_type(void_), unit(unit) { - Eolian_Type const* r_type = ::eolian_function_return_type_get(function, type); - name = ::eolian_function_name_get(function); - return_documentation = eolian_function_return_documentation_get(function, type); - scope = static_cast(eolian_function_scope_get(function, type)); - if(r_type) - return_type.set(r_type - , unit - , eolian_function_return_c_type_get(function, type) - , eolian_function_return_is_move(function, type) - , eolian_function_return_is_by_ref(function, type)); + Eolian_Type const* r_type = ::eolian_function_return_type_get(function, type); + name = ::eolian_function_name_get(function); + return_documentation = eolian_function_return_documentation_get(function, type); + scope = static_cast(eolian_function_scope_get(function, type)); + + if(r_type) + { + return_type.set(r_type + , unit + , eolian_function_return_c_type_get(function, type) + , eolian_function_return_is_move(function, type) + , eolian_function_return_is_by_ref(function, type)); + explicit_return_type = return_type; + } + if(type == EOLIAN_METHOD || type == EOLIAN_FUNCTION_POINTER) { for(efl::eina::iterator param_iterator ( ::eolian_function_parameters_get(function)) @@ -876,9 +876,10 @@ struct function_def ( ::eolian_property_keys_get(function, type)) , param_last; param_iterator != param_last; ++param_iterator) { - parameters.push_back({&*param_iterator, unit}); + parameter_def param = {&*param_iterator, unit}; + parameters.push_back(param); + keys.push_back(param); } - std::vector values; for(efl::eina::iterator param_iterator ( ::eolian_property_values_get(function, type)) , param_last; param_iterator != param_last; ++param_iterator) diff --git a/src/tests/eolian_cxx/eolian_cxx_test_binding.cc b/src/tests/eolian_cxx/eolian_cxx_test_binding.cc index 498852f28b..c6e0381551 100644 --- a/src/tests/eolian_cxx/eolian_cxx_test_binding.cc +++ b/src/tests/eolian_cxx/eolian_cxx_test_binding.cc @@ -232,12 +232,16 @@ EFL_START_TEST(eolian_cxx_test_properties) klass_def cls = init_test_data("property_holder.eo", "Property_Holder", eolian_state); auto props = cls.properties; - ck_assert_int_eq(4, cls.properties.size()); + ck_assert_int_eq(8, cls.properties.size()); ck_assert("prop_simple" == props[0].name); ck_assert("getter_only" == props[1].name); ck_assert("setter_only" == props[2].name); ck_assert("prop_with_key" == props[3].name); + ck_assert("multi_value_prop" == props[4].name); + ck_assert("setter_with_return" == props[5].name); + ck_assert("getter_with_return" == props[6].name); + ck_assert("value_override" == props[7].name); auto property = props[0]; ck_assert(property.getter.is_engaged()); @@ -249,17 +253,136 @@ EFL_START_TEST(eolian_cxx_test_properties) }); ck_assert(*property.getter == *function); + ck_assert_int_eq(0, property.getter->keys.size()); + ck_assert_int_eq(1, property.getter->values.size()); + ck_assert_int_eq(0, property.setter->keys.size()); + ck_assert_int_eq(1, property.setter->values.size()); + property = props[1]; ck_assert(property.getter.is_engaged()); ck_assert(!property.setter.is_engaged()); + ck_assert_int_eq(0, property.getter->keys.size()); + ck_assert_int_eq(1, property.getter->values.size()); property = props[2]; ck_assert(!property.getter.is_engaged()); ck_assert(property.setter.is_engaged()); + ck_assert_int_eq(0, property.setter->keys.size()); + ck_assert_int_eq(1, property.setter->values.size()); property = props[3]; ck_assert(property.getter.is_engaged()); ck_assert(property.setter.is_engaged()); + ck_assert_int_eq(1, property.getter->keys.size()); + ck_assert_int_eq(1, property.getter->values.size()); + + property = props[4]; + ck_assert(property.getter.is_engaged()); + ck_assert(property.setter.is_engaged()); + ck_assert_int_eq(0, property.getter->keys.size()); + ck_assert_int_eq(2, property.getter->values.size()); + ck_assert_int_eq(0, property.setter->keys.size()); + ck_assert_int_eq(2, property.setter->values.size()); + + property = props[5]; + ck_assert(property.getter.is_engaged()); + ck_assert(property.setter.is_engaged()); + ck_assert_int_eq(0, property.getter->keys.size()); + ck_assert_int_eq(1, property.getter->values.size()); + ck_assert_int_eq(0, property.setter->keys.size()); + ck_assert_int_eq(1, property.setter->values.size()); + + property = props[6]; + ck_assert(property.getter.is_engaged()); + ck_assert(property.setter.is_engaged()); + ck_assert_int_eq(0, property.getter->keys.size()); + ck_assert_int_eq(1, property.getter->values.size()); + ck_assert_int_eq(0, property.setter->keys.size()); + ck_assert_int_eq(1, property.setter->values.size()); + + property = props[7]; + ck_assert(property.getter.is_engaged()); + ck_assert(property.setter.is_engaged()); + ck_assert_int_eq(0, property.getter->keys.size()); + ck_assert_int_eq(1, property.getter->values.size()); + ck_assert_int_eq(0, property.setter->keys.size()); + ck_assert_int_eq(1, property.setter->values.size()); + +} +EFL_END_TEST + +EFL_START_TEST(eolian_cxx_test_property_accessor_info) +{ + efl::eolian::eolian_init eolian_init; + efl::eolian::eolian_state eolian_state; + + klass_def cls = init_test_data("property_holder.eo", "Property_Holder", eolian_state); + + auto props = cls.properties; + auto property = props[0]; + auto getter = *property.getter; + + // Single-valued getter + ck_assert(getter.return_type.c_type == "int"); + ck_assert_int_eq(0, getter.parameters.size()); + ck_assert(getter.explicit_return_type == efl::eolian::grammar::attributes::void_); + ck_assert_int_eq(1, getter.values.size()); + ck_assert_int_eq(0, getter.keys.size()); + + // Single-valued setter + property = props[2]; + auto setter = *property.setter; + ck_assert(setter.return_type.c_type == "void"); + ck_assert_int_eq(1, setter.parameters.size()); + ck_assert(setter.explicit_return_type == efl::eolian::grammar::attributes::void_); + ck_assert_int_eq(1, setter.values.size()); + ck_assert_int_eq(0, setter.keys.size()); + + // Multi valued getter + property = props[4]; + getter = *property.getter; + ck_assert(getter.return_type.c_type == "void"); + ck_assert_int_eq(2, getter.parameters.size()); + ck_assert(getter.explicit_return_type == efl::eolian::grammar::attributes::void_); + ck_assert_int_eq(2, getter.values.size()); + ck_assert_int_eq(0, getter.keys.size()); + + // Setter with return value + property = props[5]; + setter = *property.setter; + ck_assert_str_eq("Eina_Bool", setter.return_type.c_type.c_str()); + ck_assert_int_eq(1, setter.parameters.size()); + ck_assert_str_eq("Eina_Bool", setter.explicit_return_type.c_type.c_str()); + ck_assert_int_eq(1, setter.values.size()); + ck_assert_int_eq(0, setter.keys.size()); + + // Getter with return value + property = props[6]; + getter = *property.getter; + ck_assert_str_eq("Eina_Bool", getter.return_type.c_type.c_str()); + ck_assert_int_eq(1, getter.parameters.size()); + ck_assert_str_eq("Eina_Bool", getter.explicit_return_type.c_type.c_str()); + ck_assert_int_eq(1, getter.values.size()); + ck_assert_int_eq(0, getter.keys.size()); + + // Value override. This mimics Efl.Ui.Win.icon_object behavior. + property = props[7]; + getter = *property.getter; + ck_assert_str_eq("const Property_Holder *", getter.return_type.c_type.c_str()); + ck_assert_int_eq(0, getter.parameters.size()); + ck_assert_str_eq("void", getter.explicit_return_type.c_type.c_str()); + ck_assert_int_eq(1, getter.values.size()); + ck_assert_int_eq(0, getter.keys.size()); + + setter = *property.setter; + ck_assert_str_eq("void", setter.return_type.c_type.c_str()); + ck_assert_int_eq(1, setter.parameters.size()); + ck_assert_str_eq("void", setter.explicit_return_type.c_type.c_str()); + ck_assert_str_eq("Property_Holder *", setter.parameters[0].type.c_type.c_str()); + ck_assert_int_eq(1, setter.values.size()); + ck_assert_int_eq(0, setter.keys.size()); + + } EFL_END_TEST @@ -370,6 +493,7 @@ eolian_cxx_test_binding(TCase* tc) tcase_add_test(tc, eolian_cxx_test_type_generation_optional); tcase_add_test(tc, eolian_cxx_test_type_callback); tcase_add_test(tc, eolian_cxx_test_properties); + tcase_add_test(tc, eolian_cxx_test_property_accessor_info); tcase_add_test(tc, eolian_cxx_test_parent_extensions); tcase_add_test(tc, eolian_cxx_test_cls_get); tcase_add_test(tc, eolian_cxx_test_constructors); diff --git a/src/tests/eolian_cxx/property_holder.eo b/src/tests/eolian_cxx/property_holder.eo index 6c16c4ee1b..8509ffe648 100644 --- a/src/tests/eolian_cxx/property_holder.eo +++ b/src/tests/eolian_cxx/property_holder.eo @@ -38,5 +38,47 @@ class Property_Holder extends Efl.Object key: string; } } + + @property multi_value_prop { + get {} + set {} + values { + x: int; + y: int; + } + } + + @property setter_with_return { + get {} + set { + return: bool; + } + values { + data: int; + } + } + + @property getter_with_return { + get { + return: bool; + } + set {} + values { + data: int; + } + } + + @property value_override { + get { + values { + getter: const(Property_Holder); + } + } + set { + values { + setter: Property_Holder; + } + } + } } }