eolian-cxx: Add property_def
authorLauro Moura <lauromoura@expertisesolutions.com.br>
Fri, 30 Nov 2018 21:34:43 +0000 (19:34 -0200)
committerHermet Park <hermetpark@gmail.com>
Wed, 5 Dec 2018 05:52:40 +0000 (14:52 +0900)
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
src/lib/eolian_cxx/grammar/klass_def.hpp
src/tests/eolian/data/complex_type.eo
src/tests/eolian_cxx/eolian_cxx_test_binding.cc
src/tests/eolian_cxx/eolian_cxx_test_parse.cc
src/tests/eolian_cxx/meson.build
src/tests/eolian_cxx/property_holder.eo [new file with mode: 0644]

index c2c66a6..be0cbaf 100644 (file)
@@ -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\" \
index 513dac5..1db9324 100644 (file)
@@ -175,7 +175,7 @@ struct documentation_def
    std::string since;
    std::vector<std::string> 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<function_def> getter;
+  efl::eina::optional<function_def> 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<function_def> getter
+              , efl::eina::optional<function_def> 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 <int N>
 // struct tuple_element<N, function_def const> : tuple_element<N, function_def> {};
 // template <int N>
@@ -938,6 +972,7 @@ struct klass_def
   documentation_def documentation;
   std::vector<std::string> namespaces;
   std::vector<function_def> functions;
+  std::vector<property_def> properties;
   std::set<klass_name, compare_klass_name_by_name> inherits;
   class_type type;
   std::vector<event_def> 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<std::string> namespaces
             , std::vector<function_def> functions
+            , std::vector<property_def> properties
             , std::set<klass_name, compare_klass_name_by_name> inherits
             , class_type type
             , std::set<klass_name, compare_klass_name_by_name> 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<std::string> _namespaces
             , std::vector<function_def> _functions
+            , std::vector<property_def> _properties
             , std::set<klass_name, compare_klass_name_by_name> _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<function_def> getter(nullptr);
+             efl::eina::optional<function_def> 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<function_def>(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<function_def>(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<function_def> getter(nullptr);
+                  efl::eina::optional<function_def> setter(nullptr);
+                  function_def f(function, func_type, NULL, unit);
+                  if (func_type == EOLIAN_PROP_GET)
+                    getter = efl::eina::optional<function_def>(f);
+                  else if (func_type == EOLIAN_PROP_SET)
+                    setter = efl::eina::optional<function_def>(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_Function const> 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);
index e8fe1a7..9751bec 100644 (file)
@@ -4,7 +4,7 @@ class Complex_Type {
    methods {
       @property a {
          set {
-            return: list<array<ptr(Eo) @owned> > @owned;
+            return: list<array<Eo @owned> > @owned;
          }
          get {
          }
index e4d9020..0983406 100644 (file)
@@ -4,6 +4,8 @@
 
 #include <Ecore.h>
 
+#include <map>
+
 #include <generic.eo.hh>
 #include <generic.eo.impl.hh>
 #include <name1_name2_type_generation.eo.hh>
@@ -11,6 +13,9 @@
 
 #include "eolian_cxx_suite.h"
 
+#include <Eolian_Cxx.hh>
+#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);
 }
index 5462d4e..aa1297a 100644 (file)
 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
index 1c7a961..be2f5c3 100644 (file)
@@ -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 (file)
index 0000000..6c16c4e
--- /dev/null
@@ -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;
+         }
+      }
+   }
+}