felipealmeida pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=f9586a831b8ba13542f59c9e1143c3d7b276bd51

commit f9586a831b8ba13542f59c9e1143c3d7b276bd51
Author: Lauro Moura <[email protected]>
Date:   Mon Mar 19 20:35:36 2018 -0300

    csharp: Add support for efl parts as Properties
    
    Instead of
       var bg = efl.ui.Background.static_cast(myobj.Part("background"));
    
    Now do
       var bg = myobj.Background;
    
    Also a couple helper functions were added.
---
 src/Makefile_Efl_Mono.am                           |  2 +
 src/bin/eolian_mono/eolian/mono/helpers.hh         | 23 ++++++++--
 src/bin/eolian_mono/eolian/mono/klass.hh           | 13 ++++++
 src/bin/eolian_mono/eolian/mono/part_definition.hh | 52 ++++++++++++++++++++++
 src/bin/eolian_mono/eolian/mono/utils.hh           | 13 +++++-
 src/tests/efl_mono/Parts.cs                        | 41 +++++++++++++++++
 src/tests/efl_mono/libefl_mono_native_test.c       | 26 +++++++++++
 src/tests/efl_mono/test_testing.eo                 |  8 +++-
 8 files changed, 172 insertions(+), 6 deletions(-)

diff --git a/src/Makefile_Efl_Mono.am b/src/Makefile_Efl_Mono.am
index 7c2930d52b..f608676fa9 100644
--- a/src/Makefile_Efl_Mono.am
+++ b/src/Makefile_Efl_Mono.am
@@ -78,6 +78,7 @@ bin_eolian_mono_eolian_mono_SOURCES = \
        bin/eolian_mono/eolian/mono/function_registration.hh \
        bin/eolian_mono/eolian/mono/enum_definition.hh \
        bin/eolian_mono/eolian/mono/struct_definition.hh \
+       bin/eolian_mono/eolian/mono/part_definition.hh \
        bin/eolian_mono/eolian/mono/struct_fields.hh \
        bin/eolian_mono/eolian/mono/parameter.hh \
        bin/eolian_mono/eolian/mono/utils.hh \
@@ -424,6 +425,7 @@ tests_efl_mono_efl_mono_SOURCES = \
      tests/efl_mono/Evas.cs \
      tests/efl_mono/Events.cs \
      tests/efl_mono/FunctionPointers.cs \
+     tests/efl_mono/Parts.cs \
      tests/efl_mono/Strings.cs \
      tests/efl_mono/Structs.cs \
      tests/efl_mono/TestUtils.cs \
diff --git a/src/bin/eolian_mono/eolian/mono/helpers.hh 
b/src/bin/eolian_mono/eolian/mono/helpers.hh
index d1bebeee14..bdfdbb182c 100644
--- a/src/bin/eolian_mono/eolian/mono/helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/helpers.hh
@@ -2,6 +2,13 @@
 #define EOLIAN_MONO_HELPERS_HH
 
 #include "grammar/klass_def.hpp"
+#include "utils.hh"
+
+/* General helper functions for the main generators.
+ *
+ * These range from blacklisting structures to 'nano-generators' (functions 
that receive
+ * a binding-specifict structure and returns a string).
+ */
 
 namespace eolian_mono {
 
@@ -102,9 +109,19 @@ inline bool 
need_pointer_conversion(attributes::regular_type_def const* regular)
 
 inline std::string to_field_name(std::string const& in)
 {
-  std::string field_name = in;
-  field_name[0] = std::toupper(field_name[0]); // Hack to allow 'static' as a 
field name
-  return field_name;
+  return utils::capitalize(in);
+}
+
+inline std::string klass_name_to_csharp(attributes::klass_name const& clsname)
+{
+  std::ostringstream output;
+
+  for (auto namesp : clsname.namespaces)
+    output << utils::to_lowercase(namesp) << ".";
+
+  output << clsname.eolian_name;
+
+  return output.str();
 }
 
 }
diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh 
b/src/bin/eolian_mono/eolian/mono/klass.hh
index f0c73b3aaf..7de2f2b47b 100644
--- a/src/bin/eolian_mono/eolian/mono/klass.hh
+++ b/src/bin/eolian_mono/eolian/mono/klass.hh
@@ -15,6 +15,7 @@
 #include "function_registration.hh"
 #include "function_declaration.hh"
 #include "documentation.hh"
+#include "part_definition.hh"
 #include "grammar/string.hpp"
 #include "grammar/attribute_replace.hpp"
 #include "grammar/integral.hpp"
@@ -239,6 +240,10 @@ struct klass
              return false;
        }
 
