eolian-mono: Provide constructor parameters based on the constructors
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>
Fri, 1 Feb 2019 19:03:02 +0000 (14:03 -0500)
committerJongmin Lee <jm105.lee@samsung.com>
Wed, 6 Feb 2019 22:20:24 +0000 (07:20 +0900)
section of the Eo files.

Reviewers: woohyun, segfaultxavi, bu5hm4n, felipealmeida

Reviewed By: segfaultxavi

Subscribers: cedric, #reviewers, #committers

Tags: #efl

Differential Revision: https://phab.enlightenment.org/D7789

12 files changed:
src/bin/eolian_mono/eolian/mono/documentation.hh
src/bin/eolian_mono/eolian/mono/helpers.hh
src/bin/eolian_mono/eolian/mono/klass.hh
src/bin/eolian_mono/eolian/mono/name_helpers.hh
src/bin/eolian_mono/eolian/mono/parameter.hh
src/bin/eolian_mono/eolian/mono/type.hh
src/bin/eolian_mono/eolian/mono/type_impl.hh
src/bindings/mono/eo_mono/iwrapper.cs
src/tests/efl_mono/Eo.cs
src/tests/efl_mono/Events.cs
src/tests/efl_mono/dummy_child.eo
src/tests/efl_mono/libefl_mono_native_test.c

index 3acec94..d2f4669 100644 (file)
@@ -84,6 +84,29 @@ struct documentation_generator
       return name;
    }
 
+   static std::string function_conversion(attributes::function_def const& func)
+   {
+      attributes::klass_def klass(get_klass(func.klass, func.unit), func.unit);
+      std::string name = name_helpers::klass_full_concrete_or_interface_name(klass);
+      switch (func.type)
+      {
+          // managed_method_name takes care of reordering the function name so the get/set goes first
+          // for properties
+          case attributes::function_type::method:
+          case attributes::function_type::prop_set:
+          case attributes::function_type::prop_get:
+            if (blacklist::is_function_blacklisted(func.c_name))return "";
+            name += ".";
+            name += name_helpers::managed_method_name(klass.eolian_name, func.name);
+            break;
+          default:
+            // No need to deal with property as function_defs are converted to get/set when building a given klass_def.
+            break;
+      }
+
+      return name;
+   }
+
    // Turns an Eolian reference like @Efl.Input.Pointer.tool into a <see> tag
    static std::string ref_conversion(const ::Eolian_Doc_Token *token, const Eolian_State *state, std::string name_tail)
    {
@@ -299,6 +322,31 @@ struct documentation_generator
    {
       return generate_tag_summary(sink, doc.full_text, context);
    }
+
+   template<typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::constructor_def const& ctor, Context const& context) const
+   {
+      // Not sure if this is the best way to generate a reference outside the full doc generator.
+      auto unit = (const Eolian_Unit*) context_find_tag<eolian_state_context>(context).state;
+      auto func = ctor.function;
+      auto eolian_klass = get_klass(func.klass, unit);
+      attributes::klass_def klass(eolian_klass, unit);
+      std::string summary;
+
+      if (func.type == attributes::function_type::prop_set)
+          summary = func.property_documentation.summary;
+      else
+          summary = func.documentation.summary;
+
+      for (auto &&param : ctor.function.parameters)
+        {
+          if (!as_generator(
+                      scope_tab << "///<param name=\"" << constructor_parameter_name(ctor) << "\">" << summary << " See <see cref=\"" << function_conversion(func) << "\"/></param>\n"
+                      ).generate(sink, param, context))
+            return false;
+        }
+      return true;
+   }
 };
 
 struct documentation_terminal
index ed72345..87a1e9d 100644 (file)
@@ -221,6 +221,12 @@ inline bool is_unique_event(attributes::event_def const& evt
                      });
 }
 
+inline std::vector<attributes::constructor_def> reorder_constructors(std::vector<attributes::constructor_def> constructors)
+{
+  auto is_required = [](attributes::constructor_def const& ctr) { return !ctr.is_optional; };
+  std::stable_partition(constructors.begin(), constructors.end(), is_required);
+  return constructors;
+}
 
 } // namespace helpers
 
