summaryrefslogtreecommitdiff
path: root/src/bin
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2020-01-30 16:49:04 -0300
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2020-02-18 16:47:38 -0300
commit595cb754b3aa280cdbebcb5fa0c51f287099b713 (patch)
tree49ce2ed6e0e25b7268267d8255dddf46266dfe71 /src/bin
parentd00dadb79ab1c216ecc0519716ca25a1f92c3632 (diff)
eolian-mono: Make Get/Set internal for generated properties
Make Get and Set methods internal for properties that get the property syntax generated. Reviewed-by: João Paulo Taylor Ienczak Zanette <joao.tiz@expertisesolutions.com.br> Differential Revision: https://phab.enlightenment.org/D11252
Diffstat (limited to 'src/bin')
-rw-r--r--src/bin/eolian_mono/eolian/mono/async_function_definition.hh5
-rw-r--r--src/bin/eolian_mono/eolian/mono/documentation.hh174
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_definition.hh96
-rw-r--r--src/bin/eolian_mono/eolian/mono/helpers.hh106
-rw-r--r--src/bin/eolian_mono/eolian/mono/klass.hh45
-rw-r--r--src/bin/eolian_mono/eolian/mono/parameter.hh33
-rw-r--r--src/bin/eolian_mono/eolian/mono/property_definition.hh383
7 files changed, 767 insertions, 75 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/async_function_definition.hh b/src/bin/eolian_mono/eolian/mono/async_function_definition.hh
index bc0bb6863a..3fddb03780 100644
--- a/src/bin/eolian_mono/eolian/mono/async_function_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/async_function_definition.hh
@@ -36,6 +36,7 @@
36#include "using_decl.hh" 36#include "using_decl.hh"
37#include "generation_contexts.hh" 37#include "generation_contexts.hh"
38#include "blacklist.hh" 38#include "blacklist.hh"
39#include "documentation.hh"
39 40
40namespace eolian_mono { 41namespace eolian_mono {
41 42
@@ -71,8 +72,10 @@ struct async_function_declaration_generator
71 if(f.scope != attributes::member_scope::scope_public) 72 if(f.scope != attributes::member_scope::scope_public)
72 return true; 73 return true;
73 74
75 auto ref = documentation_generator::function_conversion (f, context);
76
74 if (!as_generator( 77 if (!as_generator(
75 scope_tab(2) << "/// <summary>Async wrapper for <see cref=\"" << name_helpers::managed_method_name(f) << "\" />.\n" 78 scope_tab(2) << "/// <summary>Async wrapper for <see cref=\"" << ref << "\" />.\n"
76 ).generate(sink, attributes::unused, context)) 79 ).generate(sink, attributes::unused, context))
77 return false; 80 return false;
78 81
diff --git a/src/bin/eolian_mono/eolian/mono/documentation.hh b/src/bin/eolian_mono/eolian/mono/documentation.hh
index d15f91437d..eac5e1a179 100644
--- a/src/bin/eolian_mono/eolian/mono/documentation.hh
+++ b/src/bin/eolian_mono/eolian/mono/documentation.hh
@@ -23,6 +23,7 @@
23#include "name_helpers.hh" 23#include "name_helpers.hh"
24#include "generation_contexts.hh" 24#include "generation_contexts.hh"
25#include "blacklist.hh" 25#include "blacklist.hh"
26#include "property_definition.hh"
26 27
27#include <Eina.h> 28#include <Eina.h>
28 29
@@ -76,7 +77,8 @@ struct documentation_generator
76 // The name_tail parameter is the last 4 chars of the original string, which 77 // The name_tail parameter is the last 4 chars of the original string, which
77 // could be ".set" or ".get" and in this case they are ignored by Eolian. 78 // could be ".set" or ".get" and in this case they are ignored by Eolian.
78 // We want them to know what the documentation intended to reference. 79 // We want them to know what the documentation intended to reference.
79 static std::string function_conversion(const ::Eolian_Object *klass, const ::Eolian_Function *function, std::string name_tail) 80 template <typename Context>
81 static std::string function_conversion(const ::Eolian_Object *klass, const ::Eolian_Function *function, std::string name_tail, Context const& context)
80 { 82 {
81 ::Eolian_Function_Type ftype = ::eolian_function_type_get(function); 83 ::Eolian_Function_Type ftype = ::eolian_function_type_get(function);
82 const char* eo_name = ::eolian_function_name_get(function); 84 const char* eo_name = ::eolian_function_name_get(function);
@@ -113,26 +115,65 @@ struct documentation_generator
113 name += name_helpers::managed_method_name({function, ftype, NULL, eolian_object_unit_get(EOLIAN_OBJECT(function))}); 115 name += name_helpers::managed_method_name({function, ftype, NULL, eolian_object_unit_get(EOLIAN_OBJECT(function))});
114 break; 116 break;
115 case ::EOLIAN_PROP_SET: 117 case ::EOLIAN_PROP_SET:
116 name += ".Set";
117 name += name_helpers::property_managed_name(klass_d, eo_name);
118 break;
119 case ::EOLIAN_PROP_GET: 118 case ::EOLIAN_PROP_GET:
120 name += ".Get";
121 name += name_helpers::property_managed_name(klass_d, eo_name);
122 break;
123 case ::EOLIAN_PROPERTY: 119 case ::EOLIAN_PROPERTY:
120 {
121 efl::eina::optional<attributes::function_def> getter_func;
122 efl::eina::optional<attributes::function_def> setter_func;
123 auto unit = (const Eolian_Unit*) context_find_tag<eolian_state_context>(context).state;
124 if (ftype == ::EOLIAN_PROPERTY || ftype == ::EOLIAN_PROP_GET)
125 getter_func = attributes::function_def{function, ::EOLIAN_PROP_GET, nullptr, unit};
126 if (ftype == ::EOLIAN_PROPERTY || ftype == ::EOLIAN_PROP_SET)
127 setter_func = attributes::function_def{function, ::EOLIAN_PROP_SET, nullptr, unit};
128 attributes::property_def property{function, getter_func, setter_func, unit};
129
130 std::string short_name = name_helpers::property_managed_name(klass_d, eo_name);
131 class_context::wrapper_kind klass_kind;
132 if (helpers::is_managed_interface(klass_d))
133 klass_kind = class_context::interface;
134 else
135 klass_kind = class_context::inherit;
136 auto my_context = grammar::context_replace_tag(class_context{klass_kind}, context);
137
138 if (name_tail == ".get")
139 {
140 if (property_generate_wrapper_getter (property, my_context))
141 {
142 name += "." + short_name;
143 }
144 else
145 {
146 name += ".Get" + short_name;
147 }
148 }
149 else if (name_tail == ".set")
150 {
151 if (property_generate_wrapper_setter (property, my_context))
152 {
153 name += "." + short_name;
154 }
155 else
156 {
157 name += ".Set" + short_name;
158 }
159 }
160 else
124 { 161 {
125 int getter_nkeys = property_num_keys(function, ::EOLIAN_PROP_GET); 162 switch (ftype)
126 int setter_nkeys = property_num_keys(function, ::EOLIAN_PROP_SET); 163 {
127 std::string short_name = name_helpers::property_managed_name(klass_d, eo_name); 164 case ::EOLIAN_PROPERTY:
128 bool blacklisted = blacklist::is_property_blacklisted(name + "." + short_name); 165 case ::EOLIAN_PROP_GET:
129 // EO properties with keys or blacklisted are not converted into C# properties. 166 if (property_generate_wrapper_getter (property, my_context))
130 // In these cases we refer to the getter method instead of the property. 167 name += "." + short_name;
131 if ((getter_nkeys > 0) || (setter_nkeys > 0) || (blacklisted)) name += ".Get" + short_name; 168 else
132 else if (name_tail == ".get") name += ".Get" + short_name; 169 name += ".Get" + short_name;
133 else if (name_tail == ".set") name += ".Set" + short_name; 170 break;
134 else name += "." + short_name; 171 default:
172 name += ".Set" + short_name;
173 break;
174 }
135 } 175 }
176 }
136 break; 177 break;
137 default: 178 default:
138 break; 179 break;
@@ -140,33 +181,89 @@ struct documentation_generator
140 return name; 181 return name;
141 } 182 }
142 183
143 static std::string function_conversion(attributes::function_def const& func) 184 template <typename Context>
185 static std::string function_conversion(attributes::function_def const& func, Context const& context)
144 { 186 {
145 // This function is called only from the constructor reference conversion, so it does not 187 // This function is called only from the constructor reference conversion, so it does not
146 // need to check whether this function non-public in a interface returning an empty reference (yet). 188 // need to check whether this function non-public in a interface returning an empty reference (yet).
147 std::string name = name_helpers::klass_full_concrete_or_interface_name(func.klass); 189 std::string name = name_helpers::klass_full_concrete_or_interface_name(func.klass);
148 switch (func.type) 190 switch (func.type)
149 { 191 {
150 // managed_method_name takes care of reordering the function name so the get/set goes first 192 // managed_method_name takes care of reordering the function name so the get/set goes first
151 // for properties 193 // for properties
152 case attributes::function_type::method: 194 case attributes::function_type::method:
153 case attributes::function_type::prop_set: 195 if (blacklist::is_function_blacklisted(func.c_name))return "";
154 case attributes::function_type::prop_get: 196 if (!name.empty()) name += ".";
155 if (blacklist::is_function_blacklisted(func.c_name))return ""; 197 name += name_helpers::managed_method_name(func);
156 if (!name.empty()) name += "."; 198 break;
157 name += name_helpers::managed_method_name(func); 199 case attributes::function_type::prop_set:
158 break; 200 case attributes::function_type::prop_get:
159 default: 201 case attributes::function_type::property:
160 // No need to deal with property as function_defs are converted to get/set when building a given klass_def. 202 {
161 break; 203 auto unit = (const Eolian_Unit*) context_find_tag<eolian_state_context>(context).state;
204 auto klass = get_klass(func.klass, unit);
205 attributes::klass_def klass_d(klass, unit);
206
207 auto eo_name = func.name;
208 auto prop_name = eo_name;
209 if (prop_name.size () > 4
210 &&
211 ( prop_name.substr(prop_name.size() - 4) == "_set"
212 || prop_name.substr(prop_name.size() - 4) == "_get"))
213 {
214 prop_name = prop_name.substr(0, prop_name.size() - 4);
215 }
216 std::string short_name = name_helpers::property_managed_name(klass_d, prop_name);
217 assert (prop_name.size() <= 4 ||
218 (prop_name.substr(prop_name.size() - 4) != "_set"
219 && prop_name.substr(prop_name.size() - 4) != "_get"));
220 assert (short_name.size() <= 3 ||
221 (short_name.substr(short_name.size() - 3) != "Set"
222 && short_name.substr(short_name.size() - 3) != "Get"));
223
224 // We need to replace the current class context with the context
225 // from the class that originated this property.
226 class_context::wrapper_kind klass_kind;
227 if (helpers::is_managed_interface(klass_d))
228 klass_kind = class_context::interface;
229 else
230 klass_kind = class_context::inherit;
231
232 auto my_context = grammar::context_replace_tag(class_context{klass_kind}, context);
233
234 auto function = eolian_class_function_by_name_get (klass, prop_name.c_str(), EOLIAN_PROPERTY);
235 attributes::function_def getter_func{function, ::EOLIAN_PROP_GET, nullptr, unit};
236 attributes::function_def setter_func{function, ::EOLIAN_PROP_SET, nullptr, unit};
237 attributes::property_def prop{function, getter_func, setter_func, unit};
238
239 if (func.type == attributes::function_type::prop_get || func.type == attributes::function_type::property)
240 {
241 if (property_generate_wrapper_getter (prop, my_context))
242 name += "." + short_name;
243 else
244 name += ".Get" + short_name;
245 }
246 else if (func.type == attributes::function_type::prop_set)
247 {
248 if (property_generate_wrapper_setter (prop, my_context))
249 name += "." + short_name;
250 else
251 name += ".Set" + short_name;
252 }
253 }
254 break;
255 default:
256 // No need to deal with property as function_defs are converted to get/set when building a given klass_def.
257 break;
162 } 258 }
163 259
164 return name; 260 return name;
165 } 261 }
166 262
167 // Turns an Eolian reference like @Efl.Input.Pointer.tool into a <see> tag 263 // Turns an Eolian reference like @Efl.Input.Pointer.tool into a <see> tag
264 template <typename Context>
168 static std::string ref_conversion(const ::Eolian_Doc_Token *token, const Eolian_State *state, std::string name_tail, 265 static std::string ref_conversion(const ::Eolian_Doc_Token *token, const Eolian_State *state, std::string name_tail,
169 bool want_beta) 266 bool want_beta, Context const& context)
170 { 267 {
171 const Eolian_Object *data, *data2; 268 const Eolian_Object *data, *data2;
172 ::Eolian_Object_Type type = 269 ::Eolian_Object_Type type =
@@ -195,7 +292,7 @@ struct documentation_generator
195 is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2); 292 is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2);
196 break; 293 break;
197 case ::EOLIAN_OBJECT_FUNCTION: 294 case ::EOLIAN_OBJECT_FUNCTION:
198 ref += function_conversion(data, (const ::Eolian_Function *)data2, name_tail); 295 ref += function_conversion(data, (const ::Eolian_Function *)data2, name_tail, context);
199 is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2); 296 is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2);
200 break; 297 break;
201 case ::EOLIAN_OBJECT_CONSTANT: 298 case ::EOLIAN_OBJECT_CONSTANT:
@@ -226,8 +323,9 @@ struct documentation_generator
226 return ref; 323 return ref;
227 } 324 }
228 325
229 // Turns EO documentation syntax into C# triple-slash XML comment syntax 326 // Turns EO documentation syntax into C# triple-slash XML comment syntax
230 static std::string syntax_conversion(std::string text, const Eolian_State *state, bool want_beta) 327 template <typename Context>
328 static std::string syntax_conversion(std::string text, const Eolian_State *state, bool want_beta, Context const& context)
231 { 329 {
232 std::string new_text, ref; 330 std::string new_text, ref;
233 ::Eolian_Doc_Token_Type previous_token_type = ::EOLIAN_DOC_TOKEN_UNKNOWN; 331 ::Eolian_Doc_Token_Type previous_token_type = ::EOLIAN_DOC_TOKEN_UNKNOWN;
@@ -266,7 +364,7 @@ struct documentation_generator
266 new_text += token_text; 364 new_text += token_text;
267 break; 365 break;
268 case ::EOLIAN_DOC_TOKEN_REF: 366 case ::EOLIAN_DOC_TOKEN_REF:
269 ref = ref_conversion(&token, state, name_tail, want_beta); 367 ref = ref_conversion(&token, state, name_tail, want_beta, context);
270 if (ref != "") 368 if (ref != "")
271 { 369 {
272 if (utils::ends_with(ref, BETA_REF_SUFFIX)) 370 if (utils::ends_with(ref, BETA_REF_SUFFIX))
@@ -333,7 +431,7 @@ struct documentation_generator
333 if (!as_generator(html_escaped_string).generate(std::back_inserter(new_text), text, context)) 431 if (!as_generator(html_escaped_string).generate(std::back_inserter(new_text), text, context))
334 return false; 432 return false;
335 auto options = context_find_tag<options_context>(context); 433 auto options = context_find_tag<options_context>(context);
336 new_text = syntax_conversion( new_text, context_find_tag<eolian_state_context>(context).state, options.want_beta); 434 new_text = syntax_conversion( new_text, context_find_tag<eolian_state_context>(context).state, options.want_beta, context);
337 435
338 std::string tabs; 436 std::string tabs;
339 as_generator(scope_tab(scope_size) << "/// ").generate (std::back_inserter(tabs), attributes::unused, context); 437 as_generator(scope_tab(scope_size) << "/// ").generate (std::back_inserter(tabs), attributes::unused, context);
@@ -698,7 +796,7 @@ struct documentation_generator
698 796
699 for (auto &&param : ctor.function.parameters) 797 for (auto &&param : ctor.function.parameters)
700 { 798 {
701 auto ref = function_conversion(func); 799 auto ref = function_conversion(func, context);
702 800
703 if (!context_find_tag<options_context>(context).want_beta && func.is_beta) 801 if (!context_find_tag<options_context>(context).want_beta && func.is_beta)
704 { 802 {
@@ -741,7 +839,7 @@ struct documentation_string_generator
741 839
742 auto options = context_find_tag<options_context>(context); 840 auto options = context_find_tag<options_context>(context);
743 auto state = context_find_tag<eolian_state_context>(context).state; 841 auto state = context_find_tag<eolian_state_context>(context).state;
744 if (!as_generator(string).generate(sink, documentation_generator::syntax_conversion(escaped, state, options.want_beta), context)) 842 if (!as_generator(string).generate(sink, documentation_generator::syntax_conversion(escaped, state, options.want_beta, context), context))
745 return false; 843 return false;
746 844
747 return true; 845 return true;
diff --git a/src/bin/eolian_mono/eolian/mono/function_definition.hh b/src/bin/eolian_mono/eolian/mono/function_definition.hh
index 3c30cdd3fe..6aeaadcedb 100644
--- a/src/bin/eolian_mono/eolian/mono/function_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_definition.hh
@@ -27,6 +27,7 @@
27#include "grammar/alternative.hpp" 27#include "grammar/alternative.hpp"
28#include "grammar/attribute_reorder.hpp" 28#include "grammar/attribute_reorder.hpp"
29#include "grammar/counter.hpp" 29#include "grammar/counter.hpp"
30#include "property_definition.hh"
30#include "logging.hh" 31#include "logging.hh"
31#include "type.hh" 32#include "type.hh"
32#include "name_helpers.hh" 33#include "name_helpers.hh"
@@ -44,6 +45,7 @@ namespace eolian_mono {
44struct native_function_definition_generator 45struct native_function_definition_generator
45{ 46{
46 attributes::klass_def const* klass; 47 attributes::klass_def const* klass;
48 std::vector<attributes::property_def> properties;
47 49
48 template <typename OutputIterator, typename Context> 50 template <typename OutputIterator, typename Context>
49 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const 51 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
@@ -52,6 +54,24 @@ struct native_function_definition_generator
52 if(blacklist::is_function_blacklisted(f, context)) 54 if(blacklist::is_function_blacklisted(f, context))
53 return true; 55 return true;
54 56
57 auto it = std::find_if (properties.begin(), properties.end()
58 , [&] (attributes::property_def const& prop)
59 {
60 return (prop.getter && *prop.getter == f)
61 || (prop.setter && *prop.setter == f);
62 });
63 if (it != properties.end())
64 {
65 if (it->getter && *it->getter == f)
66 {
67 if (property_generate_wrapper_getter (*it, context))
68 return true;
69 }
70 else
71 if (property_generate_wrapper_setter (*it, context))
72 return true;
73 }
74
55 auto const& indent = current_indentation(context); 75 auto const& indent = current_indentation(context);
56 76
57 // Delegate for the C# method we will export to EO as a method implementation. 77 // Delegate for the C# method we will export to EO as a method implementation.
@@ -184,10 +204,6 @@ struct native_function_definition_generator
184 204
185struct function_definition_generator 205struct function_definition_generator
186{ 206{
187 function_definition_generator(bool do_super = false)
188 : do_super(do_super)
189 {}
190
191 template <typename OutputIterator, typename Context> 207 template <typename OutputIterator, typename Context>
192 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const 208 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
193 { 209 {
@@ -197,6 +213,25 @@ struct function_definition_generator
197 if(blacklist::is_function_blacklisted(f, context)) 213 if(blacklist::is_function_blacklisted(f, context))
198 return true; 214 return true;
199 215
216 auto function_scope = eolian_mono::function_scope_get(f);
217 auto it = std::find_if (properties.begin(), properties.end()
218 , [&] (attributes::property_def const& prop)
219 {
220 return (prop.getter && *prop.getter == f)
221 || (prop.setter && *prop.setter == f);
222 });
223 if (it != properties.end())
224 {
225 if (it->getter && *it->getter == f)
226 {
227 if (property_generate_wrapper_getter (*it, context))
228 function_scope = "internal ";
229 }
230 else
231 if (property_generate_wrapper_setter (*it, context))
232 function_scope = "internal ";
233 }
234
200 // Do not generate static function for concrete class 235 // Do not generate static function for concrete class
201 if (is_concrete && f.is_static) 236 if (is_concrete && f.is_static)
202 return true; 237 return true;
@@ -219,7 +254,7 @@ struct function_definition_generator
219 self = ""; 254 self = "";
220 255
221 if(!as_generator 256 if(!as_generator
222 (scope_tab(2) << eolian_mono::function_scope_get(f) << ((do_super && !f.is_static) ? "virtual " : "") << (f.is_static ? "static " : "") << return_type << " " << string << "(" << (parameter % ", ") 257 (scope_tab(2) << function_scope << ((do_super && !f.is_static) ? "virtual " : "") << (f.is_static ? "static " : "") << return_type << " " << string << "(" << (parameter % ", ")
223 << ") {\n" 258 << ") {\n"
224 << scope_tab(3) << eolian_mono::function_definition_preamble() 259 << scope_tab(3) << eolian_mono::function_definition_preamble()
225 << klass_full_native_inherit_name(f.klass) << "." << string << "_ptr.Value.Delegate(" 260 << klass_full_native_inherit_name(f.klass) << "." << string << "_ptr.Value.Delegate("
@@ -235,24 +270,29 @@ struct function_definition_generator
235 } 270 }
236 271
237 bool do_super; 272 bool do_super;
273 std::vector<attributes::property_def> properties;
238}; 274};
239 275
240struct function_definition_parameterized 276struct function_definition_parameterized
241{ 277{
242 function_definition_generator operator()(bool do_super) const 278 function_definition_generator operator()(bool do_super, std::vector<attributes::property_def> properties) const
279 {
280 return {do_super, properties};
281 }
282 function_definition_generator operator()(std::vector<attributes::property_def> properties) const
243 { 283 {
244 return {do_super}; 284 return {false, properties};
245 } 285 }
246} const function_definition; 286} const function_definition;
247function_definition_generator as_generator(function_definition_parameterized) 287// function_definition_generator as_generator(function_definition_parameterized)
248{ 288// {
249 return {}; 289// return {};
250} 290// }
251struct native_function_definition_parameterized 291struct native_function_definition_parameterized
252{ 292{
253 native_function_definition_generator operator()(attributes::klass_def const& klass) const 293 native_function_definition_generator operator()(attributes::klass_def const& klass, std::vector<attributes::property_def> properties) const
254 { 294 {
255 return {&klass}; 295 return {&klass, properties};
256 } 296 }
257} const native_function_definition; 297} const native_function_definition;
258 298
@@ -356,27 +396,19 @@ struct property_wrapper_definition_generator
356 // if (get_params > 0 || set_params > 1) 396 // if (get_params > 0 || set_params > 1)
357 // return true; 397 // return true;
358 398
359 if (property.getter 399 if (property.getter && !property.getter->keys.empty())
360 && std::find_if (property.getter->parameters.begin()
361 , property.getter->parameters.end()
362 , [] (parameter_def const& p)
363 {
364 return p.direction != parameter_direction::out;
365 }) != property.getter->parameters.end())
366 return true; 400 return true;
367 if (property.setter 401 if (property.setter && !property.setter->keys.empty())
368 && std::find_if (property.setter->parameters.begin()
369 , property.setter->parameters.end()
370 , [] (parameter_def const& p)
371 {
372 return p.direction != parameter_direction::in;
373 }) != property.setter->parameters.end())
374 return true; 402 return true;
375 403
376 if (property.getter && property.setter) 404 if (property.getter && property.setter)
377 { 405 {
378 if (get_params != 0 && property.setter->parameters.size() != property.getter->parameters.size()) 406 if (property.setter->values.size() != property.getter->values.size())
379 return true; 407 {
408 if (!std::equal(property.setter->values.begin(), property.setter->values.end()
409 , property.getter->values.begin()))
410 return true;
411 }
380 } 412 }
381 413
382 std::vector<attributes::parameter_def> parameters; 414 std::vector<attributes::parameter_def> parameters;
@@ -481,9 +513,11 @@ struct property_wrapper_definition_generator
481 if (property.getter.is_engaged() && is_interface) 513 if (property.getter.is_engaged() && is_interface)
482 { 514 {
483 if (is_get_public) 515 if (is_get_public)
516 {
484 if (!as_generator(scope_tab(2) << scope_tab << set_scope << "get;\n" 517 if (!as_generator(scope_tab(2) << scope_tab << set_scope << "get;\n"
485 ).generate(sink, attributes::unused, context)) 518 ).generate(sink, attributes::unused, context))
486 return false; 519 return false;
520 }
487 } 521 }
488 else if (property.getter.is_engaged() && get_params == 0/*parameters.size() == 1 && property.getter.is_engaged()*/) 522 else if (property.getter.is_engaged() && get_params == 0/*parameters.size() == 1 && property.getter.is_engaged()*/)
489 { 523 {
@@ -526,9 +560,11 @@ struct property_wrapper_definition_generator
526 if (property.setter.is_engaged() && is_interface) 560 if (property.setter.is_engaged() && is_interface)
527 { 561 {
528 if (is_set_public) 562 if (is_set_public)
563 {
529 if (!as_generator(scope_tab(2) << scope_tab << set_scope << "set;\n" 564 if (!as_generator(scope_tab(2) << scope_tab << set_scope << "set;\n"
530 ).generate(sink, attributes::unused, context)) 565 ).generate(sink, attributes::unused, context))
531 return false; 566 return false;
567 }
532 } 568 }
533 else if (parameters.size() == 1 && property.setter.is_engaged()) 569 else if (parameters.size() == 1 && property.setter.is_engaged())
534 { 570 {
diff --git a/src/bin/eolian_mono/eolian/mono/helpers.hh b/src/bin/eolian_mono/eolian/mono/helpers.hh
index b34a985749..f704ef00af 100644
--- a/src/bin/eolian_mono/eolian/mono/helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/helpers.hh
@@ -248,6 +248,67 @@ std::vector<attributes::function_def> get_all_implementable_methods(attributes::
248 return ret; 248 return ret;
249} 249}
250 250
251/*
252 * Gets all properties that this class should implement (i.e. that come from an unimplemented interface/mixin and the class itself)
253 */
254template<typename Context>
255std::vector<attributes::property_def> get_all_implementable_properties(attributes::klass_def const& cls, Context const& context)
256{
257 bool want_beta = efl::eolian::grammar::context_find_tag<options_context>(context).want_beta;
258 std::vector<attributes::property_def> ret;
259 auto filter_beta = [&want_beta](attributes::property_def const& prop) {
260 if (!want_beta)
261 return prop.getter && !prop.setter ? !prop.getter->is_beta
262 : prop.getter && prop.setter ? !prop.getter->is_beta || !prop.setter->is_beta
263 : true
264 ;
265 else
266 return true;
267 };
268
269 std::copy_if(cls.properties.begin(), cls.properties.end(), std::back_inserter(ret), filter_beta);
270
271 // Non implemented interfaces
272 std::set<attributes::klass_name, attributes::compare_klass_name_by_name> implemented_interfaces;
273 std::set<attributes::klass_name, attributes::compare_klass_name_by_name> interfaces;
274 std::function<void(attributes::klass_name const&, bool)> inherit_algo =
275 [&] (attributes::klass_name const &klass, bool is_implemented)
276 {
277 attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
278 for (auto&& inherit: c.immediate_inherits)
279 {
280 switch(inherit.type)
281 {
282 case attributes::class_type::mixin:
283 case attributes::class_type::interface_:
284 interfaces.insert(inherit);
285 if (is_implemented)
286 implemented_interfaces.insert(inherit);
287 inherit_algo(inherit, is_implemented);
288 break;
289 case attributes::class_type::abstract_:
290 case attributes::class_type::regular:
291 inherit_algo(inherit, true);
292 default:
293 break;
294 }
295 }
296 };
297
298 inherit_algo(attributes::get_klass_name(cls), false);
299
300 for (auto&& inherit : implemented_interfaces)
301 interfaces.erase(inherit);
302
303 for (auto&& inherit : interfaces)
304 {
305 attributes::klass_def klass(get_klass(inherit, cls.unit), cls.unit);
306 std::copy_if(klass.properties.cbegin(), klass.properties.cend(), std::back_inserter(ret), filter_beta);
307 }
308
309 return ret;
310}
311
251template<typename Klass> 312template<typename Klass>
252inline bool is_managed_interface(Klass const& klass) 313inline bool is_managed_interface(Klass const& klass)
253{ 314{
@@ -284,6 +345,51 @@ std::vector<attributes::function_def> get_all_registerable_methods(attributes::k
284 return ret; 345 return ret;
285} 346}
286 347
348bool is_function_registerable (attributes::function_def func, attributes::klass_def const& cls)
349{
350 if (cls == func.klass)
351 return true;
352
353 if (is_managed_interface(func.klass) && func.is_static)
354 return true;
355
356 if (!is_managed_interface(func.klass) || func.scope != attributes::member_scope::scope_public)
357 return true;
358 return false;
359}
360
361// /*
362// * Gets all methods that this class should register (i.e. that comes from it and non-public interface methods
363// * that this class is the first one implementing)
364// */
365// template<typename Context>
366// std::vector<attributes::property_def> get_all_registerable_properties(attributes::klass_def const& cls, Context const& context)
367// {
368// std::vector<attributes::property_def> ret;
369
370// auto implementable_properties = get_all_implementable_properties(cls, context);
371
372// std::copy_if(implementable_properties.cbegin(), implementable_properties.cend(), std::back_inserter(ret)
373// , [&cls](attributes::property_def const & property) {
374// auto klass = property.getter ? property.getter->klass
375// : property.setter->klass;
376
377// if (cls == klass)
378// return true;
379
380// if (is_managed_interface(klass) && ((property.getter && property.getter->is_static)
381// || (property.setter && property.setter->is_static)))
382// return true;
383
384// if (!is_managed_interface(klass) || ((property.getter && property.getter->scope != attributes::member_scope::scope_public)
385// || (property.setter && property.setter->scope != attributes::member_scope::scope_public)))
386// return true;
387// return false;
388// });
389
390// return ret;
391// }
392
287/* 393/*
288 * Checks whether the given is unique going up the inheritance tree from leaf_klass 394 * Checks whether the given is unique going up the inheritance tree from leaf_klass
289 */ 395 */
diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh
index da6fd6d45c..9a494ef4c2 100644
--- a/src/bin/eolian_mono/eolian/mono/klass.hh
+++ b/src/bin/eolian_mono/eolian/mono/klass.hh
@@ -29,6 +29,7 @@
29#include "name_helpers.hh" 29#include "name_helpers.hh"
30#include "async_function_definition.hh" 30#include "async_function_definition.hh"
31#include "function_definition.hh" 31#include "function_definition.hh"
32#include "property_definition.hh"
32#include "function_registration.hh" 33#include "function_registration.hh"
33#include "function_declaration.hh" 34#include "function_declaration.hh"
34#include "documentation.hh" 35#include "documentation.hh"
@@ -142,7 +143,27 @@ struct klass
142 if(!as_generator("\n" << scope_tab << "{\n").generate(sink, attributes::unused, iface_cxt)) 143 if(!as_generator("\n" << scope_tab << "{\n").generate(sink, attributes::unused, iface_cxt))
143 return false; 144 return false;
144 145
145 if(!as_generator(*(function_declaration)).generate(sink, cls.functions, iface_cxt)) 146 auto properties = cls.properties;
147 auto functions = cls.functions;
148 functions.erase (std::remove_if (functions.begin(), functions.end()
149 , [&] (attributes::function_def const& f)
150 {
151 auto it = std::find_if (properties.begin(), properties.end()
152 , [&f] (attributes::property_def const& prop)
153 {
154 return (prop.getter && *prop.getter == f)
155 || (prop.setter && *prop.setter == f);
156 });
157 if (it != properties.end())
158 {
159 if (it->getter && *it->getter == f)
160 return property_generate_wrapper_getter (*it, iface_cxt);
161 else if (it->setter && *it->setter == f)
162 return property_generate_wrapper_setter (*it, iface_cxt);
163 }
164 return false;
165 }), functions.end());
166 if(!as_generator(*(function_declaration)).generate(sink, functions, iface_cxt))
146 return false; 167 return false;
147 168
148 if(!as_generator(*(async_function_declaration)).generate(sink, cls.functions, iface_cxt)) 169 if(!as_generator(*(async_function_declaration)).generate(sink, cls.functions, iface_cxt))
@@ -158,7 +179,10 @@ struct klass
158 ).generate(sink, p, iface_cxt)) 179 ).generate(sink, p, iface_cxt))
159 return false; 180 return false;
160 181
161 if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, cls.properties, iface_cxt)) 182 properties.erase(std::remove_if (properties.begin(), properties.end()
183 , [&] (attributes::property_def const& prop)
184 { return !property_generate_wrapper_getter (prop, iface_cxt); }), properties.end());
185 if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, properties, iface_cxt))
162 return false; 186 return false;
163 187
164 // End of interface declaration 188 // End of interface declaration
@@ -246,7 +270,7 @@ struct klass
246 270
247 // Inherit function definitions 271 // Inherit function definitions
248 auto implemented_methods = helpers::get_all_implementable_methods(cls, inherit_cxt); 272 auto implemented_methods = helpers::get_all_implementable_methods(cls, inherit_cxt);
249 if(!as_generator(*(function_definition(true))) 273 if(!as_generator(*(function_definition(true, helpers::get_all_implementable_properties(cls, inherit_cxt))))
250 .generate(sink, implemented_methods, inherit_cxt)) return false; 274 .generate(sink, implemented_methods, inherit_cxt)) return false;
251 275
252 // Async wrappers 276 // Async wrappers
@@ -337,6 +361,7 @@ struct klass
337 auto native_inherit_name = name_helpers::klass_native_inherit_name(cls); 361 auto native_inherit_name = name_helpers::klass_native_inherit_name(cls);
338 auto inherit_name = name_helpers::klass_inherit_name(cls); 362 auto inherit_name = name_helpers::klass_inherit_name(cls);
339 auto implementable_methods = helpers::get_all_registerable_methods(cls, context); 363 auto implementable_methods = helpers::get_all_registerable_methods(cls, context);
364 auto implementable_properties = helpers::get_all_implementable_properties(cls, context);
340 bool root = !helpers::has_regular_ancestor(cls); 365 bool root = !helpers::has_regular_ancestor(cls);
341 bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete; 366 bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
342 auto const& indent = current_indentation(inative_cxt).inc(); 367 auto const& indent = current_indentation(inative_cxt).inc();
@@ -376,11 +401,12 @@ struct klass
376 return false; 401 return false;
377 } 402 }
378 403
379 if(implementable_methods.size() >= 1) 404 if(!implementable_methods.empty())
380 { 405 {
381 if(!as_generator( 406 if(!as_generator(
382 indent << scope_tab << "private static Efl.Eo.NativeModule Module = new Efl.Eo.NativeModule(" 407 indent << scope_tab << "private static Efl.Eo.NativeModule Module = new Efl.Eo.NativeModule("
383 << context_find_tag<library_context>(context).actual_library_name(cls.filename) << ");\n\n" 408 << context_find_tag<library_context>(context).actual_library_name(cls.filename) << "); // " << implementable_methods.size()
409 << " " << implementable_properties.size() << "\n\n"
384 ).generate(sink, attributes::unused, inative_cxt)) 410 ).generate(sink, attributes::unused, inative_cxt))
385 return false; 411 return false;
386 } 412 }
@@ -455,10 +481,17 @@ struct klass
455 // Native method definitions 481 // Native method definitions
456 if(!as_generator( 482 if(!as_generator(
457 indent << scope_tab << "#pragma warning disable CA1707, CS1591, SA1300, SA1600\n\n" 483 indent << scope_tab << "#pragma warning disable CA1707, CS1591, SA1300, SA1600\n\n"
458 << *(native_function_definition(cls)) 484 << *(native_function_definition(cls, implementable_properties))
459 << indent << scope_tab << "#pragma warning restore CA1707, CS1591, SA1300, SA1600\n\n") 485 << indent << scope_tab << "#pragma warning restore CA1707, CS1591, SA1300, SA1600\n\n")
460 .generate(sink, implementable_methods, change_indentation(indent.inc(), inative_cxt))) return false; 486 .generate(sink, implementable_methods, change_indentation(indent.inc(), inative_cxt))) return false;
461 487
488 if(!as_generator(
489 indent << scope_tab << "#pragma warning disable CA1707, CS1591, SA1300, SA1600\n\n"
490 << *(native_property_function_definition(cls, cls))
491 << indent << scope_tab << "#pragma warning restore CA1707, CS1591, SA1300, SA1600\n\n")
492 .generate(sink, implementable_properties
493 , change_indentation(indent.inc(), inative_cxt))) return false;
494
462 if(!as_generator(indent << "}\n").generate(sink, attributes::unused, inative_cxt)) return false; 495 if(!as_generator(indent << "}\n").generate(sink, attributes::unused, inative_cxt)) return false;
463 } 496 }
464 return true; 497 return true;
diff --git a/src/bin/eolian_mono/eolian/mono/parameter.hh b/src/bin/eolian_mono/eolian/mono/parameter.hh
index abd94641ef..59faa0d493 100644
--- a/src/bin/eolian_mono/eolian/mono/parameter.hh
+++ b/src/bin/eolian_mono/eolian/mono/parameter.hh
@@ -34,6 +34,7 @@ namespace eolian_mono {
34 struct argument_generator; 34 struct argument_generator;
35 struct argument_invocation_generator; 35 struct argument_invocation_generator;
36 struct native_argument_invocation_generator; 36 struct native_argument_invocation_generator;
37 struct native_tuple_argument_invocation_generator;
37 struct native_convert_in_variable_generator; 38 struct native_convert_in_variable_generator;
38 struct convert_in_variable_generator; 39 struct convert_in_variable_generator;
39 struct native_convert_out_variable_generator; 40 struct native_convert_out_variable_generator;
@@ -109,6 +110,16 @@ struct attributes_needed< ::eolian_mono::native_argument_invocation_generator> :
109} 110}
110 111
111template <> 112template <>
113struct is_eager_generator< ::eolian_mono::native_tuple_argument_invocation_generator> : std::true_type {};
114template <>
115struct is_generator< ::eolian_mono::native_tuple_argument_invocation_generator> : std::true_type {};
116
117namespace type_traits {
118template <>
119struct attributes_needed< ::eolian_mono::native_tuple_argument_invocation_generator> : std::integral_constant<int, 1> {};
120}
121
122template <>
112struct is_eager_generator< ::eolian_mono::native_convert_in_variable_generator> : std::true_type {}; 123struct is_eager_generator< ::eolian_mono::native_convert_in_variable_generator> : std::true_type {};
113template <> 124template <>
114struct is_generator< ::eolian_mono::native_convert_in_variable_generator> : std::true_type {}; 125struct is_generator< ::eolian_mono::native_convert_in_variable_generator> : std::true_type {};
@@ -552,6 +563,28 @@ struct native_argument_invocation_generator
552 } 563 }
553} const native_argument_invocation {}; 564} const native_argument_invocation {};
554 565
566struct native_tuple_argument_invocation_generator
567{
568 template <typename OutputIterator, typename Context>
569 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
570 {
571 std::string arg;// = direction_modifier(param);
572
573 if (param_should_use_out_var(param, true))
574 arg += out_variable_name(param.param_name);
575 else if (param_should_use_in_var(param, true))
576 arg += in_variable_name(param.param_name);
577 else if (param.type.original_type.visit(is_fp_visitor{}))
578 {
579 arg += escape_keyword(param.param_name) + "_wrapper.ManagedCb";
580 }
581 else // FIXME Wrap data and C function pointers into some kind of structure.
582 arg += escape_keyword(param.param_name);
583
584 return as_generator(arg).generate(sink, attributes::unused, context);
585 }
586} const native_tuple_argument_invocation {};
587
555// Generates the correct parameter name when invoking a function 588// Generates the correct parameter name when invoking a function
556struct argument_invocation_generator 589struct argument_invocation_generator
557{ 590{
diff --git a/src/bin/eolian_mono/eolian/mono/property_definition.hh b/src/bin/eolian_mono/eolian/mono/property_definition.hh
new file mode 100644
index 0000000000..df94fc36e8
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/property_definition.hh
@@ -0,0 +1,383 @@
1/*
2 * Copyright 2019 by its authors. See AUTHORS.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef EOLIAN_MONO_PROPERTY_DEFINITION_HH
17#define EOLIAN_MONO_PROPERTY_DEFINITION_HH
18
19#include "grammar/generator.hpp"
20#include "grammar/klass_def.hpp"
21
22#include "grammar/indentation.hpp"
23#include "grammar/list.hpp"
24#include "grammar/alternative.hpp"
25#include "type.hh"
26#include "parameter.hh"
27#include "name_helpers.hh"
28#include "using_decl.hh"
29#include "blacklist.hh"
30
31#include <eina_variant.hh>
32
33namespace eolian_mono {
34
35struct compare_get_and_set_value_type
36{
37 inline bool operator () (attributes::parameter_def const& get, attributes::parameter_def const& set) const;
38 inline bool operator () (attributes::type_def const& get, attributes::type_def const& set) const;
39};
40
41struct compare_get_and_set_value_type_overload
42{
43 template <typename T, typename U>
44 bool operator()(T const& /*left*/, U const& /*right*/) const
45 {
46 return false;
47 }
48 bool operator()(attributes::regular_type_def const& left, attributes::regular_type_def const& right) const
49 {
50 return left.base_type == right.base_type
51 && left.namespaces == right.namespaces;
52 }
53 bool operator()(attributes::complex_type_def const& left, attributes::complex_type_def const& right) const
54 {
55 return (*this)(left.outer, right.outer)
56 && std::equal (left.subtypes.begin(), left.subtypes.end(), right.subtypes.begin()
57 , compare_get_and_set_value_type{});
58 }
59 bool operator()(attributes::klass_name const& left, attributes::klass_name const& right) const
60 {
61 return left.namespaces == right.namespaces
62 && left.eolian_name == right.eolian_name;
63 }
64
65 typedef bool result_type;
66};
67
68inline bool compare_get_and_set_value_type::operator () (attributes::parameter_def const& get, attributes::parameter_def const& set) const
69{
70 return efl::eina::visit(compare_get_and_set_value_type_overload{}, get.type.original_type, set.type.original_type);
71}
72inline bool compare_get_and_set_value_type::operator () (attributes::type_def const& get, attributes::type_def const& set) const
73{
74 return efl::eina::visit(compare_get_and_set_value_type_overload{}, get.original_type, set.original_type);
75}
76
77template <typename Context>
78bool property_generate_wrapper_both_check(attributes::property_def const& property, Context const& context)
79{
80 if (blacklist::is_property_blacklisted(property, context))
81 return false;
82
83 bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
84 bool is_static = (property.getter.is_engaged() && property.getter->is_static)
85 || (property.setter.is_engaged() && property.setter->is_static);
86 bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
87
88 if ((is_concrete || is_interface) && is_static)
89 return false;
90
91 if (!property.getter)
92 return false;
93
94 if (property.setter)
95 {
96 if (property.getter->values.size() == property.setter->values.size())
97 {
98 if (!std::equal (property.getter->values.begin(), property.getter->values.end(), property.setter->values.begin()
99 , compare_get_and_set_value_type{}))
100 return false;
101 }
102 else
103 return false;
104 }
105
106 return true;
107}
108
109template <typename Context>
110bool property_generate_wrapper_getter(attributes::property_def const& property, Context const& context)
111{
112 if (!property_generate_wrapper_both_check (property, context))
113 return false;
114
115 if (!property.getter->keys.empty())
116 return false;
117
118 if (property.getter->explicit_return_type != attributes::void_)
119 return false;
120
121 assert (!!property.getter.is_engaged());
122
123 bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
124 if (is_interface)
125 {
126 std::string get_scope = property.getter.is_engaged() ? eolian_mono::function_scope_get(*property.getter) : "";
127 bool is_get_public = get_scope == "public ";
128 if (!is_get_public)
129 return false;
130 }
131 return true;
132}
133
134template <typename Context>
135bool property_generate_wrapper_setter (attributes::property_def const& property, Context const& context)
136{
137 if (!property_generate_wrapper_both_check (property, context))
138 return false;
139 if (!property.setter)
140 return false;
141
142 if (property.setter->explicit_return_type != attributes::void_)
143 return false;
144
145 if (!property.setter->keys.empty())
146 return false;
147
148 bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
149 if (property.setter.is_engaged() && is_interface)
150 {
151 std::string set_scope = property.setter.is_engaged() ? eolian_mono::function_scope_get(*property.setter) : "";
152 bool is_set_public = set_scope == "public ";
153 if (!is_set_public)
154 return false;
155 }
156
157 return true;
158}
159
160struct native_property_function_definition_generator
161{
162 template <typename OutputIterator, typename Context>
163 bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const
164 {
165 EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "native_property_function_definition_generator: " << property.name << std::endl;
166
167 if(blacklist::is_property_blacklisted(property, context))
168 return true;
169
170 auto const& indent = current_indentation(context);
171
172 bool has_wrapper_getter = property_generate_wrapper_getter (property, context);
173 bool has_wrapper_setter = property_generate_wrapper_setter (property, context);
174
175 auto gen = [&] (attributes::function_def const& f, bool is_set)
176 {
177 // Delegate for the C# method we will export to EO as a method implementation.
178 if(!as_generator
179 (
180 indent << eolian_mono::marshall_annotation(true) << "\n"
181 << indent << "private delegate "
182 << eolian_mono::marshall_type(true)
183 << " "
184 << string
185 << "_delegate(" << (f.is_static ? "" : "System.IntPtr obj, System.IntPtr pd")
186 << ((!f.is_static && f.parameters.size() > 0) ? ", " : "")
187 << (grammar::attribute_reorder<-1, -1>
188 (
189 (marshall_annotation << " " << marshall_parameter)
190 ) % ", ")
191 << ");\n\n")
192 .generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
193 return false;
194
195 // API delegate is the wrapper for the Eo methods exported from C that we will use from C#.
196 if(!as_generator
197 (
198 indent << eolian_mono::marshall_annotation(true) << "\n"
199 << indent << "internal delegate "
200 << eolian_mono::marshall_type(true)
201 << " "
202 << string << "_api_delegate(" << (f.is_static ? "" : "System.IntPtr obj")
203 << ((!f.is_static && f.parameters.size() > 0) ? ", " : "")
204 << (grammar::attribute_reorder<-1, -1>
205 (
206 (marshall_annotation << " " << marshall_parameter)
207 ) % ", ")
208 << ");\n\n")
209 .generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
210 return false;
211
212 // Delegate holder (so it can't be collected).
213 if(!as_generator
214 (indent << "internal static readonly Efl.Eo.FunctionWrapper<" << string << "_api_delegate> " << string << "_ptr = new Efl.Eo.FunctionWrapper<"
215 << string << "_api_delegate>(Module, \"" << string << "\");\n\n")
216 .generate(sink, std::make_tuple(f.c_name, f.c_name, f.c_name, f.c_name), context))
217 return false;
218
219 // We do not generate the wrapper to be called from C for non public interface member directly.
220 if (blacklist::is_non_public_interface_member(f, *implementing_klass))
221 return true;
222
223 // Do not generate static method in interface
224 if (((implementing_klass->type == attributes::class_type::interface_) ||
225 (implementing_klass->type == attributes::class_type::mixin)) && f.is_static)
226 return true;
227
228 // Actual method implementation to be called from C.
229 std::string return_type;
230 if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
231 return false;
232
233 std::string klass_cast_name;
234 if ((implementing_klass->type == attributes::class_type::interface_) ||
235 ((implementing_klass->type == attributes::class_type::mixin) && !f.is_static))
236 klass_cast_name = name_helpers::klass_interface_name(*implementing_klass);
237 else
238 klass_cast_name = name_helpers::klass_inherit_name(*implementing_klass);
239
240 std::string self = "Efl.Eo.Globals.Super(obj, Efl.Eo.Globals.GetClass(obj))";
241
242 if (f.is_static)
243 self = "";
244
245 if(!as_generator
246 (indent << "[SuppressMessage(\"Microsoft.Reliability\", \"CA2000:DisposeObjectsBeforeLosingScope\", Justification = \"The instantiated objects can be stored in the called Managed API method.\")]\n"
247 << indent << "private static "
248 << eolian_mono::marshall_type(true) << " "
249 << string
250 << "(System.IntPtr obj, System.IntPtr pd"
251 << *(", " << marshall_parameter)
252 << ")\n"
253 << indent << "{\n"
254 << indent << scope_tab << "Eina.Log.Debug(\"function " << string << " was called\");\n"
255 << indent << scope_tab << "var ws = Efl.Eo.Globals.GetWrapperSupervisor(obj);\n"
256 << indent << scope_tab << "if (ws != null)\n"
257 << indent << scope_tab << "{\n"
258 << indent << scope_tab << scope_tab << eolian_mono::native_function_definition_preamble() << "\n"
259 << indent << scope_tab << scope_tab << "try\n"
260 << indent << scope_tab << scope_tab << "{\n"
261 )
262 .generate(sink, std::make_tuple(f.return_type, escape_keyword(f.name), f.parameters
263 , /***/f.c_name/***/
264 , f
265 ), context))
266 return false;
267 if (is_set/* && has_wrapper_setter*/)
268 {
269 if(!as_generator
270 (
271 indent << scope_tab << scope_tab << scope_tab << (return_type != "void" ? "_ret_var = " : "")
272 << (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")ws.Target).") << string
273 )
274 .generate(sink, std::make_tuple(name_helpers::property_managed_name(property), f.parameters), context))
275 return false;
276
277 if(!f.keys.empty() && !as_generator(lit("[(") << (native_argument_invocation % ", ") << ")]").generate (sink, f.keys, context))
278 return false;
279
280 if(!as_generator
281 (" = ("
282 << (native_tuple_argument_invocation % ", ") << ");\n"
283 )
284 .generate(sink, f.values, context))
285 return false;
286 }
287 else if (!is_set/* && has_wrapper_getter*/)
288 {
289 if(!as_generator
290 (
291 indent << scope_tab << scope_tab << scope_tab << "var ret = "
292 << (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")ws.Target).")
293 << string
294
295 )
296 .generate(sink, std::make_tuple(name_helpers::property_managed_name(property)), context))
297 return false;
298
299 if(!f.keys.empty() && !as_generator(lit("[(") << (native_argument_invocation % ", ") << ")]").generate (sink, f.keys, context))
300 return false;
301
302 if (!as_generator(";\n").generate (sink, attributes::unused, context))
303 return false;
304
305 }
306 // else if (!as_generator
307 // (indent << scope_tab << scope_tab << scope_tab << (return_type != "void" ? "_ret_var = " : "")
308 // << (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")ws.Target).") << string
309 // << "(" << (native_argument_invocation % ", ") << ");\n"
310 // ).generate(sink, std::make_tuple(name_helpers::managed_method_name(f), f.parameters), context))
311 // return false;
312
313 if(!as_generator
314 (
315 indent << scope_tab << scope_tab << "}\n"
316 << indent << scope_tab << scope_tab << "catch (Exception e)\n"
317 << indent << scope_tab << scope_tab << "{\n"
318 << indent << scope_tab << scope_tab << scope_tab << "Eina.Log.Warning($\"Callback error: {e.ToString()}\");\n"
319 << indent << scope_tab << scope_tab << scope_tab << "Eina.Error.Set(Eina.Error.UNHANDLED_EXCEPTION);\n"
320 << indent << scope_tab << scope_tab << "}\n\n"
321 << indent << eolian_mono::native_function_definition_epilogue(*implementing_klass) << "\n"
322 << indent << scope_tab << "}\n"
323 << indent << scope_tab << "else\n"
324 << indent << scope_tab << "{\n"
325 << indent << scope_tab << scope_tab << (return_type != "void" ? "return " : "") << string
326 << "_ptr.Value.Delegate(" << self << ((!f.is_static && f.parameters.size() > 0) ? ", " : "") << (argument % ", ") << ");\n"
327 << indent << scope_tab << "}\n"
328 << indent << "}\n\n"
329 )
330 .generate(sink, std::make_tuple(f, f.c_name, f.parameters), context))
331 return false;
332
333 // Static functions do not need to be called from C
334 if (f.is_static)
335 return true;
336
337 // This is the delegate that will be passed to Eo to be called from C.
338 if(!as_generator(
339 indent << "private static " << f.c_name << "_delegate " << f.c_name << "_static_delegate;\n\n"
340 ).generate(sink, attributes::unused, context))
341 return false;
342 return true;
343 };
344
345 bool r = true;
346 if(r && property.getter && has_wrapper_getter
347 && helpers::is_function_registerable (*property.getter, *implementing_klass))
348 r &= gen (*property.getter, false);
349 if(r && property.setter && has_wrapper_setter
350 && helpers::is_function_registerable (*property.setter, *implementing_klass))
351 r &= gen (*property.setter, true);
352 return r;
353 }
354
355 attributes::klass_def const* implementing_klass, *klass_from_property;
356};
357
358struct native_property_function_definition_parameterized
359{
360 native_property_function_definition_generator operator()(attributes::klass_def const& klass
361 , attributes::klass_def const& prop_from_klass) const
362 {
363 return {&klass, &prop_from_klass};
364 }
365} const native_property_function_definition;
366
367}
368
369namespace efl { namespace eolian { namespace grammar {
370
371template <>
372struct is_eager_generator< ::eolian_mono::native_property_function_definition_generator> : std::true_type {};
373template <>
374struct is_generator< ::eolian_mono::native_property_function_definition_generator> : std::true_type {};
375
376namespace type_traits {
377
378template <>
379struct attributes_needed< ::eolian_mono::native_property_function_definition_generator> : std::integral_constant<int, 1> {};
380
381} } } }
382
383#endif