From cd72923bf178cca1a0418ed55956769add2732d8 Mon Sep 17 00:00:00 2001 From: Felipe Magno de Almeida Date: Thu, 26 Dec 2019 23:50:20 -0300 Subject: [PATCH] eolian-mono: Make Get/Set protected for generated properties Make Get and Set methods protected for properties that get the property syntax generated. This is still a work in progress and fails compilation. Native calls should use the property-syntax instead of the method, which may not be available in some interfaces. --- src/bin/eolian_mono/eolian/mono/blacklist.hh | 2 +- .../eolian_mono/eolian/mono/documentation.hh | 88 +++- .../eolian/mono/function_declaration.hh | 69 +++ .../eolian/mono/function_definition.hh | 414 +++++++++++++++++- .../eolian/mono/function_registration.hh | 5 + src/bin/eolian_mono/eolian/mono/helpers.hh | 130 +++++- src/bin/eolian_mono/eolian/mono/klass.hh | 78 +++- src/bindings/mono/efl_mono/GenericModel.cs | 31 +- src/bindings/mono/efl_mono/UserModel.cs | 2 +- src/bindings/mono/efl_sharp.csproj.in | 2 +- src/bindings/mono/eo_mono/EoWrapper.cs | 2 +- src/lib/eolian_cxx/grammar/klass_def.hpp | 62 +++ src/tests/efl_mono/Eo.cs | 4 +- src/tests/efl_mono/Model.cs | 2 +- 14 files changed, 803 insertions(+), 88 deletions(-) diff --git a/src/bin/eolian_mono/eolian/mono/blacklist.hh b/src/bin/eolian_mono/eolian/mono/blacklist.hh index 70bc34a038..6e73d80e49 100644 --- a/src/bin/eolian_mono/eolian/mono/blacklist.hh +++ b/src/bin/eolian_mono/eolian/mono/blacklist.hh @@ -163,7 +163,7 @@ inline bool is_property_blacklisted(std::string const& name) // Will be bound manually , "Efl.Core.Env.Env" // Setter returns a future - , "Efl.IModel.Property" + //, "Efl.IModel.Property" // Protected , "Efl.Access.IAction.ActionName" , "Efl.Access.IAction.ActionLocalizedName" diff --git a/src/bin/eolian_mono/eolian/mono/documentation.hh b/src/bin/eolian_mono/eolian/mono/documentation.hh index db00ba8a0f..1c7c1e5409 100644 --- a/src/bin/eolian_mono/eolian/mono/documentation.hh +++ b/src/bin/eolian_mono/eolian/mono/documentation.hh @@ -118,13 +118,7 @@ struct documentation_generator name += name_helpers::managed_method_name({function, ftype, NULL, eolian_object_unit_get(EOLIAN_OBJECT(function))}); break; case ::EOLIAN_PROP_SET: - name += ".Set"; - name += name_helpers::property_managed_name(klass_d, eo_name); - break; case ::EOLIAN_PROP_GET: - name += ".Get"; - name += name_helpers::property_managed_name(klass_d, eo_name); - break; case ::EOLIAN_PROPERTY: { std::string short_name = name_helpers::property_managed_name(klass_d, eo_name); @@ -146,11 +140,16 @@ struct documentation_generator auto has_wrapper = helpers::has_property_wrapper(prop, &klass_d, my_context); - if (has_wrapper == helpers::has_property_wrapper_bit::has_none) - name += ".Get" + short_name; - else if (name_tail == ".get") name += ".Get" + short_name; - else if (name_tail == ".set") name += ".Set" + short_name; - else name += "." + short_name; + if (has_wrapper & helpers::has_property_wrapper_bit::has_getter + // If there is no getter, there's no property. + && + ( + (ftype == EOLIAN_PROP_GET || ftype == EOLIAN_PROPERTY) + || (has_wrapper & helpers::has_property_wrapper_bit::has_setter && ftype == EOLIAN_PROP_SET)) + ) + name += "." + short_name; + else if (ftype == EOLIAN_PROP_GET || name_tail == ".get") name += ".Get" + short_name; + else if (ftype == EOLIAN_PROP_SET || name_tail == ".set") name += ".Set" + short_name; } break; default: @@ -159,18 +158,69 @@ struct documentation_generator return name; } - static std::string function_conversion(attributes::function_def const& func) + template + static std::string function_conversion(attributes::function_def const& func, Context const& context) { // This function is called only from the constructor reference conversion, so it does not // need to check whether this function non-public in a interface returning an empty reference (yet). std::string name = name_helpers::klass_full_concrete_or_interface_name(func.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::property: case attributes::function_type::prop_set: case attributes::function_type::prop_get: + { + auto unit = (const Eolian_Unit*) context_find_tag(context).state; + auto klass = get_klass(func.klass, unit); + attributes::klass_def klass_d(klass, unit); + + auto eo_name = func.name; + auto prop_name = eo_name; + if (prop_name.size () > 4 + && + ( prop_name.substr(prop_name.size() - 4) == "_set" + || prop_name.substr(prop_name.size() - 4) == "_get")) + { + prop_name = prop_name.substr(0, prop_name.size() - 4); + } + std::string short_name = name_helpers::property_managed_name(klass_d, prop_name); + assert (prop_name.size() <= 4 || + (prop_name.substr(prop_name.size() - 4) != "_set" + && prop_name.substr(prop_name.size() - 4) != "_get")); + assert (short_name.size() <= 3 || + (short_name.substr(short_name.size() - 3) != "Set" + && short_name.substr(short_name.size() - 3) != "Get")); + + // We need to replace the current class context with the context + // from the class that originated this property. + class_context::wrapper_kind klass_kind; + if (helpers::is_managed_interface(klass_d)) + klass_kind = class_context::interface; + else + klass_kind = class_context::inherit; + + auto my_context = grammar::context_replace_tag(class_context{klass_kind}, context); + + auto function = eolian_class_function_by_name_get (klass, prop_name.c_str(), EOLIAN_PROPERTY); + attributes::function_def getter_func{function, ::EOLIAN_PROP_GET, nullptr, unit}; + attributes::function_def setter_func{function, ::EOLIAN_PROP_SET, nullptr, unit}; + attributes::property_def prop{function, getter_func, setter_func, unit}; + + auto has_wrapper = helpers::has_property_wrapper(prop, &klass_d, my_context); + + if (has_wrapper & helpers::has_property_wrapper_bit::has_getter + // If there is no getter, there's no property. + && + ( + (func.type == attributes::function_type::prop_get || func.type == attributes::function_type::property) + || (has_wrapper & helpers::has_property_wrapper_bit::has_setter && func.type == attributes::function_type::prop_set)) + ) + name += "." + short_name; + else if (func.type == attributes::function_type::prop_get) name += ".Get" + short_name; + else if (func.type == attributes::function_type::prop_set) name += ".Set" + short_name; + } + break; + case attributes::function_type::method: if (blacklist::is_function_blacklisted(func.c_name))return ""; if (!name.empty()) name += "."; name += name_helpers::managed_method_name(func); @@ -218,8 +268,10 @@ struct documentation_generator is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2); break; case ::EOLIAN_OBJECT_FUNCTION: - ref += function_conversion(data, (const ::Eolian_Function *)data2, name_tail, context); - is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2); + { + ref += function_conversion(data, (const ::Eolian_Function *)data2, name_tail, context); + is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2); + } break; case ::EOLIAN_OBJECT_CONSTANT: { @@ -634,7 +686,7 @@ struct documentation_generator for (auto &¶m : ctor.function.parameters) { - auto ref = function_conversion(func); + auto ref = function_conversion(func, context); if (!context_find_tag(context).want_beta && func.is_beta) { diff --git a/src/bin/eolian_mono/eolian/mono/function_declaration.hh b/src/bin/eolian_mono/eolian/mono/function_declaration.hh index b71ffb121c..ab59b85d8f 100644 --- a/src/bin/eolian_mono/eolian/mono/function_declaration.hh +++ b/src/bin/eolian_mono/eolian/mono/function_declaration.hh @@ -53,6 +53,63 @@ struct function_declaration_generator function_declaration_generator const function_declaration = {}; +struct property_declaration_generator +{ + template + bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const + { + if(blacklist::is_property_blacklisted(property, *implementing_klass, context)) + return true; + + auto has_wrapper = helpers::has_property_wrapper (property, implementing_klass, context); + bool has_getter_wrapper = has_wrapper & helpers::has_property_wrapper_bit::has_getter; + bool has_setter_wrapper = has_wrapper & helpers::has_property_wrapper_bit::has_setter; + + auto gen = [&] (attributes::function_def const& f) + { + // C# interfaces can't have non-public members + if(f.scope != attributes::member_scope::scope_public) + return true; + + if (f.is_static) + return true; + + if(!as_generator(documentation(1)).generate(sink, f, context)) + return false; + + return as_generator + (scope_tab << eolian_mono::type(true) << " " << string << "(" << (parameter % ", ") << ");\n\n") + .generate(sink, std::make_tuple(f.return_type, name_helpers::managed_method_name(f), f.parameters), context); + }; + bool r = true; + if (property.getter) + { + if (!has_getter_wrapper) + r &= gen (*property.getter); + // else + // r &= function_declaration.generate(sink, *property.getter, context); + } + if (r && property.setter) + { + if (!has_setter_wrapper) + r &= gen (*property.setter); + // else + // r &= function_declaration.generate(sink, *property.setter, context); + } + return r; + } + attributes::klass_def const* implementing_klass, *klass_from_property; +}; + +struct property_declaration_parameterized +{ + property_declaration_generator operator()(attributes::klass_def const& klass + , attributes::klass_def const& prop_from_klass) const + { + return {&klass, &prop_from_klass}; + } +} const property_declaration; + } namespace efl { namespace eolian { namespace grammar { @@ -60,11 +117,23 @@ namespace efl { namespace eolian { namespace grammar { template <> struct is_eager_generator< ::eolian_mono::function_declaration_generator> : std::true_type {}; template <> +struct is_eager_generator< ::eolian_mono::property_declaration_generator> : std::true_type {}; +template <> +struct is_eager_generator< ::eolian_mono::property_declaration_parameterized> : std::true_type {}; +template <> struct is_generator< ::eolian_mono::function_declaration_generator> : std::true_type {}; +template <> +struct is_generator< ::eolian_mono::property_declaration_generator> : std::true_type {}; +template <> +struct is_generator< ::eolian_mono::property_declaration_parameterized> : std::true_type {}; namespace type_traits { template <> struct attributes_needed< ::eolian_mono::function_declaration_generator> : std::integral_constant {}; +template <> +struct attributes_needed< ::eolian_mono::property_declaration_generator> : std::integral_constant {}; +template <> +struct attributes_needed< ::eolian_mono::property_declaration_parameterized> : std::integral_constant {}; } } } } diff --git a/src/bin/eolian_mono/eolian/mono/function_definition.hh b/src/bin/eolian_mono/eolian/mono/function_definition.hh index 86eb2db192..cbf2e2b99d 100644 --- a/src/bin/eolian_mono/eolian/mono/function_definition.hh +++ b/src/bin/eolian_mono/eolian/mono/function_definition.hh @@ -50,6 +50,10 @@ struct native_function_definition_generator bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const { EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "native_function_definition_generator: " << f.c_name << std::endl; + assert (!(f.type == attributes::function_type::property + || f.type == attributes::function_type::prop_set + || f.type == attributes::function_type::prop_get)); + if(blacklist::is_function_blacklisted(f, context)) return true; @@ -183,6 +187,203 @@ struct native_function_definition_generator } }; +struct native_property_function_definition_generator +{ + template + bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const + { + EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "native_property_function_definition_generator: " << property.name << std::endl; + + if(blacklist::is_property_blacklisted(property, *implementing_klass, context)) + return true; + + auto const& indent = current_indentation(context); + + auto has_wrapper = helpers::has_property_wrapper (property, implementing_klass, context); + bool has_wrapper_getter = has_wrapper & helpers::has_property_wrapper_bit::has_getter; + bool has_wrapper_setter = has_wrapper & helpers::has_property_wrapper_bit::has_setter; + + auto gen = [&] (attributes::function_def const& f, bool is_set) + { + // Delegate for the C# method we will export to EO as a method implementation. + if(!as_generator + ( + indent << eolian_mono::marshall_annotation(true) << "\n" + << indent << "private delegate " + << eolian_mono::marshall_type(true) + << " " + << string + << "_delegate(" << (f.is_static ? "" : "System.IntPtr obj, System.IntPtr pd") + << ((!f.is_static && f.parameters.size() > 0) ? ", " : "") + << (grammar::attribute_reorder<-1, -1> + ( + (marshall_annotation << " " << marshall_parameter) + ) % ", ") + << ");\n\n") + .generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context)) + return false; + + // API delegate is the wrapper for the Eo methods exported from C that we will use from C#. + if(!as_generator + ( + indent << eolian_mono::marshall_annotation(true) << "\n" + << indent << "internal delegate " + << eolian_mono::marshall_type(true) + << " " + << string << "_api_delegate(" << (f.is_static ? "" : "System.IntPtr obj") + << ((!f.is_static && f.parameters.size() > 0) ? ", " : "") + << (grammar::attribute_reorder<-1, -1> + ( + (marshall_annotation << " " << marshall_parameter) + ) % ", ") + << ");\n\n") + .generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context)) + return false; + + // Delegate holder (so it can't be collected). + if(!as_generator + (indent << "internal static readonly Efl.Eo.FunctionWrapper<" << string << "_api_delegate> " << string << "_ptr = new Efl.Eo.FunctionWrapper<" + << string << "_api_delegate>(Module, \"" << string << "\");\n\n") + .generate(sink, std::make_tuple(f.c_name, f.c_name, f.c_name, f.c_name), context)) + return false; + + // We do not generate the wrapper to be called from C for non public interface member directly. + if (blacklist::is_non_public_interface_member(f, *implementing_klass)) + return true; + + // Do not generate static method in interface + if (((implementing_klass->type == attributes::class_type::interface_) || + (implementing_klass->type == attributes::class_type::mixin)) && f.is_static) + return true; + + // Actual method implementation to be called from C. + std::string return_type; + if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context)) + return false; + + std::string klass_cast_name; + if ((implementing_klass->type == attributes::class_type::interface_) || + ((implementing_klass->type == attributes::class_type::mixin) && !f.is_static)) + klass_cast_name = name_helpers::klass_interface_name(*implementing_klass); + else + klass_cast_name = name_helpers::klass_inherit_name(*implementing_klass); + + std::string self = "Efl.Eo.Globals.Super(obj, Efl.Eo.Globals.GetClass(obj))"; + + if (f.is_static) + self = ""; + + if(!as_generator + (indent << "[SuppressMessage(\"Microsoft.Reliability\", \"CA2000:DisposeObjectsBeforeLosingScope\", Justification = \"The instantiated objects can be stored in the called Managed API method.\")]\n" + << indent << "private static " + << eolian_mono::marshall_type(true) << " " + << string + << "(System.IntPtr obj, System.IntPtr pd" + << *(", " << marshall_parameter) + << ")\n" + << indent << "{\n" + << indent << scope_tab << "Eina.Log.Debug(\"function " << string << " was called\");\n" + << indent << scope_tab << "var ws = Efl.Eo.Globals.GetWrapperSupervisor(obj);\n" + << indent << scope_tab << "if (ws != null)\n" + << indent << scope_tab << "{\n" + << indent << scope_tab << scope_tab << eolian_mono::native_function_definition_preamble() << "\n" + << indent << scope_tab << scope_tab << "try\n" + << indent << scope_tab << scope_tab << "{\n" + ) + .generate(sink, std::make_tuple(f.return_type, escape_keyword(f.name), f.parameters + , /***/f.c_name/***/ + , f + ), context)) + return false; + if (is_set && has_wrapper_setter) + { + if(!as_generator + ( + indent << scope_tab << scope_tab << scope_tab << (return_type != "void" ? "_ret_var = " : "") + << (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")ws.Target).") << string + ) + .generate(sink, std::make_tuple(name_helpers::property_managed_name(property), f.parameters), context)) + return false; + + if(!f.keys.empty() && !as_generator(lit("[(") << (native_argument_invocation % ", ") << ")]").generate (sink, f.keys, context)) + return false; + + if(!as_generator + (" = (" + << (native_argument_invocation % ", ") << ");\n" + ) + .generate(sink, f.values, context)) + return false; + } + else if (!is_set && has_wrapper_getter) + { + if(!as_generator + ( + indent << scope_tab << scope_tab << scope_tab << "var ret = " + << (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")ws.Target).") + << string + + ) + .generate(sink, std::make_tuple(name_helpers::property_managed_name(property)), context)) + return false; + + if(!f.keys.empty() && !as_generator(lit("[(") << (native_argument_invocation % ", ") << ")]").generate (sink, f.keys, context)) + return false; + + if (!as_generator(";\n").generate (sink, attributes::unused, context)) + return false; + + } + else if (!as_generator + (indent << scope_tab << scope_tab << scope_tab << (return_type != "void" ? "_ret_var = " : "") + << (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")ws.Target).") << string + << "(" << (native_argument_invocation % ", ") << ");\n" + ).generate(sink, std::make_tuple(name_helpers::managed_method_name(f), f.parameters), context)) + return false; + + if(!as_generator + ( + indent << scope_tab << scope_tab << "}\n" + << indent << scope_tab << scope_tab << "catch (Exception e)\n" + << indent << scope_tab << scope_tab << "{\n" + << indent << scope_tab << scope_tab << scope_tab << "Eina.Log.Warning($\"Callback error: {e.ToString()}\");\n" + << indent << scope_tab << scope_tab << scope_tab << "Eina.Error.Set(Eina.Error.UNHANDLED_EXCEPTION);\n" + << indent << scope_tab << scope_tab << "}\n\n" + << indent << eolian_mono::native_function_definition_epilogue(*implementing_klass) << "\n" + << indent << scope_tab << "}\n" + << indent << scope_tab << "else\n" + << indent << scope_tab << "{\n" + << indent << scope_tab << scope_tab << (return_type != "void" ? "return " : "") << string + << "_ptr.Value.Delegate(" << self << ((!f.is_static && f.parameters.size() > 0) ? ", " : "") << (argument % ", ") << ");\n" + << indent << scope_tab << "}\n" + << indent << "}\n\n" + ) + .generate(sink, std::make_tuple(f, f.c_name, f.parameters), context)) + return false; + + // Static functions do not need to be called from C + if (f.is_static) + return true; + + // This is the delegate that will be passed to Eo to be called from C. + // if(!as_generator( + // indent << "private static " << f.c_name << "_delegate " << f.c_name << "_static_delegate;\n\n" + // ).generate(sink, attributes::unused, context)) + // return false; + return true; + }; + + bool r = true; + if(r && property.getter) + r &= gen (*property.getter, false); + if(r && property.setter) + r &= gen (*property.setter, true); + return r; + } + + attributes::klass_def const* implementing_klass, *klass_from_property; +}; + struct function_definition_generator { function_definition_generator(bool do_super = false) @@ -194,6 +395,10 @@ struct function_definition_generator { EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "function_definition_generator: " << f.c_name << std::endl; + assert (!(f.type == attributes::function_type::property + || f.type == attributes::function_type::prop_set + || f.type == attributes::function_type::prop_get)); + bool is_concrete = context_find_tag(context).current_wrapper_kind == class_context::concrete; if(blacklist::is_function_blacklisted(f, context)) return true; @@ -256,6 +461,14 @@ struct native_function_definition_parameterized return {&klass}; } } const native_function_definition; +struct native_property_function_definition_parameterized +{ + native_property_function_definition_generator operator()(attributes::klass_def const& klass + , attributes::klass_def const& prop_from_klass) const + { + return {&klass, &prop_from_klass}; + } +} const native_property_function_definition; struct property_extension_method_definition_generator { @@ -414,9 +627,9 @@ struct property_wrapper_definition_generator } assert (!get_keys.empty()); - generate_get(sink, property, context, get_scope, get_keys, values, is_interface, "Self."); + generate_get(sink, property, context, get_scope, get_keys, values, is_interface, "((" + name_helpers::klass_full_concrete_name (*implementing_klass) + ")Self)."); if (has_setter) - generate_set(sink, property, context, set_scope, get_keys, values, is_interface, "Self."); + generate_set(sink, property, context, set_scope, get_keys, values, is_interface, "((" + name_helpers::klass_full_concrete_name (*implementing_klass) + ")Self)."); if (!as_generator ( @@ -648,22 +861,40 @@ struct property_wrapper_definition_generator std::string set_scope = has_setter ? eolian_mono::function_scope_get(*property.setter) : ""; // C# interface members are declared automatically as public - if (is_interface) + if (force_protected) + { + scope = "protected "; + get_scope = ""; + set_scope = ""; + } + else if (is_interface) { scope = ""; get_scope = ""; set_scope = ""; } - else if ((get_scope != "") && (get_scope == set_scope)) + else { - scope = get_scope; - get_scope = ""; - set_scope = ""; - } - else if (!has_setter || (get_scope == scope)) - { - scope = get_scope; - get_scope = ""; + auto want_beta = context_find_tag(context).want_beta; + if (!want_beta && property.getter->is_beta) + { + get_scope = "protected "; + } + if (property.setter && !want_beta && property.setter->is_beta) + { + set_scope = "protected "; + } + if ((get_scope != "") && (get_scope == set_scope)) + { + scope = get_scope; + get_scope = ""; + set_scope = ""; + } + else if (!has_setter || (get_scope == scope)) + { + scope = get_scope; + get_scope = ""; + } } std::string virtual_mod = (is_static || is_interface || is_concrete) ? "" : "virtual "; @@ -735,6 +966,10 @@ struct property_wrapper_definition_generator if (has_indexer) { generate_get_indexer (sink, property, context, get_scope, is_interface); + if (is_interface) + as_generator(scope_tab(2) << "set;\n").generate (sink, attributes::unused, context); + else + as_generator(scope_tab(2) << "set {}\n").generate (sink, attributes::unused, context); } else { @@ -751,18 +986,20 @@ struct property_wrapper_definition_generator return true; } attributes::klass_def const* implementing_klass, *klass_from_property; + bool force_protected; }; struct property_wrapper_definition_parameterized { property_wrapper_definition_generator operator()(attributes::klass_def const& klass - , attributes::klass_def const& prop_from_klass) const + , attributes::klass_def const& prop_from_klass + , bool force_protected = false) const { - return {&klass, &prop_from_klass}; + return {&klass, &prop_from_klass, force_protected}; } } const property_wrapper_definition; property_wrapper_definition_generator as_generator(property_wrapper_definition_parameterized) { - return {}; + return {nullptr, nullptr, false}; } struct interface_property_indexer_definition_generator @@ -776,18 +1013,52 @@ struct interface_property_indexer_definition_generator using efl::eolian::grammar::attributes::parameter_def; bool is_interface = context_find_tag(context).current_wrapper_kind == class_context::interface; + auto has_wrapper = helpers::has_property_wrapper (property, implementing_klass, context); + bool has_wrapper_getter = has_wrapper & helpers::has_property_wrapper_bit::has_getter; + bool has_wrapper_setter = has_wrapper & helpers::has_property_wrapper_bit::has_setter; + if (!has_wrapper_getter || !(has_wrapper & helpers::has_property_wrapper_bit::has_indexer)) + return true; + assert (is_interface); auto klass_name = name_helpers::klass_concrete_or_interface_name (*implementing_klass); std::string managed_name = name_helpers::property_managed_name(property); if (!as_generator - ("public interface " << name_helpers::property_interface_indexer_short_name(property, *implementing_klass) << "\n" - << "{\n" - << "}\n" + ("public interface " << name_helpers::property_interface_indexer_short_name(property, *implementing_klass) << "\n{\n" ).generate (sink, attributes::unused, context)) return false; + auto size_not_one = [] (std::vector k) { return k.size() != 1; }; + auto type_or_tuple + = + ( + ( + attribute_conditional(size_not_one)["("] + << (type(false) % ", ") + << ")" + ) + | *type(false) + ) + ; + auto keys = property.getter->keys; + auto values = property.getter->values; + if (!as_generator(scope_tab(2) << "public " + << type_or_tuple << " this[" << type_or_tuple <<" i]\n" + << scope_tab(2) << "{\n" + ).generate(sink, make_tuple(values, values, keys, keys), context)) + return false; + + property_wrapper_definition_generator p {implementing_klass, implementing_klass}; + p.generate_get_indexer (sink, property, context, "", true); + if (has_wrapper_setter) + as_generator(scope_tab(3) << "set;\n").generate (sink, attributes::unused, context); + + if (!as_generator + (scope_tab(2) << "}\n}\n" + ).generate (sink, attributes::unused, context)) + return false; + return true; } attributes::klass_def const* implementing_klass; @@ -804,6 +1075,93 @@ interface_property_indexer_definition_generator as_generator(interface_property_ return {}; } +struct property_function_definition_generator +{ + template + bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const + { + bool is_concrete = context_find_tag(context).current_wrapper_kind == class_context::concrete; + bool is_interface = context_find_tag(context).current_wrapper_kind == class_context::interface; + assert (!is_interface); + if(blacklist::is_property_blacklisted(property, *implementing_klass, context)) + return true; + + auto has_wrapper = helpers::has_property_wrapper (property, implementing_klass, context); + bool has_wrapper_getter = has_wrapper & helpers::has_property_wrapper_bit::has_getter; + bool has_wrapper_setter = has_wrapper & helpers::has_property_wrapper_bit::has_setter; + + auto gen = [&] (attributes::function_def const& f, bool is_protected) -> bool + { + // Do not generate static function for concrete class + if (is_concrete && f.is_static) + return true; + + std::string return_type; + if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context)) + return false; + + if(!as_generator + (documentation(1)).generate(sink, f, context)) + return false; + + std::string self = "this.NativeHandle"; + + // IsGeneratedBindingClass is set in the constructor, true if this + // instance is from a pure C# class (not generated). + if (do_super && !f.is_static) + self = "(IsGeneratedBindingClass ? " + self + " : Efl.Eo.Globals.Super(" + self + ", this.NativeClass))"; + else if (f.is_static) + self = ""; + + auto scope = is_protected ? "protected " : eolian_mono::function_scope_get(f); + + if(!as_generator + (scope_tab << scope << ((do_super && !f.is_static) ? "virtual " : "") << (f.is_static ? "static " : "") << return_type << " " << string << "(" << (parameter % ", ") + << ") {\n" + << scope_tab(2) << eolian_mono::function_definition_preamble() + << klass_full_native_inherit_name(f.klass) << "." << string << "_ptr.Value.Delegate(" + << self + << ((!f.is_static && (f.parameters.size() > 0)) ? ", " : "") + << (argument_invocation % ", ") << ");\n" + << scope_tab(2) << eolian_mono::function_definition_epilogue() + << scope_tab(1) << "}\n\n") + .generate(sink, std::make_tuple(name_helpers::managed_method_name(f), f.parameters, f, f.c_name, f.parameters, f), context)) + return false; + return true; + }; + + bool r = true; + bool is_self_property = *implementing_klass == *klass_from_property; + bool property_from_interface = (klass_from_property->type == attributes::class_type::interface_ + || klass_from_property->type == attributes::class_type::mixin); + //bool v = is_self_property && !is_concrete_for_interface; + + if (r && property.getter) + r &= gen ( *property.getter, always_public ? false : !property_from_interface && has_wrapper_getter); + if (r && property.setter) + r &= gen ( *property.setter, always_public ? false : !property_from_interface && has_wrapper_setter); + + return r; + } + + attributes::klass_def const* implementing_klass, *klass_from_property; + bool do_super, always_public; +}; +struct property_function_definition_parameterized +{ + property_function_definition_generator operator()(attributes::klass_def const& klass + , attributes::klass_def const& prop_from_klass + , bool do_super + , bool always_public = false) const + { + return {&klass, &prop_from_klass, do_super, always_public}; + } +} const property_function_definition; +property_function_definition_generator as_generator(property_function_definition_parameterized) +{ + return {nullptr, nullptr, false}; +} + } namespace efl { namespace eolian { namespace grammar { @@ -813,12 +1171,18 @@ struct is_eager_generator< ::eolian_mono::function_definition_generator> : std:: template <> struct is_eager_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {}; template <> +struct is_eager_generator< ::eolian_mono::native_property_function_definition_generator> : std::true_type {}; +template <> struct is_eager_generator< ::eolian_mono::property_extension_method_definition_generator> : std::true_type {}; template <> struct is_eager_generator< ::eolian_mono::property_wrapper_definition_generator> : std::true_type {}; template <> struct is_eager_generator< ::eolian_mono::property_wrapper_definition_parameterized> : std::true_type {}; template <> +struct is_eager_generator< ::eolian_mono::property_function_definition_generator> : std::true_type {}; +template <> +struct is_eager_generator< ::eolian_mono::property_function_definition_parameterized> : std::true_type {}; +template <> struct is_eager_generator< ::eolian_mono::interface_property_indexer_definition_parameterized> : std::true_type {}; template <> struct is_eager_generator< ::eolian_mono::interface_property_indexer_definition_generator> : std::true_type {}; @@ -827,6 +1191,8 @@ struct is_generator< ::eolian_mono::function_definition_generator> : std::true_t template <> struct is_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {}; template <> +struct is_generator< ::eolian_mono::native_property_function_definition_generator> : std::true_type {}; +template <> struct is_generator< ::eolian_mono::function_definition_parameterized> : std::true_type {}; template <> struct is_generator< ::eolian_mono::property_extension_method_definition_generator> : std::true_type {}; @@ -835,6 +1201,10 @@ struct is_generator< ::eolian_mono::property_wrapper_definition_generator> : std template <> struct is_generator< ::eolian_mono::property_wrapper_definition_parameterized> : std::true_type {}; template <> +struct is_generator< ::eolian_mono::property_function_definition_generator> : std::true_type {}; +template <> +struct is_generator< ::eolian_mono::property_function_definition_parameterized> : std::true_type {}; +template <> struct is_generator< ::eolian_mono::interface_property_indexer_definition_parameterized> : std::true_type {}; template <> struct is_generator< ::eolian_mono::interface_property_indexer_definition_generator> : std::true_type {}; @@ -849,6 +1219,9 @@ struct attributes_needed< ::eolian_mono::function_definition_parameterized> : st template <> struct attributes_needed< ::eolian_mono::native_function_definition_generator> : std::integral_constant {}; +template <> +struct attributes_needed< ::eolian_mono::native_property_function_definition_generator> : std::integral_constant {}; + template <> struct attributes_needed< ::eolian_mono::property_extension_method_definition_generator> : std::integral_constant {}; @@ -857,6 +1230,11 @@ struct attributes_needed< ::eolian_mono::property_wrapper_definition_generator> template <> struct attributes_needed< ::eolian_mono::property_wrapper_definition_parameterized> : std::integral_constant {}; +template <> +struct attributes_needed< ::eolian_mono::property_function_definition_generator> : std::integral_constant {}; +template <> +struct attributes_needed< ::eolian_mono::property_function_definition_parameterized> : std::integral_constant {}; + template <> struct attributes_needed< ::eolian_mono::interface_property_indexer_definition_parameterized> : std::integral_constant {}; template <> diff --git a/src/bin/eolian_mono/eolian/mono/function_registration.hh b/src/bin/eolian_mono/eolian/mono/function_registration.hh index bef9e21384..f614c26fdf 100644 --- a/src/bin/eolian_mono/eolian/mono/function_registration.hh +++ b/src/bin/eolian_mono/eolian/mono/function_registration.hh @@ -55,6 +55,11 @@ struct function_registration_generator if(blacklist::is_non_public_interface_member(f, *klass)) return true; + if (f.type == attributes::function_type::property + || f.type == attributes::function_type::prop_get + || f.type == attributes::function_type::prop_set) + return true; + if(!as_generator( indent << "if (" << f.c_name << "_static_delegate == null)\n" << indent << "{\n" diff --git a/src/bin/eolian_mono/eolian/mono/helpers.hh b/src/bin/eolian_mono/eolian/mono/helpers.hh index 049f263d80..31f85924b8 100644 --- a/src/bin/eolian_mono/eolian/mono/helpers.hh +++ b/src/bin/eolian_mono/eolian/mono/helpers.hh @@ -163,6 +163,50 @@ std::set non_imp return interfaces; } +// Returns the set of interfaces implemented by this type that haven't been implemented +// by a regular parent class and beta path information +template +std::set, attributes::compare_klass_name_by_name> + non_implemented_interfaces_and_beta(attributes::klass_def const& cls, Context const& context) +{ + auto options = efl::eolian::grammar::context_find_tag(context); + std::set, attributes::compare_klass_name_by_name> implemented_interfaces; + std::set, attributes::compare_klass_name_by_name> interfaces; + + std::function inherit_algo = + [&] (attributes::klass_name const& klass, bool is_implemented, bool pbeta) + { + // TODO we could somehow cache klass_def instantiations + attributes::klass_def c(get_klass(klass, cls.unit), cls.unit); + for(auto&& inherit : c.immediate_inherits) + { + auto beta = pbeta | inherit.is_beta; + switch(inherit.type) + { + case attributes::class_type::mixin: + case attributes::class_type::interface_: + interfaces.insert(std::make_pair(inherit, beta)); + if (is_implemented) + implemented_interfaces.insert(std::make_pair(inherit, beta)); + inherit_algo(inherit, is_implemented, beta); + break; + case attributes::class_type::abstract_: + case attributes::class_type::regular: + inherit_algo(inherit, true, beta); + default: + break; + } + } + }; + + inherit_algo(get_klass_name(cls), false, cls.is_beta); + + for (auto&& inherit : implemented_interfaces) + interfaces.erase(inherit); + + return interfaces; +} + /* * Determines whether this class has any regular ancestor or not @@ -195,18 +239,29 @@ bool inherits_from(attributes::klass_def const& cls, std::string const& name) * Gets all methods that this class should implement (i.e. that come from an unimplemented interface/mixin and the class itself) */ template -std::vector get_all_implementable_methods(attributes::klass_def const& cls, Context const& context) +std::vector get_all_implementable_methods(attributes::klass_def const& cls, Context const& context + , bool insert_properties = false) { bool want_beta = efl::eolian::grammar::context_find_tag(context).want_beta; std::vector ret; - auto filter_beta = [&want_beta](attributes::function_def const& func) { + auto filter = [&](attributes::function_def const& func) { if (!want_beta) - return !func.is_beta; + return !func.is_beta + && ( + insert_properties + ? true + : + !(func.type == attributes::function_type::property + || func.type == attributes::function_type::prop_set + || func.type == attributes::function_type::prop_get)); else - return true; + return insert_properties ? true + : !(func.type == attributes::function_type::property + || func.type == attributes::function_type::prop_set + || func.type == attributes::function_type::prop_get); }; - std::copy_if(cls.functions.begin(), cls.functions.end(), std::back_inserter(ret), filter_beta); + std::copy_if(cls.functions.begin(), cls.functions.end(), std::back_inserter(ret), filter); // Non implemented interfaces std::set implemented_interfaces; @@ -243,7 +298,66 @@ std::vector get_all_implementable_methods(attributes:: for (auto&& inherit : interfaces) { attributes::klass_def klass(get_klass(inherit, cls.unit), cls.unit); - std::copy_if(klass.functions.cbegin(), klass.functions.cend(), std::back_inserter(ret), filter_beta); + std::copy_if(klass.functions.cbegin(), klass.functions.cend(), std::back_inserter(ret), filter); + } + + return ret; +} + +/* + * Gets all methods that this class should implement (i.e. that come from an unimplemented interface/mixin and the class itself) + */ +template +std::vector get_all_implementable_properties(attributes::klass_def const& cls, Context const& context) +{ + bool want_beta = efl::eolian::grammar::context_find_tag(context).want_beta; + std::vector ret; + auto filter_beta = [want_beta, cls](attributes::property_def const& prop) { + if (!want_beta) + return !cls.is_beta && (!prop.getter || !prop.getter->is_beta) + && (!prop.setter || !prop.setter->is_beta); + else + return true; + }; + + std::copy_if(cls.properties.begin(), cls.properties.end(), std::back_inserter(ret), filter_beta); + + // Non implemented interfaces + std::set implemented_interfaces; + std::set interfaces; + std::function inherit_algo = + [&] (attributes::klass_name const &klass, bool is_implemented) + { + attributes::klass_def c(get_klass(klass, cls.unit), cls.unit); + for (auto&& inherit: c.immediate_inherits) + { + switch(inherit.type) + { + case attributes::class_type::mixin: + case attributes::class_type::interface_: + interfaces.insert(inherit); + if (is_implemented) + implemented_interfaces.insert(inherit); + inherit_algo(inherit, is_implemented); + break; + case attributes::class_type::abstract_: + case attributes::class_type::regular: + inherit_algo(inherit, true); + default: + break; + } + } + }; + + inherit_algo(attributes::get_klass_name(cls), false); + + for (auto&& inherit : implemented_interfaces) + interfaces.erase(inherit); + + for (auto&& inherit : interfaces) + { + attributes::klass_def klass(get_klass(inherit, cls.unit), cls.unit); + std::copy_if(klass.properties.cbegin(), klass.properties.cend(), std::back_inserter(ret), filter_beta); } return ret; @@ -273,6 +387,10 @@ std::vector get_all_registerable_methods(attributes::k if (cls == func.klass) return true; + if (func.type == attributes::function_type::property + || func.type == attributes::function_type::prop_set + || func.type == attributes::function_type::prop_get) + return false; if (is_managed_interface(func.klass) && func.is_static) return true; diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh index 478c6a9c80..f2ea80247b 100644 --- a/src/bin/eolian_mono/eolian/mono/klass.hh +++ b/src/bin/eolian_mono/eolian/mono/klass.hh @@ -107,7 +107,7 @@ struct klass context); // Property wrappers - if (!as_generator(*(interface_property_indexer_definition(cls))).generate(sink, cls.properties, iface_cxt)) + if (!as_generator("\n\n" << *(interface_property_indexer_definition(cls))).generate(sink, cls.properties, iface_cxt)) return false; if(!as_generator(documentation).generate(sink, cls, iface_cxt)) @@ -146,7 +146,19 @@ struct klass if(!as_generator("\n{\n").generate(sink, attributes::unused, iface_cxt)) return false; - if(!as_generator(*(function_declaration)).generate(sink, cls.functions, iface_cxt)) + if(!as_generator("\n\n" << *(property_declaration(cls, cls))).generate(sink, cls.properties, iface_cxt)) + return false; + + std::vector methods; + std::copy_if (cls.functions.begin(), cls.functions.end() + , std::back_inserter(methods) + , [] (attributes::function_def const& f) -> bool + { + return !(f.type == attributes::function_type::property + || f.type == attributes::function_type::prop_set + || f.type == attributes::function_type::prop_get); + }); + if(!as_generator("\n" << scope_tab << "//* Methods\n\n" << *(function_declaration)).generate(sink, methods, iface_cxt)) return false; if(!as_generator(*(async_function_declaration)).generate(sink, cls.functions, iface_cxt)) @@ -253,23 +265,32 @@ struct klass if(!as_generator(*(part_definition)) .generate(sink, cls.parts, concrete_cxt)) return false; - // Concrete function definitions - auto implemented_methods = helpers::get_all_implementable_methods(cls, concrete_cxt); - if(!as_generator(*(function_definition)) - .generate(sink, implemented_methods, concrete_cxt)) return false; + // Property concrete function definitions + auto implemented_properties = helpers::get_all_implementable_properties(cls, concrete_cxt); + if(!as_generator("\n\n" + << *( + property_function_definition(cls, cls, false) + )) + .generate(sink, implemented_properties, concrete_cxt)) return false; + auto implemented_methods = helpers::get_all_implementable_methods(cls, concrete_cxt); + if(!as_generator("\n" << scope_tab << "\n\n" << *(function_definition)) + .generate(sink, implemented_methods, concrete_cxt)) return false; + // Async wrappers - if(!as_generator(*(async_function_definition)).generate(sink, implemented_methods, concrete_cxt)) + if(!as_generator(*(async_function_definition)).generate(sink, helpers::get_all_implementable_methods(cls, concrete_cxt, true), concrete_cxt)) return false; // Property wrappers - if (!as_generator(*(property_wrapper_definition(cls, cls))).generate(sink, cls.properties, concrete_cxt)) + if (!as_generator(*(property_wrapper_definition(cls, cls))) + .generate(sink, cls.properties, concrete_cxt)) return false; - for (auto&& klass : helpers::non_implemented_interfaces(cls, concrete_cxt)) + for (auto&& klass : helpers::non_implemented_interfaces_and_beta(cls, concrete_cxt)) { - attributes::klass_def c(get_klass(klass, cls.unit), cls.unit); - if (!as_generator(*(property_wrapper_definition(cls, c))).generate(sink, c.properties, concrete_cxt)) + attributes::klass_def c(get_klass(klass.first, cls.unit), cls.unit); + bool force_protected = (!context_find_tag(concrete_cxt).want_beta && klass.second); + if (!as_generator(*(property_wrapper_definition(cls, c, force_protected))).generate(sink, c.properties, concrete_cxt)) return false; } @@ -291,8 +312,9 @@ struct klass if(!as_generator("}\n").generate(sink, attributes::unused, concrete_cxt)) return false; } - // Inheritable class - if(class_type == "class" || class_type == "abstract class") + // // Inheritable class + // if(class_type == "class" || class_type == "abstract class") + else { auto inherit_cxt = context_add_tag(class_context{class_context::inherit, name_helpers::klass_full_concrete_or_interface_name(cls)}, @@ -337,23 +359,31 @@ struct klass if(!as_generator(*(part_definition)) .generate(sink, cls.parts, inherit_cxt)) return false; + // Property concrete function definitions + auto implemented_properties = helpers::get_all_implementable_properties(cls, inherit_cxt); + if(!as_generator(*(property_function_definition(cls, cls, true, true))) + .generate(sink, implemented_properties, inherit_cxt)) return false; + // Inherit function definitions auto implemented_methods = helpers::get_all_implementable_methods(cls, inherit_cxt); - if(!as_generator(*(function_definition(true))) + if(!as_generator("\n" << scope_tab << "//* Methods\n\n" << *(function_definition(true))) .generate(sink, implemented_methods, inherit_cxt)) return false; // Async wrappers - if(!as_generator(*(async_function_definition(true))).generate(sink, implemented_methods, inherit_cxt)) + if(!as_generator(*(async_function_definition(true))).generate(sink, helpers::get_all_implementable_methods(cls, inherit_cxt, true), inherit_cxt)) return false; // Property wrappers - if (!as_generator(*(property_wrapper_definition(cls, cls))).generate(sink, cls.properties, inherit_cxt)) + if (!as_generator("\n\n" << *property_wrapper_definition(cls, cls) + ).generate(sink, cls.properties, inherit_cxt)) return false; - for (auto&& klass : helpers::non_implemented_interfaces(cls, inherit_cxt)) + for (auto&& klass : helpers::non_implemented_interfaces_and_beta(cls, inherit_cxt)) { - attributes::klass_def c(get_klass(klass, cls.unit), cls.unit); - if (!as_generator(*(property_wrapper_definition(cls, c))).generate(sink, c.properties, inherit_cxt)) + attributes::klass_def c(get_klass(klass.first, cls.unit), cls.unit); + assert (c != cls); + bool force_protected = (!context_find_tag(inherit_cxt).want_beta && klass.second); + if (!as_generator(*(property_wrapper_definition(cls, c, force_protected))).generate(sink, c.properties, inherit_cxt)) return false; } @@ -424,6 +454,7 @@ struct klass auto native_inherit_name = name_helpers::klass_native_inherit_name(cls); auto inherit_name = name_helpers::klass_inherit_name(cls); auto implementable_methods = helpers::get_all_registerable_methods(cls, context); + auto implementable_properties = helpers::get_all_implementable_properties(cls, inative_cxt); bool root = !helpers::has_regular_ancestor(cls); auto const& indent = current_indentation(inative_cxt); std::string klass_since; @@ -450,7 +481,8 @@ struct klass ).generate(sink, attributes::unused, inative_cxt)) return false; - if(implementable_methods.size() >= 1) + if(implementable_methods.size() >= 1 + || implementable_properties.size() >= 1) { if(!as_generator( indent << scope_tab << "private static Efl.Eo.NativeModule Module = new Efl.Eo.NativeModule(" @@ -533,6 +565,12 @@ struct klass << indent << scope_tab << "#pragma warning restore CA1707, CS1591, SA1300, SA1600\n\n") .generate(sink, implementable_methods, change_indentation(indent.inc(), inative_cxt))) return false; + if(!as_generator( + indent << scope_tab << "#pragma warning disable CA1707, CS1591, SA1300, SA1600\n\n" + << *(native_property_function_definition(cls, cls)) + << indent << scope_tab << "#pragma warning restore CA1707, CS1591, SA1300, SA1600\n\n") + .generate(sink, implementable_properties, change_indentation(indent.inc(), inative_cxt))) return false; + if(!as_generator("}\n").generate(sink, attributes::unused, inative_cxt)) return false; } return true; diff --git a/src/bindings/mono/efl_mono/GenericModel.cs b/src/bindings/mono/efl_mono/GenericModel.cs index faa2a2f099..7df833cd6c 100644 --- a/src/bindings/mono/efl_mono/GenericModel.cs +++ b/src/bindings/mono/efl_mono/GenericModel.cs @@ -31,30 +31,30 @@ public class GenericModel : Efl.Object, Efl.IModel } /// The list of properties available in the wrapped model. + /// The list of properties in the model. public IEnumerable Properties { - get { return GetProperties(); } + get { return model.Properties; } } - /// The number of children in the wrapped model. + + /// Returns the number of children in the wrapped model. + /// The number of children. public uint ChildrenCount { - get { return GetChildrenCount(); } - } - - /// The list of properties available in the wrapped model. - /// The list of properties in the model. - public IEnumerable GetProperties() - { - return model.GetProperties(); + get { return model.ChildrenCount; } } /// Gets the value of the given property in the wrapped model. /// The property of the model. /// The value of the property. - public Eina.Value GetProperty(System.String property) + public Efl.IModelPropertyIndexer Property { - return model.GetProperty(property); + get + { + return model.Property; + } + set{} } /// Sets the value of the given property in the given model. @@ -67,13 +67,6 @@ public class GenericModel : Efl.Object, Efl.IModel return model.SetProperty(property, value); } - /// Returns the number of children in the wrapped model. - /// The number of children. - public uint GetChildrenCount() - { - return model.GetChildrenCount(); - } - /// Returns an that will resolve when the property is ready to be read. /// The property of the model. /// An that resolves when the property is ready. diff --git a/src/bindings/mono/efl_mono/UserModel.cs b/src/bindings/mono/efl_mono/UserModel.cs index 99350b135a..33c3eaf384 100644 --- a/src/bindings/mono/efl_mono/UserModel.cs +++ b/src/bindings/mono/efl_mono/UserModel.cs @@ -42,7 +42,7 @@ internal class ModelHelper var properties = typeof(T).GetProperties(); foreach (var prop in properties) { - using (var v = child.GetProperty(prop.Name)) + using (var v = child.Property[prop.Name]) { SetPropertyFromValue(o, prop, v); } diff --git a/src/bindings/mono/efl_sharp.csproj.in b/src/bindings/mono/efl_sharp.csproj.in index ce6a9e463c..d0ddbcab20 100644 --- a/src/bindings/mono/efl_sharp.csproj.in +++ b/src/bindings/mono/efl_sharp.csproj.in @@ -14,7 +14,7 @@ $(AssemblyName).xml - true + diff --git a/src/bindings/mono/eo_mono/EoWrapper.cs b/src/bindings/mono/eo_mono/EoWrapper.cs index 99e60b1d2b..dc18c0da04 100644 --- a/src/bindings/mono/eo_mono/EoWrapper.cs +++ b/src/bindings/mono/eo_mono/EoWrapper.cs @@ -227,7 +227,7 @@ public abstract class EoWrapper : IWrapper, IDisposable public void Del() { // FIXME Implement this - ((Efl.Object)this).SetParent(null); + ((Efl.Object)this).Parent = null; Dispose(); } diff --git a/src/lib/eolian_cxx/grammar/klass_def.hpp b/src/lib/eolian_cxx/grammar/klass_def.hpp index 48b8b52c80..47a8ac6c35 100644 --- a/src/lib/eolian_cxx/grammar/klass_def.hpp +++ b/src/lib/eolian_cxx/grammar/klass_def.hpp @@ -1082,6 +1082,52 @@ struct property_def } }; +template <> +struct tuple_element<0ul, property_def> +{ + typedef std::string type; + static type& get(property_def& p) { return p.name; } + static type const& get(property_def const& p) { return p.name; } +}; + +template <> +struct tuple_element<1ul, property_def> +{ + typedef documentation_def type; + static type& get(property_def& p) { return p.documentation; } + static type const& get(property_def const& p) { return p.documentation; } +}; + +template <> +struct tuple_element<2ul, property_def> +{ + typedef efl::eina::optional type; + static type& get(property_def& p) { return p.getter; } + static type const& get(property_def const& p) { return p.getter; } +}; + +template <> +struct tuple_element<3ul, property_def> +{ + typedef efl::eina::optional type; + static type& get(property_def& p) { return p.setter; } + static type const& get(property_def const& p) { return p.setter; } +}; + +template +typename tuple_element::type const& +get(property_def const& f) +{ + return tuple_element::get(f); +} + +template +typename tuple_element::type& +get(property_def& f) +{ + return tuple_element::get(f); +} + struct constant_def { std::string name; @@ -1165,6 +1211,18 @@ struct compare_klass_name_by_name return lhs.namespaces < rhs.namespaces || (!(rhs.namespaces < lhs.namespaces) && lhs.eolian_name < rhs.eolian_name); } + template + bool operator()(std::pair const& lhs, std::pair const& rhs) const + { + return lhs.first.namespaces < rhs.first.namespaces + || (!(rhs.first.namespaces < lhs.first.namespaces) && lhs.first.eolian_name < rhs.first.eolian_name); + } + template + bool operator()(std::pair const& lhs, std::pair const& rhs) const + { + return lhs.second.namespaces < rhs.second.namespaces + || (!(rhs.second.namespaces < lhs.second.namespaces) && lhs.second.eolian_name < rhs.second.eolian_name); + } }; struct event_def @@ -1816,6 +1874,10 @@ namespace type_traits { template <> struct is_tuple : std::true_type {}; template <> +struct is_tuple : std::true_type {}; +template <> +struct is_tuple : std::true_type {}; +template <> struct is_tuple : std::true_type {}; } diff --git a/src/tests/efl_mono/Eo.cs b/src/tests/efl_mono/Eo.cs index af40bf12d8..a9d0d3fdc0 100644 --- a/src/tests/efl_mono/Eo.cs +++ b/src/tests/efl_mono/Eo.cs @@ -699,16 +699,16 @@ class TestProtectedInterfaceMembers { var type = typeof(Dummy.ITestIface); var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance); + var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); // Fully protected property Test.AssertNull(methods.SingleOrDefault(m => m.Name == "GetProtectedProp")); Test.AssertNull(methods.SingleOrDefault(m => m.Name == "SetProtectedProp")); // Partially protected property - Test.AssertNotNull(methods.SingleOrDefault(m => m.Name == "GetPublicGetterPrivateSetter")); + Test.AssertNotNull(properties.SingleOrDefault(m => m.Name == "PublicGetterPrivateSetter")); Test.AssertNull(methods.SingleOrDefault(m => m.Name == "SetPublicGetterPrivateSetter")); - var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); Test.AssertNull(properties.SingleOrDefault(m => m.Name == "ProtectedProp")); Test.AssertNotNull(properties.SingleOrDefault(m => m.Name == "PublicGetterPrivateSetter")); } diff --git a/src/tests/efl_mono/Model.cs b/src/tests/efl_mono/Model.cs index bb6ba3b01c..cb668db668 100644 --- a/src/tests/efl_mono/Model.cs +++ b/src/tests/efl_mono/Model.cs @@ -41,7 +41,7 @@ public static class TestModel { var veggies = CreateModel(loop); var model = new Efl.GenericModel(veggies, loop); - Test.AssertEquals(3, (int)model.GetChildrenCount()); + Test.AssertEquals(3, (int)model.ChildrenCount); VeggieViewModel r2 = await model.GetAtAsync(1).ConfigureAwait(false); Test.AssertEquals(r2.Name, "Romaine Lettuce");