index 6a2c818..d8f2e7e 100644 (file)
@@ -220,15 +220,16 @@ struct klass
          if (!generate_fields(sink, cls, concrete_cxt))
            return false;
 
+         bool root = !helpers::has_regular_ancestor(cls);
          if (!as_generator
             (
              scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(concrete_cxt).actual_library_name(cls.filename)
              << ")] internal static extern System.IntPtr\n"
              << scope_tab << scope_tab << name_helpers::klass_get_name(cls) << "();\n"
-             << scope_tab << "///<summary>Constructs an instance from a native pointer.</summary>\n"
-             << scope_tab << "public " << concrete_name << "(System.IntPtr raw)\n"
+             << scope_tab << "///<summary>Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.</summary>\n"
+             << scope_tab << "public " << concrete_name << "(System.IntPtr raw)" << (root ? "" : " : base(raw)") << "\n"
              << scope_tab << "{\n"
-             << scope_tab << scope_tab << "handle = raw;\n"
+             << scope_tab << scope_tab << (root ? "handle = raw;\n" : "")
              << scope_tab << scope_tab << "register_event_proxies();\n"
              << scope_tab << "}\n"
             )
@@ -503,48 +504,44 @@ struct klass
             ).generate(sink, attributes::unused, context))
        return false;
 
+     auto constructors = helpers::reorder_constructors(cls.get_all_constructors());
 
-     if (!root)
-       {
-          return as_generator(
+     // Public (API) constructors
+     if (!as_generator(
                      scope_tab << "///<summary>Creates a new instance.</summary>\n"
                      << scope_tab << "///<param name=\"parent\">Parent instance.</param>\n"
-                     << scope_tab << "///<param name=\"init_cb\">Delegate to call constructing methods that should be run inside the constructor.</param>\n"
-                     << scope_tab << "public " << inherit_name << "(Efl.Object parent = null, ConstructingMethod init_cb=null) : "
-                     "base(\"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) <<  "(), typeof(" << inherit_name << "), parent)\n"
+                     << *(documentation)
+                     // For constructors with arguments, the parent is also required, as optional parameters can't come before non-optional paramenters.
+                     << scope_tab << "public " << inherit_name << "(Efl.Object parent" << ((constructors.size() > 0) ? "" : "= null") << "\n"
+                     << scope_tab << scope_tab << scope_tab << *(", " << constructor_param ) << ") :\n"
+                     << scope_tab << scope_tab << (root ? "this" : "base")  << "(\"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) <<  "(), typeof(" << inherit_name << "), parent)\n"
                      << scope_tab << "{\n"
-                     << scope_tab << scope_tab << "if (init_cb != null) {\n"
-                     << scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
-                     << scope_tab << scope_tab << "}\n"
+                     << *(scope_tab << scope_tab << constructor_invocation << "\n" )
                      << scope_tab << scope_tab << "FinishInstantiation();\n"
                      << scope_tab << "}\n"
-
-                     << scope_tab << "///<summary>Internal constructor to forward the wrapper initialization to the root class.</summary>\n"
-                     << scope_tab << "protected " << inherit_name << "(String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent) : base(klass_name, base_klass, managed_type, parent) {}\n"
-
-                     << scope_tab << "///<summary>Constructs an instance from a native pointer.</summary>\n"
+                     << scope_tab << "///<summary>Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.</summary>\n"
                      << scope_tab << "public " << inherit_name << "(System.IntPtr raw)" << (root ? "" : " : base(raw)") << "\n"
                      << scope_tab << "{\n"
                      << scope_tab << scope_tab << (root ? "handle = raw;\n" : "")
                      << scope_tab << scope_tab << "register_event_proxies();\n"
                      << scope_tab << "}\n"
+                 ).generate(sink, std::make_tuple(constructors, constructors, constructors), context))
+         return false;
+
+     // Internal constructors
+     if (!root)
+     {
+         return as_generator(
+                     scope_tab << "///<summary>Internal usage: Constructor to forward the wrapper initialization to the root class that interfaces with native code. Should not be used directly.</summary>\n"
+                     << scope_tab << "protected " << inherit_name << "(String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent) : base(klass_name, base_klass, managed_type, parent) {}\n"
                   ).generate(sink, attributes::unused, context);
-       }
+
+     }
 
      // Detailed constructors go only in root classes.
      return as_generator(
-             scope_tab << "///<summary>Creates a new instance.</summary>\n"
-             << scope_tab << "///<param name=\"parent\">Parent instance.</param>\n"
-             << scope_tab << "///<param name=\"init_cb\">Delegate to call constructing methods that should be run inside the constructor.</param>\n"
-             << scope_tab << "public " << inherit_name << "(Efl.Object parent = null, ConstructingMethod init_cb=null) : this(\"" << inherit_name << "\", " << name_helpers::klass_get_name(cls) << "(), typeof(" << inherit_name << "), parent)\n"
-             << scope_tab << "{\n"
-             << scope_tab << scope_tab << "if (init_cb != null) {\n"
-             << scope_tab << scope_tab << scope_tab << "init_cb(this);\n"
-             << scope_tab << scope_tab << "}\n"
-             << scope_tab << scope_tab << "FinishInstantiation();\n"
-             << scope_tab << "}\n"
-
-             << scope_tab << "protected " << inherit_name << "(String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent)\n"
+             /// Actual root costructor that creates class and instantiates 
+             scope_tab << "protected " << inherit_name << "(String klass_name, IntPtr base_klass, System.Type managed_type, Efl.Object parent)\n"
              << scope_tab << "{\n"
              << scope_tab << scope_tab << "inherited = ((object)this).GetType() != managed_type;\n"
              << scope_tab << scope_tab << "IntPtr actual_klass = base_klass;\n"
@@ -574,12 +571,6 @@ struct klass
              << scope_tab << scope_tab << "Eina.Error.RaiseIfUnhandledException();\n"
              << scope_tab << "}\n"
 
-             << scope_tab << "///<summary>Constructs an instance from a native pointer.</summary>\n"
-             << scope_tab << "public " << inherit_name << "(System.IntPtr raw)\n"
-             << scope_tab << "{\n"
-             << scope_tab << scope_tab << "handle = raw;\n"
-             << scope_tab << scope_tab << "register_event_proxies();\n"
-             << scope_tab << "}\n"
              ).generate(sink, attributes::unused, context);
    }
 
