summaryrefslogtreecommitdiff
path: root/src/bin/eolian_mono
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/eolian_mono')
-rw-r--r--src/bin/eolian_mono/eolian/mono/alias_definition.hh73
-rw-r--r--src/bin/eolian_mono/eolian/mono/culture_info.hh61
-rw-r--r--src/bin/eolian_mono/eolian/mono/documentation.hh18
-rw-r--r--src/bin/eolian_mono/eolian/mono/enum_definition.hh16
-rw-r--r--src/bin/eolian_mono/eolian/mono/generation_contexts.hh2
-rw-r--r--src/bin/eolian_mono/eolian/mono/klass.hh40
-rw-r--r--src/bin/eolian_mono/eolian/mono/name_helpers.hh21
-rw-r--r--src/bin/eolian_mono/eolian/mono/struct_definition.hh115
-rw-r--r--src/bin/eolian_mono/eolian/mono/struct_fields.hh5
-rw-r--r--src/bin/eolian_mono/eolian/mono/utils.hh2
10 files changed, 331 insertions, 22 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/alias_definition.hh b/src/bin/eolian_mono/eolian/mono/alias_definition.hh
index 7f3f258..d7fda07 100644
--- a/src/bin/eolian_mono/eolian/mono/alias_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/alias_definition.hh
@@ -56,14 +56,20 @@ struct alias_definition_generator
56 alias_type_doc = utils::replace_all(alias_type, "<", "&lt;"); 56 alias_type_doc = utils::replace_all(alias_type, "<", "&lt;");
57 alias_type_doc = utils::replace_all(alias_type_doc, ">", "&gt;"); 57 alias_type_doc = utils::replace_all(alias_type_doc, ">", "&gt;");
58 58
59 std::string alias_since;
60 if (!documentation_helpers::generate_since_tag_line(std::back_inserter(alias_since), alias.documentation, scope_tab, context))
61 return false;
62
59 std::string const alias_name = utils::remove_all(alias.eolian_name, '_'); 63 std::string const alias_name = utils::remove_all(alias.eolian_name, '_');
60 if (!as_generator( 64 if (!as_generator(
61 documentation 65 documentation
62 << "public struct " << alias_name << "\n" 66 << "public struct " << alias_name << " : IEquatable<" << alias_name << ">\n"
63 << "{\n" 67 << "{\n"
64 << scope_tab << "private " << alias_type << " payload;\n\n" 68 << scope_tab << "private " << alias_type << " payload;\n\n"
65 69
66 << scope_tab << "/// <summary>Converts an instance of " << alias_type_doc << " to this struct.</summary>\n" 70 << scope_tab << "/// <summary>Converts an instance of " << alias_type_doc << " to this struct.\n"
71 << alias_since
72 << scope_tab << "/// </summary>\n"
67 << scope_tab << "/// <param name=\"value\">The value to be converted.</param>\n" 73 << scope_tab << "/// <param name=\"value\">The value to be converted.</param>\n"
68 << scope_tab << "/// <returns>A struct with the given value.</returns>\n" 74 << scope_tab << "/// <returns>A struct with the given value.</returns>\n"
69 << scope_tab << "public static implicit operator " << alias_name << "(" << alias_type << " value)\n" 75 << scope_tab << "public static implicit operator " << alias_name << "(" << alias_type << " value)\n"
@@ -71,7 +77,9 @@ struct alias_definition_generator
71 << scope_tab << scope_tab << "return new " << alias_name << "{payload=value};\n" 77 << scope_tab << scope_tab << "return new " << alias_name << "{payload=value};\n"
72 << scope_tab << "}\n\n" 78 << scope_tab << "}\n\n"
73 79
74 << scope_tab << "/// <summary>Converts an instance of this struct to " << alias_type_doc << ".</summary>\n" 80 << scope_tab << "/// <summary>Converts an instance of this struct to " << alias_type_doc << ".\n"
81 << alias_since
82 << scope_tab << "/// </summary>\n"
75 << scope_tab << "/// <param name=\"value\">The value to be converted packed in this struct.</param>\n" 83 << scope_tab << "/// <param name=\"value\">The value to be converted packed in this struct.</param>\n"
76 << scope_tab << "/// <returns>The actual value the alias is wrapping.</returns>\n" 84 << scope_tab << "/// <returns>The actual value the alias is wrapping.</returns>\n"
77 << scope_tab << "public static implicit operator " << alias_type << "(" << alias_name << " value)\n" 85 << scope_tab << "public static implicit operator " << alias_type << "(" << alias_name << " value)\n"
@@ -93,7 +101,64 @@ struct alias_definition_generator
93 << scope_tab << "{\n" 101 << scope_tab << "{\n"
94 << scope_tab << scope_tab << "return this;\n" 102 << scope_tab << scope_tab << "return this;\n"
95 << scope_tab << "}\n" 103 << scope_tab << "}\n"
96 << "}\n" 104 ).generate(sink, alias, context))
105 return false;
106
107 std::string since_line;
108 if (!alias.documentation.since.empty())
109 if (!as_generator(scope_tab << "/// <para>Since EFL " + alias.documentation.since + ".</para>\n"
110 ).generate(std::back_inserter(since_line), attributes::unused, context))
111 return false;
112
113 // GetHashCode (needed by the equality comparisons)
114 if (!as_generator(
115 scope_tab << "/// <summary>Get a hash code for this item.\n"
116 << since_line
117 << scope_tab << "/// </summary>\n"
118 << scope_tab << "public override int GetHashCode() => payload.GetHashCode();\n"
119 ).generate(sink, attributes::unused, context))
120 return false;
121
122 // IEquatble<T> Equals
123 if (!as_generator(
124 scope_tab << "/// <summary>Equality comparison.\n"
125 << since_line
126 << scope_tab << "/// </summary>\n"
127 << scope_tab << "public bool Equals(" << alias_name << " other) => payload == other.payload;\n"
128 ).generate(sink, attributes::unused, context))
129 return false;
130
131 // ValueType.Equals
132 if (!as_generator(
133 scope_tab << "/// <summary>Equality comparison.\n"
134 << since_line
135 << scope_tab << "/// </summary>\n"
136 << scope_tab << "public override bool Equals(object other)\n"
137 << scope_tab << scope_tab << "=> ((other is " << alias_name << ") ? Equals((" << alias_name << ")other) : false);\n"
138 ).generate(sink, attributes::unused, context))
139 return false;
140
141 // Equality operators
142 if (!as_generator(
143 scope_tab << "/// <summary>Equality comparison.\n"
144 << since_line
145 << scope_tab << "/// </summary>\n"
146 << scope_tab << "public static bool operator ==(" << alias_name << " lhs, " << alias_name << " rhs)\n"
147 << scope_tab << scope_tab << "=> lhs.payload == rhs.payload;\n"
148 ).generate(sink, attributes::unused, context))
149 return false;
150
151 if (!as_generator(
152 scope_tab << "/// <summary>Equality comparison.\n"
153 << since_line
154 << scope_tab << "/// </summary>\n"
155 << scope_tab << "public static bool operator !=(" << alias_name << " lhs, " << alias_name << " rhs)\n"
156 << scope_tab << scope_tab << "=> lhs.payload != rhs.payload;\n"
157 ).generate(sink, attributes::unused, context))
158 return false;
159
160 if (!as_generator(
161 "}\n"
97 ).generate(sink, alias, context)) 162 ).generate(sink, alias, context))
98 return false; 163 return false;
99 164
diff --git a/src/bin/eolian_mono/eolian/mono/culture_info.hh b/src/bin/eolian_mono/eolian/mono/culture_info.hh
new file mode 100644
index 0000000..f1efb1c
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/culture_info.hh
@@ -0,0 +1,61 @@
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 CULTURE_INFO_GENERATOR_HH
17#define CULTURE_INFO_GENERATOR_HH
18
19#include "grammar/generator.hpp"
20#include "grammar/klass_def.hpp"
21
22namespace eolian_mono {
23
24namespace attributes = efl::eolian::grammar::attributes;
25
26// Some methods on string require a culture info parameter due to warning CA1307
27struct culture_info_generator
28{
29 template<typename OutputIterator, typename Context>
30 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const
31 {
32 std::string managed_name;
33
34 if (!as_generator(type).generate(std::back_inserter(managed_name), field.type, context))
35 return false;
36
37 if (managed_name == "System.String")
38 if (!as_generator(lit("StringComparison.Ordinal")).generate(sink, attributes::unused, context))
39 return false;
40
41 return true;
42 }
43} const culture_info {};
44
45}
46
47namespace efl { namespace eolian { namespace grammar {
48
49template <>
50struct is_eager_generator< ::eolian_mono::culture_info_generator> : std::true_type {};
51template <>
52struct is_generator< ::eolian_mono::culture_info_generator> : std::true_type {};
53
54namespace type_traits {
55template <>
56struct attributes_needed< ::eolian_mono::culture_info_generator> : std::integral_constant<int, 1> {};
57}
58
59} } }
60
61#endif // CULTURE_INFO_GENERATOR_HH
diff --git a/src/bin/eolian_mono/eolian/mono/documentation.hh b/src/bin/eolian_mono/eolian/mono/documentation.hh
index b57dc4a..0a2179b 100644
--- a/src/bin/eolian_mono/eolian/mono/documentation.hh
+++ b/src/bin/eolian_mono/eolian/mono/documentation.hh
@@ -649,8 +649,24 @@ struct documentation_string_generator
649 649
650} const documentation_string {}; 650} const documentation_string {};
651 651
652} // namespace eolian_mono 652namespace documentation_helpers
653{
654
655template<typename OutputIterator, typename Indent, typename Context>
656bool generate_since_tag_line(OutputIterator sink, attributes::documentation_def const& doc, Indent indentation, Context context)
657{
658 if (doc.since.empty())
659 return true;
653 660
661 return as_generator
662 (
663 indentation << ("/// <para>Since EFL " + doc.since + ".</para>\n")
664 ).generate(sink, attributes::unused, context);
665}
666
667} // documentation_helpers
668
669} // namespace eolian_mono
654 670
655namespace efl { namespace eolian { namespace grammar { 671namespace efl { namespace eolian { namespace grammar {
656 672
diff --git a/src/bin/eolian_mono/eolian/mono/enum_definition.hh b/src/bin/eolian_mono/eolian/mono/enum_definition.hh
index 76bad3b..2c304fc 100644
--- a/src/bin/eolian_mono/eolian/mono/enum_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/enum_definition.hh
@@ -40,15 +40,21 @@ struct enum_definition_generator
40 if(!name_helpers::open_namespaces(sink, enum_.namespaces, context)) 40 if(!name_helpers::open_namespaces(sink, enum_.namespaces, context))
41 return false; 41 return false;
42 42
43 if(!as_generator(documentation).generate(sink, enum_, context)) 43 std::string enum_name = name_helpers::typedecl_managed_name(enum_);
44 return false; 44 std::string flags_attribute;
45
46 // CA1717
47 if (utils::ends_with(enum_name, "Flags") || utils::ends_with(enum_name, "InputHints")) // Special provision while Text api is revamped
48 flags_attribute = "[Flags]";
45 49
46 if(!as_generator 50 if(!as_generator
47 ( 51 (
48 "[Efl.Eo.BindingEntity]\n" 52 documentation
49 "public enum " << string << "\n{\n" 53 << flags_attribute
54 << "[Efl.Eo.BindingEntity]\n"
55 "public enum " << enum_name << "\n{\n"
50 ) 56 )
51 .generate(sink, name_helpers::typedecl_managed_name(enum_), context)) 57 .generate(sink, enum_, context))
52 return false; 58 return false;
53 59
54 // iterate enum fiels 60 // iterate enum fiels
diff --git a/src/bin/eolian_mono/eolian/mono/generation_contexts.hh b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh
index 4620769..f7376f0 100644
--- a/src/bin/eolian_mono/eolian/mono/generation_contexts.hh
+++ b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh
@@ -16,6 +16,8 @@
16#ifndef EOLIAN_MONO_GENERATION_CONTEXTS_HH 16#ifndef EOLIAN_MONO_GENERATION_CONTEXTS_HH
17#define EOLIAN_MONO_GENERATION_CONTEXTS_HH 17#define EOLIAN_MONO_GENERATION_CONTEXTS_HH
18 18
19#include <map>
20
19#include "grammar/context.hpp" 21#include "grammar/context.hpp"
20#include "grammar/indentation.hpp" 22#include "grammar/indentation.hpp"
21 23
diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh
index 81d5956..653acc7 100644
--- a/src/bin/eolian_mono/eolian/mono/klass.hh
+++ b/src/bin/eolian_mono/eolian/mono/klass.hh
@@ -410,6 +410,10 @@ struct klass
410 auto implementable_methods = helpers::get_all_registerable_methods(cls, context); 410 auto implementable_methods = helpers::get_all_registerable_methods(cls, context);
411 bool root = !helpers::has_regular_ancestor(cls); 411 bool root = !helpers::has_regular_ancestor(cls);
412 auto const& indent = current_indentation(inative_cxt); 412 auto const& indent = current_indentation(inative_cxt);
413 std::string klass_since;
414
415 if (!documentation_helpers::generate_since_tag_line(std::back_inserter(klass_since), cls.documentation, indent, context))
416 return false;
413 417
414 std::string base_name; 418 std::string base_name;
415 if(!root) 419 if(!root)
@@ -421,7 +425,10 @@ struct klass
421 if(!as_generator 425 if(!as_generator
422 ( 426 (
423 indent << lit("/// <summary>Wrapper for native methods and virtual method delegates.\n") 427 indent << lit("/// <summary>Wrapper for native methods and virtual method delegates.\n")
424 << indent << "/// For internal use by generated code only.</summary>\n" 428 << indent << "/// For internal use by generated code only.\n"
429 << klass_since
430 << indent << "/// </summary>\n"
431 << indent << "[EditorBrowsable(EditorBrowsableState.Never)]\n"
425 << indent << "internal new class " << native_inherit_name << " : " << (root ? "Efl.Eo.EoWrapper.NativeMethods" : base_name) << "\n" 432 << indent << "internal new class " << native_inherit_name << " : " << (root ? "Efl.Eo.EoWrapper.NativeMethods" : base_name) << "\n"
426 << indent << "{\n" 433 << indent << "{\n"
427 ).generate(sink, attributes::unused, inative_cxt)) 434 ).generate(sink, attributes::unused, inative_cxt))
@@ -437,7 +444,9 @@ struct klass
437 } 444 }
438 445
439 if(!as_generator( 446 if(!as_generator(
440 indent << scope_tab << "/// <summary>Gets the list of Eo operations to override.</summary>\n" 447 indent << scope_tab << "/// <summary>Gets the list of Eo operations to override.\n"
448 << klass_since
449 << indent << "/// </summary>\n"
441 << indent << scope_tab << "/// <returns>The list of Eo operations to be overload.</returns>\n" 450 << indent << scope_tab << "/// <returns>The list of Eo operations to be overload.</returns>\n"
442 << indent << scope_tab << "internal override System.Collections.Generic.List<EflOpDescription> GetEoOps(System.Type type, bool includeInherited)\n" 451 << indent << scope_tab << "internal override System.Collections.Generic.List<EflOpDescription> GetEoOps(System.Type type, bool includeInherited)\n"
443 << indent << scope_tab << "{\n" 452 << indent << scope_tab << "{\n"
@@ -485,9 +494,14 @@ struct klass
485 ).generate(sink, attributes::unused, inative_cxt)) 494 ).generate(sink, attributes::unused, inative_cxt))
486 return false; 495 return false;
487 496
497 if (!klass_since.empty())
498 klass_since = static_cast<std::string>(scope_tab) + klass_since;
499
488 // Attribute getter of the native 'Efl_Class *' handle (for proper inheritance from additional explicit interfaces) 500 // Attribute getter of the native 'Efl_Class *' handle (for proper inheritance from additional explicit interfaces)
489 if(!as_generator( 501 if(!as_generator(
490 indent << scope_tab << "/// <summary>Returns the Eo class for the native methods of this class.</summary>\n" 502 indent << scope_tab << "/// <summary>Returns the Eo class for the native methods of this class.\n"
503 << klass_since
504 << indent << scope_tab << "/// </summary>\n"
491 << indent << scope_tab << "/// <returns>The native class pointer.</returns>\n" 505 << indent << scope_tab << "/// <returns>The native class pointer.</returns>\n"
492 << indent << scope_tab << "internal override IntPtr GetEflClass()\n" 506 << indent << scope_tab << "internal override IntPtr GetEflClass()\n"
493 << indent << scope_tab << "{\n" 507 << indent << scope_tab << "{\n"
@@ -558,9 +572,15 @@ struct klass
558 return !blacklist::is_function_blacklisted(ctor.function, context); 572 return !blacklist::is_function_blacklisted(ctor.function, context);
559 }); 573 });
560 574
575 std::string klass_since;
576 if (!documentation_helpers::generate_since_tag_line(std::back_inserter(klass_since), cls.documentation, scope_tab, context))
577 return false;
578
561 // Public (API) constructors 579 // Public (API) constructors
562 if (!as_generator( 580 if (!as_generator(
563 scope_tab << "/// <summary>Initializes a new instance of the <see cref=\"" << inherit_name << "\"/> class.</summary>\n" 581 scope_tab << "/// <summary>Initializes a new instance of the <see cref=\"" << inherit_name << "\"/> class.\n"
582 << klass_since
583 << scope_tab << "/// </summary>\n"
564 << scope_tab << "/// <param name=\"parent\">Parent instance.</param>\n" 584 << scope_tab << "/// <param name=\"parent\">Parent instance.</param>\n"
565 << *(documentation) 585 << *(documentation)
566 // For constructors with arguments, the parent is also required, as optional parameters can't come before non-optional paramenters. 586 // For constructors with arguments, the parent is also required, as optional parameters can't come before non-optional paramenters.
@@ -572,13 +592,17 @@ struct klass
572 << scope_tab << scope_tab << "FinishInstantiation();\n" 592 << scope_tab << scope_tab << "FinishInstantiation();\n"
573 << scope_tab << "}\n\n" 593 << scope_tab << "}\n\n"
574 << scope_tab << "/// <summary>Subclasses should override this constructor if they are expected to be instantiated from native code.\n" 594 << scope_tab << "/// <summary>Subclasses should override this constructor if they are expected to be instantiated from native code.\n"
575 << scope_tab << "/// Do not call this constructor directly.</summary>\n" 595 << scope_tab << "/// Do not call this constructor directly.\n"
596 << klass_since
597 << scope_tab << "/// </summary>\n"
576 << scope_tab << "/// <param name=\"ch\">Tag struct storing the native handle of the object being constructed.</param>\n" 598 << scope_tab << "/// <param name=\"ch\">Tag struct storing the native handle of the object being constructed.</param>\n"
577 << scope_tab << "protected " << inherit_name << "(ConstructingHandle ch) : base(ch)\n" 599 << scope_tab << "protected " << inherit_name << "(ConstructingHandle ch) : base(ch)\n"
578 << scope_tab << "{\n" 600 << scope_tab << "{\n"
579 << scope_tab << "}\n\n" 601 << scope_tab << "}\n\n"
580 << scope_tab << "/// <summary>Initializes a new instance of the <see cref=\"" << inherit_name << "\"/> class.\n" 602 << scope_tab << "/// <summary>Initializes a new instance of the <see cref=\"" << inherit_name << "\"/> class.\n"
581 << scope_tab << "/// Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.</summary>\n" 603 << scope_tab << "/// Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.\n"
604 << klass_since
605 << scope_tab << "/// </summary>\n"
582 << scope_tab << "/// <param name=\"wh\">The native pointer to be wrapped.</param>\n" 606 << scope_tab << "/// <param name=\"wh\">The native pointer to be wrapped.</param>\n"
583 << scope_tab << "internal " << inherit_name << "(Efl.Eo.WrappingHandle wh) : base(wh)\n" 607 << scope_tab << "internal " << inherit_name << "(Efl.Eo.WrappingHandle wh) : base(wh)\n"
584 << scope_tab << "{\n" 608 << scope_tab << "{\n"
@@ -605,7 +629,9 @@ struct klass
605 629
606 return as_generator( 630 return as_generator(
607 scope_tab << "/// <summary>Initializes a new instance of the <see cref=\"" << inherit_name << "\"/> class.\n" 631 scope_tab << "/// <summary>Initializes a new instance of the <see cref=\"" << inherit_name << "\"/> class.\n"
608 << scope_tab << "/// Internal usage: Constructor to forward the wrapper initialization to the root class that interfaces with native code. Should not be used directly.</summary>\n" 632 << scope_tab << "/// Internal usage: Constructor to forward the wrapper initialization to the root class that interfaces with native code. Should not be used directly.\n"
633 << klass_since
634 << scope_tab << "/// </summary>\n"
609 << scope_tab << "/// <param name=\"baseKlass\">The pointer to the base native Eo class.</param>\n" 635 << scope_tab << "/// <param name=\"baseKlass\">The pointer to the base native Eo class.</param>\n"
610 << scope_tab << "/// <param name=\"parent\">The Efl.Object parent of this instance.</param>\n" 636 << scope_tab << "/// <param name=\"parent\">The Efl.Object parent of this instance.</param>\n"
611 << scope_tab << "protected " << inherit_name << "(IntPtr baseKlass, Efl.Object parent) : base(baseKlass, parent)\n" 637 << scope_tab << "protected " << inherit_name << "(IntPtr baseKlass, Efl.Object parent) : base(baseKlass, parent)\n"
diff --git a/src/bin/eolian_mono/eolian/mono/name_helpers.hh b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
index 2f3026d..867b832 100644
--- a/src/bin/eolian_mono/eolian/mono/name_helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
@@ -22,6 +22,7 @@
22#include <sstream> 22#include <sstream>
23#include <string> 23#include <string>
24#include <vector> 24#include <vector>
25#include <map>
25#include "utils.hh" 26#include "utils.hh"
26 27
27#include "grammar/integral.hpp" 28#include "grammar/integral.hpp"
@@ -563,6 +564,17 @@ std::string translate_value_type(std::string const& name)
563 return name; 564 return name;
564} 565}
565 566
567
568// Field names //
569struct struct_field_name_generator
570{
571 template <typename OutputIterator, typename Context>
572 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const
573 {
574 return as_generator(string).generate(sink, name_helpers::to_field_name(field.name), context);
575 }
576} const struct_field_name {};
577
566} // namespace name_helpers 578} // namespace name_helpers
567 579
568} // namespace eolian_mono 580} // namespace eolian_mono
@@ -590,9 +602,18 @@ struct is_eager_generator<eolian_mono::name_helpers::klass_full_concrete_name_ge
590template <> 602template <>
591struct is_generator<eolian_mono::name_helpers::klass_full_concrete_name_generator> : std::true_type {}; 603struct is_generator<eolian_mono::name_helpers::klass_full_concrete_name_generator> : std::true_type {};
592 604
605template <>
606struct is_eager_generator<eolian_mono::name_helpers::struct_field_name_generator> : std::true_type {};
607template <>
608struct is_generator< ::eolian_mono::name_helpers::struct_field_name_generator> : std::true_type {};
609
593namespace type_traits { 610namespace type_traits {
594template <> 611template <>
595struct attributes_needed<struct ::eolian_mono::name_helpers::klass_full_concrete_or_interface_name_generator> : std::integral_constant<int, 1> {}; 612struct attributes_needed<struct ::eolian_mono::name_helpers::klass_full_concrete_or_interface_name_generator> : std::integral_constant<int, 1> {};
613
614template <>
615struct attributes_needed< ::eolian_mono::name_helpers::struct_field_name_generator> : std::integral_constant<int, 1> {};
616
596} 617}
597 618
598} } } 619} } }
diff --git a/src/bin/eolian_mono/eolian/mono/struct_definition.hh b/src/bin/eolian_mono/eolian/mono/struct_definition.hh
index b3b8d71..70332c9 100644
--- a/src/bin/eolian_mono/eolian/mono/struct_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/struct_definition.hh
@@ -21,6 +21,7 @@
21#include "grammar/indentation.hpp" 21#include "grammar/indentation.hpp"
22#include "grammar/list.hpp" 22#include "grammar/list.hpp"
23#include "grammar/alternative.hpp" 23#include "grammar/alternative.hpp"
24#include "grammar/attribute_reorder.hpp"
24#include "name_helpers.hh" 25#include "name_helpers.hh"
25#include "helpers.hh" 26#include "helpers.hh"
26#include "type.hh" 27#include "type.hh"
@@ -28,6 +29,7 @@
28#include "documentation.hh" 29#include "documentation.hh"
29#include "struct_fields.hh" 30#include "struct_fields.hh"
30#include "blacklist.hh" 31#include "blacklist.hh"
32#include "culture_info.hh"
31 33
32namespace eolian_mono { 34namespace eolian_mono {
33 35
@@ -408,14 +410,15 @@ struct struct_definition_generator
408 auto const& indent = current_indentation(context); 410 auto const& indent = current_indentation(context);
409 if(!as_generator(documentation).generate(sink, struct_, context)) 411 if(!as_generator(documentation).generate(sink, struct_, context))
410 return false; 412 return false;
413 auto struct_managed_name = binding_struct_name(struct_);
411 if(!as_generator 414 if(!as_generator
412 ( 415 (
413 indent << "[StructLayout(LayoutKind.Sequential)]\n" 416 indent << "[StructLayout(LayoutKind.Sequential)]\n"
414 << indent << "[Efl.Eo.BindingEntity]\n" 417 << indent << "[Efl.Eo.BindingEntity]\n"
415 << indent << "public struct " << string << "\n" 418 << indent << "public struct " << struct_managed_name << " : IEquatable<" << struct_managed_name << ">\n"
416 << indent << "{\n" 419 << indent << "{\n"
417 ) 420 )
418 .generate(sink, binding_struct_name(struct_), context)) 421 .generate(sink, attributes::unused, context))
419 return false; 422 return false;
420 423
421 // iterate struct fields 424 // iterate struct fields
@@ -472,6 +475,114 @@ struct struct_definition_generator
472 return false; 475 return false;
473 } 476 }
474 477
478 std::string since_line;
479 if (!struct_.documentation.since.empty())
480 if (!as_generator(indent << scope_tab << "/// <para>Since EFL " + struct_.documentation.since + ".</para>\n"
481 ).generate(std::back_inserter(since_line), attributes::unused, context))
482 return false;
483
484 // GetHashCode (needed by the equality comparisons)
485 if (!as_generator(
486 indent << scope_tab << "/// <summary>Get a hash code for this item.\n"
487 << since_line
488 << indent << scope_tab << "/// </summary>\n"
489 << indent << scope_tab << "public override int GetHashCode()\n"
490 << indent << scope_tab << "{\n"
491 ).generate(sink, attributes::unused, context))
492 return false;
493
494 if (struct_.fields.size() != 0 )
495 {
496 // int hash = 17;
497 // hash = 23 * fieldA.GetHashCode();
498 // hash = 23 * fieldB.GetHashCode();
499 // hash = 23 * fieldC.GetHashCode();
500 // return hash
501 if (!as_generator(
502 indent << scope_tab << scope_tab << "int hash = 17;\n"
503 << *(grammar::attribute_reorder<-1, -1>(indent << scope_tab << scope_tab << "hash = hash * 23 + " << name_helpers::struct_field_name << ".GetHashCode(" << culture_info << ");\n"))
504 << indent << scope_tab << scope_tab << "return hash;\n"
505 ).generate(sink, struct_.fields, context))
506 return false;
507 }
508 else
509 {
510 // Just compare the place holder pointers
511 if (!as_generator(
512 "return field.GetHashCode();\n"
513 ).generate(sink, attributes::unused, context))
514 return false;
515 }
516
517 if (!as_generator(
518 indent << scope_tab << "}\n"
519 ).generate(sink, attributes::unused, context))
520 return false;
521
522 // IEquatable<T> Equals
523 if (!as_generator(
524 indent << scope_tab << "/// <summary>Equality comparison.\n"
525 << since_line
526 << indent << scope_tab << "/// </summary>\n"
527 << indent << scope_tab << "public bool Equals(" << struct_managed_name << " other)\n"
528 << indent << scope_tab << "{\n"
529 << indent << scope_tab << scope_tab << "return "
530 ).generate(sink, attributes::unused, context))
531 return false;
532
533 if (struct_.fields.size() != 0 )
534 {
535 if (!as_generator(
536 grammar::attribute_reorder<-1, -1>((name_helpers::struct_field_name << " == other." << name_helpers::struct_field_name)) % " && "
537 ).generate(sink, struct_.fields, context))
538 return false;
539 }
540 else
541 {
542 // Just compare the place holder pointers
543 if (!as_generator(
544 "field.Equals(other.field)"
545 ).generate(sink, attributes::unused, context))
546 return false;
547 }
548
549
550 if (!as_generator(
551 indent << scope_tab << scope_tab << ";\n"
552 << indent << scope_tab << "}\n"
553 ).generate(sink, attributes::unused, context))
554 return false;
555
556 // ValueType.Equals
557 if (!as_generator(
558 indent << scope_tab << "/// <summary>Equality comparison.\n"
559 << since_line
560 << indent << scope_tab << "/// </summary>\n"
561 << indent << scope_tab << "public override bool Equals(object other)\n"
562 << indent << scope_tab << scope_tab << "=> ((other is " << struct_managed_name << ") ? Equals((" << struct_managed_name << ")other) : false);\n"
563 ).generate(sink, attributes::unused, context))
564 return false;
565
566 // Equality operators
567 if (!as_generator(
568 indent << scope_tab << "/// <summary>Equality comparison.\n"
569 << since_line
570 << indent << scope_tab << "/// </summary>\n"
571 << indent << scope_tab << "public static bool operator ==(" << struct_managed_name << " lhs, " << struct_managed_name << " rhs)\n"
572 << indent << scope_tab << scope_tab << "=> lhs.Equals(rhs);"
573 ).generate(sink, attributes::unused, context))
574 return false;
575
576 if (!as_generator(
577 indent << scope_tab << "/// <summary>Equality comparison.\n"
578 << since_line
579 << indent << scope_tab << "/// </summary>\n"
580 << indent << scope_tab << "public static bool operator !=(" << struct_managed_name << " lhs, " << struct_managed_name << " rhs)\n"
581 << indent << scope_tab << scope_tab << "=> !lhs.Equals(rhs);"
582 ).generate(sink, attributes::unused, context))
583 return false;
584
585 // Conversions from/to internal struct and IntPtrs
475 if(!as_generator( 586 if(!as_generator(
476 indent << scope_tab << "/// <summary>Implicit conversion to the managed representation from a native pointer.\n" 587 indent << scope_tab << "/// <summary>Implicit conversion to the managed representation from a native pointer.\n"
477 ).generate(sink, attributes::unused, context)) 588 ).generate(sink, attributes::unused, context))
diff --git a/src/bin/eolian_mono/eolian/mono/struct_fields.hh b/src/bin/eolian_mono/eolian/mono/struct_fields.hh
index 7756d7b..b8bb0a2 100644
--- a/src/bin/eolian_mono/eolian/mono/struct_fields.hh
+++ b/src/bin/eolian_mono/eolian/mono/struct_fields.hh
@@ -45,8 +45,9 @@ struct field_argument_assignment_generator
45 template<typename OutputIterator, typename Context> 45 template<typename OutputIterator, typename Context>
46 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const 46 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const
47 { 47 {
48 if (!as_generator("this." << string << " = " << string) 48 auto field_name = name_helpers::to_field_name(field.name);
49 .generate(sink, std::make_tuple(name_helpers::to_field_name(field.name), name_helpers::to_field_name(field.name)), context)) 49 if (!as_generator("this." << field_name << " = " << field_name)
50 .generate(sink, attributes::unused, context))
50 return false; 51 return false;
51 return true; 52 return true;
52 } 53 }
diff --git a/src/bin/eolian_mono/eolian/mono/utils.hh b/src/bin/eolian_mono/eolian/mono/utils.hh
index 6eea0bd..d942903 100644
--- a/src/bin/eolian_mono/eolian/mono/utils.hh
+++ b/src/bin/eolian_mono/eolian/mono/utils.hh
@@ -98,7 +98,7 @@ namespace eolian_mono { namespace utils {
98 98
99 inline bool ends_with(std::string const& source, std::string suffix) 99 inline bool ends_with(std::string const& source, std::string suffix)
100 { 100 {
101 if (source.size() > suffix.size()) 101 if (source.size() >= suffix.size())
102 return (0 == source.compare(source.size() - suffix.size(), suffix.size(), suffix)); 102 return (0 == source.compare(source.size() - suffix.size(), suffix.size(), suffix));
103 else 103 else
104 return false; 104 return false;