summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/bin/eolian_mono/eolian/mono/blacklist.hh13
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_definition.hh78
-rw-r--r--src/bin/eolian_mono/eolian/mono/klass.hh26
-rw-r--r--src/bin/eolian_mono/eolian/mono/name_helpers.hh8
-rw-r--r--src/tests/efl_mono/Eo.cs42
-rw-r--r--src/tests/efl_mono/dummy_test_iface.eo7
-rw-r--r--src/tests/efl_mono/dummy_test_object.eo12
-rw-r--r--src/tests/efl_mono/libefl_mono_native_test.c20
8 files changed, 199 insertions, 7 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/blacklist.hh b/src/bin/eolian_mono/eolian/mono/blacklist.hh
index 99ec12e91d..646452e57c 100644
--- a/src/bin/eolian_mono/eolian/mono/blacklist.hh
+++ b/src/bin/eolian_mono/eolian/mono/blacklist.hh
@@ -15,9 +15,6 @@ inline bool is_function_blacklisted(std::string const& c_name)
15 return 15 return
16 c_name == "efl_event_callback_array_priority_add" 16 c_name == "efl_event_callback_array_priority_add"
17 || c_name == "efl_player_position_get" 17 || c_name == "efl_player_position_get"
18 || c_name == "efl_text_font_source_get"
19 || c_name == "efl_text_font_source_set"
20 || c_name == "efl_ui_focus_manager_focus_get"
21 || c_name == "efl_ui_widget_focus_set" 18 || c_name == "efl_ui_widget_focus_set"
22 || c_name == "efl_ui_widget_focus_get" 19 || c_name == "efl_ui_widget_focus_get"
23 || c_name == "efl_ui_text_password_get" 20 || c_name == "efl_ui_text_password_get"
@@ -25,8 +22,6 @@ inline bool is_function_blacklisted(std::string const& c_name)
25 || c_name == "elm_interface_scrollable_repeat_events_get" 22 || c_name == "elm_interface_scrollable_repeat_events_get"
26 || c_name == "elm_interface_scrollable_repeat_events_set" 23 || c_name == "elm_interface_scrollable_repeat_events_set"
27 || c_name == "elm_wdg_item_del" 24 || c_name == "elm_wdg_item_del"
28 || c_name == "elm_wdg_item_focus_get"
29 || c_name == "elm_wdg_item_focus_set"
30 || c_name == "elm_interface_scrollable_mirrored_set" 25 || c_name == "elm_interface_scrollable_mirrored_set"
31 || c_name == "evas_obj_table_mirrored_get" 26 || c_name == "evas_obj_table_mirrored_get"
32 || c_name == "evas_obj_table_mirrored_set" 27 || c_name == "evas_obj_table_mirrored_set"
@@ -82,6 +77,14 @@ inline bool is_alias_blacklisted(attributes::alias_def const& alias)
82 return name_helpers::alias_full_eolian_name(alias) == "Eina.Error"; 77 return name_helpers::alias_full_eolian_name(alias) == "Eina.Error";
83} 78}
84 79
80inline bool is_property_blacklisted(attributes::property_def const& property)
81{
82 auto name = name_helpers::klass_full_concrete_or_interface_name(property.klass) + "." + name_helpers::property_managed_name(property);
83 return name == "Efl.Input.Key.Key"
84 || name == "Efl.Input.Hold.Hold"
85 || name == "Efl.Text.Text";
86}
87
85} 88}
86 89
87} 90}
diff --git a/src/bin/eolian_mono/eolian/mono/function_definition.hh b/src/bin/eolian_mono/eolian/mono/function_definition.hh
index 93765065b8..2821360a04 100644
--- a/src/bin/eolian_mono/eolian/mono/function_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_definition.hh
@@ -137,8 +137,6 @@ struct function_definition_generator
137 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const 137 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
138 { 138 {
139 EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "function_definition_generator: " << f.c_name << std::endl; 139 EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "function_definition_generator: " << f.c_name << std::endl;
140 if(!do_super && f.is_static) // Static methods goes only on Concrete classes.
141 return true;
142 if(blacklist::is_function_blacklisted(f.c_name)) 140 if(blacklist::is_function_blacklisted(f.c_name))
143 return true; 141 return true;
144 142
@@ -209,6 +207,75 @@ struct native_function_definition_parameterized
209 } 207 }
210} const native_function_definition; 208} const native_function_definition;
211 209
210struct property_wrapper_definition_generator
211{
212 template<typename OutputIterator, typename Context>
213 bool generate(OutputIterator sink, attributes::property_def const& property, Context context) const
214 {
215 if (blacklist::is_property_blacklisted(property))
216 return true;
217
218 bool interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
219 bool is_static = (property.getter.is_engaged() && property.getter->is_static
220 || property.setter.is_engaged() && property.setter->is_static);
221
222
223 if (interface && is_static)
224 return true;
225
226 auto get_params = property.getter.is_engaged() ? property.getter->parameters.size() : 0;
227 auto set_params = property.setter.is_engaged() ? property.setter->parameters.size() : 0;
228
229 // C# properties must have a single value.
230 //
231 // Single values in getters are automatically converted to return_type,
232 // meaning they should have 0 parameters.
233 //
234 // For setters, we ignore the return type - usually boolean.
235 if (get_params > 0 || set_params > 1)
236 return true;
237
238 attributes::type_def prop_type;
239
240 if (property.getter.is_engaged())
241 prop_type = property.getter->return_type;
242 else if (property.setter.is_engaged())
243 prop_type = property.setter->parameters[0].type;
244 else
245 {
246 EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Property must have either a getter or a setter." << std::endl;
247 return false;
248 }
249
250 std::string dir_mod;
251 if (property.setter.is_engaged())
252 dir_mod = direction_modifier(property.setter->parameters[0]);
253
254 std::string managed_name = name_helpers::property_managed_name(property);
255
256 if (!as_generator(
257 scope_tab << documentation
258 << scope_tab << (interface ? "" : "public ") << (is_static ? "static " : "") << type(true) << " " << managed_name << " {\n"
259 ).generate(sink, std::make_tuple(property, prop_type), context))
260 return false;
261
262 if (property.getter.is_engaged())
263 if (!as_generator(scope_tab << scope_tab << "get " << (interface ? ";" : "{ return Get" + managed_name + "(); }") << "\n"
264 ).generate(sink, attributes::unused, context))
265 return false;
266
267 if (property.setter.is_engaged())
268 if (!as_generator(scope_tab << scope_tab << "set " << (interface ? ";" : "{ Set" + managed_name + "(" + dir_mod + "value); }") << "\n"
269 ).generate(sink, attributes::unused, context))
270 return false;
271
272 if (!as_generator(scope_tab << "}\n").generate(sink, attributes::unused, context))
273 return false;
274
275 return true;
276 }
277} const property_wrapper_definition;
278
212} 279}
213 280
214namespace efl { namespace eolian { namespace grammar { 281namespace efl { namespace eolian { namespace grammar {
@@ -218,11 +285,15 @@ struct is_eager_generator< ::eolian_mono::function_definition_generator> : std::
218template <> 285template <>
219struct is_eager_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {}; 286struct is_eager_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {};
220template <> 287template <>
288struct is_eager_generator< ::eolian_mono::property_wrapper_definition_generator> : std::true_type {};
289template <>
221struct is_generator< ::eolian_mono::function_definition_generator> : std::true_type {}; 290struct is_generator< ::eolian_mono::function_definition_generator> : std::true_type {};
222template <> 291template <>
223struct is_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {}; 292struct is_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {};
224template <> 293template <>
225struct is_generator< ::eolian_mono::function_definition_parameterized> : std::true_type {}; 294struct is_generator< ::eolian_mono::function_definition_parameterized> : std::true_type {};
295template <>
296struct is_generator< ::eolian_mono::property_wrapper_definition_generator> : std::true_type {};
226 297
227namespace type_traits { 298namespace type_traits {
228template <> 299template <>
@@ -233,6 +304,9 @@ struct attributes_needed< ::eolian_mono::function_definition_parameterized> : st
233 304
234template <> 305template <>
235struct attributes_needed< ::eolian_mono::native_function_definition_generator> : std::integral_constant<int, 1> {}; 306struct attributes_needed< ::eolian_mono::native_function_definition_generator> : std::integral_constant<int, 1> {};
307
308template <>
309struct attributes_needed< ::eolian_mono::property_wrapper_definition_generator> : std::integral_constant<int, 1> {};
236} 310}
237 311
238} } } 312} } }
diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh
index 077a0fad07..f10c3a38d4 100644
--- a/src/bin/eolian_mono/eolian/mono/klass.hh
+++ b/src/bin/eolian_mono/eolian/mono/klass.hh
@@ -164,6 +164,9 @@ struct klass
164 ).generate(sink, p, iface_cxt)) 164 ).generate(sink, p, iface_cxt))
165 return false; 165 return false;
166 166
167 if (!as_generator(*(property_wrapper_definition)).generate(sink, cls.properties, iface_cxt))
168 return false;
169
167 // End of interface declaration 170 // End of interface declaration
168 if(!as_generator("}\n").generate(sink, attributes::unused, iface_cxt)) return false; 171 if(!as_generator("}\n").generate(sink, attributes::unused, iface_cxt)) return false;
169 172
@@ -255,6 +258,18 @@ struct klass
255 if(!as_generator(*(async_function_definition)).generate(sink, implemented_methods, concrete_cxt)) 258 if(!as_generator(*(async_function_definition)).generate(sink, implemented_methods, concrete_cxt))
256 return false; 259 return false;
257 260
261 // Property wrappers
262 if (!as_generator(*(property_wrapper_definition)).generate(sink, cls.properties, concrete_cxt))
263 return false;
264
265 for (auto&& klass : helpers::non_implemented_interfaces(cls))
266 {
267 attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
268 if (!as_generator(*(property_wrapper_definition)).generate(sink, c.properties, concrete_cxt))
269 return false;
270 }
271
272
258 if(!as_generator("}\n").generate(sink, attributes::unused, concrete_cxt)) return false; 273 if(!as_generator("}\n").generate(sink, attributes::unused, concrete_cxt)) return false;
259 274
260 } 275 }
@@ -315,6 +330,17 @@ struct klass
315 if(!as_generator(*(async_function_definition(true))).generate(sink, implemented_methods, inherit_cxt)) 330 if(!as_generator(*(async_function_definition(true))).generate(sink, implemented_methods, inherit_cxt))
316 return false; 331 return false;
317 332
333 // Property wrappers
334 if (!as_generator(*(property_wrapper_definition)).generate(sink, cls.properties, inherit_cxt))
335 return false;
336
337 for (auto&& klass : helpers::non_implemented_interfaces(cls))
338 {
339 attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
340 if (!as_generator(*(property_wrapper_definition)).generate(sink, c.properties, inherit_cxt))
341 return false;
342 }
343
318 if(!as_generator("}\n").generate(sink, attributes::unused, inherit_cxt)) return false; 344 if(!as_generator("}\n").generate(sink, attributes::unused, inherit_cxt)) return false;
319 } 345 }
320 346
diff --git a/src/bin/eolian_mono/eolian/mono/name_helpers.hh b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
index 05bf783384..06291f412c 100644
--- a/src/bin/eolian_mono/eolian/mono/name_helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
@@ -243,6 +243,14 @@ inline std::string to_field_name(std::string const& in)
243 return utils::capitalize(in); 243 return utils::capitalize(in);
244} 244}
245 245
246inline std::string property_managed_name(attributes::property_def const& property)
247{
248 auto names = utils::split(property.name, '_');
249 // No need to escape keyword here as it will be capitalized and already
250 // namespaced inside the owner class.
251 return utils::to_pascal_case(names);
252}
253
246inline std::string managed_part_name(attributes::part_def const& part) 254inline std::string managed_part_name(attributes::part_def const& part)
247{ 255{
248 std::vector<std::string> names = utils::split(part.name, '_'); 256 std::vector<std::string> names = utils::split(part.name, '_');
diff --git a/src/tests/efl_mono/Eo.cs b/src/tests/efl_mono/Eo.cs
index 535c309e1c..7d5df72457 100644
--- a/src/tests/efl_mono/Eo.cs
+++ b/src/tests/efl_mono/Eo.cs
@@ -303,4 +303,46 @@ class TestEoMultipleChildClasses
303 } 303 }
304} 304}
305 305
306class TestCsharpProperties
307{
308 public static void test_csharp_properties()
309 {
310 var obj = new Dummy.TestObject();
311 var name = "My Name";
312 obj.Name = name;
313
314 Test.AssertEquals(name, obj.Name);
315 }
316
317 public static void test_getter_only()
318 {
319 var obj = new Dummy.TestObject();
320 Test.Assert(!obj.Invalidating);
321 }
322
323 public static void test_setter_only()
324 {
325 var obj = new Dummy.TestObject();
326 int val = -1984;
327
328 obj.SetterOnly = val;
329 Test.AssertEquals(val, obj.GetSetterOnly());
330 }
331
332 public static void test_class_property()
333 {
334 int val = -42;
335 Dummy.TestObject.KlassProp = val;
336 Test.AssertEquals(val, Dummy.TestObject.KlassProp);
337 }
338
339 public static void test_iface_property()
340 {
341 int val = -33;
342 Dummy.TestIface iface = new Dummy.TestObject();
343 iface.IfaceProp = val;
344 Test.AssertEquals(val, iface.IfaceProp);
345 }
346}
347
306} 348}
diff --git a/src/tests/efl_mono/dummy_test_iface.eo b/src/tests/efl_mono/dummy_test_iface.eo
index f7295e719e..9cad4c41c2 100644
--- a/src/tests/efl_mono/dummy_test_iface.eo
+++ b/src/tests/efl_mono/dummy_test_iface.eo
@@ -5,6 +5,13 @@ interface Dummy.Test_Iface ()
5 } 5 }
6 emit_nonconflicted { 6 emit_nonconflicted {
7 } 7 }
8 @property iface_prop {
9 get {}
10 set {}
11 values {
12 data: int;
13 }
14 }
8 } 15 }
9 events { 16 events {
10 conflicted: void; 17 conflicted: void;
diff --git a/src/tests/efl_mono/dummy_test_object.eo b/src/tests/efl_mono/dummy_test_object.eo
index a72e13ace3..e37616c979 100644
--- a/src/tests/efl_mono/dummy_test_object.eo
+++ b/src/tests/efl_mono/dummy_test_object.eo
@@ -1641,6 +1641,17 @@ class Dummy.Test_Object extends Efl.Object implements Efl.Part, Dummy.Test_Iface
1641 } 1641 }
1642 return: accessor<ptr(int)> @owned; 1642 return: accessor<ptr(int)> @owned;
1643 } 1643 }
1644
1645 @property setter_only {
1646 set {}
1647 values {
1648 prop: int;
1649 }
1650 }
1651
1652 get_setter_only {
1653 return: int;
1654 }
1644 } 1655 }
1645 implements { 1656 implements {
1646 class.constructor; 1657 class.constructor;
@@ -1649,6 +1660,7 @@ class Dummy.Test_Object extends Efl.Object implements Efl.Part, Dummy.Test_Iface
1649 Efl.Part.part_get; 1660 Efl.Part.part_get;
1650 Dummy.Test_Iface.emit_test_conflicted; 1661 Dummy.Test_Iface.emit_test_conflicted;
1651 Dummy.Test_Iface.emit_nonconflicted; 1662 Dummy.Test_Iface.emit_nonconflicted;
1663 Dummy.Test_Iface.iface_prop { get; set; }
1652 Dummy.Another_Iface.emit_another_conflicted; 1664 Dummy.Another_Iface.emit_another_conflicted;
1653 } 1665 }
1654 events { 1666 events {
diff --git a/src/tests/efl_mono/libefl_mono_native_test.c b/src/tests/efl_mono/libefl_mono_native_test.c
index 8a4592e35b..52876e6859 100644
--- a/src/tests/efl_mono/libefl_mono_native_test.c
+++ b/src/tests/efl_mono/libefl_mono_native_test.c
@@ -57,6 +57,8 @@ typedef struct Dummy_Test_Object_Data
57 Eo *part_two; 57 Eo *part_two;
58 Eina_Promise *promise; 58 Eina_Promise *promise;
59 Eina_List *list_for_accessor; 59 Eina_List *list_for_accessor;
60 int setter_only;
61 int iface_prop;
60} Dummy_Test_Object_Data; 62} Dummy_Test_Object_Data;
61 63
62typedef struct Dummy_Numberwrapper_Data 64typedef struct Dummy_Numberwrapper_Data
@@ -3876,7 +3878,25 @@ void _dummy_test_object_dummy_another_iface_emit_another_conflicted(Eo *obj, Dum
3876 efl_event_callback_legacy_call(obj, DUMMY_ANOTHER_IFACE_EVENT_CONFLICTED, NULL); 3878 efl_event_callback_legacy_call(obj, DUMMY_ANOTHER_IFACE_EVENT_CONFLICTED, NULL);
3877} 3879}
3878 3880
3881void _dummy_test_object_setter_only_set(EINA_UNUSED Eo *obj, Dummy_Test_Object_Data *pd, int value)
3882{
3883 pd->setter_only = value;
3884}
3885
3886int _dummy_test_object_get_setter_only(EINA_UNUSED Eo *obj, Dummy_Test_Object_Data *pd)
3887{
3888 return pd->setter_only;
3889}
3879 3890
3891void _dummy_test_object_dummy_test_iface_iface_prop_set(EINA_UNUSED Eo *obj, Dummy_Test_Object_Data *pd, int value)
3892{
3893 pd->iface_prop = value;
3894}
3895
3896int _dummy_test_object_dummy_test_iface_iface_prop_get(EINA_UNUSED const Eo *obj, Dummy_Test_Object_Data *pd)
3897{
3898 return pd->iface_prop;
3899}
3880 3900
3881#include "dummy_test_object.eo.c" 3901#include "dummy_test_object.eo.c"
3882#include "dummy_numberwrapper.eo.c" 3902#include "dummy_numberwrapper.eo.c"