index 8910447..ccbbfce 100644 (file)
@@ -187,6 +187,12 @@ inline std::string managed_method_name(std::string const& klass, std::string con
   return candidate;
 }
 
+inline std::string managed_name(std::string const& name, char separator='_')
+{
+  auto tokens = utils::split(name, separator);
+  return utils::to_pascal_case(tokens);
+}
+
 inline std::string managed_method_name(attributes::function_def const& f)
 {
   return managed_method_name(f.klass.eolian_name, f.name);
@@ -420,7 +426,12 @@ bool close_namespaces(OutputIterator sink, std::vector<std::string> const& names
      return as_generator(close_namespace).generate(sink, namespaces, context);
 }
 
+std::string constructor_managed_name(std::string full_name)
+{
+    auto tokens = utils::split(full_name, '.');
 
+    return managed_name(tokens.at(tokens.size()-1));
+}
 
 } // namespace name_helpers
 
index 416cacb..efb907f 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "grammar/generator.hpp"
 #include "grammar/klass_def.hpp"
+#include "grammar/attribute_reorder.hpp"
 #include "grammar/case.hpp"
 #include "helpers.hh"
 #include "marshall_type.hh"
@@ -34,6 +35,10 @@ namespace eolian_mono {
     struct native_convert_return_variable_generator;
     struct convert_function_pointer_generator;
     struct native_convert_function_pointer_generator;
+    struct constructor_param_generator;
+    struct constructor_invocation_generator;
+    struct constructor_parameter_name_generator;
+    struct constructor_parameter_name_paremeterized;
 }
 
 namespace efl { namespace eolian { namespace grammar {
@@ -232,6 +237,38 @@ template <>
 struct attributes_needed< ::eolian_mono::native_convert_function_pointer_generator> : std::integral_constant<int, 1> {};
 }
 
+template <>
+struct is_eager_generator< ::eolian_mono::constructor_param_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::constructor_param_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::constructor_param_generator> : std::integral_constant<int, 1> {};
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::constructor_invocation_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::constructor_invocation_generator> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::constructor_invocation_generator> : std::integral_constant<int, 1> {};
+}
+
+template <>
+struct is_eager_generator< ::eolian_mono::constructor_parameter_name_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::constructor_parameter_name_generator> : std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::constructor_parameter_name_paremeterized> : std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::constructor_parameter_name_generator> : std::integral_constant<int, 1> {};
+}
+
 } } }
 
 namespace eolian_mono {
@@ -1436,6 +1473,89 @@ struct native_convert_function_pointer_generator
 
 } const native_convert_function_pointer {};
 