+     for (auto &&p : cls.parts)
+       if (!as_generator( klass_name_to_csharp(p.klass) << " " << 
utils::capitalize(p.name) << "{ get;}\n").generate(sink, attributes::unused, 
iface_cxt))
+         return false;
+
      // End of interface declaration
      if(!as_generator("}\n").generate(sink, attributes::unused, iface_cxt)) 
return false;
      }
@@ -331,6 +336,10 @@ struct klass
          if (!generate_events_registration(sink, cls, concrete_cxt))
              return false;
 
+         // Parts
+         if(!as_generator(*(part_definition))
+            .generate(sink, cls.get_all_parts(), concrete_cxt)) return false;
+
          // Concrete function definitions
          if(!as_generator(*(function_definition))
             .generate(sink, methods, concrete_cxt)) return false;
@@ -431,6 +440,10 @@ struct klass
          if (!generate_events_registration(sink, cls, inherit_cxt))
              return false;
 
+         // Parts
+         if(!as_generator(*(part_definition))
+            .generate(sink, cls.get_all_parts(), inherit_cxt)) return false;
+
          // Inherit function definitions
          if(!as_generator(*(function_definition(true)))
             .generate(sink, methods, inherit_cxt)) return false;
diff --git a/src/bin/eolian_mono/eolian/mono/part_definition.hh 
b/src/bin/eolian_mono/eolian/mono/part_definition.hh
new file mode 100644
index 0000000000..83222c9ed4
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/part_definition.hh
@@ -0,0 +1,52 @@
+#ifndef EOLIAN_MONO_PART_DEFINITION_HH
+#define EOLIAN_MONO_PART_DEFINITION_HH
+
+#include <Eina.hh>
+
+#include "grammar/generator.hpp"
+#include "grammar/klass_def.hpp"
+#include "grammar/indentation.hpp"
+
+#include "utils.hh"
+#include "documentation.hh"
+
+namespace eolian_mono {
+
+struct part_definition_generator
+{
+  template <typename OutputIterator, typename Context>
+  bool generate(OutputIterator sink, attributes::part_def const& part, Context 
const& context) const
+  {
+     std::string part_klass_name = klass_name_to_csharp(part.klass);
+     return as_generator(scope_tab << documentation
+                       << scope_tab << "public " << part_klass_name << " " << 
utils::capitalize(part.name) << "\n"
+                       << scope_tab << "{\n"
+                       << scope_tab << scope_tab << "get\n"
+                       << scope_tab << scope_tab << "{\n"
+                       << scope_tab << scope_tab << scope_tab << "efl.Object 
obj = efl_part(raw_handle, \"" << part.name << "\");\n"
+                       << scope_tab << scope_tab << scope_tab << "return " << 
part_klass_name << "Concrete.static_cast(obj);\n"
+                       << scope_tab << scope_tab << "}\n"
+                       << scope_tab << "}\n"
+            ).generate(sink, part.documentation, context);
+  }
+
+} const part_definition {};
+
+}
+
+namespace efl { namespace eolian { namespace grammar {
+
+template <>
+struct is_eager_generator< ::eolian_mono::part_definition_generator> : 
std::true_type {};
+template <>
+struct is_generator< ::eolian_mono::part_definition_generator> : 
std::true_type {};
+
+namespace type_traits {
+template <>
+struct attributes_needed< ::eolian_mono::part_definition_generator> : 
std::integral_constant<int, 1> {};
+
+}
+} } }
+
+#endif
+
diff --git a/src/bin/eolian_mono/eolian/mono/utils.hh 
b/src/bin/eolian_mono/eolian/mono/utils.hh
index 3e48e518b5..6be2076caa 100644
--- a/src/bin/eolian_mono/eolian/mono/utils.hh
+++ b/src/bin/eolian_mono/eolian/mono/utils.hh
@@ -4,19 +4,28 @@
 #include <string>
 #include <algorithm>
 
+/* Compared to the helpers.hh header, these functions are lower level, not 
dealing with
+ * binding-specific structures or knowledge */
+
 namespace eolian_mono { namespace utils {
 
    // Helper method to avoid multiple as_generator calls when mixing case 
strings
-   std::string to_uppercase(std::string s)
+   inline std::string to_uppercase(std::string s)
    {
        std::transform(s.begin(), s.end(), s.begin(), ::toupper);
        return s;
    }
-   std::string to_lowercase(std::string s)
+   inline std::string to_lowercase(std::string s)
    {
        std::transform(s.begin(), s.end(), s.begin(), ::tolower);
        return s;
    }
+   inline std::string capitalize(std::string const &s)
+   {
+      std::string ret = s;
+      ret[0] = std::toupper(ret[0]);
+      return ret;
+   }
 } }
 
 #endif
diff --git a/src/tests/efl_mono/Parts.cs b/src/tests/efl_mono/Parts.cs
new file mode 100644
index 0000000000..b6ed9a882c
--- /dev/null
+++ b/src/tests/efl_mono/Parts.cs
@@ -0,0 +1,41 @@
+#define CODE_ANALYSIS
+
+#pragma warning disable 1591
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace TestSuite {
+
+
+[SuppressMessage("Gendarme.Rules.Portability", "DoNotHardcodePathsRule")]
+public static class TestParts
+{
+    public static void basic_part_test()
+    {
+        test.Testing t = new test.TestingConcrete();
+        do_part_test(t);
+    }
+
+    private class Child : test.TestingInherit
+    {
+        public Child() : base(null) {}
+    }
+
+    public static void inherited_part_test() {
+        var t = new Child();
+        do_part_test(t);
+    }
+
+    private static void do_part_test(test.Testing t)
+    {
+        var p1 = t.Part1;
+        var p2 = t.Part2;
+        Test.Assert(p1 is test.Testing);
+        Test.AssertEquals("part1", p1.GetName());
+        Test.Assert(p2 is test.Testing);
+        Test.AssertEquals("part2", p2.GetName());
+    }
+}
+
+}
diff --git a/src/tests/efl_mono/libefl_mono_native_test.c 
b/src/tests/efl_mono/libefl_mono_native_test.c
index 04fd12053f..19fe984022 100644
--- a/src/tests/efl_mono/libefl_mono_native_test.c
+++ b/src/tests/efl_mono/libefl_mono_native_test.c
@@ -34,6 +34,8 @@
 #include "test_numberwrapper.eo.h"
 #include "test_testing.eo.h"
 
+#include <interfaces/efl_part.eo.h>
+
 #define EQUAL(a, b) ((a) == (b) ? 1 : (fprintf(stderr, "NOT EQUAL! %s:%i 
(%s)", __FILE__, __LINE__, __FUNCTION__), fflush(stderr), 0))
 #define STR_EQUAL(a, b) (strcmp((a), (b)) == 0 ? 1 : (fprintf(stderr, "NOT 
EQUAL! %s:%i (%s) '%s' != '%s'", __FILE__, __LINE__, __FUNCTION__, (a), (b)), 
fflush(stderr), 0))
 
