From 22c8bc2f59ff03a658eaf1ffcbe82f39aca05384 Mon Sep 17 00:00:00 2001 From: Lauro Moura Date: Fri, 30 Nov 2018 19:34:43 -0200 Subject: [PATCH] eolian-cxx: Add property_def Summary: While individual getters and setters are added to the list of methods of a class, property_def will hold them as a pair. This will help defining accessors like C#'s where they're grouped. Also update some eolian-cxx tests that were commented out. Depends: D7262 Test Plan: run eolian-cxx tests Reviewers: vitor.sousa, felipealmeida Reviewed By: vitor.sousa Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D7389 --- src/Makefile_Eolian_Cxx.am | 1 + src/lib/eolian_cxx/grammar/klass_def.hpp | 77 +++++++++++++++++-- src/tests/eolian/data/complex_type.eo | 2 +- .../eolian_cxx/eolian_cxx_test_binding.cc | 70 +++++++++++++++++ src/tests/eolian_cxx/eolian_cxx_test_parse.cc | 6 +- src/tests/eolian_cxx/meson.build | 1 + src/tests/eolian_cxx/property_holder.eo | 42 ++++++++++ 7 files changed, 188 insertions(+), 11 deletions(-) create mode 100644 src/tests/eolian_cxx/property_holder.eo diff --git a/src/Makefile_Eolian_Cxx.am b/src/Makefile_Eolian_Cxx.am index c2c66a6d91..be0cbaf501 100644 --- a/src/Makefile_Eolian_Cxx.am +++ b/src/Makefile_Eolian_Cxx.am @@ -178,6 +178,7 @@ tests_eolian_cxx_eolian_cxx_suite_CXXFLAGS = \ -I$(top_builddir)/src/tests/eolian_cxx \ -DTESTS_WD=\"`pwd`\" \ -DTESTS_SRC_DIR=\"$(top_srcdir)/src/tests/eolian_cxx\" \ +-DEO_SRC_DIR=\"$(top_srcdir)/src/lib\" \ -DPACKAGE_BUILD_DIR=\"$(abs_top_builddir)\" \ -DPACKAGE_DATA_DIR=\"$(top_srcdir)/src/tests/eolian_cxx\" \ -DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eolian_cxx\" \ diff --git a/src/lib/eolian_cxx/grammar/klass_def.hpp b/src/lib/eolian_cxx/grammar/klass_def.hpp index 513dac582b..1db9324001 100644 --- a/src/lib/eolian_cxx/grammar/klass_def.hpp +++ b/src/lib/eolian_cxx/grammar/klass_def.hpp @@ -175,7 +175,7 @@ struct documentation_def std::string since; std::vector desc_paragraphs; - documentation_def() {} + documentation_def() = default; documentation_def(std::string summary, std::string description, std::string since) : summary(summary), description(description), since(since) {} @@ -296,7 +296,7 @@ struct type_def bool has_own; bool is_ptr; - type_def() {} + type_def() = default; type_def(variant_type original_type, std::string c_type, bool has_own) : original_type(original_type), c_type(c_type), has_own(has_own) {} @@ -798,6 +798,40 @@ struct tuple_element<2ul, function_def> static type const& get(function_def const& f) { return f.parameters; } }; +struct property_def +{ + klass_name klass; + std::string name; + + efl::eina::optional getter; + efl::eina::optional setter; + + friend inline bool operator==(property_def const& lhs, property_def const& rhs) + { + return lhs.klass == rhs.klass + && lhs.name == rhs.name + && lhs.getter == rhs.getter + && lhs.setter == rhs.setter; + } + + friend inline bool operator!=(property_def const& lhs, property_def const& rhs) + { + return !(lhs == rhs); + } + + property_def() = default; + property_def(Eolian_Function const *function, efl::eina::optional getter + , efl::eina::optional setter, Eolian_Unit const* unit) + : getter(getter), setter(setter) + { + name = ::eolian_function_name_get(function); + + const Eolian_Class *eolian_klass = eolian_function_class_get(function); + klass = klass_name(eolian_klass, {attributes::qualifier_info::is_none, std::string()}); + } +}; + + // template // struct tuple_element : tuple_element {}; // template @@ -938,6 +972,7 @@ struct klass_def documentation_def documentation; std::vector namespaces; std::vector functions; + std::vector properties; std::set inherits; class_type type; std::vector events; @@ -952,6 +987,7 @@ struct klass_def && lhs.filename == lhs.filename && lhs.namespaces == rhs.namespaces && lhs.functions == rhs.functions + && lhs.properties == rhs.properties && lhs.inherits == rhs.inherits && lhs.type == rhs.type && lhs.events == rhs.events @@ -973,23 +1009,25 @@ struct klass_def , documentation_def documentation , std::vector namespaces , std::vector functions + , std::vector properties , std::set inherits , class_type type , std::set immediate_inherits) : eolian_name(eolian_name), cxx_name(cxx_name), filename(filename) , documentation(documentation) , namespaces(namespaces) - , functions(functions), inherits(inherits), type(type) + , functions(functions), properties(properties), inherits(inherits), type(type) , immediate_inherits(immediate_inherits) {} klass_def(std::string _eolian_name, std::string _cxx_name , std::vector _namespaces , std::vector _functions + , std::vector _properties , std::set _inherits , class_type _type, Eolian_Unit const* unit) : eolian_name(_eolian_name), cxx_name(_cxx_name) , namespaces(_namespaces) - , functions(_functions), inherits(_inherits), type(_type), unit(unit) + , functions(_functions), properties(_properties), inherits(_inherits), type(_type), unit(unit) {} klass_def(Eolian_Class const* klass, Eolian_Unit const* unit) : unit(unit) { @@ -1007,22 +1045,45 @@ struct klass_def Eolian_Function_Type func_type = ::eolian_function_type_get(function); if(func_type == EOLIAN_PROPERTY) { + efl::eina::optional getter(nullptr); + efl::eina::optional setter(nullptr); try { if(! ::eolian_function_is_legacy_only(function, EOLIAN_PROP_GET) && ::eolian_function_scope_get(function, EOLIAN_PROP_GET) != EOLIAN_SCOPE_PRIVATE) - functions.push_back({function, EOLIAN_PROP_GET, NULL, unit}); + { + function_def f(function, EOLIAN_PROP_GET, NULL, unit); + functions.push_back(f); + getter = efl::eina::optional(f); + } } catch(std::exception const&) {} try { if(! ::eolian_function_is_legacy_only(function, EOLIAN_PROP_SET) && ::eolian_function_scope_get(function, EOLIAN_PROP_SET) != EOLIAN_SCOPE_PRIVATE) - functions.push_back({function, EOLIAN_PROP_SET, NULL, unit}); + { + function_def f(function, EOLIAN_PROP_SET, NULL, unit); + functions.push_back(f); + setter = efl::eina::optional(f); + } } catch(std::exception const&) {} + if (getter.is_engaged() || setter.is_engaged()) + properties.push_back({function, getter, setter, unit}); } else try { if(! ::eolian_function_is_legacy_only(function, func_type) && ::eolian_function_scope_get(function, func_type) != EOLIAN_SCOPE_PRIVATE) - functions.push_back({function, func_type, NULL, unit}); + { + efl::eina::optional getter(nullptr); + efl::eina::optional setter(nullptr); + function_def f(function, func_type, NULL, unit); + if (func_type == EOLIAN_PROP_GET) + getter = efl::eina::optional(f); + else if (func_type == EOLIAN_PROP_SET) + setter = efl::eina::optional(f); + functions.push_back(f); + if (func_type == EOLIAN_PROP_GET || func_type == EOLIAN_PROP_SET) + properties.push_back({function, getter, setter, unit}); + } } catch(std::exception const&) {} } for(efl::eina::iterator eolian_functions ( ::eolian_class_functions_get(klass, EOLIAN_METHOD)) @@ -1154,7 +1215,7 @@ struct value_def std::string literal; type_def type; - value_def() {} + value_def() = default; value_def(Eolian_Value value_obj) { type.set(value_obj.type); diff --git a/src/tests/eolian/data/complex_type.eo b/src/tests/eolian/data/complex_type.eo index e8fe1a785e..9751bec5ed 100644 --- a/src/tests/eolian/data/complex_type.eo +++ b/src/tests/eolian/data/complex_type.eo @@ -4,7 +4,7 @@ class Complex_Type { methods { @property a { set { - return: list > @owned; + return: list > @owned; } get { } diff --git a/src/tests/eolian_cxx/eolian_cxx_test_binding.cc b/src/tests/eolian_cxx/eolian_cxx_test_binding.cc index e4d90202b5..09834069c5 100644 --- a/src/tests/eolian_cxx/eolian_cxx_test_binding.cc +++ b/src/tests/eolian_cxx/eolian_cxx_test_binding.cc @@ -4,6 +4,8 @@ #include +#include + #include #include #include @@ -11,6 +13,9 @@ #include "eolian_cxx_suite.h" +#include +#include "grammar/klass_def.hpp" + EFL_START_TEST(eolian_cxx_test_binding_constructor_only_required) { efl::eo::eo_init init; @@ -223,6 +228,70 @@ EFL_START_TEST(eolian_cxx_test_type_callback) } EFL_END_TEST +using efl::eolian::grammar::attributes::klass_def; +using efl::eolian::grammar::attributes::function_def; +using efl::eolian::grammar::attributes::property_def; +using efl::eolian::grammar::attributes::type_def; + +// FIXME Unify this definition some so we can share it with documentation tests. +static +klass_def init_test_data(std::string const target_file, std::string const target_klass, efl::eolian::eolian_state const& state) +{ + ck_assert(::eolian_state_directory_add(state.value, TESTS_SRC_DIR)); + ck_assert(::eolian_state_directory_add(state.value, EO_SRC_DIR)); + ck_assert(::eolian_state_all_eot_files_parse(state.value)); + std::string filename = TESTS_SRC_DIR; + filename += "/" + target_file; + ck_assert(::eolian_state_file_parse(state.value, filename.c_str())); + + const Eolian_Class *c_klass = ::eolian_state_class_by_name_get(state.value, target_klass.c_str()); + ck_assert_ptr_ne(c_klass, NULL); + + klass_def klass(c_klass, state.as_unit()); + return klass; +} + +EFL_START_TEST(eolian_cxx_test_properties) +{ + 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); + + // FIXME Currently parsing only properties with both get/set values. + auto props = cls.properties; + ck_assert_int_eq(4, 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); + + auto property = props[0]; + ck_assert(property.getter.is_engaged()); + ck_assert(property.setter.is_engaged()); + ck_assert(property.getter->name == "prop_simple_get"); + ck_assert(property.setter->name == "prop_simple_set"); + auto function = std::find_if(cls.functions.cbegin(), cls.functions.cend(), [](const function_def &f) { + return f.name == "prop_simple_get"; + }); + ck_assert(*property.getter == *function); + + property = props[1]; + ck_assert(property.getter.is_engaged()); + ck_assert(!property.setter.is_engaged()); + + property = props[2]; + ck_assert(!property.getter.is_engaged()); + ck_assert(property.setter.is_engaged()); + + property = props[3]; + ck_assert(property.getter.is_engaged()); + ck_assert(property.setter.is_engaged()); + +} +EFL_END_TEST + void eolian_cxx_test_binding(TCase* tc) { @@ -233,4 +302,5 @@ eolian_cxx_test_binding(TCase* tc) tcase_add_test(tc, eolian_cxx_test_type_generation_return); 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); } diff --git a/src/tests/eolian_cxx/eolian_cxx_test_parse.cc b/src/tests/eolian_cxx/eolian_cxx_test_parse.cc index 5462d4ef78..aa1297a0ba 100644 --- a/src/tests/eolian_cxx/eolian_cxx_test_parse.cc +++ b/src/tests/eolian_cxx/eolian_cxx_test_parse.cc @@ -12,8 +12,10 @@ EFL_START_TEST(eolian_cxx_test_parse_complex_types) { efl::eolian::eolian_init init; - // fail_if(!::eolian_state_directory_add(PACKAGE_DATA_DIR"/data")); - // fail_if(!::eolian_state_file_parse(PACKAGE_DATA_DIR"/data/complex_type.eo")); + efl::eolian::eolian_state state; + fail_if(!::eolian_state_directory_add(state.value, EO_SRC_DIR)); + fail_if(!::eolian_state_directory_add(state.value, TESTS_SRC_DIR)); + fail_if(!::eolian_state_file_parse(state.value, TESTS_SRC_DIR"/complex.eo")); // TODO finish } EFL_END_TEST diff --git a/src/tests/eolian_cxx/meson.build b/src/tests/eolian_cxx/meson.build index 1c7a961277..be2f5c37c8 100644 --- a/src/tests/eolian_cxx/meson.build +++ b/src/tests/eolian_cxx/meson.build @@ -65,6 +65,7 @@ eolian_cxx_suite = executable('eolian_cxx_suite', # package_c_args contains -D definitions for the package cpp_args : package_c_args +[ '-DTESTS_BUILD_DIR="'+meson.current_build_dir()+'"', + '-DEO_SRC_DIR="'+join_paths(meson.source_root(), 'src', 'lib')+'"', '-DTESTS_SRC_DIR="'+meson.current_source_dir()+'"'] ) diff --git a/src/tests/eolian_cxx/property_holder.eo b/src/tests/eolian_cxx/property_holder.eo new file mode 100644 index 0000000000..6c16c4ee1b --- /dev/null +++ b/src/tests/eolian_cxx/property_holder.eo @@ -0,0 +1,42 @@ +class Property_Holder extends Efl.Object +{ + methods { + some_method { + return: int; + } + + @property prop_simple { + get {} + set {} + values { + data: int; + } + } + + @property getter_only { + get {} + values { + data: int; + } + } + + @property setter_only { + set {} + values { + data: int; + } + } + + @property prop_with_key { + get {} + set {} + values { + data: int; + } + + keys { + key: string; + } + } + } +}