+struct constructor_parameter_name_generator
+{
+   
+   template <typename OutputIterator, typename Context>
+   bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
+   {
+     auto target_name = name_helpers::constructor_managed_name(ctor.name);
+
+     // Only multi-valued constructing methods get their actual parameter names
+     if (ctor.function.parameters.size() > 1)
+       target_name += '_' + param.param_name;
+
+     auto name = name_helpers::managed_name(target_name);
+     name[0] = std::tolower(name[0]);
+
+     return as_generator(string).generate(sink, name, context);
+   }
+
+   attributes::constructor_def const& ctor;
+};
+
+struct constructor_parameter_name_parameterized
+{
+   constructor_parameter_name_generator const operator()(attributes::constructor_def const& ctor) const
+   {
+       return {ctor};
+   }
+} const constructor_parameter_name;
+
+// Generates the parameters for the given constructor
+// If the constructor receives multiple parameters, they get the name
+// of the constructor plus the name of the parameter (e.g. DefineParentData, DefineIndex)
+struct constructor_param_generator
+{
+  template<typename OutputIterator, typename Context>
+  bool generate(OutputIterator sink, attributes::constructor_def const& ctor, Context context) const
+  {
+     auto params = ctor.function.parameters;
+
+     if (!as_generator(
+                       efl::eolian::grammar::attribute_reorder<1, -1>
+                       (type(false, ctor.is_optional) << " " << constructor_parameter_name(ctor) << (ctor.is_optional ? " = null" : "")) % ","
+                ).generate(sink, params, context))
+       return false;
+     //   }
+     return true;
+  }
+
+} const constructor_param;
+
+// Generates the invocation of the given parameter
+struct constructor_invocation_generator
+{
+  template<typename OutputIterator, typename Context>
+  bool generate(OutputIterator sink, attributes::constructor_def const& ctor, Context context) const
+  {
+     auto params = ctor.function.parameters;
+     if (!as_generator(
+                       "if (" <<
+                       (efl::eolian::grammar::attribute_reorder<-1>
+                        ("Efl.Eo.Globals.ParamHelperCheck(" << constructor_parameter_name(ctor) << ")") % "||") << ")\n"
+                       << scope_tab << scope_tab << scope_tab << name_helpers::managed_method_name(ctor.function) << "("
+             ).generate(sink, params, context))
+       return false;
+
+     size_t idx = 0;
+
+     for (auto&& param : params)
+       {
+          idx++;
+          if (!as_generator(
+              "Efl.Eo.Globals.GetParamHelper(" << constructor_parameter_name(ctor) << ")" << ((idx < params.size()) ? ", " : "")
+              ).generate(sink, param, context))
+            return false;
+       }
+
+     if (!as_generator(");").generate(sink, attributes::unused, context))
+       return false;
+     return true;
+  }
+
+} const constructor_invocation;
+
 }
 
 #endif
index b968d9e..f6a5285 100644 (file)
@@ -14,29 +14,29 @@ struct visitor_generate;
       
 struct type_generator
 {
-   type_generator(bool is_return = false)
-     : is_return(is_return) {}
+   type_generator(bool is_return = false, bool is_optional = false)
+     : is_return(is_return), is_optional(is_optional) {}
   
    template <typename OutputIterator, typename Context>
    bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const
    {
-      return type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr});
+      return type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, type.c_type, false, is_return, type.is_ptr, is_optional});
    }
    template <typename OutputIterator, typename Context>
    bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
    {
       return param.type.original_type.visit(visitor_generate<OutputIterator, Context>{sink, &context, param.type.c_type
-            , param.direction != attributes::parameter_direction::in, false, param.type.is_ptr});
+          , param.direction != attributes::parameter_direction::in, false, param.type.is_ptr, is_optional});
    }
 
