summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2020-02-11 17:48:26 +0000
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2020-02-18 17:53:19 -0300
commitdf0715a9aa27903dd549c2b4516ab2cba0274413 (patch)
tree338fa2ea31b02e0a36dc16e8375e978569d6e38e
parenteba07471a0cb9baed2204856078f44cc2d31f7d9 (diff)
C#: Add error checking for Eina.Success_Flag return type
When a get and/or set from property is defined to return, explicitly, a Eina.Success_Flag, the mono generator will check the return value and generate an exception if the call fails. Resolves T8383. Reviewed-by: João Paulo Taylor Ienczak Zanette <joao.tiz@expertisesolutions.com.br> Differential Revision: https://phab.enlightenment.org/D11281
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_definition.hh147
-rw-r--r--src/bin/eolian_mono/eolian/mono/property_definition.hh7
-rw-r--r--src/lib/eina/eina_error.h9
-rw-r--r--src/lib/eo/eina_types.eot4
-rw-r--r--src/lib/eolian_cxx/grammar/eps.hpp8
-rw-r--r--src/tests/efl_mono/Eo.cs21
-rw-r--r--src/tests/efl_mono/dummy_test_object.c58
-rw-r--r--src/tests/efl_mono/dummy_test_object.eo58
8 files changed, 250 insertions, 62 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/function_definition.hh b/src/bin/eolian_mono/eolian/mono/function_definition.hh
index 6aeaadcedb..5fc0e84fbf 100644
--- a/src/bin/eolian_mono/eolian/mono/function_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_definition.hh
@@ -39,6 +39,7 @@
39#include "using_decl.hh" 39#include "using_decl.hh"
40#include "generation_contexts.hh" 40#include "generation_contexts.hh"
41#include "blacklist.hh" 41#include "blacklist.hh"
42#include "grammar/eps.hpp"
42 43
43namespace eolian_mono { 44namespace eolian_mono {
44 45
@@ -369,6 +370,7 @@ struct property_wrapper_definition_generator
369 { 370 {
370 using efl::eolian::grammar::attribute_reorder; 371 using efl::eolian::grammar::attribute_reorder;
371 using efl::eolian::grammar::counter; 372 using efl::eolian::grammar::counter;
373 using efl::eolian::grammar::eps;
372 using efl::eolian::grammar::attributes::parameter_direction; 374 using efl::eolian::grammar::attributes::parameter_direction;
373 using efl::eolian::grammar::attributes::parameter_def; 375 using efl::eolian::grammar::attributes::parameter_def;
374 376
@@ -457,6 +459,7 @@ struct property_wrapper_definition_generator
457 bool is_get_public = get_scope == "public "; 459 bool is_get_public = get_scope == "public ";
458 std::string set_scope = property.setter.is_engaged() ? eolian_mono::function_scope_get(*property.setter) : ""; 460 std::string set_scope = property.setter.is_engaged() ? eolian_mono::function_scope_get(*property.setter) : "";
459 bool is_set_public = set_scope == "public "; 461 bool is_set_public = set_scope == "public ";
462 bool get_has_return_error = false, set_has_return_error = false;
460 463
461 // No need to generate this wrapper as no accessor is public. 464 // No need to generate this wrapper as no accessor is public.
462 if (is_interface && (!is_get_public && !is_set_public)) 465 if (is_interface && (!is_get_public && !is_set_public))
@@ -490,6 +493,12 @@ struct property_wrapper_definition_generator
490 set_scope = ""; 493 set_scope = "";
491 } 494 }
492 495
496 if (property.getter && property.getter->explicit_return_type.c_type == "Eina_Success_Flag")
497 get_has_return_error = true;
498
499 if (property.setter && property.setter->explicit_return_type.c_type == "Eina_Success_Flag")
500 set_has_return_error = true;
501
493 if (parameters.size() == 1) 502 if (parameters.size() == 1)
494 { 503 {
495 if (!as_generator( 504 if (!as_generator(
@@ -510,73 +519,95 @@ struct property_wrapper_definition_generator
510 return false; 519 return false;
511 } 520 }
512 521
513 if (property.getter.is_engaged() && is_interface) 522 if (property.getter)
514 { 523 {
515 if (is_get_public) 524 auto managed_getter_name = name_helpers::managed_method_name(*property.getter);
525 if (is_interface)
526 {
527 if (is_get_public)
528 {
529 if (!as_generator(scope_tab(2) << scope_tab << set_scope << "get;\n"
530 ).generate(sink, attributes::unused, context))
531 return false;
532 }
533 }
534 else if (get_params == 0)
516 { 535 {
517 if (!as_generator(scope_tab(2) << scope_tab << set_scope << "get;\n" 536 if (!as_generator
518 ).generate(sink, attributes::unused, context)) 537 (scope_tab(2) << scope_tab << get_scope
538 << "get " << "{ return " + managed_getter_name + "(); }\n"
539 ).generate(sink, attributes::unused, context))
519 return false; 540 return false;
520 } 541 }
521 } 542 else if (parameters.size() >= 1)
522 else if (property.getter.is_engaged() && get_params == 0/*parameters.size() == 1 && property.getter.is_engaged()*/)
523 {
524 if (!as_generator
525 (scope_tab(2) << scope_tab << get_scope
526 << "get " << "{ return " + name_helpers::managed_method_name(*property.getter) + "(); }\n"
527 ).generate(sink, attributes::unused, context))
528 return false;
529 }
530 else if (parameters.size() >= 1 && property.getter)
531 {
532 if (!as_generator
533 (scope_tab(2) << scope_tab << get_scope << "get "
534 << "{\n"
535 << *attribute_reorder<1, -1, 1>
536 (scope_tab(4) << type(true) << " _out_"
537 << argument(false) << " = default(" << type(true) << ");\n"
538 )
539 << scope_tab(4) << name_helpers::managed_method_name(*property.getter)
540 << "(" << (("out _out_" << argument(false)) % ", ") << ");\n"
541 << scope_tab(4) << "return (" << (("_out_"<< argument(false)) % ", ") << ");\n"
542 << scope_tab(3) << "}" << "\n"
543 ).generate(sink, std::make_tuple(parameters, parameters, parameters), context))
544 return false;
545 }
546 // else if (parameters.size() == 1)
547 // {
548 // if (!as_generator
549 // (scope_tab << scope_tab << get_scope << "get "
550 // << "{\n"
551 // << *attribute_reorder<1, -1, 1>(scope_tab(3) << type(true) << " _out_" << argument(false) << " = default(" << type(true) << ");\n")
552 // << scope_tab(3) << name_helpers::managed_method_name(*property.getter)
553 // << "(" << (("out _out_" << argument(false)) % ",") << ");\n"
554 // << scope_tab(3) << "return " << (("_out_"<< argument(false)) % ",") << ";\n"
555 // << scope_tab(2) << "}" << "\n"
556 // ).generate(sink, std::make_tuple(parameters, parameters, parameters), context))
557 // return false;
558 // }
559
560 if (property.setter.is_engaged() && is_interface)
561 {
562 if (is_set_public)
563 { 543 {
564 if (!as_generator(scope_tab(2) << scope_tab << set_scope << "set;\n" 544 if (!as_generator
565 ).generate(sink, attributes::unused, context)) 545 (scope_tab(2) << scope_tab << get_scope << "get "
546 << "{\n"
547 << *attribute_reorder<1, -1, 1>
548 (scope_tab(4) << type(true) << " _out_"
549 << argument(false) << " = default(" << type(true) << ");\n"
550 )
551 << scope_tab(4) << (get_has_return_error ? "var s = " : "")
552 << name_helpers::managed_method_name(*property.getter)
553 << "(" << (("out _out_" << argument(false)) % ", ") << ");\n"
554 << ((eps(get_has_return_error) << scope_tab(4)
555 << "if (s == '\\0') throw new Efl.EflException("
556 << "\"Call of native function for " << managed_getter_name << " returned an error.\""
557 << ");\n")
558 | eps)
559 << scope_tab(4) << "return (" << (("_out_"<< argument(false)) % ", ") << ");\n"
560 << scope_tab(3) << "}" << "\n"
561 ).generate(sink, std::make_tuple(parameters, parameters, parameters), context))
566 return false; 562 return false;
567 } 563 }
568 } 564 }
569 else if (parameters.size() == 1 && property.setter.is_engaged()) 565
570 { 566 if (property.setter)
571 if (!as_generator(scope_tab(2) << scope_tab << set_scope << "set " << "{ " + name_helpers::managed_method_name(*property.setter) + "(" + dir_mod + "value); }\n"
572 ).generate(sink, attributes::unused, context))
573 return false;
574 }
575 else if (parameters.size() > 1 && property.setter.is_engaged())
576 { 567 {
577 if (!as_generator(scope_tab(2) << scope_tab << set_scope << "set " << ("{ " + name_helpers::managed_method_name(*property.setter) + "(" + dir_mod) << ((" value.Item" << counter(1)) % ", ") << "); }" << "\n" 568 auto managed_setter_name = name_helpers::managed_method_name(*property.setter);
578 ).generate(sink, parameters, context)) 569 if (is_interface)
579 return false; 570 {
571 if (is_set_public)
572 {
573 if (!as_generator(scope_tab(2) << scope_tab << set_scope << "set;\n"
574 ).generate(sink, attributes::unused, context))
575 return false;
576 }
577 }
578 else if (parameters.size() == 1)
579 {
580 if (!as_generator(scope_tab(2) << scope_tab << set_scope << "set "
581 << "{ "
582 << ((eps (set_has_return_error) << "\n" << scope_tab(4) << "var s = ") | eps)
583 << managed_setter_name
584 << "(" << dir_mod << "value);"
585 << ((eps(set_has_return_error) << "\n" << scope_tab(4)
586 << "if (s == '\\0') throw new Efl.EflException("
587 << "\"Call of native function for " << managed_setter_name << " returned an error.\""
588 << ");\n" << scope_tab(3))
589 | eps)
590 << " }\n"
591 ).generate(sink, attributes::unused, context))
592 return false;
593 }
594 else if (parameters.size() > 1)
595 {
596 if (!as_generator(scope_tab(2) << scope_tab
597 << set_scope << "set "
598 << "{ "
599 << ((eps (set_has_return_error) << "\n" << scope_tab(4) << "var s = ") | eps)
600 << name_helpers::managed_method_name(*property.setter)
601 << "(" << dir_mod << ((" value.Item" << counter(1)) % ", ") << ");"
602 << ((eps(set_has_return_error) << "\n" << scope_tab(4)
603 << "if (s == '\\0') throw new Efl.EflException("
604 << "\"Call of native function for " << managed_setter_name << " returned an error.\""
605 << ");\n" << scope_tab(3))
606 | eps)
607 << " }" << "\n"
608 ).generate(sink, parameters, context))
609 return false;
610 }
580 } 611 }
581 612
582 if (!as_generator(scope_tab(2) << "}\n\n").generate(sink, attributes::unused, context)) 613 if (!as_generator(scope_tab(2) << "}\n\n").generate(sink, attributes::unused, context))
diff --git a/src/bin/eolian_mono/eolian/mono/property_definition.hh b/src/bin/eolian_mono/eolian/mono/property_definition.hh
index df94fc36e8..703b70269d 100644
--- a/src/bin/eolian_mono/eolian/mono/property_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/property_definition.hh
@@ -115,11 +115,14 @@ bool property_generate_wrapper_getter(attributes::property_def const& property,
115 if (!property.getter->keys.empty()) 115 if (!property.getter->keys.empty())
116 return false; 116 return false;
117 117
118 if (property.getter->explicit_return_type != attributes::void_) 118 if (property.getter->explicit_return_type != attributes::void_
119 && property.getter->explicit_return_type.c_type != "Eina_Success_Flag")
120 {
119 return false; 121 return false;
122 }
120 123
121 assert (!!property.getter.is_engaged()); 124 assert (!!property.getter.is_engaged());
122 125
123 bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface; 126 bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
124 if (is_interface) 127 if (is_interface)
125 { 128 {
diff --git a/src/lib/eina/eina_error.h b/src/lib/eina/eina_error.h
index c21cb7bc7e..e2dfd122ae 100644
--- a/src/lib/eina/eina_error.h
+++ b/src/lib/eina/eina_error.h
@@ -89,6 +89,15 @@
89typedef int Eina_Error; 89typedef int Eina_Error;
90 90
91/** 91/**
92 * @typedef Eina_Success_Flag
93 * @brief A flag indicating a function completed succesfully.
94 *
95 * Errors are reported with a EINA_FALSE value for Eina_Success_Flag
96 * return and success with a EINA_TRUE.
97 */
98typedef Eina_Bool Eina_Success_Flag;
99
100/**
92 * @def EINA_ERROR_NO_ERROR 101 * @def EINA_ERROR_NO_ERROR
93 * @brief No error reported. 102 * @brief No error reported.
94 * 103 *
diff --git a/src/lib/eo/eina_types.eot b/src/lib/eo/eina_types.eot
index 04d728a8d3..bff83968c1 100644
--- a/src/lib/eo/eina_types.eot
+++ b/src/lib/eo/eina_types.eot
@@ -163,3 +163,7 @@ struct @extern @free(eina_promise_free) Eina.Promise; [[Eina promise type
163/* FIXME: This definitely shouldn't be here. */ 163/* FIXME: This definitely shouldn't be here. */
164type @beta Efl.Event_Cb: __undefined_type; [[Efl event callback type]] 164type @beta Efl.Event_Cb: __undefined_type; [[Efl event callback type]]
165 165
166type @extern Eina.Success_Flag: char; [[Eina error type
167
168 @since 1.24
169]]
diff --git a/src/lib/eolian_cxx/grammar/eps.hpp b/src/lib/eolian_cxx/grammar/eps.hpp
index 6416bc918f..354c8d7cdb 100644
--- a/src/lib/eolian_cxx/grammar/eps.hpp
+++ b/src/lib/eolian_cxx/grammar/eps.hpp
@@ -22,11 +22,17 @@ namespace efl { namespace eolian { namespace grammar {
22 22
23struct eps_generator 23struct eps_generator
24{ 24{
25 eps_generator () : r(true) {}
26 eps_generator (bool r) : r(r) {}
27 bool r;
28
25 template <typename OutputIterator, typename Attribute, typename Context> 29 template <typename OutputIterator, typename Attribute, typename Context>
26 bool generate(OutputIterator, Attribute const&, Context const&) const 30 bool generate(OutputIterator, Attribute const&, Context const&) const
27 { 31 {
28 return true; 32 return r;
29 } 33 }
34
35 eps_generator operator()(bool r) const { return {r}; }
30}; 36};
31 37
32template <> 38template <>
diff --git a/src/tests/efl_mono/Eo.cs b/src/tests/efl_mono/Eo.cs
index 8c0c9ab994..641ddc0748 100644
--- a/src/tests/efl_mono/Eo.cs
+++ b/src/tests/efl_mono/Eo.cs
@@ -468,6 +468,27 @@ class TestCsharpProperties
468 Test.AssertEquals(ret, (1, 2)); 468 Test.AssertEquals(ret, (1, 2));
469 obj.Dispose(); 469 obj.Dispose();
470 } 470 }
471
472 public static void test_csharp_return_type_get_prop ()
473 {
474 var obj = new Dummy.TestObject();
475 obj.ReturnTypeGetProp = 5;
476 var i = obj.ReturnTypeGetProp;
477 }
478
479 public static void test_csharp_return_type_set_prop ()
480 {
481 var obj = new Dummy.TestObject();
482 obj.ReturnTypeSetProp = 5;
483 var i = obj.ReturnTypeSetProp;
484 }
485
486 public static void test_csharp_return_type_prop ()
487 {
488 var obj = new Dummy.TestObject();
489 obj.ReturnTypeProp = 5;
490 var i = obj.ReturnTypeProp;
491 }
471} 492}
472 493
473class TestEoGrandChildrenFinalize 494class TestEoGrandChildrenFinalize
diff --git a/src/tests/efl_mono/dummy_test_object.c b/src/tests/efl_mono/dummy_test_object.c
index 687737a4aa..210f2ca51f 100644
--- a/src/tests/efl_mono/dummy_test_object.c
+++ b/src/tests/efl_mono/dummy_test_object.c
@@ -4819,5 +4819,63 @@ const char* _dummy_inherit_helper_receive_dummy_and_call_in_stringshare(Dummy_Te
4819 return dummy_inherit_iface_stringshare_test (x, eina_stringshare_add("hello world")); 4819 return dummy_inherit_iface_stringshare_test (x, eina_stringshare_add("hello world"));
4820} 4820}
4821 4821
4822Eina_Success_Flag _dummy_test_object_return_type_get_prop_get(EINA_UNUSED const Eo *obj, Dummy_Test_Object_Data *pd EINA_UNUSED, int* i EINA_UNUSED)
4823{
4824 return EINA_TRUE;
4825}
4826
4827void _dummy_test_object_return_type_get_prop_set(EINA_UNUSED Eo *obj, Dummy_Test_Object_Data *pd EINA_UNUSED, int i EINA_UNUSED)
4828{
4829}
4830
4831int _dummy_test_object_return_type_set_prop_get(EINA_UNUSED const Eo *obj, Dummy_Test_Object_Data *pd EINA_UNUSED)
4832{
4833 return 0;
4834}
4835
4836Eina_Success_Flag _dummy_test_object_return_type_set_prop_set(EINA_UNUSED Eo *obj, Dummy_Test_Object_Data *pd EINA_UNUSED, int i EINA_UNUSED)
4837{
4838 return EINA_TRUE;
4839}
4840
4841Eina_Success_Flag _dummy_test_object_return_type_prop_get(EINA_UNUSED const Eo *obj, Dummy_Test_Object_Data *pd EINA_UNUSED, int* i EINA_UNUSED)
4842{
4843 return EINA_TRUE;
4844}
4845
4846Eina_Success_Flag _dummy_test_object_return_type_prop_set(EINA_UNUSED Eo *obj, Dummy_Test_Object_Data *pd EINA_UNUSED, int i EINA_UNUSED)
4847{
4848 return EINA_TRUE;
4849}
4850
4851Eina_Success_Flag _dummy_test_object_multi_value_return_type_get_prop_get(EINA_UNUSED const Eo *obj, Dummy_Test_Object_Data *pd EINA_UNUSED, int* i EINA_UNUSED, int* j EINA_UNUSED)
4852{
4853 return EINA_TRUE;
4854}
4855
4856void _dummy_test_object_multi_value_return_type_get_prop_set(EINA_UNUSED Eo *obj, Dummy_Test_Object_Data *pd EINA_UNUSED, int i EINA_UNUSED, int j EINA_UNUSED)
4857{
4858}
4859
4860void _dummy_test_object_multi_value_return_type_set_prop_get(EINA_UNUSED const Eo *obj, Dummy_Test_Object_Data *pd EINA_UNUSED, int* i EINA_UNUSED, int* j EINA_UNUSED)
4861{
4862}
4863
4864Eina_Success_Flag _dummy_test_object_multi_value_return_type_set_prop_set(EINA_UNUSED Eo *obj, Dummy_Test_Object_Data *pd EINA_UNUSED, int i EINA_UNUSED, int j EINA_UNUSED)
4865{
4866 return EINA_TRUE;
4867}
4868
4869Eina_Success_Flag _dummy_test_object_multi_value_return_type_prop_get(EINA_UNUSED const Eo *obj, Dummy_Test_Object_Data *pd EINA_UNUSED, int* i EINA_UNUSED, int* j EINA_UNUSED)
4870{
4871 return EINA_TRUE;
4872}
4873
4874Eina_Success_Flag _dummy_test_object_multi_value_return_type_prop_set(EINA_UNUSED Eo *obj, Dummy_Test_Object_Data *pd EINA_UNUSED, int i EINA_UNUSED, int j EINA_UNUSED)
4875{
4876 return EINA_TRUE;
4877}
4878
4879
4822#include "dummy_test_object.eo.c" 4880#include "dummy_test_object.eo.c"
4823 4881
diff --git a/src/tests/efl_mono/dummy_test_object.eo b/src/tests/efl_mono/dummy_test_object.eo
index fa3b52cace..85740f8b06 100644
--- a/src/tests/efl_mono/dummy_test_object.eo
+++ b/src/tests/efl_mono/dummy_test_object.eo
@@ -1686,7 +1686,63 @@ class Dummy.Test_Object extends Efl.Object implements Dummy.Test_Iface {
1686 prop: Dummy.Test_Iface; 1686 prop: Dummy.Test_Iface;
1687 } 1687 }
1688 } 1688 }
1689 } 1689
1690 @property return_type_get_prop {
1691 get { return: Eina.Success_Flag; }
1692 set {}
1693 values { i: int; }
1694 }
1695
1696 @property return_type_set_prop {
1697 set { return: Eina.Success_Flag; }
1698 get {}
1699 values { i: int; }
1700 }
1701
1702 @property return_type_prop {
1703 get {
1704 return: Eina.Success_Flag;
1705 }
1706 set {
1707 return: Eina.Success_Flag;
1708 }
1709 values { i: int; }
1710 }
1711
1712 @property multi_value_return_type_get_prop {
1713 get { return: Eina.Success_Flag; }
1714 set {}
1715 values
1716 {
1717 i: int;
1718 j: int;
1719 }
1720 }
1721
1722 @property multi_value_return_type_set_prop {
1723 set { return: Eina.Success_Flag; }
1724 get {}
1725 values
1726 {
1727 i: int;
1728 j: int;
1729 }
1730 }
1731
1732 @property multi_value_return_type_prop {
1733 get {
1734 return: Eina.Success_Flag;
1735 }
1736 set {
1737 return: Eina.Success_Flag;
1738 }
1739 values
1740 {
1741 i: int;
1742 j: int;
1743 }
1744 }
1745}
1690 implements { 1746 implements {
1691 Efl.Object.constructor; 1747 Efl.Object.constructor;
1692 Efl.Object.destructor; 1748 Efl.Object.destructor;