From 97098dcc50b62e51dad3469619ed55242ca01a80 Mon Sep 17 00:00:00 2001 From: Yeongjong Lee Date: Thu, 23 Jan 2020 07:30:13 +0900 Subject: [PATCH] csharp: cleanup concrete class Summary: Concrete class is only used to call static member of NativeMethod. they don't need any inheritance and implementation of c functions. Depends on D9893 Test Plan: ninja test Reviewers: lauromoura, felipealmeida Subscribers: Jaehyun_Cho, woohyun, segfaultxavi, cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D9894 --- src/bin/eolian_mono/eolian/mono/events.hh | 2 +- src/bin/eolian_mono/eolian/mono/klass.hh | 108 +++--------------- .../eolian_mono/eolian/mono/name_helpers.hh | 17 ++- .../eolian/mono/struct_definition.hh | 3 +- .../mono/eina_mono/eina_container_common.cs | 24 ---- src/bindings/mono/eo_mono/iwrapper.cs | 12 +- src/tests/efl_mono/Eo.cs | 32 ++++++ src/tests/efl_mono/dummy_test_object.c | 22 ++++ src/tests/efl_mono/dummy_test_object.eo | 17 +++ 9 files changed, 106 insertions(+), 131 deletions(-) diff --git a/src/bin/eolian_mono/eolian/mono/events.hh b/src/bin/eolian_mono/eolian/mono/events.hh index 7405f8c2e1..b6cb4aa511 100644 --- a/src/bin/eolian_mono/eolian/mono/events.hh +++ b/src/bin/eolian_mono/eolian/mono/events.hh @@ -131,7 +131,7 @@ struct unpack_event_args_visitor } bool operator()(grammar::attributes::klass_name const& cls) const { - return as_generator("(Efl.Eo.Globals.CreateWrapperFor(info) as " + name_helpers::klass_full_concrete_name(cls) + ")").generate(sink, attributes::unused, *context); + return as_generator("(Efl.Eo.Globals.CreateWrapperFor(info) as " + name_helpers::klass_full_interface_name(cls) + ")").generate(sink, attributes::unused, *context); } bool operator()(attributes::complex_type_def const& types) const { diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh index 072ea6c143..da6fd6d45c 100644 --- a/src/bin/eolian_mono/eolian/mono/klass.hh +++ b/src/bin/eolian_mono/eolian/mono/klass.hh @@ -193,98 +193,9 @@ struct klass auto concrete_cxt = context_add_tag(class_context{class_context::concrete, name_helpers::klass_full_concrete_or_interface_name(cls)}, context); - auto concrete_name = name_helpers::klass_concrete_name(cls); - auto interface_name = name_helpers::klass_interface_name(cls); - // We can't make these internal yet as they have methods that are used by - // other classes that implement the interface. - if(!as_generator - ( - documentation(1) - << scope_tab << "public sealed " << (is_partial ? "partial ":"") << "class " << concrete_name << " :\n" - << scope_tab(2) << (root ? "Efl.Eo.EoWrapper" : "") << (klass_full_concrete_or_interface_name % "") - << ",\n" << scope_tab(2) << interface_name - << *(",\n" << scope_tab(2) << name_helpers::klass_full_concrete_or_interface_name) << "\n" - << scope_tab << "{\n" - ).generate(sink, std::make_tuple(cls, inherit_classes, inherit_interfaces), concrete_cxt)) - return false; - - if (!generate_fields(sink, cls, concrete_cxt)) - return false; - - if (!as_generator - ( - scope_tab(2) << "/// Subclasses should override this constructor if they are expected to be instantiated from native code.\n" - << scope_tab(2) << "/// Do not call this constructor directly.\n" - << scope_tab(2) << "/// Tag struct storing the native handle of the object being constructed.\n" - << scope_tab(2) << "private " << concrete_name << "(ConstructingHandle ch) : base(ch)\n" - << scope_tab(2) << "{\n" - << scope_tab(2) << "}\n\n" - ) - .generate(sink, attributes::unused, concrete_cxt)) - return false; - - if (!as_generator - ( - scope_tab(2) << "[System.Runtime.InteropServices.DllImport(" << context_find_tag(concrete_cxt).actual_library_name(cls.filename) - << ")] internal static extern System.IntPtr\n" - << scope_tab(2) << scope_tab << name_helpers::klass_get_name(cls) << "();\n\n" - << scope_tab(2) << "/// Initializes a new instance of the class.\n" - << scope_tab(2) << "/// Internal usage: This is used when interacting with C code and should not be used directly.\n" - << scope_tab(2) << "/// The native pointer to be wrapped.\n" - << scope_tab(2) << "private " << concrete_name << "(Efl.Eo.WrappingHandle wh) : base(wh)\n" - << scope_tab(2) << "{\n" - << scope_tab(2) << "}\n\n" - ) - .generate(sink, attributes::unused, concrete_cxt)) - return false; - - if (!generate_events(sink, cls, concrete_cxt)) - return false; - - if (!as_generator(lit("#pragma warning disable CS0628\n")).generate(sink, attributes::unused, concrete_cxt)) - return false; - - // Parts - 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; - - // Async wrappers - if(!as_generator(*(async_function_definition)).generate(sink, implemented_methods, concrete_cxt)) - return false; - - // Property wrappers - if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, cls.properties, concrete_cxt)) - return false; - - for (auto&& klass : helpers::non_implemented_interfaces(cls, concrete_cxt)) - { - attributes::klass_def c(get_klass(klass, cls.unit), cls.unit); - if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, c.properties, concrete_cxt)) - return false; - } - - if (!as_generator(lit("#pragma warning restore CS0628\n")).generate(sink, attributes::unused, concrete_cxt)) - return false; - - // Copied from nativeinherit class, used when setting up providers. - if(!as_generator( - scope_tab(2) << "private static IntPtr GetEflClassStatic()\n" - << scope_tab(2) << "{\n" - << scope_tab(2) << scope_tab << "return " << name_helpers::klass_get_full_name(cls) << "();\n" - << scope_tab(2) << "}\n\n" - ).generate(sink, attributes::unused, concrete_cxt)) - return false; - - if(!generate_native_inherit_class(sink, cls, change_indentation(indent.inc(), concrete_cxt))) + if(!generate_native_inherit_class(sink, cls, change_indentation(indent, concrete_cxt))) return true; - - if(!as_generator(scope_tab << "}\n").generate(sink, attributes::unused, concrete_cxt)) return false; } // Inheritable class @@ -427,6 +338,7 @@ struct klass auto inherit_name = name_helpers::klass_inherit_name(cls); auto implementable_methods = helpers::get_all_registerable_methods(cls, context); bool root = !helpers::has_regular_ancestor(cls); + bool is_concrete = context_find_tag(context).current_wrapper_kind == class_context::concrete; auto const& indent = current_indentation(inative_cxt).inc(); std::string klass_since; @@ -447,11 +359,23 @@ struct klass << klass_since << indent << "/// \n" << indent << "[EditorBrowsable(EditorBrowsableState.Never)]\n" - << indent << "internal new class " << native_inherit_name << " : " << (root ? "Efl.Eo.EoWrapper.NativeMethods" : base_name) << "\n" + << indent << "internal " << (is_concrete ? "" : "new ") << "class " << native_inherit_name << " : " << (root ? "Efl.Eo.EoWrapper.NativeMethods" : base_name) << "\n" << indent << "{\n" ).generate(sink, attributes::unused, inative_cxt)) return false; + if(is_concrete) + { + if (!as_generator + ( + scope_tab(2) << "[System.Runtime.InteropServices.DllImport(" << context_find_tag(context).actual_library_name(cls.filename) + << ")] internal static extern System.IntPtr\n" + << scope_tab(2) << scope_tab << name_helpers::klass_get_name(cls) << "();\n" + ) + .generate(sink, attributes::unused, inative_cxt)) + return false; + } + if(implementable_methods.size() >= 1) { if(!as_generator( @@ -502,7 +426,7 @@ struct klass ).generate(sink, attributes::unused, inative_cxt)) return false; - if (!root || context_find_tag(context).current_wrapper_kind != class_context::concrete) + if (!root || !is_concrete) if(!as_generator(indent << scope_tab << scope_tab << "descs.AddRange(base.GetEoOps(type, false));\n").generate(sink, attributes::unused, inative_cxt)) return false; diff --git a/src/bin/eolian_mono/eolian/mono/name_helpers.hh b/src/bin/eolian_mono/eolian/mono/name_helpers.hh index 7f71d9279b..ae958ba623 100644 --- a/src/bin/eolian_mono/eolian/mono/name_helpers.hh +++ b/src/bin/eolian_mono/eolian/mono/name_helpers.hh @@ -399,9 +399,7 @@ struct klass_full_interface_name_generator template inline std::string klass_concrete_name(T const& klass) { - return utils::remove_all(klass.eolian_name, '_') + ((klass.type == attributes::class_type::mixin - || klass.type == attributes::class_type::interface_) - ? "Concrete" : ""); + return utils::remove_all(klass.eolian_name, '_'); } template @@ -467,14 +465,19 @@ inline std::string klass_inherit_name(T const& klass) } template -inline std::string klass_native_inherit_name(EINA_UNUSED T const& klass) +inline std::string klass_native_inherit_name(T const& klass) { - return "NativeMethods"; + return ((klass.type == attributes::class_type::mixin + || klass.type == attributes::class_type::interface_) ? klass_interface_name(klass) : "") + "NativeMethods"; } template inline std::string klass_full_native_inherit_name(T const& klass) { + if(klass.type == attributes::class_type::mixin + || klass.type == attributes::class_type::interface_) + return join_namespaces(klass.namespaces, '.', managed_namespace) + klass_native_inherit_name(klass); + return klass_full_concrete_name(klass) + "." + klass_native_inherit_name(klass); } @@ -487,6 +490,10 @@ inline std::string klass_get_name(T const& clsname) template inline std::string klass_get_full_name(T const& clsname) { + if(clsname.type == attributes::class_type::mixin + || clsname.type == attributes::class_type::interface_) + return klass_get_name(clsname); + return klass_full_concrete_name(clsname) + "." + klass_get_name(clsname); } diff --git a/src/bin/eolian_mono/eolian/mono/struct_definition.hh b/src/bin/eolian_mono/eolian/mono/struct_definition.hh index 176b5518d7..1f4152aa74 100644 --- a/src/bin/eolian_mono/eolian/mono/struct_definition.hh +++ b/src/bin/eolian_mono/eolian/mono/struct_definition.hh @@ -190,11 +190,10 @@ struct to_external_field_convert_generator if (klass) { auto interface_name = name_helpers::klass_full_interface_name(*klass); - auto concrete_name = name_helpers::klass_full_concrete_name(*klass); if (!as_generator( "\n" << indent << scope_tab << scope_tab << "_external_struct." << string - << " = (" << concrete_name << ") Efl.Eo.Globals.CreateWrapperFor(_internal_struct." << string << ");\n" + << " = (" << interface_name << ") Efl.Eo.Globals.CreateWrapperFor(_internal_struct." << string << ");\n" ).generate(sink, std::make_tuple(field_name, field_name), context)) return false; } diff --git a/src/bindings/mono/eina_mono/eina_container_common.cs b/src/bindings/mono/eina_mono/eina_container_common.cs index 192469a033..a07153e51a 100644 --- a/src/bindings/mono/eina_mono/eina_container_common.cs +++ b/src/bindings/mono/eina_mono/eina_container_common.cs @@ -1003,22 +1003,6 @@ internal static class TraitFunctions private static IDictionary register = new Dictionary(); - private static System.Type AsEflInstantiableType(System.Type type) - { - if (!IsEflObject(type)) - { - return null; - } - - if (type.IsInterface) - { - string fullName = type.FullName + "Concrete"; - return type.Assembly.GetType(fullName); // That was our best guess... - } - - return type; // Not interface, so it should be a concrete. - } - public static object RegisterTypeTraits() { Eina.Log.Debug($"Finding TypeTraits for {typeof(T).Name}"); @@ -1026,14 +1010,6 @@ internal static class TraitFunctions var type = typeof(T); if (IsEflObject(type)) { - System.Type concrete = AsEflInstantiableType(type); - if (concrete == null || !type.IsAssignableFrom(concrete)) - { - throw new Exception("Failed to get a suitable concrete class for this type."); - } - - // No need to pass concrete as the traits class will use reflection to get the actually most - // derived type returned. traits = new EflObjectElementTraits(); } else if (IsString(type)) diff --git a/src/bindings/mono/eo_mono/iwrapper.cs b/src/bindings/mono/eo_mono/iwrapper.cs index 780735fcca..ceae250bc9 100644 --- a/src/bindings/mono/eo_mono/iwrapper.cs +++ b/src/bindings/mono/eo_mono/iwrapper.cs @@ -1221,14 +1221,12 @@ internal static class ClassRegister if (objectType.IsInterface) { - // Try to get the *Concrete class - var assembly = objectType.Assembly; - objectType = assembly.GetType(objectType.FullName + "Concrete"); - - if (objectType == null) - { + // Try to get the *NativeMethods class + var nativeMethods = (Efl.Eo.NativeClass)System.Attribute.GetCustomAttributes(objectType)?.FirstOrDefault(attr => attr is Efl.Eo.NativeClass); + if (nativeMethods == null) return IntPtr.Zero; - } + + return nativeMethods.GetEflClass(); } var method = objectType.GetMethod("GetEflClassStatic", diff --git a/src/tests/efl_mono/Eo.cs b/src/tests/efl_mono/Eo.cs index 70e9d29c16..8d00155e10 100644 --- a/src/tests/efl_mono/Eo.cs +++ b/src/tests/efl_mono/Eo.cs @@ -385,6 +385,16 @@ class TestEoMultipleChildClasses class TestCsharpProperties { + + private class MyObject : Dummy.TestObject + { + public MyObject(Efl.Object parent = null) : base(parent) + { + } + private MyObject(ConstructingHandle ch) : base(ch) + { + } + } public static void test_csharp_properties() { var obj = new Dummy.TestObject(); @@ -428,6 +438,28 @@ class TestCsharpProperties iface.Dispose(); } + public static void test_iface_value_property() + { + var obj = new Dummy.TestObject(); + var prop = new MyObject(); + + obj.IfaceValueProp = prop; + Test.AssertEquals(obj.IfaceValueProp, prop); + + obj.Dispose(); + prop.Dispose(); + } + + public static void test_iface_value_from_c() + { + var obj = new Dummy.TestObject(); + + obj.SetIfaceKlassProp(typeof(MyObject)); + Test.AssertEquals(obj.IfaceValueFromC.GetType(), typeof(MyObject)); + + obj.Dispose(); + } + public static void test_csharp_multi_valued_prop() { var obj = new Dummy.TestObject(); diff --git a/src/tests/efl_mono/dummy_test_object.c b/src/tests/efl_mono/dummy_test_object.c index b87aff1cd4..687737a4aa 100644 --- a/src/tests/efl_mono/dummy_test_object.c +++ b/src/tests/efl_mono/dummy_test_object.c @@ -38,6 +38,8 @@ typedef struct Dummy_Test_Object_Data int prop1; int prop2; Eo *hidden_object; + Dummy_Test_Iface *iface_value_prop; + Efl_Class *iface_klass; // Containers passed to C# as iterator/accessors Eina_Array *out_array; @@ -4784,6 +4786,26 @@ Eo *_dummy_test_object_hidden_object_get(EINA_UNUSED const Eo *obj, Dummy_Test_O return pd->hidden_object; } +Dummy_Test_Iface *_dummy_test_object_iface_value_prop_get(EINA_UNUSED const Eo *obj, Dummy_Test_Object_Data *pd) +{ + return pd->iface_value_prop; +} + +void _dummy_test_object_iface_value_prop_set(EINA_UNUSED Eo *obj, Dummy_Test_Object_Data *pd, Dummy_Test_Iface *prop) +{ + pd->iface_value_prop = prop; +} + +void _dummy_test_object_iface_klass_prop_set(EINA_UNUSED Eo *obj, Dummy_Test_Object_Data *pd, Efl_Class *klass) +{ + pd->iface_klass = klass; +} + +Dummy_Test_Iface *_dummy_test_object_iface_value_from_c_get(const Eo *obj, Dummy_Test_Object_Data *pd) +{ + return efl_add(pd->iface_klass, (Eo*)obj); +} + // Inherit int _dummy_inherit_helper_receive_dummy_and_call_int_out(Dummy_Test_Object *x) { diff --git a/src/tests/efl_mono/dummy_test_object.eo b/src/tests/efl_mono/dummy_test_object.eo index cf2ae7ce03..ee24e5ef9b 100644 --- a/src/tests/efl_mono/dummy_test_object.eo +++ b/src/tests/efl_mono/dummy_test_object.eo @@ -1664,6 +1664,23 @@ class Dummy.Test_Object extends Efl.Object implements Dummy.Test_Iface { obj: Efl.Object; } } + @property iface_value_prop { + values { + prop: Dummy.Test_Iface; + } + } + @property iface_klass_prop { + set {} + values { + klass: Efl.Class; + } + } + @property iface_value_from_c { + get {} + values { + prop: Dummy.Test_Iface; + } + } } implements { Efl.Object.constructor;