-   bool is_return;
+  bool is_return, is_optional;
 };
 
 struct type_terminal
 {
-  type_generator const operator()(bool is_return) const
+  type_generator const operator()(bool is_return, bool is_optional = false) const
   {
-    return type_generator(is_return);
+    return type_generator(is_return, is_optional);
   }
 } const type = {};
 
index 3e4ae8d..c449d21 100644 (file)
@@ -34,6 +34,20 @@ attributes::regular_type_def replace_base_integer(attributes::regular_type_def v
   }
 }
 
+template <typename T>
+attributes::regular_type_def replace_base_opt_integer(attributes::regular_type_def v)
+{
+  bool s = std::is_signed<T>::value;
+  switch (sizeof(T))
+  {
+  case 1: return s ? replace_base_type(v, " sbyte?") : replace_base_type(v, " byte?");
+  case 2: return s ? replace_base_type(v, " short?") : replace_base_type(v, " ushort?");
+  case 4: return s ? replace_base_type(v, " int?") : replace_base_type(v, " uint?");
+  case 8: return s ? replace_base_type(v, " long?") : replace_base_type(v, " ulong?");
+  default: return v;
+  }
+}
+  
 inline
 attributes::complex_type_def replace_outer(attributes::complex_type_def v, attributes::regular_type_def const& regular)
 {
@@ -63,6 +77,7 @@ struct visitor_generate
    bool is_out;
    bool is_return;
    bool is_ptr;
+   mutable bool is_optional;
 
    typedef visitor_generate<OutputIterator, Context> visitor_type;
    typedef bool result_type;
@@ -76,6 +91,40 @@ struct visitor_generate
         eina::optional<bool> has_own;
         std::function<attributes::type_def::variant_type()> function;
       }