@@ -46,6 +48,8 @@ typedef struct Test_Testing_Data
   Eina_Value *stored_value;
   Test_StructSimple stored_struct;
   int stored_int;
+  Eo *part1;
+  Eo *part2;
 } Test_Testing_Data;
 
 typedef struct Test_Numberwrapper_Data
@@ -3714,6 +3718,28 @@ void _test_testing_emit_event_with_obj(Eo *obj, 
EINA_UNUSED Test_Testing_Data *p
     efl_event_callback_legacy_call(obj, TEST_TESTING_EVENT_EVT_WITH_OBJ, data);
 }
 
+Efl_Object *_test_testing_efl_part_part(const Eo *obj, Test_Testing_Data *pd, 
const char *name)
+{
+    if (!strcmp(name, "part1"))
+      {
+         if (pd->part1 == NULL)
+           {
+              pd->part1 = efl_add(TEST_TESTING_CLASS, obj, 
efl_name_set(efl_added, "part1"));
+           }
+         return pd->part1;
+      }
+    else if (!strcmp(name, "part2"))
+      {
+         if (pd->part2 == NULL)
+           {
+              pd->part2 = efl_add(TEST_TESTING_CLASS, obj, 
efl_name_set(efl_added, "part2"));
+           }
+         return pd->part2;
+      }
+    else
+      return NULL;
+}
+
 #include "test_testing.eo.c"
 #include "test_numberwrapper.eo.c"
 
diff --git a/src/tests/efl_mono/test_testing.eo 
b/src/tests/efl_mono/test_testing.eo
index c2d3edcd2e..90d512e763 100644
--- a/src/tests/efl_mono/test_testing.eo
+++ b/src/tests/efl_mono/test_testing.eo
@@ -81,7 +81,12 @@ function Test.SimpleCb {
    return: int;
 };
 
-class Test.Testing (Efl.Object) {
+class Test.Testing (Efl.Object, Efl.Part) {
+
+   parts {
+      part1: Test.Testing; [[ Part number one. ]]
+      part2: Test.Testing; [[ Part number two. ]]
+   }
    methods {
       return_object {
          return: Test.Testing;
@@ -1547,6 +1552,7 @@ class Test.Testing (Efl.Object) {
    implements {
       class.constructor;
       class.destructor;
+      Efl.Part.part;
    }
    events {
       evt,with,string @hot: string;

-- 


Reply via email to