eolian_cxx: Add key/value to function_def

Summary:
This commit adds explicit eolian key/value/return info to function_def. The
original parameter/return types are kept for compatibility.

parameter/return -> Mimics the behavior of the generated C API (i.e.
single-valued getters have their lone value translated to be their
return type)

explicit_return -> The actual return value for that block in the EO
file.
keys/values -> The values for respectively key and values blocks.

This should help working with properties in the generators instead of
fumbling with paremeter/return directly

Fixes T8431

Test Plan: extra tests in the diff

Reviewers: felipealmeida, brunobelo, segfaultxavi, YOhoho

Reviewed By: brunobelo

Subscribers: cedric, #reviewers, #committers, woohyun

Tags: #efl

Maniphest Tasks: T8431

Differential Revision: https://phab.enlightenment.org/D10494
This commit is contained in:
Lauro Moura 2019-10-28 20:35:39 -03:00
parent ba34325f43
commit 135c69b23c
3 changed files with 210 additions and 43 deletions

View File

@ -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<parameter_def> 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<parameter_def> keys;
// Original Eolian values of this function. Used only for properties
std::vector<parameter_def> values;
// Name of this function in the C api
std::string c_name;
std::string filename;
std::vector<std::string> namespaces; // Namespaces for top-level function pointers
// Namespaces for top-level function pointers
std::vector<std::string> 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<parameter_def> const& _parameters,
std::string const& _c_name,
std::string _filename,
std::vector<std::string> 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<member_scope>(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<member_scope>(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<Eolian_Function_Parameter> 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<parameter_def> values;
for(efl::eina::iterator<Eolian_Function_Parameter> param_iterator
( ::eolian_property_values_get(function, type))
, param_last; param_iterator != param_last; ++param_iterator)

View File

@ -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);

View File

@ -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;
}
}
}
}
}