+      const optional_match_table[] =
+        {
+           // signed primitives
+             {"byte", nullptr, [&] { return replace_base_type(regular, " sbyte?"); }}
+           , {"float", nullptr, [&] { return replace_base_type(regular, " float?"); }}
+           , {"double", nullptr, [&] { return replace_base_type(regular, " double?"); }}
+           , {"bool", nullptr, [&] { return replace_base_type(regular, " bool?"); }}
+           , {"short", nullptr, [&] { return replace_base_opt_integer<short>(regular); }}
+           , {"int", nullptr, [&] { return replace_base_opt_integer<int>(regular); }}
+           , {"long", nullptr, [&] { return replace_base_opt_integer<long>(regular); }}
+           , {"llong", nullptr, [&] { return replace_base_opt_integer<long long>(regular); }}
+           , {"int8", nullptr, [&] { return replace_base_type(regular, " sbyte?"); }}
+           , {"int16", nullptr, [&] { return replace_base_type(regular, " short?"); }}
+           , {"int32", nullptr, [&] { return replace_base_type(regular, " int?"); }}
+           , {"int64", nullptr, [&] { return replace_base_type(regular, " long?"); }}
+           , {"ssize", nullptr, [&] { return replace_base_opt_integer<ssize_t>(regular); }}
+           // unsigned primitives
+           , {"ubyte", nullptr, [&] { return replace_base_type(regular, " byte?"); }}
+           , {"ushort", nullptr, [&] { return replace_base_opt_integer<unsigned short>(regular); }}
+           , {"uint", nullptr, [&] { return replace_base_opt_integer<unsigned int>(regular); }}
+           , {"ulong", nullptr, [&] { return replace_base_opt_integer<unsigned long>(regular); }}
+           , {"ullong", nullptr, [&] { return replace_base_opt_integer<unsigned long long>(regular); }}
+           , {"uint8", nullptr, [&] { return replace_base_type(regular, " byte?"); }}
+           , {"uint16", nullptr, [&] { return replace_base_type(regular, " ushort?"); }}
+           , {"uint32", nullptr, [&] { return replace_base_type(regular, " uint?"); }}
+           , {"uint64", nullptr, [&] { return replace_base_type(regular, " ulong?"); }}
+           , {"size", nullptr, [&] { return replace_base_opt_integer<size_t>(regular); }}
+           
+           , {"ptrdiff", nullptr, [&] { return replace_base_opt_integer<ptrdiff_t>(regular); }}
+           , {"intptr", nullptr, [&] { return replace_base_type(regular, " System.IntPtr?"); }}
+           , {"uintptr", nullptr, [&] { return replace_base_type(regular, " System.IntPtr?"); }}
+           , {"void_ptr", nullptr, [&] { return replace_base_type(regular, " System.IntPtr?"); }}
+        };
+      struct match
       const match_table[] =
         {
            // signed primitives
@@ -153,6 +202,29 @@ struct visitor_generate
         };
         std::string full_type_name = name_helpers::type_full_eolian_name(regular);
         if(eina::optional<bool> b = call_match
+         (optional_match_table
+          , [&] (match const& m)
+          {
+            return is_optional
+              && (!m.name || *m.name == regular.base_type || *m.name == full_type_name)
+              && (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own))
+            ;
+          }
+          , [&] (attributes::type_def::variant_type const& v)
+          {
+            return v.visit(*this); // we want to keep is_out info
+          }))
+        {
+           return *b;
+        }
+        else if (is_optional && (regular.is_struct() || regular.is_enum() || regular.is_struct_opaque()))
+        {
+          attributes::regular_type_def r = regular;
+          r.base_type.push_back('?');
+          is_optional = false;
+          return (*this)(r);
+        }
+        else if(eina::optional<bool> b = call_match
          (match_table
           , [&] (match const& m)
           {
index fe96088..2119e07 100644 (file)
@@ -157,6 +157,23 @@ public class Globals {
 
     public delegate byte class_initializer(IntPtr klass);
 
+    public static T GetParamHelper<T>(Nullable<T> v) where T : struct
+    {
+        return v.Value;
+    }
+    public static U GetParamHelper<U>(U v)
+    {
+        return v;
+    }
+    public static bool ParamHelperCheck<T>(Nullable<T> v) where T : struct
+    {
+        return v.HasValue;
+    }
+    public static bool ParamHelperCheck<U>(U v)
+    {
+        return v != null;
+    }
+    
     public static IntPtr register_class(String class_name, IntPtr base_klass, System.Type type)
     {
         ClassDescription description;
index 5567f1e..37d4735 100644 (file)
@@ -114,43 +114,6 @@ class TestEoNames
     }
 }
 
-class TestEoConstructingMethods
-{
-    public static void constructing_method()
-    {
-        bool called = false;
-        string name = "Test object";
-        var obj = new Dummy.TestObject(null, (Dummy.TestObject a) => {
-                called = true;
-                Console.WriteLine("callback: obj NativeHandle: {0:x}", a.NativeHandle);
-                a.SetName(name);
-            });
-
-        Test.Assert(called);
-        Test.AssertEquals(name, obj.GetName());
-    }
-
-    private class Derived : Dummy.TestObject
-    {
-        public Derived(Dummy.TestObject parent = null,
-                       Dummy.TestObject.ConstructingMethod cb = null) : base(parent, cb) {
-        }
-    }
-
-    public static void constructing_method_inherit()
-    {
-        bool called = false;
-        string name = "Another test object";
-        Derived obj = new Derived(null, (Dummy.TestObject a) => {
-                called = true;
-                a.SetComment(name);
-            });
-
-        Test.Assert(called);
-        Test.AssertEquals(name, obj.GetComment());
-    }
-}
-
 class TestEoParent
 {
     public static void basic_parent()
@@ -365,6 +328,9 @@ class TestEoGrandChildrenFinalize
 
     public sealed class GrandChild : Dummy.Child
     {
+
+        public GrandChild() : base(null, "", 0.0) { }
+
         public int receivedValue = 0;
         public override Efl.Object FinalizeAdd()
         {
@@ -380,4 +346,27 @@ class TestEoGrandChildrenFinalize
     }
 }
 
+class TestConstructors
+{
+    public static void test_simple_constructor()
+    {
+        int iface_prop = 42;
+        string a = "LFE";
+        double b = 3.14;
+        var obj = new Dummy.Child(null, a, b, iface_prop);
+        Test.AssertEquals(iface_prop, obj.IfaceProp);
+
+        obj = new Dummy.Child(parent: null, ifaceProp : iface_prop, doubleParamsA : a, doubleParamsB : b);
+        Test.AssertEquals(iface_prop, obj.IfaceProp);
+    }
+
+    public static void test_optional_constructor()
+    {
+        string a = "LFE";
+        double b = 3.14;
+        var obj = new Dummy.Child(null, a, b);
+        Test.Assert(!obj.GetIfaceWasSet());
+    }
+}
+
 }
index 84918b9..7856878 100644 (file)
@@ -168,11 +168,10 @@ class TestEoEvents
     {
         int received = 0;
         int sent = 42;
-        var obj = new Dummy.TestObject(null, (Dummy.TestObject t) => {
-            t.EvtWithIntEvt += (object sender, Dummy.TestObjectEvtWithIntEvt_Args e) => {
-                received = e.arg;
-            };
-        });
+        var obj = new Dummy.TestObject();
+        obj.EvtWithIntEvt += (object sender, Dummy.TestObjectEvtWithIntEvt_Args e) => {
+            received = e.arg;
+        };
 
         obj.EmitEventWithInt(sent);
 
index e3e1a7c..b7845d9 100644 (file)
@@ -2,8 +2,29 @@ import eina_types;
 
 class Dummy.Child extends Dummy.Test_Object {
 
+   methods {
+      double_params {
+         params {
+            @in a: string;
+            @in b: double;
+         }
+      }
+
+      @property iface_was_set {
+        get {}
+        values {
+         data: bool;
+       }
+      }
+   }
+   constructors {
+      Dummy.Test_Iface.iface_prop @optional;
+      .double_params;
+   }
    implements {
+      Dummy.Test_Iface.iface_prop { get; set; }
       class.constructor;
       class.destructor;
+      Efl.Object.constructor;
    }
 }
index 986cd1f..5108621 100644 (file)
@@ -82,6 +82,10 @@ typedef struct Dummy_Numberwrapper_Data
 
 typedef struct Dummy_Child_Data
 {
+  int iface_prop;
+  const char* a;
+  double b;
+  Eina_Bool iface_was_set;
 } Dummy_Child_Data;
 
 typedef struct Dummy_Inherit_Helper_Data
@@ -3936,6 +3940,42 @@ int _dummy_test_object_dummy_test_iface_iface_prop_get(EINA_UNUSED const Eo *obj
 }
 
 /// Dummy.Child
+
+static Efl_Object *
+_dummy_child_efl_object_constructor(Eo *obj, Dummy_Child_Data *pd)
+{
+    efl_constructor(efl_super(obj, DUMMY_CHILD_CLASS));
+
+    pd->iface_prop = 1984;
+    pd->iface_was_set = EINA_FALSE;
+    return obj;
+}
+
+void _dummy_child_dummy_test_iface_iface_prop_set(EINA_UNUSED Eo *obj, Dummy_Child_Data *pd, int value)
+{
+    pd->iface_prop = value;
+    pd->iface_was_set = EINA_TRUE;
+}
+
+int _dummy_child_dummy_test_iface_iface_prop_get(EINA_UNUSED const Eo *obj, Dummy_Child_Data *pd)
+{
+    return pd->iface_prop;
+}
+
+void _dummy_child_double_params(EINA_UNUSED Eo* obj, Dummy_Child_Data *pd, const char* a, double b)
+{
+    if (pd->a)
+      free((void*)pd->a);
+    pd->a = malloc(sizeof(char)*(strlen(a) + 1));
+    strcpy((char*)pd->a, a);
+
+    pd->b = b;
+}
+
+Eina_Bool _dummy_child_iface_was_set_get(EINA_UNUSED const Eo* obj, Dummy_Child_Data *pd)
+{
+    return pd->iface_was_set;
+}
 EOLIAN static void
 _dummy_child_class_constructor(Efl_Class *klass)
 {