From e1116eb78f4c936a08be29de220eec7d3d3aa986 Mon Sep 17 00:00:00 2001 From: Felipe Magno de Almeida Date: Fri, 1 Feb 2019 14:03:02 -0500 Subject: [PATCH] eolian-mono: Provide constructor parameters based on the constructors 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 --- src/bin/eolian_mono/eolian/mono/documentation.hh | 48 +++++++++ src/bin/eolian_mono/eolian/mono/helpers.hh | 6 ++ src/bin/eolian_mono/eolian/mono/klass.hh | 63 +++++------- src/bin/eolian_mono/eolian/mono/name_helpers.hh | 11 +++ src/bin/eolian_mono/eolian/mono/parameter.hh | 120 +++++++++++++++++++++++ src/bin/eolian_mono/eolian/mono/type.hh | 14 +-- src/bin/eolian_mono/eolian/mono/type_impl.hh | 72 ++++++++++++++ src/bindings/mono/eo_mono/iwrapper.cs | 17 ++++ src/tests/efl_mono/Eo.cs | 63 +++++------- src/tests/efl_mono/Events.cs | 9 +- src/tests/efl_mono/dummy_child.eo | 21 ++++ src/tests/efl_mono/libefl_mono_native_test.c | 40 ++++++++ 12 files changed, 399 insertions(+), 85 deletions(-) diff --git a/src/bin/eolian_mono/eolian/mono/documentation.hh b/src/bin/eolian_mono/eolian/mono/documentation.hh index 3acec94..d2f4669 100644 --- a/src/bin/eolian_mono/eolian/mono/documentation.hh +++ b/src/bin/eolian_mono/eolian/mono/documentation.hh @@ -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 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 + 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(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 &¶m : ctor.function.parameters) + { + if (!as_generator( + scope_tab << "///" << summary << " See \n" + ).generate(sink, param, context)) + return false; + } + return true; + } }; struct documentation_terminal diff --git a/src/bin/eolian_mono/eolian/mono/helpers.hh b/src/bin/eolian_mono/eolian/mono/helpers.hh index ed72345..87a1e9d 100644 --- a/src/bin/eolian_mono/eolian/mono/helpers.hh +++ b/src/bin/eolian_mono/eolian/mono/helpers.hh @@ -221,6 +221,12 @@ inline bool is_unique_event(attributes::event_def const& evt }); } +inline std::vector reorder_constructors(std::vector 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 diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh index 6a2c818..d8f2e7e 100644 --- a/src/bin/eolian_mono/eolian/mono/klass.hh +++ b/src/bin/eolian_mono/eolian/mono/klass.hh @@ -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(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 << "///Constructs an instance from a native pointer.\n" - << scope_tab << "public " << concrete_name << "(System.IntPtr raw)\n" + << scope_tab << "///Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.\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 << "///Creates a new instance.\n" << scope_tab << "///Parent instance.\n" - << scope_tab << "///Delegate to call constructing methods that should be run inside the constructor.\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 << "///Internal constructor to forward the wrapper initialization to the root class.\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 << "///Constructs an instance from a native pointer.\n" + << scope_tab << "///Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.\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 << "///Internal usage: Constructor to forward the wrapper initialization to the root class that interfaces with native code. Should not be used directly.\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 << "///Creates a new instance.\n" - << scope_tab << "///Parent instance.\n" - << scope_tab << "///Delegate to call constructing methods that should be run inside the constructor.\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 << "///Constructs an instance from a native pointer.\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); } diff --git a/src/bin/eolian_mono/eolian/mono/name_helpers.hh b/src/bin/eolian_mono/eolian/mono/name_helpers.hh index 8910447..ccbbfce 100644 --- a/src/bin/eolian_mono/eolian/mono/name_helpers.hh +++ b/src/bin/eolian_mono/eolian/mono/name_helpers.hh @@ -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 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 diff --git a/src/bin/eolian_mono/eolian/mono/parameter.hh b/src/bin/eolian_mono/eolian/mono/parameter.hh index 416cacb..efb907f 100644 --- a/src/bin/eolian_mono/eolian/mono/parameter.hh +++ b/src/bin/eolian_mono/eolian/mono/parameter.hh @@ -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 {}; } +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 {}; +} + +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 {}; +} + +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 {}; +} + } } } namespace eolian_mono { @@ -1436,6 +1473,89 @@ struct native_convert_function_pointer_generator } const native_convert_function_pointer {}; +struct constructor_parameter_name_generator +{ + + template + 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 + 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 + 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 diff --git a/src/bin/eolian_mono/eolian/mono/type.hh b/src/bin/eolian_mono/eolian/mono/type.hh index b968d9e..f6a5285 100644 --- a/src/bin/eolian_mono/eolian/mono/type.hh +++ b/src/bin/eolian_mono/eolian/mono/type.hh @@ -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 bool generate(OutputIterator sink, attributes::type_def const& type, Context const& context) const { - return type.original_type.visit(visitor_generate{sink, &context, type.c_type, false, is_return, type.is_ptr}); + return type.original_type.visit(visitor_generate{sink, &context, type.c_type, false, is_return, type.is_ptr, is_optional}); } template bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const { return param.type.original_type.visit(visitor_generate{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 = {}; diff --git a/src/bin/eolian_mono/eolian/mono/type_impl.hh b/src/bin/eolian_mono/eolian/mono/type_impl.hh index 3e4ae8d..c449d21 100644 --- a/src/bin/eolian_mono/eolian/mono/type_impl.hh +++ b/src/bin/eolian_mono/eolian/mono/type_impl.hh @@ -34,6 +34,20 @@ attributes::regular_type_def replace_base_integer(attributes::regular_type_def v } } +template +attributes::regular_type_def replace_base_opt_integer(attributes::regular_type_def v) +{ + bool s = std::is_signed::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 visitor_type; typedef bool result_type; @@ -76,6 +91,40 @@ struct visitor_generate eina::optional has_own; std::function 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(regular); }} + , {"int", nullptr, [&] { return replace_base_opt_integer(regular); }} + , {"long", nullptr, [&] { return replace_base_opt_integer(regular); }} + , {"llong", nullptr, [&] { return replace_base_opt_integer(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(regular); }} + // unsigned primitives + , {"ubyte", nullptr, [&] { return replace_base_type(regular, " byte?"); }} + , {"ushort", nullptr, [&] { return replace_base_opt_integer(regular); }} + , {"uint", nullptr, [&] { return replace_base_opt_integer(regular); }} + , {"ulong", nullptr, [&] { return replace_base_opt_integer(regular); }} + , {"ullong", nullptr, [&] { return replace_base_opt_integer(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(regular); }} + + , {"ptrdiff", nullptr, [&] { return replace_base_opt_integer(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 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 b = call_match (match_table , [&] (match const& m) { diff --git a/src/bindings/mono/eo_mono/iwrapper.cs b/src/bindings/mono/eo_mono/iwrapper.cs index fe96088..2119e07 100644 --- a/src/bindings/mono/eo_mono/iwrapper.cs +++ b/src/bindings/mono/eo_mono/iwrapper.cs @@ -157,6 +157,23 @@ public class Globals { public delegate byte class_initializer(IntPtr klass); + public static T GetParamHelper(Nullable v) where T : struct + { + return v.Value; + } + public static U GetParamHelper(U v) + { + return v; + } + public static bool ParamHelperCheck(Nullable v) where T : struct + { + return v.HasValue; + } + public static bool ParamHelperCheck(U v) + { + return v != null; + } + public static IntPtr register_class(String class_name, IntPtr base_klass, System.Type type) { ClassDescription description; diff --git a/src/tests/efl_mono/Eo.cs b/src/tests/efl_mono/Eo.cs index 5567f1e..37d4735 100644 --- a/src/tests/efl_mono/Eo.cs +++ b/src/tests/efl_mono/Eo.cs @@ -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()); + } +} + } diff --git a/src/tests/efl_mono/Events.cs b/src/tests/efl_mono/Events.cs index 84918b9..7856878 100644 --- a/src/tests/efl_mono/Events.cs +++ b/src/tests/efl_mono/Events.cs @@ -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); diff --git a/src/tests/efl_mono/dummy_child.eo b/src/tests/efl_mono/dummy_child.eo index e3e1a7c..b7845d9 100644 --- a/src/tests/efl_mono/dummy_child.eo +++ b/src/tests/efl_mono/dummy_child.eo @@ -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; } } diff --git a/src/tests/efl_mono/libefl_mono_native_test.c b/src/tests/efl_mono/libefl_mono_native_test.c index 986cd1f..5108621 100644 --- a/src/tests/efl_mono/libefl_mono_native_test.c +++ b/src/tests/efl_mono/libefl_mono_native_test.c @@ -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) { -- 2.7.4