summaryrefslogtreecommitdiff
path: root/src/bin
diff options
context:
space:
mode:
authorLauro Moura <lauromoura@expertisesolutions.com.br>2019-12-20 01:35:23 +0000
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2019-12-23 13:50:12 -0300
commit0954e501fd4008c40b3848de1f2c91bcd53b2f71 (patch)
tree3b6e45b69d24c85fcd0463eb605837cebe410c6a /src/bin
parented0572a33a28429f1ad6e47cb5bee9ef816e4a45 (diff)
csharp: Property Indexer implementation
Use Indexers to use brackets, eg [i], syntax. Keys now can be used as following: var someVal = obj.SomeProperty[key]; obj.SomeProperty[key] = someNewVal; And for multiple keys: var someVal = obj.SomeProperty[(key1, key2)]; obj.SomeProperty[(key1, key2)] = someNewVal; T8384 Reviewed-by: WooHyun Jung <wh0705.jung@samsung.com> Differential Revision: https://phab.enlightenment.org/D10791
Diffstat (limited to 'src/bin')
-rw-r--r--src/bin/eolian_mono/eolian/mono/blacklist.hh29
-rw-r--r--src/bin/eolian_mono/eolian/mono/documentation.hh52
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_definition.hh574
-rw-r--r--src/bin/eolian_mono/eolian/mono/generation_contexts.hh7
-rw-r--r--src/bin/eolian_mono/eolian/mono/helpers.hh101
-rw-r--r--src/bin/eolian_mono/eolian/mono/klass.hh14
-rw-r--r--src/bin/eolian_mono/eolian/mono/name_helpers.hh61
-rw-r--r--src/bin/eolian_mono/eolian/mono/parameter.hh12
-rw-r--r--src/bin/eolian_mono/eolian_mono.cc3
9 files changed, 646 insertions, 207 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/blacklist.hh b/src/bin/eolian_mono/eolian/mono/blacklist.hh
index 8d8de9d..70bc34a 100644
--- a/src/bin/eolian_mono/eolian/mono/blacklist.hh
+++ b/src/bin/eolian_mono/eolian/mono/blacklist.hh
@@ -150,9 +150,34 @@ inline bool is_alias_blacklisted(attributes::alias_def const& alias, Context con
150 return name_helpers::alias_full_eolian_name(alias) == "Eina.Error"; 150 return name_helpers::alias_full_eolian_name(alias) == "Eina.Error";
151} 151}
152 152
153inline bool is_property_blacklisted(std::string const&) 153inline bool is_property_blacklisted(std::string const& name)
154{ 154{
155 return false; 155 auto properties = std::vector<std::string>{
156 // These properties encode (void* arr, int len) arrays
157 "Efl.Gfx.IGradient.Stop"
158 , "Efl.Gfx.GradientConcrete.Stop"
159 , "Efl.Gfx.IShape.StrokeDash"
160 , "Efl.Gfx.ShapeConcrete.StrokeDash"
161 , "Efl.Gfx.Vg.ValueProvider.Transform"
162 , "Efl.Canvas.Vg.Node.Transformation"
163 // Will be bound manually
164 , "Efl.Core.Env.Env"
165 // Setter returns a future
166 , "Efl.IModel.Property"
167 // Protected
168 , "Efl.Access.IAction.ActionName"
169 , "Efl.Access.IAction.ActionLocalizedName"
170 , "Efl.Access.IComponent.Extents"
171 , "Efl.Access.IText.AccessSelection"
172 , "Efl.Access.IText.AccessText"
173 , "Efl.Access.IText.BoundedRanges"
174 , "Efl.Access.IText.Character"
175 , "Efl.Access.IText.OffsetAtPoint"
176 , "Efl.Access.IText.String"
177 , "Efl.Access.IText.TextAttributes"
178 };
179
180 return std::find(std::begin(properties), std::end(properties), name) != std::end(properties);
156} 181}
157 182
158template<typename Context> 183template<typename Context>
diff --git a/src/bin/eolian_mono/eolian/mono/documentation.hh b/src/bin/eolian_mono/eolian/mono/documentation.hh
index d009e45..db00ba8 100644
--- a/src/bin/eolian_mono/eolian/mono/documentation.hh
+++ b/src/bin/eolian_mono/eolian/mono/documentation.hh
@@ -21,6 +21,7 @@
21#include "grammar/html_escaped_string.hpp" 21#include "grammar/html_escaped_string.hpp"
22#include "using_decl.hh" 22#include "using_decl.hh"
23#include "name_helpers.hh" 23#include "name_helpers.hh"
24#include "helpers.hh"
24#include "generation_contexts.hh" 25#include "generation_contexts.hh"
25#include "blacklist.hh" 26#include "blacklist.hh"
26 27
@@ -76,7 +77,11 @@ 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
82 , const ::Eolian_Function *function
83 , std::string name_tail
84 , Context const& context)
80 { 85 {
81 ::Eolian_Function_Type ftype = ::eolian_function_type_get(function); 86 ::Eolian_Function_Type ftype = ::eolian_function_type_get(function);
82 const char* eo_name = ::eolian_function_name_get(function); 87 const char* eo_name = ::eolian_function_name_get(function);
@@ -122,13 +127,27 @@ struct documentation_generator
122 break; 127 break;
123 case ::EOLIAN_PROPERTY: 128 case ::EOLIAN_PROPERTY:
124 { 129 {
125 int getter_nkeys = property_num_keys(function, ::EOLIAN_PROP_GET);
126 int setter_nkeys = property_num_keys(function, ::EOLIAN_PROP_SET);
127 std::string short_name = name_helpers::property_managed_name(klass_d, eo_name); 130 std::string short_name = name_helpers::property_managed_name(klass_d, eo_name);
128 bool blacklisted = blacklist::is_property_blacklisted(name + "." + short_name); 131
129 // EO properties with keys or blacklisted are not converted into C# properties. 132 // We need to replace the current class context with the context
130 // In these cases we refer to the getter method instead of the property. 133 // from the class that originated this property.
131 if ((getter_nkeys > 0) || (setter_nkeys > 0) || (blacklisted)) name += ".Get" + short_name; 134 class_context::wrapper_kind klass_kind;
135 if (helpers::is_managed_interface(klass_d))
136 klass_kind = class_context::interface;
137 else
138 klass_kind = class_context::inherit;
139
140 auto my_context = grammar::context_replace_tag(class_context{klass_kind}, context);
141
142 auto unit = eolian_object_unit_get((const Eolian_Object*)function);
143 attributes::function_def getter_func{function, ::EOLIAN_PROP_GET, nullptr, unit};
144 attributes::function_def setter_func{function, ::EOLIAN_PROP_SET, nullptr, unit};
145 attributes::property_def prop{function, getter_func, setter_func, unit};
146
147 auto has_wrapper = helpers::has_property_wrapper(prop, &klass_d, my_context);
148
149 if (has_wrapper == helpers::has_property_wrapper_bit::has_none)
150 name += ".Get" + short_name;
132 else if (name_tail == ".get") name += ".Get" + short_name; 151 else if (name_tail == ".get") name += ".Get" + short_name;
133 else if (name_tail == ".set") name += ".Set" + short_name; 152 else if (name_tail == ".set") name += ".Set" + short_name;
134 else name += "." + short_name; 153 else name += "." + short_name;
@@ -165,9 +184,13 @@ struct documentation_generator
165 } 184 }
166 185
167 // Turns an Eolian reference like @Efl.Input.Pointer.tool into a <see> tag 186 // Turns an Eolian reference like @Efl.Input.Pointer.tool into a <see> tag
168 static std::string ref_conversion(const ::Eolian_Doc_Token *token, const Eolian_State *state, std::string name_tail, 187 template<typename Context>
169 bool want_beta) 188 static std::string ref_conversion(const ::Eolian_Doc_Token *token
189 , const Eolian_State *state
190 , std::string name_tail
191 , Context const& context)
170 { 192 {
193 bool want_beta = context_want_beta(context);
171 const Eolian_Object *data, *data2; 194 const Eolian_Object *data, *data2;
172 ::Eolian_Object_Type type = 195 ::Eolian_Object_Type type =
173 ::eolian_doc_token_ref_resolve(token, state, &data, &data2); 196 ::eolian_doc_token_ref_resolve(token, state, &data, &data2);
@@ -195,7 +218,7 @@ struct documentation_generator
195 is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2); 218 is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2);
196 break; 219 break;
197 case ::EOLIAN_OBJECT_FUNCTION: 220 case ::EOLIAN_OBJECT_FUNCTION:
198 ref += function_conversion(data, (const ::Eolian_Function *)data2, name_tail); 221 ref += function_conversion(data, (const ::Eolian_Function *)data2, name_tail, context);
199 is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2); 222 is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2);
200 break; 223 break;
201 case ::EOLIAN_OBJECT_CONSTANT: 224 case ::EOLIAN_OBJECT_CONSTANT:
@@ -227,7 +250,8 @@ struct documentation_generator
227 } 250 }
228 251
229 // Turns EO documentation syntax into C# triple-slash XML comment syntax 252 // 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) 253 template<typename Context>
254 static std::string syntax_conversion(std::string text, const Eolian_State *state, Context const& context)
231 { 255 {
232 std::string new_text, ref; 256 std::string new_text, ref;
233 ::Eolian_Doc_Token_Type previous_token_type = ::EOLIAN_DOC_TOKEN_UNKNOWN; 257 ::Eolian_Doc_Token_Type previous_token_type = ::EOLIAN_DOC_TOKEN_UNKNOWN;
@@ -266,7 +290,7 @@ struct documentation_generator
266 new_text += token_text; 290 new_text += token_text;
267 break; 291 break;
268 case ::EOLIAN_DOC_TOKEN_REF: 292 case ::EOLIAN_DOC_TOKEN_REF:
269 ref = ref_conversion(&token, state, name_tail, want_beta); 293 ref = ref_conversion(&token, state, name_tail, context);
270 if (ref != "") 294 if (ref != "")
271 { 295 {
272 if (utils::ends_with(ref, BETA_REF_SUFFIX)) 296 if (utils::ends_with(ref, BETA_REF_SUFFIX))
@@ -331,7 +355,7 @@ struct documentation_generator
331 if (!as_generator(html_escaped_string).generate(std::back_inserter(new_text), text, context)) 355 if (!as_generator(html_escaped_string).generate(std::back_inserter(new_text), text, context))
332 return false; 356 return false;
333 auto options = context_find_tag<options_context>(context); 357 auto options = context_find_tag<options_context>(context);
334 new_text = syntax_conversion( new_text, context_find_tag<eolian_state_context>(context).state, options.want_beta); 358 new_text = syntax_conversion( new_text, context_find_tag<eolian_state_context>(context).state, context);
335 359
336 std::string tabs; 360 std::string tabs;
337 as_generator(scope_tab(scope_size) << "/// ").generate (std::back_inserter(tabs), attributes::unused, context); 361 as_generator(scope_tab(scope_size) << "/// ").generate (std::back_inserter(tabs), attributes::unused, context);
@@ -653,7 +677,7 @@ struct documentation_string_generator
653 677
654 auto options = context_find_tag<options_context>(context); 678 auto options = context_find_tag<options_context>(context);
655 auto state = context_find_tag<eolian_state_context>(context).state; 679 auto state = context_find_tag<eolian_state_context>(context).state;
656 if (!as_generator(string).generate(sink, documentation_generator::syntax_conversion(escaped, state, options.want_beta), context)) 680 if (!as_generator(string).generate(sink, documentation_generator::syntax_conversion(escaped, state, context), context))
657 return false; 681 return false;
658 682
659 return true; 683 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 cded973..86eb2db 100644
--- a/src/bin/eolian_mono/eolian/mono/function_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_definition.hh
@@ -26,6 +26,7 @@
26#include "grammar/list.hpp" 26#include "grammar/list.hpp"
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/eps.hpp"
29#include "grammar/counter.hpp" 30#include "grammar/counter.hpp"
30#include "logging.hh" 31#include "logging.hh"
31#include "type.hh" 32#include "type.hh"
@@ -44,7 +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;
47 48
48 template <typename OutputIterator, typename Context> 49 template <typename OutputIterator, typename Context>
49 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const 50 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
50 { 51 {
@@ -181,7 +182,7 @@ struct native_function_definition_generator
181 return true; 182 return true;
182 } 183 }
183}; 184};
184 185
185struct function_definition_generator 186struct function_definition_generator
186{ 187{
187 function_definition_generator(bool do_super = false) 188 function_definition_generator(bool do_super = false)
@@ -323,6 +324,199 @@ property_extension_method_definition_generator property_extension_method_definit
323 324
324struct property_wrapper_definition_generator 325struct property_wrapper_definition_generator
325{ 326{
327 template <typename OutputIterator, typename Context>
328 bool generate_get_indexer(OutputIterator sink, attributes::property_def const& property, Context const& context
329 , std::string get_scope
330 , bool is_interface) const
331 {
332 if (is_interface)
333 {
334 if (!as_generator(scope_tab << scope_tab << get_scope << "get;\n"
335 ).generate(sink, attributes::unused, context))
336 return false;
337 }
338 else
339 {
340 if (!as_generator(scope_tab << scope_tab << get_scope << "get\n"
341 << scope_tab << scope_tab << "{\n"
342 << scope_tab << scope_tab(2) << "var i = new "
343 << name_helpers::property_concrete_indexer_name(property) << "();\n"
344 << scope_tab << scope_tab(2) << "i.Self = this;\n"
345 << scope_tab << scope_tab(2) << "return i;\n"
346 << scope_tab << scope_tab << "}\n"
347 ).generate(sink, attributes::unused, context))
348 return false;
349 }
350
351 return true;
352 }
353
354 template <typename OutputIterator, typename Context, typename C1, typename C2>
355 bool generate_indexer(OutputIterator sink
356 , attributes::property_def const& property
357 , Context const& context
358 , std::string scope, std::string get_scope, std::string set_scope
359 , std::string class_name
360 , C1 keys, C2 values
361 , bool is_interface
362 , bool is_concrete_for_interface
363 , bool has_setter) const
364 {
365 if (is_interface)
366 return true;
367
368 auto size_not_one = [] (std::vector<attributes::parameter_def> k) { return k.size() != 1; };
369 auto type_or_tuple
370 =
371 (
372 (
373 attribute_conditional(size_not_one)["("]
374 << (type(false) % ", ")
375 << ")"
376 )
377 | *type(false)
378 )
379 ;
380
381 std::string parentship = "\n";
382
383 bool is_self_property = *implementing_klass == *klass_from_property;
384
385 if (!(is_self_property && !is_concrete_for_interface))
386 parentship = " : " + name_helpers::property_interface_indexer_name(property, *klass_from_property) + "\n";
387
388 if (!as_generator
389 (
390 scope_tab << scope << "class " << name_helpers::property_concrete_indexer_name(property) << parentship
391 << scope_tab << "{\n"
392 << scope_tab(2) << "public " << class_name << " Self {get; set;}\n"
393 << scope_tab(2) << "public "
394 << type_or_tuple << " this[" << type_or_tuple <<" i]\n"
395 << scope_tab(2) << "{\n"
396 ).generate(sink, make_tuple(values, values, keys, keys), context))
397 return false;
398
399 assert (!keys.empty());
400 std::vector<std::string> get_keys;
401 if(keys.size() != 1)
402 {
403 unsigned int i = 0;
404 for (auto&& key : keys)
405 {
406 static_cast<void>(key);
407 ++i;
408 get_keys.push_back("i.Item" + std::to_string(i));
409 }
410 }
411 else
412 {
413 get_keys.push_back ("i");
414 }
415 assert (!get_keys.empty());
416
417 generate_get(sink, property, context, get_scope, get_keys, values, is_interface, "Self.");
418 if (has_setter)
419 generate_set(sink, property, context, set_scope, get_keys, values, is_interface, "Self.");
420
421 if (!as_generator
422 (
423 scope_tab(2) << "}\n"
424 << scope_tab << "};\n"
425 ).generate(sink, attributes::unused, context))
426 return false;
427 return true;
428 }
429 template <typename OutputIterator, typename Context, typename CK, typename CV>
430 bool generate_set(OutputIterator sink, attributes::property_def const& property, Context const& context
431 , std::string set_scope
432 , CK keys, CV values
433 , bool is_interface
434 , std::string name_prefix = "") const
435 {
436 using efl::eolian::grammar::counter;
437 if (is_interface)
438 {
439 if (!as_generator(scope_tab << scope_tab << set_scope << "set;\n"
440 ).generate(sink, attributes::unused, context))
441 return false;
442 }
443 else if (values.size() == 1)
444 {
445 if (!as_generator(scope_tab << scope_tab << set_scope << "set " << "{ " << name_prefix << name_helpers::managed_method_name(*property.setter) + "(" << *(string << ",") << "value); }\n"
446 ).generate(sink, keys, context))
447 return false;
448 }
449 else if (values.size() > 1)
450 {
451 if (!as_generator(
452 scope_tab << scope_tab << set_scope << "set "
453 << ("{ " << name_prefix << name_helpers::managed_method_name(*property.setter) + "(")
454 << *(string << ",") << ((" value.Item" << counter(1)) % ", ")
455 << "); }\n"
456 ).generate(sink, std::make_tuple(keys, values), context))
457 return false;
458 }
459 return true;
460 }
461 template <typename OutputIterator, typename Context, typename CK, typename CV>
462 bool generate_get(OutputIterator sink, attributes::property_def const& property, Context const& context
463 , std::string get_scope
464 , CK keys, CV values
465 , bool is_interface
466 , std::string name_prefix = "") const
467 {
468 using efl::eolian::grammar::attribute_reorder;
469 using efl::eolian::grammar::attributes::parameter_direction;
470 using efl::eolian::grammar::attributes::parameter_def;
471
472 if (is_interface) // only declaration
473 {
474 if (!as_generator(scope_tab << scope_tab << get_scope << "get;\n"
475 ).generate(sink, attributes::unused, context))
476 return false;
477 }
478 else
479 if (/*has_getter && */values.size() == 1)
480 {
481 if (!as_generator
482 (scope_tab << scope_tab << get_scope
483 << "get " << "{ return " << name_prefix << name_helpers::managed_method_name(*property.getter)
484 << "(" << (string % ",") << "); }\n"
485 ).generate(sink, keys, context))
486 return false;
487 }
488 else if (/*has_getter && */values.size() > 1)
489 {
490 if (!as_generator
491 (scope_tab << scope_tab << get_scope << "get "
492 << "{\n"
493 << *attribute_reorder<1, -1, 1>
494 (scope_tab(3) << type(true) << " _out_"
495 << argument(false) << " = default(" << type(true) << ");\n"
496 )
497 << scope_tab(3) << name_prefix << name_helpers::managed_method_name(*property.getter)
498 << "(" << *(string << ",") << (("out _out_" << argument(false)) % ", ") << ");\n"
499 << scope_tab(3) << "return (" << (("_out_"<< argument(false)) % ", ") << ");\n"
500 << scope_tab(2) << "}" << "\n"
501 ).generate(sink, std::make_tuple(values, keys, values, values), context))
502 return false;
503 }
504 // else if (values.size() == 1)
505 // {
506 // if (!as_generator
507 // (scope_tab << scope_tab << get_scope << "get "
508 // << "{\n"
509 // << *attribute_reorder<1, -1, 1>(scope_tab(3) << type(true) << " _out_" << argument(false) << " = default(" << type(true) << ");\n")
510 // << scope_tab(3) << name_prefix << name_helpers::managed_method_name(*property.getter)
511 // << "(" << *(string << ",") << (("out _out_" << argument(false)) % ",") << ");\n"
512 // << scope_tab(3) << "return " << (("_out_"<< argument(false)) % ",") << ";\n"
513 // << scope_tab(2) << "}" << "\n"
514 // ).generate(sink, std::make_tuple(values, keys, values, values), context))
515 // return false;
516 // }
517 return true;
518 }
519
326 template<typename OutputIterator, typename Context> 520 template<typename OutputIterator, typename Context>
327 bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const 521 bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const
328 { 522 {
@@ -331,103 +525,127 @@ struct property_wrapper_definition_generator
331 using efl::eolian::grammar::attributes::parameter_direction; 525 using efl::eolian::grammar::attributes::parameter_direction;
332 using efl::eolian::grammar::attributes::parameter_def; 526 using efl::eolian::grammar::attributes::parameter_def;
333 527
334 if (blacklist::is_property_blacklisted(property, *implementing_klass, context)) 528 /// C(k) = keys count, C(v) = values count
335 return true; 529 /// /------------\ /------\.
530 /// |blacklisted?|---yes-----| skip |--------------\.
531 /// \------------/ \------/ |
532 /// | | |
533 /// no yes |
534 /// | | |
535 /// /---------\ /------------\ |
536 /// |is-static|----yes-----|is-interface| |
537 /// \---------/ \------------/ |
538 /// | | |
539 /// no no |
540 /// | | |
541 /// /--------\ /-----------\ |
542 /// |has-get?|---no-conc---|is-concrete|-----yes---/
543 /// \--------/ \-----------/
544 /// / \.
545 /// no yes
546 /// / \.
547 /// /----\ /--------------------------------------\.
548 /// |skip|-yes-|explicit return != Eina.Error or void |
549 /// \----/ \--------------------------------------/
550 /// |
551 /// no
552 /// |
553 /// /--------\.
554 /// |has-set?|
555 /// \--------/
556 /// / \.
557 /// no yes
558 /// / \.
559 /// /------\ /--------------------------------------\.
560 /// /------------------|no-set| |explicit return != Eina.Error or void |---- yes --\.
561 /// | \------/ \--------------------------------------/ |
562 /// | \------------|----------------------------------------------/
563 /// | no
564 /// | |
565 /// | /--------\.
566 /// | |has-both|
567 /// | \--------/
568 /// | |
569 /// | /-------------------\.
570 /// | |set-keys = get-keys|
571 /// | \-------------------/
572 /// | / |
573 /// | no |
574 /// | / |
575 /// | /----\ /-----------------------\.
576 /// | |skip|--no---|set-values = get-values|
577 /// | \----/ \-----------------------/
578 /// | /
579 /// | yes
580 /// | /
581 /// | /--------\.
582 /// \-------------------------| keys |
583 /// \--------/
584 /// / \.
585 /// 0 >0
586 /// / \.
587 /// /----------\ /----------\.
588 /// |no-indexer| | keys > 1 |
589 /// \----------/ \----------/
590 /// | / |
591 /// | no yes
592 /// | / |
593 /// | / |
594 /// | /---------\ /-------------------\.
595 /// | | indexer | | indexer tuple key |
596 /// | \---------/ \-------------------/
597 /// | / |
598 /// /--------\ |
599 /// | values |----------/
600 /// \--------/
601 /// / \.
602 /// 1 >1
603 /// / \.
604 /// /----------------\ /-------------\.
605 /// | no tuple value | | tuple value |
606 /// \----------------/ \-------------/
607 ///
608
609 auto has_wrapper = helpers::has_property_wrapper (property, implementing_klass, context);
610 bool has_getter = has_wrapper & helpers::has_property_wrapper_bit::has_getter;
611 if (!has_getter) return true;
612 bool has_setter = has_wrapper & helpers::has_property_wrapper_bit::has_setter;
613 bool has_indexer = has_wrapper & helpers::has_property_wrapper_bit::has_indexer;
336 614
337 bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface; 615 bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
338 bool is_static = (property.getter.is_engaged() && property.getter->is_static) 616 bool is_static = (property.getter.is_engaged() && property.getter->is_static)
339 || (property.setter.is_engaged() && property.setter->is_static); 617 || (property.setter.is_engaged() && property.setter->is_static);
340 bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete; 618 bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
619 bool is_concrete_for_interface = is_concrete
620 && (implementing_klass->type == attributes::class_type::interface_
621 || implementing_klass->type == attributes::class_type::mixin);
341 622
342 623 //if (name_helpers::klass_concrete_or_interface_name (*implementing_klass) == "IMapping")
343 if ((is_concrete || is_interface) && is_static) 624 if (false)
344 return true;
345
346 auto get_params = property.getter.is_engaged() ? property.getter->parameters.size() : 0;
347 //auto set_params = property.setter.is_engaged() ? property.setter->parameters.size() : 0;
348
349 // C# properties must have a single value.
350 //
351 // Single values in getters are automatically converted to return_type,
352 // meaning they should have 0 parameters.
353 //
354 // For setters, we ignore the return type - usually boolean.
355 // if (get_params > 0 || set_params > 1)
356 // return true;
357
358 if (property.getter
359 && std::find_if (property.getter->parameters.begin()
360 , property.getter->parameters.end()
361 , [] (parameter_def const& p)
362 {
363 return p.direction != parameter_direction::out;
364 }) != property.getter->parameters.end())
365 return true;
366 if (property.setter
367 && std::find_if (property.setter->parameters.begin()
368 , property.setter->parameters.end()
369 , [] (parameter_def const& p)
370 {
371 return p.direction != parameter_direction::in;
372 }) != property.setter->parameters.end())
373 return true;
374
375 if (property.getter && property.setter)
376 {
377 if (get_params != 0 && property.setter->parameters.size() != property.getter->parameters.size())
378 return true;
379 }
380
381 std::vector<attributes::parameter_def> parameters;
382
383 if (property.setter.is_engaged())
384 {
385 std::transform (property.setter->parameters.begin(), property.setter->parameters.end()
386 , std::back_inserter(parameters)
387 , [] (parameter_def p) -> parameter_def
388 {
389 //p.direction = efl::eolian::attributes::parameter_direction::in;
390 return p;
391 });
392 }
393 else if (property.getter.is_engaged())
394 { 625 {
395 // if getter has parameters, then we ignore return type, otherwise 626 if (!as_generator(grammar::lit("/// is interface ") << (int)is_interface
396 // we use the return type. 627 << " is static " << (int)is_static
397 if (get_params == 0) 628 << " is concrete " << (int)is_concrete
398 parameters.push_back({parameter_direction::in 629 << " is concrete_for_interface " << (int)is_concrete_for_interface
399 , property.getter->return_type, "propertyResult", {} 630 << " klass_from_property->type " << (int)klass_from_property->type
400 , property.getter->unit}); 631 << " has_setter " << (int)has_setter
401 else 632 << " property.setter->explicit_return_type != attributes::void_ " << (property.setter && property.setter->explicit_return_type != attributes::void_)
402 std::transform (property.getter->parameters.begin(), property.getter->parameters.end() 633 << " property.setter->keys != property.getter->keys " << (property.setter && property.setter->keys != property.getter->keys)
403 , std::back_inserter(parameters) 634 << " property.setter->values != property.getter->values " << (property.setter && property.setter->values != property.getter->values)
404 , [] (parameter_def p) -> parameter_def 635 << " has_setter && property.setter->scope != attributes::member_scope::scope_public " << (property.setter && property.setter->scope != attributes::member_scope::scope_public)
405 { 636 << "\n")
406 p.direction = parameter_direction::in; 637 .generate (sink, attributes::unused, context))
407 return p; 638 return false;
408 });
409 } 639 }
410 else
411 {
412 EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Property must have either a getter or a setter." << std::endl;
413 return false;
414 }
415 640
416 std::string dir_mod; 641 if (blacklist::is_property_blacklisted(property, context))
417 if (property.setter.is_engaged()) 642 return true;
418 dir_mod = direction_modifier(property.setter->parameters[0]);
419 643
420 std::string managed_name = name_helpers::property_managed_name(property); 644 std::string managed_name = name_helpers::property_managed_name(property);
421 645
422 std::string scope = "public "; 646 std::string scope = "public ";
423 std::string get_scope = property.getter.is_engaged() ? eolian_mono::function_scope_get(*property.getter) : ""; 647 std::string get_scope = eolian_mono::function_scope_get(*property.getter);
424 bool is_get_public = get_scope == "public "; 648 std::string set_scope = has_setter ? eolian_mono::function_scope_get(*property.setter) : "";
425 std::string set_scope = property.setter.is_engaged() ? eolian_mono::function_scope_get(*property.setter) : "";
426 bool is_set_public = set_scope == "public ";
427
428 // No need to generate this wrapper as no accessor is public.
429 if (is_interface && (!is_get_public && !is_set_public))
430 return true;
431 649
432 // C# interface members are declared automatically as public 650 // C# interface members are declared automatically as public
433 if (is_interface) 651 if (is_interface)
@@ -442,23 +660,64 @@ struct property_wrapper_definition_generator
442 get_scope = ""; 660 get_scope = "";
443 set_scope = ""; 661 set_scope = "";
444 } 662 }
445 else if (!property.setter.is_engaged() || (get_scope == scope)) 663 else if (!has_setter || (get_scope == scope))
446 { 664 {
447 scope = get_scope; 665 scope = get_scope;
448 get_scope = ""; 666 get_scope = "";
449 } 667 }
450 else if (!property.getter.is_engaged() || (set_scope == scope)) 668
669 std::string virtual_mod = (is_static || is_interface || is_concrete) ? "" : "virtual ";
670
671 auto keys = property.getter->keys;
672 auto values = property.getter->values;
673 auto generated_values = values;
674 auto klass_name = name_helpers::klass_concrete_or_interface_name (*implementing_klass);
675
676 if (has_indexer)
677 {
678 assert (!!implementing_klass);
679 generate_indexer (sink, property, context, scope, get_scope, set_scope
680 , klass_name, keys, values
681 , is_interface, is_concrete_for_interface, has_setter);
682
683 generated_values.clear();
684 if (!is_interface && *implementing_klass == *klass_from_property
685 && !is_concrete_for_interface)
451 { 686 {
452 scope = set_scope; 687 generated_values.push_back
453 set_scope = ""; 688 (attributes::parameter_def
689 {parameter_direction::in
690 , attributes::type_def
691 {
692 attributes::regular_type_def{name_helpers::property_concrete_indexer_name(property), {attributes::qualifier_info::is_none, ""}, {}}
693 , name_helpers::property_concrete_indexer_name(property)
694 , false, false, false, ""
695 }
696 , "indexer", {}, nullptr
697 });
698 }
699 else
700 {
701 generated_values.push_back
702 (attributes::parameter_def
703 {parameter_direction::in
704 , attributes::type_def
705 {
706 attributes::regular_type_def{name_helpers::klass_full_concrete_or_interface_name (*klass_from_property) + managed_name + "Indexer", {attributes::qualifier_info::is_none, ""}, {}}
707 , name_helpers::property_interface_indexer_name(property, *klass_from_property)
708 , false, false, false, ""
709 }
710 , "indexer", {}, nullptr
711 });
454 } 712 }
713 }
455 714
456 if (parameters.size() == 1) 715 if (generated_values.size() == 1)
457 { 716 {
458 if (!as_generator( 717 if (!as_generator(
459 documentation(1) 718 documentation(1)
460 << scope_tab << scope << (is_static ? "static " : "") << type(true) << " " << managed_name << " {\n" 719 << scope_tab << scope << (is_static ? "static " : virtual_mod) << type(true) << " " << managed_name << " {\n"
461 ).generate(sink, std::make_tuple(property, parameters[0].type), context)) 720 ).generate(sink, std::make_tuple(property, generated_values[0].type), context))
462 return false; 721 return false;
463 } 722 }
464 else 723 else
@@ -469,73 +728,21 @@ struct property_wrapper_definition_generator
469 << scope_tab << scope << (is_static ? "static (" : "(") 728 << scope_tab << scope << (is_static ? "static (" : "(")
470 << (attribute_reorder<1, -1>(type(true) /*<< " " << argument*/) % ", ") << ") " 729 << (attribute_reorder<1, -1>(type(true) /*<< " " << argument*/) % ", ") << ") "
471 << managed_name << " {\n" 730 << managed_name << " {\n"
472 ).generate(sink, std::make_tuple(property, parameters), context)) 731 ).generate(sink, std::make_tuple(property, generated_values), context))
473 return false; 732 return false;
474 } 733 }
475 734
476 if (property.getter.is_engaged() && is_interface) 735 if (has_indexer)
477 {
478 if (is_get_public)
479 if (!as_generator(scope_tab << scope_tab << set_scope << "get;\n"
480 ).generate(sink, attributes::unused, context))
481 return false;
482 }
483 else if (property.getter.is_engaged() && get_params == 0/*parameters.size() == 1 && property.getter.is_engaged()*/)
484 { 736 {
485 if (!as_generator 737 generate_get_indexer (sink, property, context, get_scope, is_interface);
486 (scope_tab << scope_tab << get_scope
487 << "get " << "{ return " + name_helpers::managed_method_name(*property.getter) + "(); }\n"
488 ).generate(sink, attributes::unused, context))
489 return false;
490 } 738 }
491 else if (parameters.size() >= 1 && property.getter) 739 else
492 { 740 {
493 if (!as_generator 741 std::vector<std::string> empty_keys;
494 (scope_tab << scope_tab << get_scope << "get " 742 generate_get(sink, property, context, get_scope, empty_keys, values, is_interface);
495 << "{\n"
496 << *attribute_reorder<1, -1, 1>
497 (scope_tab(3) << type(true) << " _out_"
498 << argument(false) << " = default(" << type(true) << ");\n"
499 )
500 << scope_tab(3) << name_helpers::managed_method_name(*property.getter)
501 << "(" << (("out _out_" << argument(false)) % ", ") << ");\n"
502 << scope_tab(3) << "return (" << (("_out_"<< argument(false)) % ", ") << ");\n"
503 << scope_tab(2) << "}" << "\n"
504 ).generate(sink, std::make_tuple(parameters, parameters, parameters), context))
505 return false;
506 }
507 // else if (parameters.size() == 1)
508 // {
509 // if (!as_generator
510 // (scope_tab << scope_tab << get_scope << "get "
511 // << "{\n"
512 // << *attribute_reorder<1, -1, 1>(scope_tab(3) << type(true) << " _out_" << argument(false) << " = default(" << type(true) << ");\n")
513 // << scope_tab(3) << name_helpers::managed_method_name(*property.getter)
514 // << "(" << (("out _out_" << argument(false)) % ",") << ");\n"
515 // << scope_tab(3) << "return " << (("_out_"<< argument(false)) % ",") << ";\n"
516 // << scope_tab(2) << "}" << "\n"
517 // ).generate(sink, std::make_tuple(parameters, parameters, parameters), context))
518 // return false;
519 // }
520 743
521 if (property.setter.is_engaged() && is_interface) 744 if (has_setter)
522 { 745 generate_set (sink, property, context, set_scope, empty_keys, values, is_interface);
523 if (is_set_public)
524 if (!as_generator(scope_tab << scope_tab << set_scope << "set;\n"
525 ).generate(sink, attributes::unused, context))
526 return false;
527 }
528 else if (parameters.size() == 1 && property.setter.is_engaged())
529 {
530 if (!as_generator(scope_tab << scope_tab << set_scope << "set " << "{ " + name_helpers::managed_method_name(*property.setter) + "(" + dir_mod + "value); }\n"
531 ).generate(sink, attributes::unused, context))
532 return false;
533 }
534 else if (parameters.size() > 1 && property.setter.is_engaged())
535 {
536 if (!as_generator(scope_tab << scope_tab << set_scope << "set " << ("{ " + name_helpers::managed_method_name(*property.setter) + "(" + dir_mod) << ((" value.Item" << counter(1)) % ", ") << "); }" << "\n"
537 ).generate(sink, parameters, context))
538 return false;
539 } 746 }
540 747
541 if (!as_generator(scope_tab << "}\n\n").generate(sink, attributes::unused, context)) 748 if (!as_generator(scope_tab << "}\n\n").generate(sink, attributes::unused, context))
@@ -543,13 +750,14 @@ struct property_wrapper_definition_generator
543 750
544 return true; 751 return true;
545 } 752 }
546 attributes::klass_def const* implementing_klass; 753 attributes::klass_def const* implementing_klass, *klass_from_property;
547}; 754};
548struct property_wrapper_definition_parameterized 755struct property_wrapper_definition_parameterized
549{ 756{
550 property_wrapper_definition_generator operator()(attributes::klass_def const& klass) const 757 property_wrapper_definition_generator operator()(attributes::klass_def const& klass
758 , attributes::klass_def const& prop_from_klass) const
551 { 759 {
552 return {&klass}; 760 return {&klass, &prop_from_klass};
553 } 761 }
554} const property_wrapper_definition; 762} const property_wrapper_definition;
555property_wrapper_definition_generator as_generator(property_wrapper_definition_parameterized) 763property_wrapper_definition_generator as_generator(property_wrapper_definition_parameterized)
@@ -557,6 +765,45 @@ property_wrapper_definition_generator as_generator(property_wrapper_definition_p
557 return {}; 765 return {};
558} 766}
559 767
768struct interface_property_indexer_definition_generator
769{
770 template<typename OutputIterator, typename Context>
771 bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const
772 {
773 using efl::eolian::grammar::attribute_reorder;
774 using efl::eolian::grammar::counter;
775 using efl::eolian::grammar::attributes::parameter_direction;
776 using efl::eolian::grammar::attributes::parameter_def;
777
778 bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
779
780 assert (is_interface);
781 auto klass_name = name_helpers::klass_concrete_or_interface_name (*implementing_klass);
782 std::string managed_name = name_helpers::property_managed_name(property);
783
784 if (!as_generator
785 ("public interface " << name_helpers::property_interface_indexer_short_name(property, *implementing_klass) << "\n"
786 << "{\n"
787 << "}\n"
788 ).generate (sink, attributes::unused, context))
789 return false;
790
791 return true;
792 }
793 attributes::klass_def const* implementing_klass;
794};
795struct interface_property_indexer_definition_parameterized
796{
797 interface_property_indexer_definition_generator operator()(attributes::klass_def const& klass) const
798 {
799 return {&klass};
800 }
801} const interface_property_indexer_definition;
802interface_property_indexer_definition_generator as_generator(interface_property_indexer_definition_parameterized)
803{
804 return {};
805}
806
560} 807}
561 808
562namespace efl { namespace eolian { namespace grammar { 809namespace efl { namespace eolian { namespace grammar {
@@ -572,6 +819,10 @@ struct is_eager_generator< ::eolian_mono::property_wrapper_definition_generator>
572template <> 819template <>
573struct is_eager_generator< ::eolian_mono::property_wrapper_definition_parameterized> : std::true_type {}; 820struct is_eager_generator< ::eolian_mono::property_wrapper_definition_parameterized> : std::true_type {};
574template <> 821template <>
822struct is_eager_generator< ::eolian_mono::interface_property_indexer_definition_parameterized> : std::true_type {};
823template <>
824struct is_eager_generator< ::eolian_mono::interface_property_indexer_definition_generator> : std::true_type {};
825template <>
575struct is_generator< ::eolian_mono::function_definition_generator> : std::true_type {}; 826struct is_generator< ::eolian_mono::function_definition_generator> : std::true_type {};
576template <> 827template <>
577struct is_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {}; 828struct is_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {};
@@ -583,6 +834,10 @@ template <>
583struct is_generator< ::eolian_mono::property_wrapper_definition_generator> : std::true_type {}; 834struct is_generator< ::eolian_mono::property_wrapper_definition_generator> : std::true_type {};
584template <> 835template <>
585struct is_generator< ::eolian_mono::property_wrapper_definition_parameterized> : std::true_type {}; 836struct is_generator< ::eolian_mono::property_wrapper_definition_parameterized> : std::true_type {};
837template <>
838struct is_generator< ::eolian_mono::interface_property_indexer_definition_parameterized> : std::true_type {};
839template <>
840struct is_generator< ::eolian_mono::interface_property_indexer_definition_generator> : std::true_type {};
586 841
587namespace type_traits { 842namespace type_traits {
588template <> 843template <>
@@ -601,8 +856,13 @@ template <>
601struct attributes_needed< ::eolian_mono::property_wrapper_definition_generator> : std::integral_constant<int, 1> {}; 856struct attributes_needed< ::eolian_mono::property_wrapper_definition_generator> : std::integral_constant<int, 1> {};
602template <> 857template <>
603struct attributes_needed< ::eolian_mono::property_wrapper_definition_parameterized> : std::integral_constant<int, 1> {}; 858struct attributes_needed< ::eolian_mono::property_wrapper_definition_parameterized> : std::integral_constant<int, 1> {};
859
860template <>
861struct attributes_needed< ::eolian_mono::interface_property_indexer_definition_parameterized> : std::integral_constant<int, 1> {};
862template <>
863struct attributes_needed< ::eolian_mono::interface_property_indexer_definition_generator> : std::integral_constant<int, 1> {};
604} 864}
605 865
606} } } 866} } }
607 867
608#endif 868#endif
diff --git a/src/bin/eolian_mono/eolian/mono/generation_contexts.hh b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh
index f7376f0..2ac16b0 100644
--- a/src/bin/eolian_mono/eolian/mono/generation_contexts.hh
+++ b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh
@@ -26,6 +26,7 @@ namespace eolian_mono {
26struct class_context 26struct class_context
27{ 27{
28 enum wrapper_kind { 28 enum wrapper_kind {
29 none,
29 interface, 30 interface,
30 concrete, 31 concrete,
31 inherit, 32 inherit,
@@ -109,6 +110,12 @@ struct options_context {
109 std::string examples_dir; 110 std::string examples_dir;
110}; 111};
111 112
113template<typename Context>
114bool context_want_beta(Context const& context)
115{
116 return efl::eolian::grammar::context_find_tag<options_context>(context).want_beta;
117}
118
112} 119}
113 120
114#endif 121#endif
diff --git a/src/bin/eolian_mono/eolian/mono/helpers.hh b/src/bin/eolian_mono/eolian/mono/helpers.hh
index b34a985..049f263 100644
--- a/src/bin/eolian_mono/eolian/mono/helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/helpers.hh
@@ -17,6 +17,7 @@
17#define EOLIAN_MONO_HELPERS_HH 17#define EOLIAN_MONO_HELPERS_HH
18 18
19#include "grammar/klass_def.hpp" 19#include "grammar/klass_def.hpp"
20#include "grammar/context.hpp"
20#include "blacklist.hh" 21#include "blacklist.hh"
21#include "generation_contexts.hh" 22#include "generation_contexts.hh"
22#include "name_helpers.hh" 23#include "name_helpers.hh"
@@ -305,6 +306,106 @@ inline std::vector<attributes::constructor_def> reorder_constructors(std::vector
305 return constructors; 306 return constructors;
306} 307}
307 308
309enum class has_property_wrapper_bit
310{
311 has_none = 0
312 , has_getter = 1 << 0
313 , has_setter = 1 << 1
314 , has_indexer = 1 << 2
315 , has_key_tuple = 1 << 3
316 , has_value_tuple = 1 << 4
317 , has_set_error_check = 1 << 5
318 , has_get_error_check = 1 << 6
319};
320
321has_property_wrapper_bit& operator|=(has_property_wrapper_bit& self, has_property_wrapper_bit bit)
322{
323 self = static_cast<has_property_wrapper_bit>(static_cast<int>(self) | static_cast<int>(bit));
324 return self;
325}
326
327bool operator&(has_property_wrapper_bit self, has_property_wrapper_bit bit)
328{
329 return static_cast<int>(self) & static_cast<int>(bit);
330}
331
332template <typename Context>
333has_property_wrapper_bit has_property_wrapper(attributes::property_def const& property, attributes::klass_def const* implementing_klass
334 , Context const& context)
335{
336 using efl::eolian::grammar::context_find_tag;
337 has_property_wrapper_bit r = has_property_wrapper_bit::has_none;
338
339 if (blacklist::is_property_blacklisted(property, *implementing_klass, context))
340 return r;
341
342 bool has_getter = property.getter.is_engaged();
343 bool has_setter = property.setter.is_engaged();
344
345 bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
346 bool is_static = (property.getter.is_engaged() && property.getter->is_static)
347 || (has_setter && property.setter->is_static);
348 bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
349
350 if (is_static)
351 {
352 if (is_interface) return r;
353 else if (is_concrete) return r;
354 }
355
356 // EINA_LOG_ERR("Generating property %s", name_helpers::property_managed_name(property).c_str());
357 // C# interface can have only
358 if (is_interface)
359 {
360 has_getter = has_getter && property.getter->scope == attributes::member_scope:: scope_public;
361 }
362
363 if (!has_getter)
364 {
365 return r;
366 }
367
368 if (property.getter->explicit_return_type != attributes::void_)
369 {
370 return r;
371 }
372 else if (has_setter)
373 {
374 if (property.setter->explicit_return_type != attributes::void_)
375 has_setter = false; // do not generate setter
376 else if (property.setter->keys != property.getter->keys)
377 has_setter = false;
378 else if (property.setter->values != property.getter->values)
379 has_setter = false;
380 }
381
382 if (is_interface)
383 {
384 if (property.getter->scope != attributes::member_scope::scope_public)
385 return r;
386 else if (has_setter && property.setter->scope != attributes::member_scope::scope_public)
387 has_setter = false;
388 }
389
390 if (has_getter)
391 r |= has_property_wrapper_bit::has_getter;
392 if (has_setter)
393 r |= has_property_wrapper_bit::has_setter;
394
395 if (property.getter->keys.size() == 1)
396 r |= has_property_wrapper_bit::has_indexer;
397 else if (property.getter->keys.size() > 1)
398 {
399 r |= has_property_wrapper_bit::has_indexer;
400 r |= has_property_wrapper_bit::has_key_tuple;
401 }
402
403 if (property.getter->values.size() > 1)
404 r |= has_property_wrapper_bit::has_value_tuple;
405
406 return r;
407}
408
308} // namespace helpers 409} // namespace helpers
309 410
310} // namespace eolian_mono 411} // namespace eolian_mono
diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh
index 11a7cd6..e26121c 100644
--- a/src/bin/eolian_mono/eolian/mono/klass.hh
+++ b/src/bin/eolian_mono/eolian/mono/klass.hh
@@ -106,6 +106,10 @@ struct klass
106 name_helpers::klass_full_concrete_or_interface_name(cls)}, 106 name_helpers::klass_full_concrete_or_interface_name(cls)},
107 context); 107 context);
108 108
109 // Property wrappers
110 if (!as_generator(*(interface_property_indexer_definition(cls))).generate(sink, cls.properties, iface_cxt))
111 return false;
112
109 if(!as_generator(documentation).generate(sink, cls, iface_cxt)) 113 if(!as_generator(documentation).generate(sink, cls, iface_cxt))
110 return false; 114 return false;
111 115
@@ -158,7 +162,7 @@ struct klass
158 ).generate(sink, p, iface_cxt)) 162 ).generate(sink, p, iface_cxt))
159 return false; 163 return false;
160 164
161 if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, cls.properties, iface_cxt)) 165 if (!as_generator(*(property_wrapper_definition(cls, cls))).generate(sink, cls.properties, iface_cxt))
162 return false; 166 return false;
163 167
164 // End of interface declaration 168 // End of interface declaration
@@ -259,13 +263,13 @@ struct klass
259 return false; 263 return false;
260 264
261 // Property wrappers 265 // Property wrappers
262 if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, cls.properties, concrete_cxt)) 266 if (!as_generator(*(property_wrapper_definition(cls, cls))).generate(sink, cls.properties, concrete_cxt))
263 return false; 267 return false;
264 268
265 for (auto&& klass : helpers::non_implemented_interfaces(cls, concrete_cxt)) 269 for (auto&& klass : helpers::non_implemented_interfaces(cls, concrete_cxt))
266 { 270 {
267 attributes::klass_def c(get_klass(klass, cls.unit), cls.unit); 271 attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
268 if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, c.properties, concrete_cxt)) 272 if (!as_generator(*(property_wrapper_definition(cls, c))).generate(sink, c.properties, concrete_cxt))
269 return false; 273 return false;
270 } 274 }
271 275
@@ -343,13 +347,13 @@ struct klass
343 return false; 347 return false;
344 348
345 // Property wrappers 349 // Property wrappers
346 if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, cls.properties, inherit_cxt)) 350 if (!as_generator(*(property_wrapper_definition(cls, cls))).generate(sink, cls.properties, inherit_cxt))
347 return false; 351 return false;
348 352
349 for (auto&& klass : helpers::non_implemented_interfaces(cls, inherit_cxt)) 353 for (auto&& klass : helpers::non_implemented_interfaces(cls, inherit_cxt))
350 { 354 {
351 attributes::klass_def c(get_klass(klass, cls.unit), cls.unit); 355 attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
352 if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, c.properties, inherit_cxt)) 356 if (!as_generator(*(property_wrapper_definition(cls, c))).generate(sink, c.properties, inherit_cxt))
353 return false; 357 return false;
354 } 358 }
355 359
diff --git a/src/bin/eolian_mono/eolian/mono/name_helpers.hh b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
index 7f71d92..bf0abb7 100644
--- a/src/bin/eolian_mono/eolian/mono/name_helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
@@ -334,28 +334,6 @@ inline std::string to_field_name(std::string const& in)
334 return utils::capitalize(in); 334 return utils::capitalize(in);
335} 335}
336 336
337
338
339template<typename T>
340inline std::string property_managed_name(T const& klass, std::string const& name)
341{
342 auto names = utils::split(name, '_');
343 // No need to escape keyword here as it will be capitalized and already
344 // namespaced inside the owner class.
345 auto managed_name = utils::to_pascal_case(names);
346 auto managed_klass_name = klass_concrete_or_interface_name(klass);
347
348 if (managed_name == "Type")
349 managed_name = managed_klass_name + managed_name;
350
351 return managed_name;
352}
353
354inline std::string property_managed_name(attributes::property_def const& property)
355{
356 return property_managed_name(property.klass, property.name);
357}
358
359inline std::string managed_part_name(attributes::part_def const& part) 337inline std::string managed_part_name(attributes::part_def const& part)
360{ 338{
361 std::vector<std::string> names = utils::split(part.name, '_'); 339 std::vector<std::string> names = utils::split(part.name, '_');
@@ -512,6 +490,45 @@ inline std::string translate_inherited_event_name(const attributes::event_def &e
512 return join_namespaces(klass.namespaces, '_') + klass_interface_name(klass) + "_" + managed_event_name(evt.name); 490 return join_namespaces(klass.namespaces, '_') + klass_interface_name(klass) + "_" + managed_event_name(evt.name);
513} 491}
514 492
493// Properties
494
495template<typename T>
496inline std::string property_managed_name(T const& klass, std::string const& name)
497{
498 auto names = utils::split(name, '_');
499 // No need to escape keyword here as it will be capitalized and already
500 // namespaced inside the owner class.
501 auto managed_name = utils::to_pascal_case(names);
502 auto managed_klass_name = klass_concrete_or_interface_name(klass);
503
504 if (managed_name == "Type")
505 managed_name = managed_klass_name + managed_name;
506
507 return managed_name;
508}
509
510inline std::string property_managed_name(attributes::property_def const& property)
511{
512 return property_managed_name(property.klass, property.name);
513}
514
515inline std::string property_concrete_indexer_name(attributes::property_def const& property)
516{
517 return property_managed_name(property) + "Indexer";
518}
519
520template<typename T>
521inline std::string property_interface_indexer_name(attributes::property_def const& property, T const& current_klass)
522{
523 return name_helpers::klass_full_interface_name(current_klass) + property_concrete_indexer_name(property);
524}
525
526template<typename T>
527inline std::string property_interface_indexer_short_name(attributes::property_def const& property, T const& current_klass)
528{
529 return name_helpers::klass_interface_name(current_klass) + property_concrete_indexer_name(property);
530}
531
515// Open/close namespaces 532// Open/close namespaces
516template<typename OutputIterator, typename Context> 533template<typename OutputIterator, typename Context>
517bool open_namespaces(OutputIterator sink, std::vector<std::string> namespaces, Context const& context) 534bool open_namespaces(OutputIterator sink, std::vector<std::string> namespaces, Context const& context)
diff --git a/src/bin/eolian_mono/eolian/mono/parameter.hh b/src/bin/eolian_mono/eolian/mono/parameter.hh
index 210e5f2..4af5fe2 100644
--- a/src/bin/eolian_mono/eolian/mono/parameter.hh
+++ b/src/bin/eolian_mono/eolian/mono/parameter.hh
@@ -65,7 +65,7 @@ struct is_generator< ::eolian_mono::parameter_generator> : std::true_type {};
65 65
66namespace type_traits { 66namespace type_traits {
67template <> 67template <>
68struct attributes_needed< ::eolian_mono::parameter_generator> : std::integral_constant<int, 1> {}; 68struct attributes_needed< ::eolian_mono::parameter_generator> : std::integral_constant<int, 1> {};
69} 69}
70 70
71template <> 71template <>
@@ -75,9 +75,9 @@ struct is_generator< ::eolian_mono::marshall_parameter_generator> : std::true_ty
75 75
76namespace type_traits { 76namespace type_traits {
77template <> 77template <>
78struct attributes_needed< ::eolian_mono::marshall_parameter_generator> : std::integral_constant<int, 1> {}; 78struct attributes_needed< ::eolian_mono::marshall_parameter_generator> : std::integral_constant<int, 1> {};
79} 79}
80 80
81template <> 81template <>
82struct is_eager_generator< ::eolian_mono::argument_generator> : std::true_type {}; 82struct is_eager_generator< ::eolian_mono::argument_generator> : std::true_type {};
83template <> 83template <>
@@ -85,9 +85,9 @@ struct is_generator< ::eolian_mono::argument_generator> : std::true_type {};
85 85
86namespace type_traits { 86namespace type_traits {
87template <> 87template <>
88struct attributes_needed< ::eolian_mono::argument_generator> : std::integral_constant<int, 1> {}; 88struct attributes_needed< ::eolian_mono::argument_generator> : std::integral_constant<int, 1> {};
89} 89}
90 90
91template <> 91template <>
92struct is_eager_generator< ::eolian_mono::argument_invocation_generator> : std::true_type {}; 92struct is_eager_generator< ::eolian_mono::argument_invocation_generator> : std::true_type {};
93template <> 93template <>
@@ -1553,7 +1553,7 @@ struct native_convert_function_pointer_generator
1553 1553
1554struct constructor_parameter_name_generator 1554struct constructor_parameter_name_generator
1555{ 1555{
1556 1556
1557 template <typename OutputIterator, typename Context> 1557 template <typename OutputIterator, typename Context>
1558 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const 1558 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
1559 { 1559 {
diff --git a/src/bin/eolian_mono/eolian_mono.cc b/src/bin/eolian_mono/eolian_mono.cc
index 62eed11..b6d2b6f 100644
--- a/src/bin/eolian_mono/eolian_mono.cc
+++ b/src/bin/eolian_mono/eolian_mono.cc
@@ -182,13 +182,14 @@ run(options_type const& opts)
182 182
183 auto context = context_add_tag(eolian_mono::indentation_context{0}, 183 auto context = context_add_tag(eolian_mono::indentation_context{0},
184 context_add_tag(eolian_mono::eolian_state_context{opts.state}, 184 context_add_tag(eolian_mono::eolian_state_context{opts.state},
185 context_add_tag(eolian_mono::class_context{eolian_mono::class_context::none},
185 context_add_tag(eolian_mono::options_context{opts.want_beta, 186 context_add_tag(eolian_mono::options_context{opts.want_beta,
186 opts.examples_dir}, 187 opts.examples_dir},
187 context_add_tag(eolian_mono::library_context{opts.dllimport, 188 context_add_tag(eolian_mono::library_context{opts.dllimport,
188 opts.v_major, 189 opts.v_major,
189 opts.v_minor, 190 opts.v_minor,
190 opts.references_map}, 191 opts.references_map},
191 efl::eolian::grammar::context_null())))); 192 efl::eolian::grammar::context_null())))));
192 193
193 EINA_ITERATOR_FOREACH(aliases, tp) 194 EINA_ITERATOR_FOREACH(aliases, tp)
194 { 195 {