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.hh103
-rw-r--r--src/bin/eolian_mono/eolian/mono/async_function_definition.hh49
-rw-r--r--src/bin/eolian_mono/eolian/mono/blacklist.hh25
-rw-r--r--src/bin/eolian_mono/eolian/mono/culture_info.hh61
-rw-r--r--src/bin/eolian_mono/eolian/mono/documentation.hh181
-rw-r--r--src/bin/eolian_mono/eolian/mono/enum_definition.hh37
-rw-r--r--src/bin/eolian_mono/eolian/mono/events.hh240
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_declaration.hh19
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_definition.hh83
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_helpers.hh22
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_pointer.hh48
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_registration.hh17
-rw-r--r--src/bin/eolian_mono/eolian/mono/generation_contexts.hh17
-rw-r--r--src/bin/eolian_mono/eolian/mono/helpers.hh15
-rw-r--r--src/bin/eolian_mono/eolian/mono/klass.hh335
-rw-r--r--src/bin/eolian_mono/eolian/mono/logging.hh15
-rw-r--r--src/bin/eolian_mono/eolian/mono/marshall_annotation.hh158
-rw-r--r--src/bin/eolian_mono/eolian/mono/marshall_type.hh15
-rw-r--r--src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh20
-rw-r--r--src/bin/eolian_mono/eolian/mono/name_helpers.hh82
-rw-r--r--src/bin/eolian_mono/eolian/mono/parameter.hh326
-rw-r--r--src/bin/eolian_mono/eolian/mono/part_definition.hh39
-rw-r--r--src/bin/eolian_mono/eolian/mono/struct_definition.hh328
-rw-r--r--src/bin/eolian_mono/eolian/mono/struct_fields.hh60
-rw-r--r--src/bin/eolian_mono/eolian/mono/type.hh15
-rw-r--r--src/bin/eolian_mono/eolian/mono/type_impl.hh43
-rw-r--r--src/bin/eolian_mono/eolian/mono/type_match.hh46
-rw-r--r--src/bin/eolian_mono/eolian/mono/using_decl.hh15
-rw-r--r--src/bin/eolian_mono/eolian/mono/utils.hh17
-rw-r--r--src/bin/eolian_mono/eolian/mono/variable_definition.hh21
-rw-r--r--src/bin/eolian_mono/eolian_mono.cc38
31 files changed, 1792 insertions, 698 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/alias_definition.hh b/src/bin/eolian_mono/eolian/mono/alias_definition.hh
index 5d275a3..d7fda07 100644
--- a/src/bin/eolian_mono/eolian/mono/alias_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/alias_definition.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_ALIAS_DEFINITION_HH 16#ifndef EOLIAN_MONO_ALIAS_DEFINITION_HH
2#define EOLIAN_MONO_ALIAS_DEFINITION_HH 17#define EOLIAN_MONO_ALIAS_DEFINITION_HH
3 18
@@ -41,14 +56,20 @@ struct alias_definition_generator
41 alias_type_doc = utils::replace_all(alias_type, "<", "&lt;"); 56 alias_type_doc = utils::replace_all(alias_type, "<", "&lt;");
42 alias_type_doc = utils::replace_all(alias_type_doc, ">", "&gt;"); 57 alias_type_doc = utils::replace_all(alias_type_doc, ">", "&gt;");
43 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
44 std::string const alias_name = utils::remove_all(alias.eolian_name, '_'); 63 std::string const alias_name = utils::remove_all(alias.eolian_name, '_');
45 if (!as_generator( 64 if (!as_generator(
46 documentation 65 documentation
47 << "public struct " << alias_name << "\n" 66 << "public struct " << alias_name << " : IEquatable<" << alias_name << ">\n"
48 << "{\n" 67 << "{\n"
49 << scope_tab << "private " << alias_type << " payload;\n\n" 68 << scope_tab << "private " << alias_type << " payload;\n\n"
50 69
51 << 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"
52 << 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"
53 << scope_tab << "/// <returns>A struct with the given value.</returns>\n" 74 << scope_tab << "/// <returns>A struct with the given value.</returns>\n"
54 << 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"
@@ -56,14 +77,88 @@ struct alias_definition_generator
56 << scope_tab << scope_tab << "return new " << alias_name << "{payload=value};\n" 77 << scope_tab << scope_tab << "return new " << alias_name << "{payload=value};\n"
57 << scope_tab << "}\n\n" 78 << scope_tab << "}\n\n"
58 79
59 << 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"
60 << 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"
61 << 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"
62 << 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"
63 << scope_tab << "{\n" 86 << scope_tab << "{\n"
64 << scope_tab << scope_tab << "return value.payload;\n" 87 << scope_tab << scope_tab << "return value.payload;\n"
65 << scope_tab << "}\n" 88 << scope_tab << "}\n"
66 << "}\n" 89
90 << scope_tab << "/// <summary>Converts an instance of " << alias_type_doc << " to this struct.</summary>\n"
91 << scope_tab << "/// <param name=\"value\">The value to be converted.</param>\n"
92 << scope_tab << "/// <returns>A struct with the given value.</returns>\n"
93 << scope_tab << "public static " << alias_name << " From" << name_helpers::translate_value_type(alias_type) << "(" << alias_type << " value)\n"
94 << scope_tab << "{\n"
95 << scope_tab << scope_tab << "return value;\n"
96 << scope_tab << "}\n\n"
97
98 << scope_tab << "/// <summary>Converts an instance of this struct to " << alias_type_doc << ".</summary>\n"
99 << scope_tab << "/// <returns>The actual value the alias is wrapping.</returns>\n"
100 << scope_tab << "public " << alias_type << " To" << name_helpers::translate_value_type(alias_type) << "()\n"
101 << scope_tab << "{\n"
102 << scope_tab << scope_tab << "return this;\n"
103 << scope_tab << "}\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"
67 ).generate(sink, alias, context)) 162 ).generate(sink, alias, context))
68 return false; 163 return false;
69 164
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 8ca3c5c..bc0bb68 100644
--- a/src/bin/eolian_mono/eolian/mono/async_function_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/async_function_definition.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_ASYNC_FUNCTION_DEFINITION_HH 16#ifndef EOLIAN_MONO_ASYNC_FUNCTION_DEFINITION_HH
2#define EOLIAN_MONO_ASYNC_FUNCTION_DEFINITION_HH 17#define EOLIAN_MONO_ASYNC_FUNCTION_DEFINITION_HH
3 18
@@ -57,30 +72,30 @@ struct async_function_declaration_generator
57 return true; 72 return true;
58 73
59 if (!as_generator( 74 if (!as_generator(
60 scope_tab << "/// <summary>Async wrapper for <see cref=\"" << name_helpers::managed_method_name(f) << "\" />.\n" 75 scope_tab(2) << "/// <summary>Async wrapper for <see cref=\"" << name_helpers::managed_method_name(f) << "\" />.\n"
61 ).generate(sink, attributes::unused, context)) 76 ).generate(sink, attributes::unused, context))
62 return false; 77 return false;
63 78
64 if (!f.documentation.since.empty()) 79 if (!f.documentation.since.empty())
65 if (!as_generator 80 if (!as_generator
66 (scope_tab << "/// <para>Since EFL " + f.documentation.since + ".</para>\n") 81 (scope_tab(2) << "/// <para>Since EFL " + f.documentation.since + ".</para>\n")
67 .generate (sink, attributes::unused, context)) 82 .generate (sink, attributes::unused, context))
68 return false; 83 return false;
69 84
70 if (!as_generator( 85 if (!as_generator(
71 scope_tab << "/// </summary>\n" 86 scope_tab(2) << "/// </summary>\n"
72 ).generate(sink, attributes::unused, context)) 87 ).generate(sink, attributes::unused, context))
73 return false; 88 return false;
74 89
75 // generate_parameter is not a proper as_generator-compatible generator, so we had to do an old fashioned loop 90 // generate_parameter is not a proper as_generator-compatible generator, so we had to do an old fashioned loop
76 for (auto&& param : f.parameters) 91 for (auto&& param : f.parameters)
77 if (!documentation(1).generate_parameter(sink, param, context)) 92 if (!documentation(2).generate_parameter(sink, param, context))
78 return false; 93 return false;
79 94
80 if (!as_generator( 95 if (!as_generator(
81 scope_tab << "/// <param name=\"token\">Token to notify the async operation of external request to cancel.</param>\n" 96 scope_tab(2) << "/// <param name=\"token\">Token to notify the async operation of external request to cancel.</param>\n"
82 << scope_tab << "/// <returns>An async task wrapping the result of the operation.</returns>\n" 97 << scope_tab(2) << "/// <returns>An async task wrapping the result of the operation.</returns>\n"
83 << scope_tab << "System.Threading.Tasks.Task<Eina.Value> " << name_helpers::managed_async_method_name(f) << "(" << *(parameter << ",") << 98 << scope_tab(2) << "System.Threading.Tasks.Task<Eina.Value> " << name_helpers::managed_async_method_name(f) << "(" << *(parameter << ", ") <<
84 " System.Threading.CancellationToken token = default(System.Threading.CancellationToken));\n\n" 99 " System.Threading.CancellationToken token = default(System.Threading.CancellationToken));\n\n"
85 ).generate(sink, f.parameters, context)) 100 ).generate(sink, f.parameters, context))
86 return false; 101 return false;
@@ -115,18 +130,18 @@ struct async_function_definition_generator
115 std::transform(f.parameters.begin(), f.parameters.end(), std::back_inserter(param_forwarding), parameter_forwarding); 130 std::transform(f.parameters.begin(), f.parameters.end(), std::back_inserter(param_forwarding), parameter_forwarding);
116 131
117 if (!as_generator( 132 if (!as_generator(
118 scope_tab << "/// <summary>Async wrapper for <see cref=\"" << name_helpers::managed_method_name(f) << "\" />.\n" 133 scope_tab(2) << "/// <summary>Async wrapper for <see cref=\"" << name_helpers::managed_method_name(f) << "\" />.\n"
119 ).generate(sink, attributes::unused, context)) 134 ).generate(sink, attributes::unused, context))
120 return false; 135 return false;
121 136
122 if (!f.documentation.since.empty()) 137 if (!f.documentation.since.empty())
123 if (!as_generator 138 if (!as_generator
124 (scope_tab << "/// <para>Since EFL " + f.documentation.since + ".</para>\n") 139 (scope_tab(2) << "/// <para>Since EFL " + f.documentation.since + ".</para>\n")
125 .generate (sink, attributes::unused, context)) 140 .generate (sink, attributes::unused, context))
126 return false; 141 return false;
127 142
128 if (!as_generator( 143 if (!as_generator(
129 scope_tab << "/// </summary>\n" 144 scope_tab(2) << "/// </summary>\n"
130 ).generate(sink, attributes::unused, context)) 145 ).generate(sink, attributes::unused, context))
131 return false; 146 return false;
132 147
@@ -136,13 +151,13 @@ struct async_function_definition_generator
136 return false; 151 return false;
137 152
138 if(!as_generator( 153 if(!as_generator(
139 scope_tab << "/// <param name=\"token\">Token to notify the async operation of external request to cancel.</param>\n" 154 scope_tab(2) << "/// <param name=\"token\">Token to notify the async operation of external request to cancel.</param>\n"
140 << scope_tab << "/// <returns>An async task wrapping the result of the operation.</returns>\n" 155 << scope_tab(2) << "/// <returns>An async task wrapping the result of the operation.</returns>\n"
141 << scope_tab << "public System.Threading.Tasks.Task<Eina.Value> " << name_helpers::managed_async_method_name(f) << "(" << *(parameter << ",") << " System.Threading.CancellationToken token = default(System.Threading.CancellationToken))\n" 156 << scope_tab(2) << "public System.Threading.Tasks.Task<Eina.Value> " << name_helpers::managed_async_method_name(f) << "(" << *(parameter << ", ") << " System.Threading.CancellationToken token = default(System.Threading.CancellationToken))\n"
142 << scope_tab << "{\n" 157 << scope_tab(2) << "{\n"
143 << scope_tab << scope_tab << "Eina.Future future = " << name_helpers::managed_method_name(f) << "(" << (string % ",") << ");\n" 158 << scope_tab(2) << scope_tab << "Eina.Future future = " << name_helpers::managed_method_name(f) << "(" << (string % ", ") << ");\n"
144 << scope_tab << scope_tab << "return Efl.Eo.Globals.WrapAsync(future, token);\n" 159 << scope_tab(2) << scope_tab << "return Efl.Eo.Globals.WrapAsync(future, token);\n"
145 << scope_tab << "}\n\n" 160 << scope_tab(2) << "}\n\n"
146 ).generate(sink, std::make_tuple(f.parameters, param_forwarding), context)) 161 ).generate(sink, std::make_tuple(f.parameters, param_forwarding), context))
147 return false; 162 return false;
148 return true; 163 return true;
diff --git a/src/bin/eolian_mono/eolian/mono/blacklist.hh b/src/bin/eolian_mono/eolian/mono/blacklist.hh
index 49cded5..8d8de9d 100644
--- a/src/bin/eolian_mono/eolian/mono/blacklist.hh
+++ b/src/bin/eolian_mono/eolian/mono/blacklist.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_BLACKLIST_HH 16#ifndef EOLIAN_MONO_BLACKLIST_HH
2#define EOLIAN_MONO_BLACKLIST_HH 17#define EOLIAN_MONO_BLACKLIST_HH
3 18
@@ -49,6 +64,12 @@ inline bool is_function_blacklisted(std::string const& c_name)
49 || c_name == "efl_ui_list_model_size_get" 64 || c_name == "efl_ui_list_model_size_get"
50 || c_name == "efl_ui_list_relayout_layout_do" 65 || c_name == "efl_ui_list_relayout_layout_do"
51 || c_name == "efl_event_callback_forwarder_priority_add" // Depends on constants support. 66 || c_name == "efl_event_callback_forwarder_priority_add" // Depends on constants support.
67 || c_name == "efl_event_callback_forwarder_del"
68 || c_name == "efl_ui_text_context_menu_item_add"
69 || c_name == "efl_ui_widget_input_event_handler"
70 || c_name == "efl_access_object_event_handler_add"
71 || c_name == "efl_access_object_event_handler_del"
72 || c_name == "efl_access_object_event_emit"
52 ; 73 ;
53} 74}
54 75
@@ -129,9 +150,9 @@ inline bool is_alias_blacklisted(attributes::alias_def const& alias, Context con
129 return name_helpers::alias_full_eolian_name(alias) == "Eina.Error"; 150 return name_helpers::alias_full_eolian_name(alias) == "Eina.Error";
130} 151}
131 152
132inline bool is_property_blacklisted(std::string const& name) 153inline bool is_property_blacklisted(std::string const&)
133{ 154{
134 return name == "Efl.IText.Text"; 155 return false;
135} 156}
136 157
137template<typename Context> 158template<typename Context>
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 7bcdfc5..d009e45 100644
--- a/src/bin/eolian_mono/eolian/mono/documentation.hh
+++ b/src/bin/eolian_mono/eolian/mono/documentation.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_DOCUMENTATION_HPP 16#ifndef EOLIAN_MONO_DOCUMENTATION_HPP
2#define EOLIAN_MONO_DOCUMENTATION_HPP 17#define EOLIAN_MONO_DOCUMENTATION_HPP
3 18
@@ -27,18 +42,15 @@ struct documentation_generator
27 : scope_size(scope_size) {} 42 : scope_size(scope_size) {}
28 43
29 44
30 // Returns the number of parameters (values + keys) that a property method requires 45 // Returns the number of keys that a property method requires
31 // Specify if you want the Setter or the Getter method. 46 // Specify if you want the Setter or the Getter method.
32 static int property_num_parameters(const ::Eolian_Function *function, ::Eolian_Function_Type ftype) 47 static int property_num_keys(const ::Eolian_Function *function, ::Eolian_Function_Type ftype)
33 { 48 {
34 Eina_Iterator *itr = ::eolian_property_keys_get(function, ftype); 49 Eina_Iterator *itr = ::eolian_property_keys_get(function, ftype);
35 Eolian_Function_Parameter *pr; 50 Eolian_Function_Parameter *pr;
36 int n = 0; 51 int n = 0;
37 EINA_ITERATOR_FOREACH(itr, pr) { n++; } 52 EINA_ITERATOR_FOREACH(itr, pr) { n++; }
38 eina_iterator_free(itr); 53 eina_iterator_free(itr);
39 itr = ::eolian_property_values_get(function, ftype);
40 EINA_ITERATOR_FOREACH(itr, pr) { n++; }
41 eina_iterator_free(itr);
42 return n; 54 return n;
43 } 55 }
44 56
@@ -70,7 +82,7 @@ struct documentation_generator
70 const char* eo_name = ::eolian_function_name_get(function); 82 const char* eo_name = ::eolian_function_name_get(function);
71 std::string name = object_ref_conversion(klass); 83 std::string name = object_ref_conversion(klass);
72 84
73 // Klass is needed to check the property naming rulles 85 // Klass is needed to check the property naming rules
74 attributes::klass_def klass_d((const ::Eolian_Class *)klass, eolian_object_unit_get(klass)); 86 attributes::klass_def klass_d((const ::Eolian_Class *)klass, eolian_object_unit_get(klass));
75 87
76 // Comment the block below to enable @see reference conversion for non-public interface members. 88 // Comment the block below to enable @see reference conversion for non-public interface members.
@@ -110,14 +122,13 @@ struct documentation_generator
110 break; 122 break;
111 case ::EOLIAN_PROPERTY: 123 case ::EOLIAN_PROPERTY:
112 { 124 {
113 int getter_params = property_num_parameters(function, ::EOLIAN_PROP_GET); 125 int getter_nkeys = property_num_keys(function, ::EOLIAN_PROP_GET);
114 int setter_params = property_num_parameters(function, ::EOLIAN_PROP_SET); 126 int setter_nkeys = property_num_keys(function, ::EOLIAN_PROP_SET);
115 std::string short_name = name_helpers::property_managed_name(klass_d, eo_name); 127 std::string short_name = name_helpers::property_managed_name(klass_d, eo_name);
116 bool blacklisted = blacklist::is_property_blacklisted(name + "." + short_name); 128 bool blacklisted = blacklist::is_property_blacklisted(name + "." + short_name);
117 // EO properties with keys, with more than one value, or blacklisted, are not 129 // EO properties with keys or blacklisted are not converted into C# properties.
118 // converted into C# properties.
119 // In these cases we refer to the getter method instead of the property. 130 // In these cases we refer to the getter method instead of the property.
120 if ((getter_params > 1) || (setter_params > 1) || (blacklisted)) name += ".Get" + short_name; 131 if ((getter_nkeys > 0) || (setter_nkeys > 0) || (blacklisted)) name += ".Get" + short_name;
121 else if (name_tail == ".get") name += ".Get" + short_name; 132 else if (name_tail == ".get") name += ".Get" + short_name;
122 else if (name_tail == ".set") name += ".Set" + short_name; 133 else if (name_tail == ".set") name += ".Set" + short_name;
123 else name += "." + short_name; 134 else name += "." + short_name;
@@ -219,68 +230,84 @@ struct documentation_generator
219 static std::string syntax_conversion(std::string text, const Eolian_State *state, bool want_beta) 230 static std::string syntax_conversion(std::string text, const Eolian_State *state, bool want_beta)
220 { 231 {
221 std::string new_text, ref; 232 std::string new_text, ref;
222 ::Eolian_Doc_Token token;
223 const char *text_ptr = text.c_str();
224 ::eolian_doc_token_init(&token);
225 ::Eolian_Doc_Token_Type previous_token_type = ::EOLIAN_DOC_TOKEN_UNKNOWN; 233 ::Eolian_Doc_Token_Type previous_token_type = ::EOLIAN_DOC_TOKEN_UNKNOWN;
226 while ((text_ptr = ::eolian_documentation_tokenize(text_ptr, &token)) != NULL) 234 ::Eina_List *paragraphs = ::eolian_documentation_string_split(text.c_str());
235 if (!paragraphs) return new_text;
236 ::Eina_List *data = paragraphs;
237 // For every paragraph
238 do
227 { 239 {
228 std::string token_text, name_tail; 240 char *par = (char *)::eina_list_data_get(data);
229 char *token_text_cstr = ::eolian_doc_token_text_get(&token); 241 const char *text_ptr = par;
230 if (token_text_cstr) 242 ::Eolian_Doc_Token token;
243 ::eolian_doc_token_init(&token);
244 // For every token inside the paragraph
245 while ((text_ptr = ::eolian_documentation_tokenize(text_ptr, &token)) != NULL)
231 { 246 {
232 token_text = token_text_cstr; 247 std::string token_text, name_tail;
233 free(token_text_cstr); 248 char *token_text_cstr = ::eolian_doc_token_text_get(&token);
234 if (token_text.length() > 4) 249 if (token_text_cstr)
235 name_tail = token_text.substr(token_text.length() - 4, 4);
236 }
237 ::Eolian_Doc_Token_Type token_type = ::eolian_doc_token_type_get(&token);
238 switch(token_type)
239 {
240 case ::EOLIAN_DOC_TOKEN_TEXT:
241 // If previous token was a reference and this text token starts with
242 // parentheses, remove them, since the reference will be rendered
243 // with the parentheses already.
244 if ((previous_token_type == ::EOLIAN_DOC_TOKEN_REF) &&
245 (token_text.substr(0, 2) == "()"))
246 token_text = token_text.substr(2, token_text.length() - 2);
247 new_text += token_text;
248 break;
249 case ::EOLIAN_DOC_TOKEN_REF:
250 ref = ref_conversion(&token, state, name_tail, want_beta);
251 if (ref != "")
252 { 250 {
253 if (utils::ends_with(ref, BETA_REF_SUFFIX)) 251 token_text = token_text_cstr;
254 new_text += "<span class=\"text-muted\">" + ref + "</span>"; 252 free(token_text_cstr);
255 else 253 if (token_text.length() > 4)
256 new_text += "<see cref=\"" + ref + "\"/>"; 254 name_tail = token_text.substr(token_text.length() - 4, 4);
257 } 255 }
258 else 256 ::Eolian_Doc_Token_Type token_type = ::eolian_doc_token_type_get(&token);
259 // Unresolved references are passed through. 257 switch(token_type)
260 // They will appear in the docs as plain text, without link, 258 {
261 // but at least they won't be removed by DocFX. 259 case ::EOLIAN_DOC_TOKEN_TEXT:
262 new_text += token_text; 260 // If previous token was a reference and this text token starts with
263 break; 261 // parentheses, remove them, since the reference will be rendered
264 case ::EOLIAN_DOC_TOKEN_MARK_NOTE: 262 // with the parentheses already.
265 new_text += "NOTE: " + token_text; 263 if ((previous_token_type == ::EOLIAN_DOC_TOKEN_REF) &&
266 break; 264 (token_text.substr(0, 2) == "()"))
267 case ::EOLIAN_DOC_TOKEN_MARK_WARNING: 265 token_text = token_text.substr(2, token_text.length() - 2);
268 new_text += "WARNING: " + token_text; 266 new_text += token_text;
269 break; 267 break;
270 case ::EOLIAN_DOC_TOKEN_MARK_REMARK: 268 case ::EOLIAN_DOC_TOKEN_REF:
271 new_text += "REMARK: " + token_text; 269 ref = ref_conversion(&token, state, name_tail, want_beta);
272 break; 270 if (ref != "")
273 case ::EOLIAN_DOC_TOKEN_MARK_TODO: 271 {
274 new_text += "TODO: " + token_text; 272 if (utils::ends_with(ref, BETA_REF_SUFFIX))
275 break; 273 new_text += "<span class=\"text-muted\">" + ref + "</span>";
276 case ::EOLIAN_DOC_TOKEN_MARKUP_MONOSPACE: 274 else
277 new_text += "<c>" + token_text + "</c>"; 275 new_text += "<see cref=\"" + ref + "\"/>";
278 break; 276 }
279 default: 277 else
280 break; 278 // Unresolved references are passed through.
281 } 279 // They will appear in the docs as plain text, without link,
282 previous_token_type = token_type; 280 // but at least they won't be removed by DocFX.
283 } 281 new_text += token_text;
282 break;
283 case ::EOLIAN_DOC_TOKEN_MARK_NOTE:
284 new_text += "<b>NOTE: </b>";
285 break;
286 case ::EOLIAN_DOC_TOKEN_MARK_WARNING:
287 new_text += "<b>WARNING: </b>";
288 break;
289 case ::EOLIAN_DOC_TOKEN_MARK_REMARK:
290 new_text += "<b>REMARK: </b>";
291 break;
292 case ::EOLIAN_DOC_TOKEN_MARK_TODO:
293 new_text += "<b>TODO: </b>";
294 break;
295 case ::EOLIAN_DOC_TOKEN_MARKUP_MONOSPACE:
296 new_text += "<c>" + token_text + "</c>";
297 break;
298 default:
299 break;
300 }
301 previous_token_type = token_type;
302 }
303 // Free this paragraph
304 free(par);
305 // Fetch the next paragraph
306 data = ::eina_list_next(data);
307 // If there's another paragraph afterwards, separate them with a blank line
308 if (data) new_text += "\n\n";
309 } while (data);
310 ::eina_list_free(paragraphs);
284 return new_text; 311 return new_text;
285 } 312 }
286 313
@@ -634,8 +661,24 @@ struct documentation_string_generator
634 661
635} const documentation_string {}; 662} const documentation_string {};
636 663
637} // namespace eolian_mono 664namespace documentation_helpers
665{
666
667template<typename OutputIterator, typename Indent, typename Context>
668bool generate_since_tag_line(OutputIterator sink, attributes::documentation_def const& doc, Indent indentation, Context context)
669{
670 if (doc.since.empty())
671 return true;
638 672
673 return as_generator
674 (
675 indentation << ("/// <para>Since EFL " + doc.since + ".</para>\n")
676 ).generate(sink, attributes::unused, context);
677}
678
679} // documentation_helpers
680
681} // namespace eolian_mono
639 682
640namespace efl { namespace eolian { namespace grammar { 683namespace efl { namespace eolian { namespace grammar {
641 684
diff --git a/src/bin/eolian_mono/eolian/mono/enum_definition.hh b/src/bin/eolian_mono/eolian/mono/enum_definition.hh
index 96595d3..4b07652 100644
--- a/src/bin/eolian_mono/eolian/mono/enum_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/enum_definition.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_ENUM_DEFINITION_HH 16#ifndef EOLIAN_MONO_ENUM_DEFINITION_HH
2#define EOLIAN_MONO_ENUM_DEFINITION_HH 17#define EOLIAN_MONO_ENUM_DEFINITION_HH
3 18
@@ -25,15 +40,22 @@ struct enum_definition_generator
25 if(!name_helpers::open_namespaces(sink, enum_.namespaces, context)) 40 if(!name_helpers::open_namespaces(sink, enum_.namespaces, context))
26 return false; 41 return false;
27 42
28 if(!as_generator(documentation).generate(sink, enum_, context)) 43 std::string enum_name = name_helpers::typedecl_managed_name(enum_);
29 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]";
30 49
31 if(!as_generator 50 if(!as_generator
32 ( 51 (
33 "[Efl.Eo.BindingEntity]\n" 52 documentation(1)
34 "public enum " << string << "\n{\n" 53 << scope_tab << flags_attribute << "\n"
54 << scope_tab << "[Efl.Eo.BindingEntity]\n"
55 << scope_tab << "public enum " << enum_name << "\n"
56 << scope_tab << "{\n"
35 ) 57 )
36 .generate(sink, name_helpers::typedecl_managed_name(enum_), context)) 58 .generate(sink, enum_, context))
37 return false; 59 return false;
38 60
39 // iterate enum fiels 61 // iterate enum fiels
@@ -44,13 +66,14 @@ struct enum_definition_generator
44 auto literal = (*first).value.literal; 66 auto literal = (*first).value.literal;
45 if (!as_generator 67 if (!as_generator
46 ( 68 (
47 documentation << string << " = " << string << ",\n" 69 documentation(2)
70 << scope_tab(2) << string << " = " << string << ",\n"
48 ) 71 )
49 .generate(sink, std::make_tuple(*first, name, literal), context)) 72 .generate(sink, std::make_tuple(*first, name, literal), context))
50 return false; 73 return false;
51 } 74 }
52 75
53 if(!as_generator("}\n").generate(sink, attributes::unused, context)) return false; 76 if(!as_generator(scope_tab << "}\n").generate(sink, attributes::unused, context)) return false;
54 77
55 if(!name_helpers::close_namespaces(sink, enum_.namespaces, context)) 78 if(!name_helpers::close_namespaces(sink, enum_.namespaces, context))
56 return false; 79 return false;
diff --git a/src/bin/eolian_mono/eolian/mono/events.hh b/src/bin/eolian_mono/eolian/mono/events.hh
index 5ca6b1b..b6cb4aa 100644
--- a/src/bin/eolian_mono/eolian/mono/events.hh
+++ b/src/bin/eolian_mono/eolian/mono/events.hh
@@ -1,16 +1,35 @@
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 */
1#ifndef EOLIAN_MONO_EVENTS_HH 16#ifndef EOLIAN_MONO_EVENTS_HH
2#define EOLIAN_MONO_EVENTS_HH 17#define EOLIAN_MONO_EVENTS_HH
3 18
4#include <iterator> 19#include <iterator>
5 20
21#include <Eina.hh>
22
6#include "grammar/generator.hpp" 23#include "grammar/generator.hpp"
7#include "grammar/klass_def.hpp" 24#include "grammar/klass_def.hpp"
8#include "type_impl.hh" // For call_match 25#include "type_match.hh"
9#include "name_helpers.hh" 26#include "name_helpers.hh"
10#include "using_decl.hh" 27#include "using_decl.hh"
11 28
12namespace eolian_mono { 29namespace eolian_mono {
13 30
31namespace eina = efl::eina;
32
14template<typename OutputIterator, typename Context> 33template<typename OutputIterator, typename Context>
15struct unpack_event_args_visitor 34struct unpack_event_args_visitor
16{ 35{
@@ -22,7 +41,7 @@ struct unpack_event_args_visitor
22 typedef bool result_type; 41 typedef bool result_type;
23 bool operator()(grammar::attributes::regular_type_def const& regular) const 42 bool operator()(grammar::attributes::regular_type_def const& regular) const
24 { 43 {
25 std::string const& arg = "evt.Info"; 44 std::string const& arg = "info";
26 std::string arg_type = name_helpers::type_full_managed_name(regular); 45 std::string arg_type = name_helpers::type_full_managed_name(regular);
27 46
28 if (regular.is_struct()) 47 if (regular.is_struct())
@@ -30,7 +49,7 @@ struct unpack_event_args_visitor
30 // Structs are usually passed by pointer to events, like having a ptr<> modifier 49 // Structs are usually passed by pointer to events, like having a ptr<> modifier
31 // Uses implicit conversion from IntPtr 50 // Uses implicit conversion from IntPtr
32 return as_generator( 51 return as_generator(
33 " evt.Info" 52 " info"
34 ).generate(sink, attributes::unused, *context); 53 ).generate(sink, attributes::unused, *context);
35 } 54 }
36 else if (type.is_ptr) 55 else if (type.is_ptr)
@@ -99,24 +118,33 @@ struct unpack_event_args_visitor
99 return as_generator(conversion).generate(sink, attributes::unused, *context); 118 return as_generator(conversion).generate(sink, attributes::unused, *context);
100 }; 119 };
101 120
102 if (eina::optional<bool> b = call_match(match_table, filter_func, accept_func)) 121 if (eina::optional<bool> b = type_match::get_match(match_table, filter_func, accept_func))
103 return *b; 122 return *b;
104 else 123 else
105 { 124 {
106 // Type defined in Eo is passed here. (e.g. enum type defined in Eo) 125 // Type defined in Eo is passed here. (e.g. enum type defined in Eo)
107 // Uses conversion from IntPtr with type casting to the given type. 126 // Uses conversion from IntPtr with type casting to the given type.
108 return as_generator( 127 return as_generator(
109 " (" << arg_type << ")evt.Info" 128 " (" << arg_type << ")info"
110 ).generate(sink, attributes::unused, *context); 129 ).generate(sink, attributes::unused, *context);
111 } 130 }
112 } 131 }
113 bool operator()(grammar::attributes::klass_name const& cls) const 132 bool operator()(grammar::attributes::klass_name const& cls) const
114 { 133 {
115 return as_generator("(Efl.Eo.Globals.CreateWrapperFor(evt.Info) as " + name_helpers::klass_full_concrete_name(cls) + ")").generate(sink, attributes::unused, *context); 134 return as_generator("(Efl.Eo.Globals.CreateWrapperFor(info) as " + name_helpers::klass_full_interface_name(cls) + ")").generate(sink, attributes::unused, *context);
116 } 135 }
117 bool operator()(attributes::complex_type_def const&) const 136 bool operator()(attributes::complex_type_def const& types) const
118 { 137 {
119 return as_generator("new " << eolian_mono::type << "(evt.Info, false, false)").generate(sink, type, *context); 138 if (types.outer.base_type == "iterator")
139 return as_generator("Efl.Eo.Globals.IteratorTo" << eolian_mono::type << "(info)").generate(sink, type, *context);
140 else if (types.outer.base_type == "accessor")
141 return as_generator("Efl.Eo.Globals.AccessorTo" << eolian_mono::type << "(info)").generate(sink, type, *context);
142 else if (types.outer.base_type == "array")
143 return as_generator("Efl.Eo.Globals.NativeArrayTo" << eolian_mono::type << "(info)").generate(sink, type, *context);
144 else if (types.outer.base_type == "list")
145 return as_generator("Efl.Eo.Globals.NativeListTo" << eolian_mono::type << "(info)").generate(sink, type, *context);
146 else
147 return as_generator("new " << eolian_mono::type << "(info, false, false)").generate(sink, type, *context);
120 } 148 }
121}; 149};
122 150
@@ -126,8 +154,8 @@ struct pack_event_info_and_call_visitor
126 mutable OutputIterator sink; 154 mutable OutputIterator sink;
127 Context const* context; 155 Context const* context;
128 attributes::type_def const& type; 156 attributes::type_def const& type;
129 157 std::string library_name;
130 static auto constexpr native_call = "Efl.Eo.Globals.CallEventCallback(this.NativeHandle, desc, info);\n"; 158 std::string evt_c_name;
131 159
132 typedef pack_event_info_and_call_visitor<OutputIterator, Context> visitor_type; 160 typedef pack_event_info_and_call_visitor<OutputIterator, Context> visitor_type;
133 typedef bool result_type; 161 typedef bool result_type;
@@ -141,16 +169,9 @@ struct pack_event_info_and_call_visitor
141 if (regular.is_struct()) 169 if (regular.is_struct())
142 { 170 {
143 return as_generator( 171 return as_generator(
144 indent << "IntPtr info = Marshal.AllocHGlobal(Marshal.SizeOf(e.arg));\n" 172 indent.inc() << "Contract.Requires(e != null, nameof(e));\n"
145 << indent << "try\n" 173 << indent.inc() << "IntPtr info = Marshal.AllocHGlobal(Marshal.SizeOf(e.arg));\n"
146 << indent << "{\n" 174 << indent.inc() << "CallNativeEventCallback(" + library_name + ", \"_" + evt_c_name + "\", info, " << "(p) => Marshal.FreeHGlobal(p));\n"
147 << indent << scope_tab << "Marshal.StructureToPtr(e.arg, info, false);\n"
148 << indent << scope_tab << this->native_call
149 << indent << "}\n"
150 << indent << "finally\n"
151 << indent << "{\n"
152 << indent << scope_tab << "Marshal.FreeHGlobal(info);\n"
153 << indent << "}\n"
154 ).generate(sink, attributes::unused, *context); 175 ).generate(sink, attributes::unused, *context);
155 } 176 }
156 177
@@ -176,18 +197,13 @@ struct pack_event_info_and_call_visitor
176 auto str_accept_func = [&](std::string const& conversion) 197 auto str_accept_func = [&](std::string const& conversion)
177 { 198 {
178 return as_generator( 199 return as_generator(
179 indent << "IntPtr info = Eina.StringConversion.ManagedStringToNativeUtf8Alloc(" << conversion << ");\n" 200 indent.inc() << "Contract.Requires(e != null, nameof(e));\n"
180 << indent << "try\n" 201 << indent.inc() << "IntPtr info = Eina.StringConversion.ManagedStringToNativeUtf8Alloc(" << conversion << ");\n"
181 << indent << "{\n" 202 << indent.inc() << "CallNativeEventCallback(" + library_name + ", \"_" + evt_c_name + "\", info, " << "(p) => Eina.MemoryNative.Free(p));\n"
182 << indent << scope_tab << this->native_call 203 ).generate(sink, attributes::unused, *context);
183 << indent << "}\n"
184 << indent << "finally\n"
185 << indent << "{\n"
186 << indent << scope_tab << "Eina.MemoryNative.Free(info);\n"
187 << indent << "}\n").generate(sink, attributes::unused, *context);
188 }; 204 };
189 205
190 if (eina::optional<bool> b = call_match(str_table, filter_func, str_accept_func)) 206 if (eina::optional<bool> b = type_match::get_match(str_table, filter_func, str_accept_func))
191 return *b; 207 return *b;
192 208
193 match const value_table [] = 209 match const value_table [] =
@@ -200,18 +216,13 @@ struct pack_event_info_and_call_visitor
200 auto value_accept_func = [&](std::string const& conversion) 216 auto value_accept_func = [&](std::string const& conversion)
201 { 217 {
202 return as_generator( 218 return as_generator(
203 indent << "IntPtr info = Eina.PrimitiveConversion.ManagedToPointerAlloc(" << conversion << ");\n" 219 indent.inc() << "Contract.Requires(e != null, nameof(e));\n"
204 << indent << "try\n" 220 << indent.inc() << "IntPtr info = Eina.PrimitiveConversion.ManagedToPointerAlloc(" << conversion << ");\n"
205 << indent << "{\n" 221 << indent.inc() << "CallNativeEventCallback(" + library_name + ", \"_" + evt_c_name + "\", info, " << "(p) => Marshal.FreeHGlobal(p));\n"
206 << indent << scope_tab << this->native_call 222 ).generate(sink, attributes::unused, *context);
207 << indent << "}\n"
208 << indent << "finally\n"
209 << indent << "{\n"
210 << indent << scope_tab << "Marshal.FreeHGlobal(info);\n"
211 << indent << "}\n").generate(sink, attributes::unused, *context);
212 }; 223 };
213 224
214 if (eina::optional<bool> b = call_match(value_table, filter_func, value_accept_func)) 225 if (eina::optional<bool> b = type_match::get_match(value_table, filter_func, value_accept_func))
215 return *b; 226 return *b;
216 227
217 return value_accept_func("e.args"); 228 return value_accept_func("e.args");
@@ -219,14 +230,32 @@ struct pack_event_info_and_call_visitor
219 bool operator()(grammar::attributes::klass_name const&) const 230 bool operator()(grammar::attributes::klass_name const&) const
220 { 231 {
221 auto const& indent = current_indentation(*context); 232 auto const& indent = current_indentation(*context);
222 return as_generator(indent << "IntPtr info = e.arg.NativeHandle;\n" 233 return as_generator(
223 << indent << this->native_call).generate(sink, attributes::unused, *context); 234 indent.inc() << "Contract.Requires(e != null, nameof(e));\n"
235 << indent.inc() << "IntPtr info = e.arg.NativeHandle;\n"
236 << indent.inc() << "CallNativeEventCallback(" << library_name << ", \"_" << evt_c_name << "\", info, null);\n"
237 ).generate(sink, attributes::unused, *context);
224 } 238 }
225 bool operator()(attributes::complex_type_def const&) const 239 bool operator()(attributes::complex_type_def const& type) const
226 { 240 {
227 auto const& indent = current_indentation(*context); 241 auto const& indent = current_indentation(*context);
228 return as_generator(indent << "IntPtr info = e.arg.Handle;\n" 242 bool is_own = type.outer.base_qualifier & attributes::qualifier_info::is_own;
229 << indent << this->native_call).generate(sink, attributes::unused, *context); 243 std::string info_variable;
244
245 if (type.outer.base_type == "iterator")
246 info_variable = std::string("IntPtr info = Efl.Eo.Globals.IEnumerableToIterator(e.arg, ") + (is_own ? "true" : "false") + ");\n";
247 else if (type.outer.base_type == "accessor")
248 info_variable = std::string("IntPtr info = Efl.Eo.Globals.IEnumerableToAccessor(e.arg, ") + (is_own ? "true" : "false") + ");\n";
249 else if (type.outer.base_type == "array")
250 info_variable = std::string("IntPtr info = Efl.Eo.Globals.IListToNativeArray(e.arg, ") + (is_own ? "true" : "false") + ");\n";
251 else if (type.outer.base_type == "list")
252 info_variable = std::string("IntPtr info = Efl.Eo.Globals.IListToNativeList(e.arg, ") + (is_own ? "true" : "false") + ");\n";
253 else
254 info_variable = "IntPtr info = e.arg.Handle;\n";
255 return as_generator(indent.inc() << "Contract.Requires(e != null, nameof(e));\n"
256 << indent.inc() << info_variable
257 << indent.inc() << "CallNativeEventCallback(" << library_name << ", \"_" << evt_c_name << "\", info, null);\n"
258 ).generate(sink, attributes::unused, *context);
230 } 259 }
231}; 260};
232 261
@@ -247,7 +276,7 @@ struct event_argument_wrapper_generator
247 276
248 std::string evt_name = name_helpers::managed_event_name(evt.name); 277 std::string evt_name = name_helpers::managed_event_name(evt.name);
249 278
250 if (!as_generator("/// <summary>Event argument wrapper for event <see cref=\"" 279 if (!as_generator(scope_tab << "/// <summary>Event argument wrapper for event <see cref=\""
251 << join_namespaces(evt.klass.namespaces, '.', managed_namespace) 280 << join_namespaces(evt.klass.namespaces, '.', managed_namespace)
252 << klass_interface_name(evt.klass) << "." << evt_name << "\"/>.\n" 281 << klass_interface_name(evt.klass) << "." << evt_name << "\"/>.\n"
253 ).generate(sink, nullptr, context)) 282 ).generate(sink, nullptr, context))
@@ -270,7 +299,7 @@ struct event_argument_wrapper_generator
270 { 299 {
271 300
272 if (!as_generator( 301 if (!as_generator(
273 lit("/// <para>Since EFL ") << evt.documentation.since << ".</para>\n" 302 scope_tab << lit("/// <para>Since EFL ") << evt.documentation.since << ".</para>\n"
274 ).generate(sink, nullptr, context)) 303 ).generate(sink, nullptr, context))
275 return false; 304 return false;
276 } 305 }
@@ -282,23 +311,23 @@ struct event_argument_wrapper_generator
282 } 311 }
283 } 312 }
284 313
285 if (!as_generator(lit("/// </summary>\n") 314 if (!as_generator(scope_tab << lit("/// </summary>\n")
286 << "[Efl.Eo.BindingEntity]\n" 315 << scope_tab << "[Efl.Eo.BindingEntity]\n"
287 << "public class " << name_helpers::managed_event_args_short_name(evt) << " : EventArgs {\n" 316 << scope_tab << "public class " << name_helpers::managed_event_args_short_name(evt) << " : EventArgs {\n"
288 << scope_tab << "/// <summary>Actual event payload.\n" 317 << scope_tab(2) << "/// <summary>Actual event payload.\n"
289 ).generate(sink, nullptr, context)) 318 ).generate(sink, nullptr, context))
290 return false; 319 return false;
291 320
292 if (since != "") 321 if (since != "")
293 { 322 {
294 if (!as_generator(scope_tab << "/// <para>Since EFL " << since << ".</para>\n").generate(sink, nullptr, context)) 323 if (!as_generator(scope_tab(2) << "/// <para>Since EFL " << since << ".</para>\n").generate(sink, nullptr, context))
295 return false; 324 return false;
296 } 325 }
297 326
298 if (!as_generator(scope_tab << "/// </summary>\n" 327 if (!as_generator(scope_tab(2) << "/// </summary>\n"
299 << scope_tab << "/// <value>" << documentation_string << "</value>\n" 328 << scope_tab(2) << "/// <value>" << documentation_string << "</value>\n"
300 << scope_tab << "public " << type << " arg { get; set; }\n" 329 << scope_tab(2) << "public " << type << " arg { get; set; }\n"
301 << "}\n\n" 330 << scope_tab << "}\n\n"
302 ).generate(sink, std::make_tuple(evt.documentation.summary, *etype), context)) 331 ).generate(sink, std::make_tuple(evt.documentation.summary, *etype), context))
303 return false; 332 return false;
304 333
@@ -325,14 +354,14 @@ struct event_declaration_generator
325 if (evt.type.is_engaged()) 354 if (evt.type.is_engaged())
326 wrapper_args_type = "<" + name_helpers::managed_event_args_name(evt) + ">"; 355 wrapper_args_type = "<" + name_helpers::managed_event_args_name(evt) + ">";
327 356
328 if (!as_generator(documentation(1)) 357 if (!as_generator(documentation(2))
329 .generate(sink, evt, context)) return false; 358 .generate(sink, evt, context)) return false;
330 if (evt.type.is_engaged()) 359 if (evt.type.is_engaged())
331 if (!as_generator( 360 if (!as_generator(
332 scope_tab << "/// <value><see cref=\"" << name_helpers::managed_event_args_name(evt) << "\"/></value>\n" 361 scope_tab(2) << "/// <value><see cref=\"" << name_helpers::managed_event_args_name(evt) << "\"/></value>\n"
333 ).generate(sink, evt, context)) return false; 362 ).generate(sink, evt, context)) return false;
334 if (!as_generator( 363 if (!as_generator(
335 scope_tab << "event EventHandler" << wrapper_args_type << " " << evt_name << ";\n" 364 scope_tab(2) << "event EventHandler" << wrapper_args_type << " " << evt_name << ";\n"
336 ).generate(sink, evt, context)) 365 ).generate(sink, evt, context))
337 return false; 366 return false;
338 367
@@ -352,6 +381,7 @@ struct event_definition_generator
352 if (blacklist::is_event_blacklisted(evt, context)) 381 if (blacklist::is_event_blacklisted(evt, context))
353 return true; 382 return true;
354 383
384 auto library_name = context_find_tag<library_context>(context).actual_library_name(klass.filename);
355 std::string managed_evt_name = name_helpers::managed_event_name(evt.name); 385 std::string managed_evt_name = name_helpers::managed_event_name(evt.name);
356 auto const& indent = current_indentation(context); 386 auto const& indent = current_indentation(context);
357 387
@@ -381,7 +411,7 @@ struct event_definition_generator
381 if (!etype.is_engaged()) 411 if (!etype.is_engaged())
382 { 412 {
383 auto event_call_site_sink = std::back_inserter(event_native_call); 413 auto event_call_site_sink = std::back_inserter(event_native_call);
384 if (!as_generator(indent.inc().inc() << "Efl.Eo.Globals.CallEventCallback(this.NativeHandle, desc, IntPtr.Zero);\n") 414 if (!as_generator(indent.inc().inc().inc() << "CallNativeEventCallback(" << library_name << ", \"_" << utils::to_uppercase(evt.c_name) << "\", IntPtr.Zero, null);\n")
385 .generate(event_call_site_sink, attributes::unused, context)) 415 .generate(event_call_site_sink, attributes::unused, context))
386 return false; 416 return false;
387 } 417 }
@@ -396,25 +426,25 @@ struct event_definition_generator
396 426
397 auto sub_context = change_indentation(indent.inc().inc(), context); 427 auto sub_context = change_indentation(indent.inc().inc(), context);
398 428
399 if (!as_generator(wrapper_args_type << " args = new " << wrapper_args_type << "();\n" 429 if (!as_generator(", info => new " << wrapper_args_type << "{ "
400 << scope_tab(6) << "args.arg = ").generate(arg_initializer_sink, attributes::unused, context)) 430 << "arg = ").generate(arg_initializer_sink, attributes::unused, context))
401 return false; 431 return false;
402 if (!(*etype).original_type.visit(unpack_event_args_visitor<decltype(arg_initializer_sink), decltype(sub_context)>{arg_initializer_sink, &sub_context, *etype})) 432 if (!(*etype).original_type.visit(unpack_event_args_visitor<decltype(arg_initializer_sink), decltype(sub_context)>{arg_initializer_sink, &sub_context, *etype}))
403 return false; 433 return false;
404 434
405 if (!(*etype).original_type.visit(pack_event_info_and_call_visitor<decltype(event_call_site_sink), decltype(sub_context)>{event_call_site_sink, &sub_context, *etype})) 435 if (!(*etype).original_type.visit(pack_event_info_and_call_visitor<decltype(event_call_site_sink), decltype(sub_context)>{event_call_site_sink, &sub_context, *etype, library_name, utils::to_uppercase(evt.c_name)}))
406 return false; 436 return false;
407 437
408 arg_initializer += ";\n"; 438 arg_initializer += " }";
409 439
410 event_args = arg_initializer; 440 event_args = arg_initializer;
411 } 441 }
412 442
413 if(!as_generator(documentation(1)).generate(sink, evt, context)) 443 if(!as_generator(documentation(2)).generate(sink, evt, context))
414 return false; 444 return false;
415 if (etype.is_engaged()) 445 if (etype.is_engaged())
416 if (!as_generator( 446 if (!as_generator(
417 scope_tab << "/// <value><see cref=\"" << wrapper_args_type << "\"/></value>\n" 447 scope_tab(2) << "/// <value><see cref=\"" << wrapper_args_type << "\"/></value>\n"
418 ).generate(sink, evt, context)) return false; 448 ).generate(sink, evt, context)) return false;
419 449
420 // Visible event declaration. Either a regular class member or an explicit interface implementation. 450 // Visible event declaration. Either a regular class member or an explicit interface implementation.
@@ -422,7 +452,7 @@ struct event_definition_generator
422 { 452 {
423 // Public event implementation. 453 // Public event implementation.
424 if (!as_generator( 454 if (!as_generator(
425 scope_tab << (!use_explicit_impl ? "public " : " ") << "event EventHandler" << wrapper_args_template << " " << (use_explicit_impl ? (klass_name + ".") : "") << managed_evt_name << "\n" 455 scope_tab(2) << (!use_explicit_impl ? "public " : " ") << "event EventHandler" << wrapper_args_template << " " << (use_explicit_impl ? (klass_name + ".") : "") << managed_evt_name << "\n"
426 ).generate(sink, attributes::unused, context)) 456 ).generate(sink, attributes::unused, context))
427 return false; 457 return false;
428 } 458 }
@@ -435,7 +465,7 @@ struct event_definition_generator
435 visibility += "new "; 465 visibility += "new ";
436 466
437 if (!as_generator( 467 if (!as_generator(
438 scope_tab << visibility << "event EventHandler" << wrapper_args_template << " " << wrapper_evt_name << "\n" 468 scope_tab(2) << visibility << "event EventHandler" << wrapper_args_template << " " << wrapper_evt_name << "\n"
439 ).generate(sink, attributes::unused, context)) 469 ).generate(sink, attributes::unused, context))
440 return false; 470 return false;
441 } 471 }
@@ -459,9 +489,10 @@ struct event_definition_generator
459 { 489 {
460 auto library_name = context_find_tag<library_context>(context).actual_library_name(klass.filename); 490 auto library_name = context_find_tag<library_context>(context).actual_library_name(klass.filename);
461 std::string upper_c_name = utils::to_uppercase(evt.c_name); 491 std::string upper_c_name = utils::to_uppercase(evt.c_name);
492 bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
462 493
463 if (!as_generator( 494 if (!as_generator(
464 scope_tab << "/// <summary>Method to raise event "<< event_name << ".\n" 495 scope_tab(2) << "/// <summary>Method to raise event "<< event_name << ".\n"
465 ).generate(sink, nullptr, context)) 496 ).generate(sink, nullptr, context))
466 return false; 497 return false;
467 498
@@ -480,7 +511,7 @@ struct event_definition_generator
480 { 511 {
481 512
482 if (!as_generator( 513 if (!as_generator(
483 scope_tab << "/// <para>Since EFL " << evt.documentation.since << ".</para>\n" 514 scope_tab(2) << "/// <para>Since EFL " << evt.documentation.since << ".</para>\n"
484 ).generate(sink, nullptr, context)) 515 ).generate(sink, nullptr, context))
485 return false; 516 return false;
486 } 517 }
@@ -492,20 +523,22 @@ struct event_definition_generator
492 } 523 }
493 } 524 }
494 525
526 // Close summary
527 if (!as_generator(scope_tab(2) << "/// </summary>\n").generate(sink, nullptr, context))
528 return false;
529
530 if (evt.type.is_engaged())
531 {
532 if (!as_generator(scope_tab(2) << "/// <param name=\"e\">Event to raise.</param>\n"
533 ).generate(sink, nullptr, context))
534 return false;
535 }
536
495 if (!as_generator( 537 if (!as_generator(
496 scope_tab << "/// </summary>\n" 538 scope_tab(2) << (is_concrete ? "public" : "protected virtual") << " void On" << event_name << "(" << (!evt.type.is_engaged() ? "" : event_args_type + " e") << ")\n"
497 << scope_tab << "/// <param name=\"e\">Event to raise.</param>\n" 539 << scope_tab(2) << "{\n"
498 << scope_tab << "public void On" << event_name << "(" << event_args_type << " e)\n"
499 << scope_tab << "{\n"
500 << scope_tab << scope_tab << "var key = \"_" << upper_c_name << "\";\n"
501 << scope_tab << scope_tab << "IntPtr desc = Efl.EventDescription.GetNative(" << library_name << ", key);\n"
502 << scope_tab << scope_tab << "if (desc == IntPtr.Zero)\n"
503 << scope_tab << scope_tab << "{\n"
504 << scope_tab << scope_tab << scope_tab << "Eina.Log.Error($\"Failed to get native event {key}\");\n"
505 << scope_tab << scope_tab << scope_tab << "return;\n"
506 << scope_tab << scope_tab << "}\n\n"
507 << event_native_call 540 << event_native_call
508 << scope_tab << "}\n\n" 541 << scope_tab(2) << "}\n\n"
509 ).generate(sink, nullptr, context)) 542 ).generate(sink, nullptr, context))
510 return false; 543 return false;
511 544
@@ -523,35 +556,20 @@ struct event_definition_generator
523 attributes::klass_def klass(get_klass(evt.klass, unit), unit); 556 attributes::klass_def klass(get_klass(evt.klass, unit), unit);
524 auto library_name = context_find_tag<library_context>(context).actual_library_name(klass.filename); 557 auto library_name = context_find_tag<library_context>(context).actual_library_name(klass.filename);
525 return as_generator( 558 return as_generator(
526 scope_tab << "{\n" 559 scope_tab(2) << "{\n"
527 << scope_tab << scope_tab << "add\n" 560 << scope_tab(2) << scope_tab << "add\n"
528 << scope_tab << scope_tab << "{\n" 561 << scope_tab(2) << scope_tab << "{\n"//evt.type.is_engaged()
529 << scope_tab << scope_tab << scope_tab << "Efl.EventCb callerCb = (IntPtr data, ref Efl.Event.NativeStruct evt) =>\n" 562 << scope_tab(2) << scope_tab << scope_tab << "Efl.EventCb callerCb = GetInternalEventCallback(value"
530 << scope_tab << scope_tab << scope_tab << "{\n" 563 << (evt.type.is_engaged() ? event_args : "") << ");\n"
531 << scope_tab << scope_tab << scope_tab << scope_tab << "var obj = Efl.Eo.Globals.WrapperSupervisorPtrToManaged(data).Target;\n" 564 << scope_tab(2) << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n"
532 << scope_tab << scope_tab << scope_tab << scope_tab << "if (obj != null)\n" 565 << scope_tab(2) << scope_tab << scope_tab << "AddNativeEventHandler(" << library_name << ", key, callerCb, value);\n"
533 << scope_tab << scope_tab << scope_tab << scope_tab << "{\n" 566 << scope_tab(2) << scope_tab << "}\n\n"
534 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << event_args 567 << scope_tab(2) << scope_tab << "remove\n"
535 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "try\n" 568 << scope_tab(2) << scope_tab << "{\n"
536 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "{\n" 569 << scope_tab(2) << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n"
537 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "value?.Invoke(obj, args);\n" 570 << scope_tab(2) << scope_tab << scope_tab << "RemoveNativeEventHandler(" << library_name << ", key, value);\n"
538 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "}\n" 571 << scope_tab(2) << scope_tab << "}\n"
539 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "catch (Exception e)\n" 572 << scope_tab(2) << "}\n\n"
540 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "{\n"
541 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "Eina.Log.Error(e.ToString());\n"
542 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "Eina.Error.Set(Eina.Error.UNHANDLED_EXCEPTION);\n"
543 << scope_tab << scope_tab << scope_tab << scope_tab << scope_tab << "}\n"
544 << scope_tab << scope_tab << scope_tab << scope_tab << "}\n"
545 << scope_tab << scope_tab << scope_tab << "};\n\n"
546 << scope_tab << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n"
547 << scope_tab << scope_tab << scope_tab << "AddNativeEventHandler(" << library_name << ", key, callerCb, value);\n"
548 << scope_tab << scope_tab << "}\n\n"
549 << scope_tab << scope_tab << "remove\n"
550 << scope_tab << scope_tab << "{\n"
551 << scope_tab << scope_tab << scope_tab << "string key = \"_" << upper_c_name << "\";\n"
552 << scope_tab << scope_tab << scope_tab << "RemoveNativeEventHandler(" << library_name << ", key, value);\n"
553 << scope_tab << scope_tab << "}\n"
554 << scope_tab << "}\n\n"
555 ).generate(sink, attributes::unused, context); 573 ).generate(sink, attributes::unused, context);
556 } 574 }
557}; 575};
diff --git a/src/bin/eolian_mono/eolian/mono/function_declaration.hh b/src/bin/eolian_mono/eolian/mono/function_declaration.hh
index 734700c..d209f06 100644
--- a/src/bin/eolian_mono/eolian/mono/function_declaration.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_declaration.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_FUNCTION_DECLARATION_HH 16#ifndef EOLIAN_MONO_FUNCTION_DECLARATION_HH
2#define EOLIAN_MONO_FUNCTION_DECLARATION_HH 17#define EOLIAN_MONO_FUNCTION_DECLARATION_HH
3 18
@@ -27,11 +42,11 @@ struct function_declaration_generator
27 if(f.scope != attributes::member_scope::scope_public) 42 if(f.scope != attributes::member_scope::scope_public)
28 return true; 43 return true;
29 44
30 if(!as_generator(documentation(1)).generate(sink, f, context)) 45 if(!as_generator(documentation(2)).generate(sink, f, context))
31 return false; 46 return false;
32 47
33 return as_generator 48 return as_generator
34 (scope_tab << eolian_mono::type(true) << " " << string << "(" << (parameter % ", ") << ");\n\n") 49 (scope_tab(2) << eolian_mono::type(true) << " " << string << "(" << (parameter % ", ") << ");\n\n")
35 .generate(sink, std::make_tuple(f.return_type, name_helpers::managed_method_name(f), f.parameters), context); 50 .generate(sink, std::make_tuple(f.return_type, name_helpers::managed_method_name(f), f.parameters), context);
36 } 51 }
37}; 52};
diff --git a/src/bin/eolian_mono/eolian/mono/function_definition.hh b/src/bin/eolian_mono/eolian/mono/function_definition.hh
index d17ac56..3c30cdd 100644
--- a/src/bin/eolian_mono/eolian/mono/function_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_definition.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_FUNCTION_DEFINITION_HH 16#ifndef EOLIAN_MONO_FUNCTION_DEFINITION_HH
2#define EOLIAN_MONO_FUNCTION_DEFINITION_HH 17#define EOLIAN_MONO_FUNCTION_DEFINITION_HH
3 18
@@ -61,7 +76,7 @@ struct native_function_definition_generator
61 if(!as_generator 76 if(!as_generator
62 ( 77 (
63 indent << eolian_mono::marshall_annotation(true) << "\n" 78 indent << eolian_mono::marshall_annotation(true) << "\n"
64 << indent << "public delegate " 79 << indent << "internal delegate "
65 << eolian_mono::marshall_type(true) 80 << eolian_mono::marshall_type(true)
66 << " " 81 << " "
67 << string << "_api_delegate(" << (f.is_static ? "" : "System.IntPtr obj") 82 << string << "_api_delegate(" << (f.is_static ? "" : "System.IntPtr obj")
@@ -76,7 +91,7 @@ struct native_function_definition_generator
76 91
77 // Delegate holder (so it can't be collected). 92 // Delegate holder (so it can't be collected).
78 if(!as_generator 93 if(!as_generator
79 (indent << "public static readonly Efl.Eo.FunctionWrapper<" << string << "_api_delegate> " << string << "_ptr = new Efl.Eo.FunctionWrapper<" 94 (indent << "internal static readonly Efl.Eo.FunctionWrapper<" << string << "_api_delegate> " << string << "_ptr = new Efl.Eo.FunctionWrapper<"
80 << string << "_api_delegate>(Module, \"" << string << "\");\n\n") 95 << string << "_api_delegate>(Module, \"" << string << "\");\n\n")
81 .generate(sink, std::make_tuple(f.c_name, f.c_name, f.c_name, f.c_name), context)) 96 .generate(sink, std::make_tuple(f.c_name, f.c_name, f.c_name, f.c_name), context))
82 return false; 97 return false;
@@ -108,7 +123,8 @@ struct native_function_definition_generator
108 self = ""; 123 self = "";
109 124
110 if(!as_generator 125 if(!as_generator
111 (indent << "private static " 126 (indent << "[SuppressMessage(\"Microsoft.Reliability\", \"CA2000:DisposeObjectsBeforeLosingScope\", Justification = \"The instantiated objects can be stored in the called Managed API method.\")]\n"
127 << indent << "private static "
112 << eolian_mono::marshall_type(true) << " " 128 << eolian_mono::marshall_type(true) << " "
113 << string 129 << string
114 << "(System.IntPtr obj, System.IntPtr pd" 130 << "(System.IntPtr obj, System.IntPtr pd"
@@ -190,7 +206,7 @@ struct function_definition_generator
190 return false; 206 return false;
191 207
192 if(!as_generator 208 if(!as_generator
193 (documentation(1)).generate(sink, f, context)) 209 (documentation(2)).generate(sink, f, context))
194 return false; 210 return false;
195 211
196 std::string self = "this.NativeHandle"; 212 std::string self = "this.NativeHandle";
@@ -203,15 +219,15 @@ struct function_definition_generator
203 self = ""; 219 self = "";
204 220
205 if(!as_generator 221 if(!as_generator
206 (scope_tab << eolian_mono::function_scope_get(f) << ((do_super && !f.is_static) ? "virtual " : "") << (f.is_static ? "static " : "") << return_type << " " << string << "(" << (parameter % ", ") 222 (scope_tab(2) << eolian_mono::function_scope_get(f) << ((do_super && !f.is_static) ? "virtual " : "") << (f.is_static ? "static " : "") << return_type << " " << string << "(" << (parameter % ", ")
207 << ") {\n" 223 << ") {\n"
208 << scope_tab(2) << eolian_mono::function_definition_preamble() 224 << scope_tab(3) << eolian_mono::function_definition_preamble()
209 << klass_full_native_inherit_name(f.klass) << "." << string << "_ptr.Value.Delegate(" 225 << klass_full_native_inherit_name(f.klass) << "." << string << "_ptr.Value.Delegate("
210 << self 226 << self
211 << ((!f.is_static && (f.parameters.size() > 0)) ? "," : "") 227 << ((!f.is_static && (f.parameters.size() > 0)) ? ", " : "")
212 << (argument_invocation % ", ") << ");\n" 228 << (argument_invocation % ", ") << ");\n"
213 << scope_tab(2) << eolian_mono::function_definition_epilogue() 229 << scope_tab(3) << eolian_mono::function_definition_epilogue()
214 << scope_tab(1) << "}\n\n") 230 << scope_tab(2) << "}\n\n")
215 .generate(sink, std::make_tuple(name_helpers::managed_method_name(f), f.parameters, f, f.c_name, f.parameters, f), context)) 231 .generate(sink, std::make_tuple(name_helpers::managed_method_name(f), f.parameters, f, f.c_name, f.parameters, f), context))
216 return false; 232 return false;
217 233
@@ -268,11 +284,11 @@ struct property_extension_method_definition_generator
268 if (property.setter.is_engaged()) 284 if (property.setter.is_engaged())
269 { 285 {
270 attributes::type_def prop_type = property.setter->parameters[0].type; 286 attributes::type_def prop_type = property.setter->parameters[0].type;
271 if (!as_generator(scope_tab << "public static Efl.BindableProperty<" << type(true) << "> " << managed_name << "<T>(this Efl.Ui.ItemFactory<T> fac, Efl.Csharp.ExtensionTag<" 287 if (!as_generator(scope_tab(2) << "public static Efl.BindableProperty<" << type(true) << "> " << managed_name << "<T>(this Efl.Ui.ItemFactory<T> fac, Efl.Csharp.ExtensionTag<"
272 << name_helpers::klass_full_concrete_or_interface_name(cls) 288 << name_helpers::klass_full_concrete_or_interface_name(cls)
273 << ", T>magic = null) where T : " << name_helpers::klass_full_concrete_or_interface_name(cls) << " {\n" 289 << ", T>magic = null) where T : " << name_helpers::klass_full_concrete_or_interface_name(cls) << " {\n"
274 << scope_tab << scope_tab << "return new Efl.BindableProperty<" << type(true) << ">(\"" << property.name << "\", fac);\n" 290 << scope_tab(2) << scope_tab << "return new Efl.BindableProperty<" << type(true) << ">(\"" << property.name << "\", fac);\n"
275 << scope_tab << "}\n\n" 291 << scope_tab(2) << "}\n\n"
276 ).generate(sink, std::make_tuple(prop_type, prop_type), context)) 292 ).generate(sink, std::make_tuple(prop_type, prop_type), context))
277 return false; 293 return false;
278 } 294 }
@@ -285,11 +301,12 @@ struct property_extension_method_definition_generator
285 if (property.setter.is_engaged()) 301 if (property.setter.is_engaged())
286 { 302 {
287 attributes::type_def prop_type = property.setter->parameters[0].type; 303 attributes::type_def prop_type = property.setter->parameters[0].type;
288 if (!as_generator(scope_tab << "public static Efl.BindableProperty<" << type(true) << "> " << managed_name << "<T>(this Efl.BindablePart<T> part, Efl.Csharp.ExtensionTag<" 304 if (!as_generator(scope_tab(2) << "public static Efl.BindableProperty<" << type(true) << "> " << managed_name << "<T>(this Efl.BindablePart<T> part, Efl.Csharp.ExtensionTag<"
289 << name_helpers::klass_full_concrete_or_interface_name(cls) 305 << name_helpers::klass_full_concrete_or_interface_name(cls)
290 << ", T>magic = null) where T : " << name_helpers::klass_full_concrete_or_interface_name(cls) << " {\n" 306 << ", T>magic = null) where T : " << name_helpers::klass_full_concrete_or_interface_name(cls) << " {\n"
291 << scope_tab << scope_tab << "return new Efl.BindableProperty<" << type(true) << ">(part.PartName, \"" << property.name << "\", part.Binder);\n" 307 << scope_tab(2) << scope_tab << "Contract.Requires(part != null, nameof(part));\n"
292 << scope_tab << "}\n\n" 308 << scope_tab(2) << scope_tab << "return new Efl.BindableProperty<" << type(true) << ">(part.PartName, \"" << property.name << "\", part.Binder);\n"
309 << scope_tab(2) << "}\n\n"
293 ).generate(sink, std::make_tuple(prop_type, prop_type), context)) 310 ).generate(sink, std::make_tuple(prop_type, prop_type), context))
294 return false; 311 return false;
295 } 312 }
@@ -413,6 +430,10 @@ struct property_wrapper_definition_generator
413 if (is_interface && (!is_get_public && !is_set_public)) 430 if (is_interface && (!is_get_public && !is_set_public))
414 return true; 431 return true;
415 432
433 // Do not generate set-only proeprty
434 if (property.setter.is_engaged() && !property.getter.is_engaged())
435 return true;
436
416 // C# interface members are declared automatically as public 437 // C# interface members are declared automatically as public
417 if (is_interface) 438 if (is_interface)
418 { 439 {
@@ -440,8 +461,8 @@ struct property_wrapper_definition_generator
440 if (parameters.size() == 1) 461 if (parameters.size() == 1)
441 { 462 {
442 if (!as_generator( 463 if (!as_generator(
443 documentation(1) 464 documentation(2)
444 << scope_tab << scope << (is_static ? "static " : "") << type(true) << " " << managed_name << " {\n" 465 << scope_tab(2) << scope << (is_static ? "static " : "") << type(true) << " " << managed_name << " {\n"
445 ).generate(sink, std::make_tuple(property, parameters[0].type), context)) 466 ).generate(sink, std::make_tuple(property, parameters[0].type), context))
446 return false; 467 return false;
447 } 468 }
@@ -449,8 +470,8 @@ struct property_wrapper_definition_generator
449 { 470 {
450 if (!as_generator 471 if (!as_generator
451 ( 472 (
452 documentation(1) 473 documentation(2)
453 << scope_tab << scope << (is_static ? "static (" : "(") 474 << scope_tab(2) << scope << (is_static ? "static (" : "(")
454 << (attribute_reorder<1, -1>(type(true) /*<< " " << argument*/) % ", ") << ") " 475 << (attribute_reorder<1, -1>(type(true) /*<< " " << argument*/) % ", ") << ") "
455 << managed_name << " {\n" 476 << managed_name << " {\n"
456 ).generate(sink, std::make_tuple(property, parameters), context)) 477 ).generate(sink, std::make_tuple(property, parameters), context))
@@ -460,14 +481,14 @@ struct property_wrapper_definition_generator
460 if (property.getter.is_engaged() && is_interface) 481 if (property.getter.is_engaged() && is_interface)
461 { 482 {
462 if (is_get_public) 483 if (is_get_public)
463 if (!as_generator(scope_tab << scope_tab << set_scope << "get;\n" 484 if (!as_generator(scope_tab(2) << scope_tab << set_scope << "get;\n"
464 ).generate(sink, attributes::unused, context)) 485 ).generate(sink, attributes::unused, context))
465 return false; 486 return false;
466 } 487 }
467 else if (property.getter.is_engaged() && get_params == 0/*parameters.size() == 1 && property.getter.is_engaged()*/) 488 else if (property.getter.is_engaged() && get_params == 0/*parameters.size() == 1 && property.getter.is_engaged()*/)
468 { 489 {
469 if (!as_generator 490 if (!as_generator
470 (scope_tab << scope_tab << get_scope 491 (scope_tab(2) << scope_tab << get_scope
471 << "get " << "{ return " + name_helpers::managed_method_name(*property.getter) + "(); }\n" 492 << "get " << "{ return " + name_helpers::managed_method_name(*property.getter) + "(); }\n"
472 ).generate(sink, attributes::unused, context)) 493 ).generate(sink, attributes::unused, context))
473 return false; 494 return false;
@@ -475,16 +496,16 @@ struct property_wrapper_definition_generator
475 else if (parameters.size() >= 1 && property.getter) 496 else if (parameters.size() >= 1 && property.getter)
476 { 497 {
477 if (!as_generator 498 if (!as_generator
478 (scope_tab << scope_tab << get_scope << "get " 499 (scope_tab(2) << scope_tab << get_scope << "get "
479 << "{\n" 500 << "{\n"
480 << *attribute_reorder<1, -1, 1> 501 << *attribute_reorder<1, -1, 1>
481 (scope_tab(3) << type(true) << " _out_" 502 (scope_tab(4) << type(true) << " _out_"
482 << argument(false) << " = default(" << type(true) << ");\n" 503 << argument(false) << " = default(" << type(true) << ");\n"
483 ) 504 )
484 << scope_tab(3) << name_helpers::managed_method_name(*property.getter) 505 << scope_tab(4) << name_helpers::managed_method_name(*property.getter)
485 << "(" << (("out _out_" << argument(false)) % ",") << ");\n" 506 << "(" << (("out _out_" << argument(false)) % ", ") << ");\n"
486 << scope_tab(3) << "return (" << (("_out_"<< argument(false)) % ",") << ");\n" 507 << scope_tab(4) << "return (" << (("_out_"<< argument(false)) % ", ") << ");\n"
487 << scope_tab(2) << "}" << "\n" 508 << scope_tab(3) << "}" << "\n"
488 ).generate(sink, std::make_tuple(parameters, parameters, parameters), context)) 509 ).generate(sink, std::make_tuple(parameters, parameters, parameters), context))
489 return false; 510 return false;
490 } 511 }
@@ -505,24 +526,24 @@ struct property_wrapper_definition_generator
505 if (property.setter.is_engaged() && is_interface) 526 if (property.setter.is_engaged() && is_interface)
506 { 527 {
507 if (is_set_public) 528 if (is_set_public)
508 if (!as_generator(scope_tab << scope_tab << set_scope << "set;\n" 529 if (!as_generator(scope_tab(2) << scope_tab << set_scope << "set;\n"
509 ).generate(sink, attributes::unused, context)) 530 ).generate(sink, attributes::unused, context))
510 return false; 531 return false;
511 } 532 }
512 else if (parameters.size() == 1 && property.setter.is_engaged()) 533 else if (parameters.size() == 1 && property.setter.is_engaged())
513 { 534 {
514 if (!as_generator(scope_tab << scope_tab << set_scope << "set " << "{ " + name_helpers::managed_method_name(*property.setter) + "(" + dir_mod + "value); }\n" 535 if (!as_generator(scope_tab(2) << scope_tab << set_scope << "set " << "{ " + name_helpers::managed_method_name(*property.setter) + "(" + dir_mod + "value); }\n"
515 ).generate(sink, attributes::unused, context)) 536 ).generate(sink, attributes::unused, context))
516 return false; 537 return false;
517 } 538 }
518 else if (parameters.size() > 1 && property.setter.is_engaged()) 539 else if (parameters.size() > 1 && property.setter.is_engaged())
519 { 540 {
520 if (!as_generator(scope_tab << scope_tab << set_scope << "set " << ("{ " + name_helpers::managed_method_name(*property.setter) + "(" + dir_mod) << ((" value.Item" << counter(1)) % ", ") << "); }" << "\n" 541 if (!as_generator(scope_tab(2) << scope_tab << set_scope << "set " << ("{ " + name_helpers::managed_method_name(*property.setter) + "(" + dir_mod) << ((" value.Item" << counter(1)) % ", ") << "); }" << "\n"
521 ).generate(sink, parameters, context)) 542 ).generate(sink, parameters, context))
522 return false; 543 return false;
523 } 544 }
524 545
525 if (!as_generator(scope_tab << "}\n\n").generate(sink, attributes::unused, context)) 546 if (!as_generator(scope_tab(2) << "}\n\n").generate(sink, attributes::unused, context))
526 return false; 547 return false;
527 548
528 return true; 549 return true;
diff --git a/src/bin/eolian_mono/eolian/mono/function_helpers.hh b/src/bin/eolian_mono/eolian/mono/function_helpers.hh
index 26146f7..a70df96 100644
--- a/src/bin/eolian_mono/eolian/mono/function_helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_helpers.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_FUNCTION_DEFINITION_HELPERS_HH 16#ifndef EOLIAN_MONO_FUNCTION_DEFINITION_HELPERS_HH
2#define EOLIAN_MONO_FUNCTION_DEFINITION_HELPERS_HH 17#define EOLIAN_MONO_FUNCTION_DEFINITION_HELPERS_HH
3 18
@@ -102,7 +117,7 @@ struct function_definition_epilogue_generator
102 "Eina.Error.RaiseIfUnhandledException();\n" 117 "Eina.Error.RaiseIfUnhandledException();\n"
103 << *(convert_out_assign) 118 << *(convert_out_assign)
104 << *(convert_in_ptr_assign) 119 << *(convert_in_ptr_assign)
105 << scope_tab(2) << convert_return << "\n" 120 << scope_tab(3) << convert_return << "\n"
106 ).generate(sink, std::make_tuple(f.parameters, f.parameters, f.return_type), context)) 121 ).generate(sink, std::make_tuple(f.parameters, f.parameters, f.return_type), context))
107 return false; 122 return false;
108 123
@@ -172,6 +187,11 @@ inline std::string function_scope_get(attributes::function_def const& f)
172 case attributes::member_scope::scope_private: 187 case attributes::member_scope::scope_private:
173 return "private "; 188 return "private ";
174 case attributes::member_scope::scope_protected: 189 case attributes::member_scope::scope_protected:
190 // Efl.Part.part.get is protected in C to force developers to use `efl_part`.
191 // There is no such restriction in C# as the binding takes care of the returned
192 // object lifetime.
193 if (f.c_name == "efl_part_get")
194 return "public ";
175 return "protected "; 195 return "protected ";
176 case attributes::member_scope::scope_unknown: 196 case attributes::member_scope::scope_unknown:
177 // This should trigger a compilation error 197 // This should trigger a compilation error
diff --git a/src/bin/eolian_mono/eolian/mono/function_pointer.hh b/src/bin/eolian_mono/eolian/mono/function_pointer.hh
index 721368f..3b50403 100644
--- a/src/bin/eolian_mono/eolian/mono/function_pointer.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_pointer.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_FUNCTION_POINTER_HPP 16#ifndef EOLIAN_MONO_FUNCTION_POINTER_HPP
2#define EOLIAN_MONO_FUNCTION_POINTER_HPP 17#define EOLIAN_MONO_FUNCTION_POINTER_HPP
3 18
@@ -51,19 +66,19 @@ struct function_pointer {
51 return false; 66 return false;
52 // "Internal" delegate, 1-to-1 with the Unamaged function type 67 // "Internal" delegate, 1-to-1 with the Unamaged function type
53 if (!as_generator(marshall_annotation(true) 68 if (!as_generator(marshall_annotation(true)
54 << "public delegate " << marshall_type(true) << " " << string // public? 69 << "internal delegate " << marshall_type(true) << " " << string // public?
55 << "Internal(IntPtr data" << *grammar::attribute_reorder<-1, -1>((", " << marshall_annotation << " " << marshall_parameter)) << ");\n") 70 << "Internal(IntPtr data" << *grammar::attribute_reorder<-1, -1>((", " << marshall_annotation << " " << marshall_parameter)) << ");\n")
56 .generate(sink, std::make_tuple(f.return_type, f.return_type, f_name, f.parameters), funcptr_ctx)) 71 .generate(sink, std::make_tuple(f.return_type, f.return_type, f_name, f.parameters), funcptr_ctx))
57 return false; 72 return false;
58 73
59 // Wrapper type, with callback matching the Unamanaged one 74 // Wrapper type, with callback matching the Unamanaged one
60 if (!as_generator("internal class " << f_name << "Wrapper : IDisposable\n" 75 if (!as_generator("internal class " << f_name << "Wrapper\n"
61 << "{\n\n" 76 << "{\n\n"
62 << scope_tab << "private " << f_name << "Internal _cb;\n" 77 << scope_tab << "private " << f_name << "Internal _cb;\n"
63 << scope_tab << "private IntPtr _cb_data;\n" 78 << scope_tab << "private IntPtr _cb_data;\n"
64 << scope_tab << "private EinaFreeCb _cb_free_cb;\n\n" 79 << scope_tab << "private Eina.Callbacks.EinaFreeCb _cb_free_cb;\n\n"
65 80
66 << scope_tab << "internal " << f_name << "Wrapper (" << f_name << "Internal _cb, IntPtr _cb_data, EinaFreeCb _cb_free_cb)\n" 81 << scope_tab << "internal " << f_name << "Wrapper (" << f_name << "Internal _cb, IntPtr _cb_data, Eina.Callbacks.EinaFreeCb _cb_free_cb)\n"
67 << scope_tab << "{\n" 82 << scope_tab << "{\n"
68 << scope_tab << scope_tab << "this._cb = _cb;\n" 83 << scope_tab << scope_tab << "this._cb = _cb;\n"
69 << scope_tab << scope_tab << "this._cb_data = _cb_data;\n" 84 << scope_tab << scope_tab << "this._cb_data = _cb_data;\n"
@@ -72,34 +87,13 @@ struct function_pointer {
72 87
73 << scope_tab << "~" << f_name << "Wrapper()\n" 88 << scope_tab << "~" << f_name << "Wrapper()\n"
74 << scope_tab << "{\n" 89 << scope_tab << "{\n"
75 << scope_tab << scope_tab << "Dispose(false);\n"
76 << scope_tab << "}\n\n"
77
78 << scope_tab << "protected virtual void Dispose(bool disposing)\n"
79 << scope_tab << "{\n"
80 << scope_tab << scope_tab << "if (this._cb_free_cb != null)\n" 90 << scope_tab << scope_tab << "if (this._cb_free_cb != null)\n"
81 << scope_tab << scope_tab << "{\n" 91 << scope_tab << scope_tab << "{\n"
82 << scope_tab << scope_tab << scope_tab << "if (disposing)\n" 92 << scope_tab << scope_tab << scope_tab << "Efl.Eo.Globals.ThreadSafeFreeCbExec(this._cb_free_cb, this._cb_data);\n"
83 << scope_tab << scope_tab << scope_tab << "{\n"
84 << scope_tab << scope_tab << scope_tab << scope_tab << "this._cb_free_cb(this._cb_data);\n"
85 << scope_tab << scope_tab << scope_tab << "}\n"
86 << scope_tab << scope_tab << scope_tab << "else\n"
87 << scope_tab << scope_tab << scope_tab << "{\n"
88 << scope_tab << scope_tab << scope_tab << scope_tab << "Efl.Eo.Globals.ThreadSafeFreeCbExec(this._cb_free_cb, this._cb_data);\n"
89 << scope_tab << scope_tab << scope_tab << "}\n"
90 << scope_tab << scope_tab << scope_tab << "this._cb_free_cb = null;\n"
91 << scope_tab << scope_tab << scope_tab << "this._cb_data = IntPtr.Zero;\n"
92 << scope_tab << scope_tab << scope_tab << "this._cb = null;\n"
93 << scope_tab << scope_tab << "}\n" 93 << scope_tab << scope_tab << "}\n"
94 << scope_tab << "}\n\n" 94 << scope_tab << "}\n\n"
95 95
96 << scope_tab << "public void Dispose()\n" 96 << scope_tab << "internal " << type << " ManagedCb(" << (parameter % ", ") << ")\n"
97 << scope_tab << "{\n"
98 << scope_tab << scope_tab << "Dispose(true);\n"
99 << scope_tab << scope_tab << "GC.SuppressFinalize(this);\n"
100 << scope_tab << "}\n\n"
101
102 << scope_tab << "internal " << type << " ManagedCb(" << (parameter % ",") << ")\n"
103 << scope_tab << "{\n" 97 << scope_tab << "{\n"
104 << function_definition_preamble << "_cb(_cb_data, " << (argument_invocation % ", ") << ");\n" 98 << function_definition_preamble << "_cb(_cb_data, " << (argument_invocation % ", ") << ");\n"
105 << function_definition_epilogue 99 << function_definition_epilogue
diff --git a/src/bin/eolian_mono/eolian/mono/function_registration.hh b/src/bin/eolian_mono/eolian/mono/function_registration.hh
index cdcb903..bef9e21 100644
--- a/src/bin/eolian_mono/eolian/mono/function_registration.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_registration.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_FUNCTION_REGISTRATION_HH 16#ifndef EOLIAN_MONO_FUNCTION_REGISTRATION_HH
2#define EOLIAN_MONO_FUNCTION_REGISTRATION_HH 17#define EOLIAN_MONO_FUNCTION_REGISTRATION_HH
3 18
@@ -49,7 +64,7 @@ struct function_registration_generator
49 return false; 64 return false;
50 65
51 if(!as_generator( 66 if(!as_generator(
52 indent << "if (methods.FirstOrDefault(m => m.Name == \"" << string << "\") != null)\n" 67 indent << "if (methods.Contains(\"" << string << "\"))\n"
53 << indent << "{\n" 68 << indent << "{\n"
54 << indent << scope_tab << "descs.Add(new EflOpDescription() {" 69 << indent << scope_tab << "descs.Add(new EflOpDescription() {"
55#ifdef _WIN32 70#ifdef _WIN32
diff --git a/src/bin/eolian_mono/eolian/mono/generation_contexts.hh b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh
index 985e373..f7376f0 100644
--- a/src/bin/eolian_mono/eolian/mono/generation_contexts.hh
+++ b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh
@@ -1,6 +1,23 @@
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 */
1#ifndef EOLIAN_MONO_GENERATION_CONTEXTS_HH 16#ifndef EOLIAN_MONO_GENERATION_CONTEXTS_HH
2#define EOLIAN_MONO_GENERATION_CONTEXTS_HH 17#define EOLIAN_MONO_GENERATION_CONTEXTS_HH
3 18
19#include <map>
20
4#include "grammar/context.hpp" 21#include "grammar/context.hpp"
5#include "grammar/indentation.hpp" 22#include "grammar/indentation.hpp"
6 23
diff --git a/src/bin/eolian_mono/eolian/mono/helpers.hh b/src/bin/eolian_mono/eolian/mono/helpers.hh
index 5c1db6d..b34a985 100644
--- a/src/bin/eolian_mono/eolian/mono/helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/helpers.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_HELPERS_HH 16#ifndef EOLIAN_MONO_HELPERS_HH
2#define EOLIAN_MONO_HELPERS_HH 17#define EOLIAN_MONO_HELPERS_HH
3 18
diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh
index 65645d3..da6fd6d 100644
--- a/src/bin/eolian_mono/eolian/mono/klass.hh
+++ b/src/bin/eolian_mono/eolian/mono/klass.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_CLASS_DEFINITION_HPP 16#ifndef EOLIAN_MONO_CLASS_DEFINITION_HPP
2#define EOLIAN_MONO_CLASS_DEFINITION_HPP 17#define EOLIAN_MONO_CLASS_DEFINITION_HPP
3 18
@@ -91,21 +106,21 @@ struct klass
91 name_helpers::klass_full_concrete_or_interface_name(cls)}, 106 name_helpers::klass_full_concrete_or_interface_name(cls)},
92 context); 107 context);
93 108
94 if(!as_generator(documentation).generate(sink, cls, iface_cxt)) 109 if(!as_generator(documentation(1)).generate(sink, cls, iface_cxt))
95 return false; 110 return false;
96 111
97 // Mark the interface with the proper native Efl_Class* getter 112 // Mark the interface with the proper native Efl_Class* getter
98 if(!as_generator(lit("[") << name_helpers::klass_full_native_inherit_name(cls) << "]\n") 113 if(!as_generator(scope_tab << lit("[") << name_helpers::klass_full_native_inherit_name(cls) << "]\n")
99 .generate(sink, attributes::unused, iface_cxt)) 114 .generate(sink, attributes::unused, iface_cxt))
100 return false; 115 return false;
101 116
102 if(!as_generator("[Efl.Eo.BindingEntity]\n").generate(sink, attributes::unused, iface_cxt)) 117 if(!as_generator(scope_tab << "[Efl.Eo.BindingEntity]\n").generate(sink, attributes::unused, iface_cxt))
103 return false; 118 return false;
104 119
105 using efl::eolian::grammar::lit; 120 using efl::eolian::grammar::lit;
106 if(!as_generator 121 if(!as_generator
107 ( 122 (
108 lit("public ") << (is_partial ? "partial ":"") 123 scope_tab << lit("public ") << (is_partial ? "partial ":"")
109 /*<< class_type*/ << "interface" /*<<*/ " " << string << " : " 124 /*<< class_type*/ << "interface" /*<<*/ " " << string << " : "
110 ) 125 )
111 .generate(sink, name_helpers::klass_interface_name(cls), iface_cxt)) 126 .generate(sink, name_helpers::klass_interface_name(cls), iface_cxt))
@@ -117,14 +132,14 @@ struct klass
117 continue; 132 continue;
118 133
119 if(first->type != attributes::class_type::regular && first->type != attributes::class_type::abstract_) 134 if(first->type != attributes::class_type::regular && first->type != attributes::class_type::abstract_)
120 if(!as_generator("\n" << scope_tab << string << " ,").generate(sink, name_helpers::klass_full_interface_name(*first), iface_cxt)) 135 if(!as_generator("\n" << scope_tab << string << ",").generate(sink, name_helpers::klass_full_interface_name(*first), iface_cxt))
121 return false; 136 return false;
122 } 137 }
123 138
124 if(!as_generator("\n" << scope_tab << "Efl.Eo.IWrapper, IDisposable").generate(sink, attributes::unused, iface_cxt)) 139 if(!as_generator("\n" << scope_tab(2) << "Efl.Eo.IWrapper, IDisposable").generate(sink, attributes::unused, iface_cxt))
125 return false; 140 return false;
126 141
127 if(!as_generator("\n{\n").generate(sink, attributes::unused, iface_cxt)) 142 if(!as_generator("\n" << scope_tab << "{\n").generate(sink, attributes::unused, iface_cxt))
128 return false; 143 return false;
129 144
130 if(!as_generator(*(function_declaration)).generate(sink, cls.functions, iface_cxt)) 145 if(!as_generator(*(function_declaration)).generate(sink, cls.functions, iface_cxt))
@@ -138,7 +153,7 @@ struct klass
138 153
139 for (auto &&p : cls.parts) 154 for (auto &&p : cls.parts)
140 if (!as_generator( 155 if (!as_generator(
141 documentation(1) 156 documentation(2)
142 << name_helpers::klass_full_concrete_or_interface_name(p.klass) << " " << utils::capitalize(p.name) << "{ get;}\n" 157 << name_helpers::klass_full_concrete_or_interface_name(p.klass) << " " << utils::capitalize(p.name) << "{ get;}\n"
143 ).generate(sink, p, iface_cxt)) 158 ).generate(sink, p, iface_cxt))
144 return false; 159 return false;
@@ -147,7 +162,7 @@ struct klass
147 return false; 162 return false;
148 163
149 // End of interface declaration 164 // End of interface declaration
150 if(!as_generator("}\n\n").generate(sink, attributes::unused, iface_cxt)) return false; 165 if(!as_generator(scope_tab << "}\n\n").generate(sink, attributes::unused, iface_cxt)) return false;
151 } 166 }
152 167
153 // Events arguments go in the top namespace to avoid the Concrete suffix clutter in interface events. 168 // Events arguments go in the top namespace to avoid the Concrete suffix clutter in interface events.
@@ -178,98 +193,9 @@ struct klass
178 auto concrete_cxt = context_add_tag(class_context{class_context::concrete, 193 auto concrete_cxt = context_add_tag(class_context{class_context::concrete,
179 name_helpers::klass_full_concrete_or_interface_name(cls)}, 194 name_helpers::klass_full_concrete_or_interface_name(cls)},
180 context); 195 context);
181 auto concrete_name = name_helpers::klass_concrete_name(cls);
182 auto interface_name = name_helpers::klass_interface_name(cls);
183 196
184 // We can't make these internal yet as they have methods that are used by 197 if(!generate_native_inherit_class(sink, cls, change_indentation(indent, concrete_cxt)))
185 // other classes that implement the interface.
186 if(!as_generator
187 (
188 documentation
189 << "public sealed " << (is_partial ? "partial ":"") << "class " << concrete_name << " :\n"
190 << scope_tab << (root ? "Efl.Eo.EoWrapper" : "") << (klass_full_concrete_or_interface_name % "") << "\n"
191 << scope_tab << ", " << interface_name << "\n"
192 << scope_tab << *(", " << name_helpers::klass_full_concrete_or_interface_name) << "\n"
193 << "{\n"
194 ).generate(sink, std::make_tuple(cls, inherit_classes, inherit_interfaces), concrete_cxt))
195 return false;
196
197 if (!generate_fields(sink, cls, concrete_cxt))
198 return false;
199
200 if (!as_generator
201 (
202 scope_tab << "/// <summary>Subclasses should override this constructor if they are expected to be instantiated from native code.\n"
203 << scope_tab << "/// Do not call this constructor directly.</summary>\n"
204 << scope_tab << "/// <param name=\"ch\">Tag struct storing the native handle of the object being constructed.</param>\n"
205 << scope_tab << "private " << concrete_name << "(ConstructingHandle ch) : base(ch)\n"
206 << scope_tab << "{\n"
207 << scope_tab << "}\n\n"
208 )
209 .generate(sink, attributes::unused, concrete_cxt))
210 return false;
211
212 if (!as_generator
213 (
214 scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(concrete_cxt).actual_library_name(cls.filename)
215 << ")] internal static extern System.IntPtr\n"
216 << scope_tab << scope_tab << name_helpers::klass_get_name(cls) << "();\n\n"
217 << scope_tab << "/// <summary>Initializes a new instance of the <see cref=\"" << interface_name << "\"/> class.\n"
218 << scope_tab << "/// Internal usage: This is used when interacting with C code and should not be used directly.</summary>\n"
219 << scope_tab << "/// <param name=\"wh\">The native pointer to be wrapped.</param>\n"
220 << scope_tab << "private " << concrete_name << "(Efl.Eo.Globals.WrappingHandle wh) : base(wh)\n"
221 << scope_tab << "{\n"
222 << scope_tab << "}\n\n"
223 )
224 .generate(sink, attributes::unused, concrete_cxt))
225 return false;
226
227 if (!generate_events(sink, cls, concrete_cxt))
228 return false;
229
230 if (!as_generator(lit("#pragma warning disable CS0628\n")).generate(sink, attributes::unused, concrete_cxt))
231 return false;
232
233 // Parts
234 if(!as_generator(*(part_definition))
235 .generate(sink, cls.parts, concrete_cxt)) return false;
236
237 // Concrete function definitions
238 auto implemented_methods = helpers::get_all_implementable_methods(cls, concrete_cxt);
239 if(!as_generator(*(function_definition))
240 .generate(sink, implemented_methods, concrete_cxt)) return false;
241
242 // Async wrappers
243 if(!as_generator(*(async_function_definition)).generate(sink, implemented_methods, concrete_cxt))
244 return false;
245
246 // Property wrappers
247 if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, cls.properties, concrete_cxt))
248 return false;
249
250 for (auto&& klass : helpers::non_implemented_interfaces(cls, concrete_cxt))
251 {
252 attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
253 if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, c.properties, concrete_cxt))
254 return false;
255 }
256
257 if (!as_generator(lit("#pragma warning restore CS0628\n")).generate(sink, attributes::unused, concrete_cxt))
258 return false;
259
260 // Copied from nativeinherit class, used when setting up providers.
261 if(!as_generator(
262 scope_tab << "private static IntPtr GetEflClassStatic()\n"
263 << scope_tab << "{\n"
264 << scope_tab << scope_tab << "return " << name_helpers::klass_get_full_name(cls) << "();\n"
265 << scope_tab << "}\n\n"
266 ).generate(sink, attributes::unused, concrete_cxt))
267 return false;
268
269 if(!generate_native_inherit_class(sink, cls, change_indentation(indent.inc(), concrete_cxt)))
270 return true; 198 return true;
271
272 if(!as_generator("}\n").generate(sink, attributes::unused, concrete_cxt)) return false;
273 } 199 }
274 200
275 // Inheritable class 201 // Inheritable class
@@ -282,10 +208,11 @@ struct klass
282 // Class header 208 // Class header
283 if(!as_generator 209 if(!as_generator
284 ( 210 (
285 documentation 211 documentation(1)
286 << "[" << name_helpers::klass_full_native_inherit_name(cls) << "]\n" 212 << scope_tab << "[" << name_helpers::klass_full_native_inherit_name(cls) << "]\n"
287 << "[Efl.Eo.BindingEntity]\n" 213 << scope_tab << "[Efl.Eo.BindingEntity]\n"
288 << "public " 214 << scope_tab << "[SuppressMessage(\"Microsoft.Naming\", \"CA1724:TypeNamesShouldNotMatchNamespaces\")]\n"
215 << scope_tab<< "public "
289 << (is_partial 216 << (is_partial
290 ? class_type == "class" 217 ? class_type == "class"
291 ? "partial class" 218 ? "partial class"
@@ -297,7 +224,7 @@ struct klass
297 << (root ? "Efl.Eo.EoWrapper" : "") // ... or root 224 << (root ? "Efl.Eo.EoWrapper" : "") // ... or root
298 << (inherit_interfaces.empty() ? "" : ", ") 225 << (inherit_interfaces.empty() ? "" : ", ")
299 << (klass_full_concrete_or_interface_name % ", ") // interfaces 226 << (klass_full_concrete_or_interface_name % ", ") // interfaces
300 << "\n{\n" 227 << "\n" << scope_tab << "{\n"
301 ) 228 )
302 .generate(sink, std::make_tuple(cls, inherit_classes, inherit_interfaces), inherit_cxt)) 229 .generate(sink, std::make_tuple(cls, inherit_classes, inherit_interfaces), inherit_cxt))
303 return false; 230 return false;
@@ -339,17 +266,17 @@ struct klass
339 266
340 // Copied from nativeinherit class, used when setting up providers. 267 // Copied from nativeinherit class, used when setting up providers.
341 if(!as_generator( 268 if(!as_generator(
342 scope_tab << "private static IntPtr GetEflClassStatic()\n" 269 scope_tab(2) << "private static IntPtr GetEflClassStatic()\n"
343 << scope_tab << "{\n" 270 << scope_tab(2) << "{\n"
344 << scope_tab << scope_tab << "return " << name_helpers::klass_get_full_name(cls) << "();\n" 271 << scope_tab(2) << scope_tab << "return " << name_helpers::klass_get_full_name(cls) << "();\n"
345 << scope_tab << "}\n\n" 272 << scope_tab(2) << "}\n\n"
346 ).generate(sink, attributes::unused, inherit_cxt)) 273 ).generate(sink, attributes::unused, inherit_cxt))
347 return false; 274 return false;
348 275
349 if(!generate_native_inherit_class(sink, cls, change_indentation(indent.inc(), inherit_cxt))) 276 if(!generate_native_inherit_class(sink, cls, change_indentation(indent.inc(), inherit_cxt)))
350 return true; 277 return true;
351 278
352 if(!as_generator("}\n").generate(sink, attributes::unused, inherit_cxt)) return false; 279 if(!as_generator(scope_tab << "}\n").generate(sink, attributes::unused, inherit_cxt)) return false;
353 } 280 }
354 281
355 282
@@ -365,19 +292,36 @@ struct klass
365 std::copy(c.properties.begin(), c.properties.end(), std::back_inserter(implementable_properties)); 292 std::copy(c.properties.begin(), c.properties.end(), std::back_inserter(implementable_properties));
366 } 293 }
367 294
295 std::stringstream extension_method_stream;
296 std::ostream_iterator<char> extension_method_iterator(extension_method_stream);
297
298 if (!as_generator
299 (*property_extension_method_definition(cls)
300 << *part_extension_method_definition(cls))
301 .generate(extension_method_iterator, std::make_tuple(implementable_properties, cls.parts), context))
302 return false;
303
304 if (extension_method_stream.tellp() <= 0)
305 return true;
306
307 if (!name_helpers::open_namespaces(sink, cls.namespaces, context))
308 return false;
309
368 if(!as_generator 310 if(!as_generator
369 (lit("#if EFL_BETA\n") 311 (lit("#if EFL_BETA\n")
370 << "#pragma warning disable CS1591\n" // Disabling warnings as DocFx will hide these classes 312 << "#pragma warning disable CS1591\n" // Disabling warnings as DocFx will hide these classes
371 <<"public static class " << (string % "_") << name_helpers::klass_inherit_name(cls) 313 << scope_tab << "public static class " << name_helpers::klass_concrete_name(cls)
372 << "_ExtensionMethods {\n" 314 << "Extensions {\n"
373 << *(property_extension_method_definition(cls)) 315 << extension_method_stream.str()
374 << *(part_extension_method_definition(cls)) 316 << scope_tab << "}\n"
375 << "}\n"
376 << "#pragma warning restore CS1591\n" 317 << "#pragma warning restore CS1591\n"
377 << "#endif\n") 318 << "#endif\n")
378 .generate(sink, std::make_tuple(cls.namespaces, implementable_properties, cls.parts), context)) 319 .generate(sink, cls.namespaces, context))
379 return false; 320 return false;
380 321
322 if (!name_helpers::close_namespaces(sink, cls.namespaces, context))
323 return false;
324
381 return true; 325 return true;
382 } 326 }
383 327
@@ -394,7 +338,12 @@ struct klass
394 auto inherit_name = name_helpers::klass_inherit_name(cls); 338 auto inherit_name = name_helpers::klass_inherit_name(cls);
395 auto implementable_methods = helpers::get_all_registerable_methods(cls, context); 339 auto implementable_methods = helpers::get_all_registerable_methods(cls, context);
396 bool root = !helpers::has_regular_ancestor(cls); 340 bool root = !helpers::has_regular_ancestor(cls);
397 auto const& indent = current_indentation(inative_cxt); 341 bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
342 auto const& indent = current_indentation(inative_cxt).inc();
343 std::string klass_since;
344
345 if (!documentation_helpers::generate_since_tag_line(std::back_inserter(klass_since), cls.documentation, indent, context))
346 return false;
398 347
399 std::string base_name; 348 std::string base_name;
400 if(!root) 349 if(!root)
@@ -406,12 +355,27 @@ struct klass
406 if(!as_generator 355 if(!as_generator
407 ( 356 (
408 indent << lit("/// <summary>Wrapper for native methods and virtual method delegates.\n") 357 indent << lit("/// <summary>Wrapper for native methods and virtual method delegates.\n")
409 << indent << "/// For internal use by generated code only.</summary>\n" 358 << indent << "/// For internal use by generated code only.\n"
410 << indent << "public new class " << native_inherit_name << " : " << (root ? "Efl.Eo.EoWrapper.NativeMethods" : base_name) << "\n" 359 << klass_since
360 << indent << "/// </summary>\n"
361 << indent << "[EditorBrowsable(EditorBrowsableState.Never)]\n"
362 << indent << "internal " << (is_concrete ? "" : "new ") << "class " << native_inherit_name << " : " << (root ? "Efl.Eo.EoWrapper.NativeMethods" : base_name) << "\n"
411 << indent << "{\n" 363 << indent << "{\n"
412 ).generate(sink, attributes::unused, inative_cxt)) 364 ).generate(sink, attributes::unused, inative_cxt))
413 return false; 365 return false;
414 366
367 if(is_concrete)
368 {
369 if (!as_generator
370 (
371 scope_tab(2) << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(context).actual_library_name(cls.filename)
372 << ")] internal static extern System.IntPtr\n"
373 << scope_tab(2) << scope_tab << name_helpers::klass_get_name(cls) << "();\n"
374 )
375 .generate(sink, attributes::unused, inative_cxt))
376 return false;
377 }
378
415 if(implementable_methods.size() >= 1) 379 if(implementable_methods.size() >= 1)
416 { 380 {
417 if(!as_generator( 381 if(!as_generator(
@@ -422,9 +386,11 @@ struct klass
422 } 386 }
423 387
424 if(!as_generator( 388 if(!as_generator(
425 indent << scope_tab << "/// <summary>Gets the list of Eo operations to override.</summary>\n" 389 indent << scope_tab << "/// <summary>Gets the list of Eo operations to override.\n"
390 << klass_since
391 << indent << "/// </summary>\n"
426 << indent << scope_tab << "/// <returns>The list of Eo operations to be overload.</returns>\n" 392 << indent << scope_tab << "/// <returns>The list of Eo operations to be overload.</returns>\n"
427 << indent << scope_tab << "public override System.Collections.Generic.List<EflOpDescription> GetEoOps(System.Type type, bool includeInherited)\n" 393 << indent << scope_tab << "internal override System.Collections.Generic.List<EflOpDescription> GetEoOps(System.Type type, bool includeInherited)\n"
428 << indent << scope_tab << "{\n" 394 << indent << scope_tab << "{\n"
429 << indent << scope_tab << scope_tab << "var descs = new System.Collections.Generic.List<EflOpDescription>();\n" 395 << indent << scope_tab << scope_tab << "var descs = new System.Collections.Generic.List<EflOpDescription>();\n"
430 ) 396 )
@@ -460,7 +426,7 @@ struct klass
460 ).generate(sink, attributes::unused, inative_cxt)) 426 ).generate(sink, attributes::unused, inative_cxt))
461 return false; 427 return false;
462 428
463 if (!root || context_find_tag<class_context>(context).current_wrapper_kind != class_context::concrete) 429 if (!root || !is_concrete)
464 if(!as_generator(indent << scope_tab << scope_tab << "descs.AddRange(base.GetEoOps(type, false));\n").generate(sink, attributes::unused, inative_cxt)) 430 if(!as_generator(indent << scope_tab << scope_tab << "descs.AddRange(base.GetEoOps(type, false));\n").generate(sink, attributes::unused, inative_cxt))
465 return false; 431 return false;
466 432
@@ -470,11 +436,16 @@ struct klass
470 ).generate(sink, attributes::unused, inative_cxt)) 436 ).generate(sink, attributes::unused, inative_cxt))
471 return false; 437 return false;
472 438
439 if (!klass_since.empty())
440 klass_since = static_cast<std::string>(scope_tab(2)) + klass_since;
441
473 // Attribute getter of the native 'Efl_Class *' handle (for proper inheritance from additional explicit interfaces) 442 // Attribute getter of the native 'Efl_Class *' handle (for proper inheritance from additional explicit interfaces)
474 if(!as_generator( 443 if(!as_generator(
475 indent << scope_tab << "/// <summary>Returns the Eo class for the native methods of this class.</summary>\n" 444 indent << scope_tab << "/// <summary>Returns the Eo class for the native methods of this class.\n"
445 << klass_since
446 << indent << scope_tab << "/// </summary>\n"
476 << indent << scope_tab << "/// <returns>The native class pointer.</returns>\n" 447 << indent << scope_tab << "/// <returns>The native class pointer.</returns>\n"
477 << indent << scope_tab << "public override IntPtr GetEflClass()\n" 448 << indent << scope_tab << "internal override IntPtr GetEflClass()\n"
478 << indent << scope_tab << "{\n" 449 << indent << scope_tab << "{\n"
479 << indent << scope_tab << scope_tab << "return " << name_helpers::klass_get_full_name(cls) << "();\n" 450 << indent << scope_tab << scope_tab << "return " << name_helpers::klass_get_full_name(cls) << "();\n"
480 << indent << scope_tab << "}\n\n" 451 << indent << scope_tab << "}\n\n"
@@ -488,7 +459,7 @@ struct klass
488 << indent << scope_tab << "#pragma warning restore CA1707, CS1591, SA1300, SA1600\n\n") 459 << indent << scope_tab << "#pragma warning restore CA1707, CS1591, SA1300, SA1600\n\n")
489 .generate(sink, implementable_methods, change_indentation(indent.inc(), inative_cxt))) return false; 460 .generate(sink, implementable_methods, change_indentation(indent.inc(), inative_cxt))) return false;
490 461
491 if(!as_generator("}\n").generate(sink, attributes::unused, inative_cxt)) return false; 462 if(!as_generator(indent << "}\n").generate(sink, attributes::unused, inative_cxt)) return false;
492 } 463 }
493 return true; 464 return true;
494 } 465 }
@@ -503,21 +474,21 @@ struct klass
503 auto inherit_name = name_helpers::klass_concrete_name(cls); 474 auto inherit_name = name_helpers::klass_concrete_name(cls);
504 475
505 if(!as_generator( 476 if(!as_generator(
506 scope_tab << "/// <summary>Pointer to the native class description.</summary>\n" 477 scope_tab(2) << "/// <summary>Pointer to the native class description.</summary>\n"
507 << scope_tab << "public override System.IntPtr NativeClass\n" 478 << scope_tab(2) << "public override System.IntPtr NativeClass\n"
508 << scope_tab << "{\n" 479 << scope_tab(2) << "{\n"
509 << scope_tab << scope_tab << "get\n" 480 << scope_tab(2) << scope_tab << "get\n"
510 << scope_tab << scope_tab << "{\n" 481 << scope_tab(2) << scope_tab << "{\n"
511 << scope_tab << scope_tab << scope_tab << "if (((object)this).GetType() == typeof(" << inherit_name << "))\n" 482 << scope_tab(2) << scope_tab << scope_tab << "if (((object)this).GetType() == typeof(" << inherit_name << "))\n"
512 << scope_tab << scope_tab << scope_tab << "{\n" 483 << scope_tab(2) << scope_tab << scope_tab << "{\n"
513 << scope_tab << scope_tab << scope_tab << scope_tab << "return GetEflClassStatic();\n" 484 << scope_tab(2) << scope_tab << scope_tab << scope_tab << "return GetEflClassStatic();\n"
514 << scope_tab << scope_tab << scope_tab << "}\n" 485 << scope_tab(2) << scope_tab << scope_tab << "}\n"
515 << scope_tab << scope_tab << scope_tab << "else\n" 486 << scope_tab(2) << scope_tab << scope_tab << "else\n"
516 << scope_tab << scope_tab << scope_tab << "{\n" 487 << scope_tab(2) << scope_tab << scope_tab << "{\n"
517 << scope_tab << scope_tab << scope_tab << scope_tab << "return Efl.Eo.ClassRegister.klassFromType[((object)this).GetType()];\n" 488 << scope_tab(2) << scope_tab << scope_tab << scope_tab << "return Efl.Eo.ClassRegister.klassFromType[((object)this).GetType()];\n"
518 << scope_tab << scope_tab << scope_tab << "}\n" 489 << scope_tab(2) << scope_tab << scope_tab << "}\n"
519 << scope_tab << scope_tab << "}\n" 490 << scope_tab(2) << scope_tab << "}\n"
520 << scope_tab << "}\n\n" 491 << scope_tab(2) << "}\n\n"
521 ).generate(sink, attributes::unused, context)) 492 ).generate(sink, attributes::unused, context))
522 return false; 493 return false;
523 494
@@ -530,9 +501,9 @@ struct klass
530 auto inherit_name = name_helpers::klass_concrete_name(cls); 501 auto inherit_name = name_helpers::klass_concrete_name(cls);
531 502
532 if(!as_generator( 503 if(!as_generator(
533 scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(context).actual_library_name(cls.filename) 504 scope_tab(2) << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(context).actual_library_name(cls.filename)
534 << ")] internal static extern System.IntPtr\n" 505 << ")] internal static extern System.IntPtr\n"
535 << scope_tab << scope_tab << name_helpers::klass_get_name(cls) << "();\n\n" 506 << scope_tab(2) << scope_tab << name_helpers::klass_get_name(cls) << "();\n\n"
536 ).generate(sink, attributes::unused, context)) 507 ).generate(sink, attributes::unused, context))
537 return false; 508 return false;
538 509
@@ -543,31 +514,41 @@ struct klass
543 return !blacklist::is_function_blacklisted(ctor.function, context); 514 return !blacklist::is_function_blacklisted(ctor.function, context);
544 }); 515 });
545 516
517 std::string klass_since;
518 if (!documentation_helpers::generate_since_tag_line(std::back_inserter(klass_since), cls.documentation, scope_tab(2), context))
519 return false;
520
546 // Public (API) constructors 521 // Public (API) constructors
547 if (!as_generator( 522 if (!as_generator(
548 scope_tab << "/// <summary>Initializes a new instance of the <see cref=\"" << inherit_name << "\"/> class.</summary>\n" 523 scope_tab(2) << "/// <summary>Initializes a new instance of the <see cref=\"" << inherit_name << "\"/> class.\n"
549 << scope_tab << "/// <param name=\"parent\">Parent instance.</param>\n" 524 << klass_since
550 << *(documentation) 525 << scope_tab(2) << "/// </summary>\n"
526 << scope_tab(2) << "/// <param name=\"parent\">Parent instance.</param>\n"
527 << *(documentation(1))
551 // For constructors with arguments, the parent is also required, as optional parameters can't come before non-optional paramenters. 528 // For constructors with arguments, the parent is also required, as optional parameters can't come before non-optional paramenters.
552 << scope_tab << "public " << inherit_name << "(Efl.Object parent" << ((constructors.size() > 0) ? "" : "= null") << "\n" 529 << scope_tab(2) << "public " << inherit_name << "(Efl.Object parent" << ((constructors.size() > 0) ? "" : "= null")
553 << scope_tab << scope_tab << scope_tab << *(", " << constructor_param ) << ") : " 530 << *(", " << constructor_param ) << ") : "
554 << "base(" << name_helpers::klass_get_name(cls) << "(), parent)\n" 531 << "base(" << name_helpers::klass_get_name(cls) << "(), parent)\n"
555 << scope_tab << "{\n" 532 << scope_tab(2) << "{\n"
556 << (*(scope_tab << scope_tab << constructor_invocation << "\n")) 533 << (*(scope_tab << scope_tab << constructor_invocation << "\n"))
557 << scope_tab << scope_tab << "FinishInstantiation();\n" 534 << scope_tab(2) << scope_tab << "FinishInstantiation();\n"
558 << scope_tab << "}\n\n" 535 << scope_tab(2) << "}\n\n"
559 << scope_tab << "/// <summary>Subclasses should override this constructor if they are expected to be instantiated from native code.\n" 536 << scope_tab(2) << "/// <summary>Subclasses should override this constructor if they are expected to be instantiated from native code.\n"
560 << scope_tab << "/// Do not call this constructor directly.</summary>\n" 537 << scope_tab(2) << "/// Do not call this constructor directly.\n"
561 << scope_tab << "/// <param name=\"ch\">Tag struct storing the native handle of the object being constructed.</param>\n" 538 << klass_since
562 << scope_tab << "protected " << inherit_name << "(ConstructingHandle ch) : base(ch)\n" 539 << scope_tab(2) << "/// </summary>\n"
563 << scope_tab << "{\n" 540 << scope_tab(2) << "/// <param name=\"ch\">Tag struct storing the native handle of the object being constructed.</param>\n"
564 << scope_tab << "}\n\n" 541 << scope_tab(2) << "protected " << inherit_name << "(ConstructingHandle ch) : base(ch)\n"
565 << scope_tab << "/// <summary>Initializes a new instance of the <see cref=\"" << inherit_name << "\"/> class.\n" 542 << scope_tab(2) << "{\n"
566 << 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" 543 << scope_tab(2) << "}\n\n"
567 << scope_tab << "/// <param name=\"wh\">The native pointer to be wrapped.</param>\n" 544 << scope_tab(2) << "/// <summary>Initializes a new instance of the <see cref=\"" << inherit_name << "\"/> class.\n"
568 << scope_tab << "protected " << inherit_name << "(Efl.Eo.Globals.WrappingHandle wh) : base(wh)\n" 545 << scope_tab(2) << "/// Internal usage: Constructs an instance from a native pointer. This is used when interacting with C code and should not be used directly.\n"
569 << scope_tab << "{\n" 546 << klass_since
570 << scope_tab << "}\n\n" 547 << scope_tab(2) << "/// </summary>\n"
548 << scope_tab(2) << "/// <param name=\"wh\">The native pointer to be wrapped.</param>\n"
549 << scope_tab(2) << "internal " << inherit_name << "(Efl.Eo.WrappingHandle wh) : base(wh)\n"
550 << scope_tab(2) << "{\n"
551 << scope_tab(2) << "}\n\n"
571 ).generate(sink, std::make_tuple(constructors, constructors, constructors), context)) 552 ).generate(sink, std::make_tuple(constructors, constructors, constructors), context))
572 return false; 553 return false;
573 554
@@ -577,25 +558,27 @@ struct klass
577 if (cls.type == attributes::class_type::abstract_) 558 if (cls.type == attributes::class_type::abstract_)
578 { 559 {
579 if (!as_generator( 560 if (!as_generator(
580 scope_tab << "[Efl.Eo.PrivateNativeClass]\n" 561 scope_tab(2) << "[Efl.Eo.PrivateNativeClass]\n"
581 << scope_tab << "private class " << inherit_name << "Realized : " << inherit_name << "\n" 562 << scope_tab(2) << "private class " << inherit_name << "Realized : " << inherit_name << "\n"
582 << scope_tab << "{\n" 563 << scope_tab(2) << "{\n"
583 << scope_tab << scope_tab << "private " << inherit_name << "Realized(Efl.Eo.Globals.WrappingHandle wh) : base(wh)\n" 564 << scope_tab(2) << scope_tab << "private " << inherit_name << "Realized(Efl.Eo.WrappingHandle wh) : base(wh)\n"
584 << scope_tab << scope_tab << "{\n" 565 << scope_tab(2) << scope_tab << "{\n"
585 << scope_tab << scope_tab << "}\n" 566 << scope_tab(2) << scope_tab << "}\n"
586 << scope_tab << "}\n" 567 << scope_tab(2) << "}\n"
587 ).generate(sink, attributes::unused, context)) 568 ).generate(sink, attributes::unused, context))
588 return false; 569 return false;
589 } 570 }
590 571
591 return as_generator( 572 return as_generator(
592 scope_tab << "/// <summary>Initializes a new instance of the <see cref=\"" << inherit_name << "\"/> class.\n" 573 scope_tab(2) << "/// <summary>Initializes a new instance of the <see cref=\"" << inherit_name << "\"/> class.\n"
593 << 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" 574 << scope_tab(2) << "/// Internal usage: Constructor to forward the wrapper initialization to the root class that interfaces with native code. Should not be used directly.\n"
594 << scope_tab << "/// <param name=\"baseKlass\">The pointer to the base native Eo class.</param>\n" 575 << klass_since
595 << scope_tab << "/// <param name=\"parent\">The Efl.Object parent of this instance.</param>\n" 576 << scope_tab(2) << "/// </summary>\n"
596 << scope_tab << "protected " << inherit_name << "(IntPtr baseKlass, Efl.Object parent) : base(baseKlass, parent)\n" 577 << scope_tab(2) << "/// <param name=\"baseKlass\">The pointer to the base native Eo class.</param>\n"
597 << scope_tab << "{\n" 578 << scope_tab(2) << "/// <param name=\"parent\">The Efl.Object parent of this instance.</param>\n"
598 << scope_tab << "}\n\n" 579 << scope_tab(2) << "protected " << inherit_name << "(IntPtr baseKlass, Efl.Object parent) : base(baseKlass, parent)\n"
580 << scope_tab(2) << "{\n"
581 << scope_tab(2) << "}\n\n"
599 ).generate(sink, attributes::unused, context); 582 ).generate(sink, attributes::unused, context);
600 } 583 }
601 584
diff --git a/src/bin/eolian_mono/eolian/mono/logging.hh b/src/bin/eolian_mono/eolian/mono/logging.hh
index d13c395..e5b297b 100644
--- a/src/bin/eolian_mono/eolian/mono/logging.hh
+++ b/src/bin/eolian_mono/eolian/mono/logging.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_LOGGING_HH 16#ifndef EOLIAN_MONO_LOGGING_HH
2#define EOLIAN_MONO_LOGGING_HH 17#define EOLIAN_MONO_LOGGING_HH
3 18
diff --git a/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh b/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh
index 82bbd13..a9fc45d 100644
--- a/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh
+++ b/src/bin/eolian_mono/eolian/mono/marshall_annotation.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_MARSHALL_ANNOTATION_IMPL_HH 16#ifndef EOLIAN_MONO_MARSHALL_ANNOTATION_IMPL_HH
2#define EOLIAN_MONO_MARSHALL_ANNOTATION_IMPL_HH 17#define EOLIAN_MONO_MARSHALL_ANNOTATION_IMPL_HH
3 18
@@ -6,25 +21,13 @@
6#include "grammar/case.hpp" 21#include "grammar/case.hpp"
7#include "name_helpers.hh" 22#include "name_helpers.hh"
8#include "type_impl.hh" 23#include "type_impl.hh"
24#include "type_match.hh"
9 25
10namespace eolian_mono { 26namespace eolian_mono {
11 27
12namespace eina = efl::eina; 28namespace eina = efl::eina;
13 29
14namespace detail { 30namespace detail {
15
16template <typename Array, typename F, int N, typename A>
17eina::optional<bool> call_annotation_match(Array const (&array)[N], F f, A a)
18{
19 typedef Array const* iterator_type;
20 iterator_type match_iterator = &array[0], match_last = match_iterator + N;
21 match_iterator = std::find_if(match_iterator, match_last, f);
22 if(match_iterator != match_last)
23 {
24 return a(match_iterator->function());
25 }
26 return {nullptr};
27}
28 31
29template <typename OutputIterator, typename Context> 32template <typename OutputIterator, typename Context>
30struct marshall_annotation_visitor_generate 33struct marshall_annotation_visitor_generate
@@ -48,103 +51,108 @@ struct marshall_annotation_visitor_generate
48 eina::optional<bool> has_own; 51 eina::optional<bool> has_own;
49 std::function<std::string()> function; 52 std::function<std::string()> function;
50 }; 53 };
54 // These two tables are currently the same but will hold different marshallers
55 // for @in and @out/return semantics in a future commit.
51 match const parameter_match_table[] = 56 match const parameter_match_table[] =
52 { 57 {
53 // signed primitives 58 // signed primitives
54 {"bool", nullptr, [&] { return "[MarshalAs(UnmanagedType.U1)]"; }}, 59 {"bool", nullptr, [] { return "MarshalAs(UnmanagedType.U1)"; }},
55 {"string", true, [&] { 60 {"string", true, [] {
56 return "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))]"; 61 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))";
57 }}, 62 }},
58 {"string", false, [&] { 63 {"string", false, [] {
59 return "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))]"; 64 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))";
60 }}, 65 }},
61 {"mstring", true, [&] { 66 {"mstring", true, [] {
62 return "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))]"; 67 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))";
63 }}, 68 }},
64 {"mstring", false, [&] { 69 {"mstring", false, [] {
65 return "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))]"; 70 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))";
66 }}, 71 }},
67 {"stringshare", true, [&] { 72 {"stringshare", true, [] {
68 return "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringsharePassOwnershipMarshaler))]"; 73 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringsharePassOwnershipMarshaler))";
69 }}, 74 }},
70 {"stringshare", false, [&] { 75 {"stringshare", false, [] {
71 return "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringshareKeepOwnershipMarshaler))]"; 76 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringshareKeepOwnershipMarshaler))";
72 }}, 77 }},
73 {"any_value_ref", true, [&] { 78 {"any_value_ref", true, [] {
74 return "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Eina.ValueMarshalerOwn))]"; 79 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Eina.ValueMarshalerOwn))";
75 }}, 80 }},
76 {"any_value_ref", false, [&] { 81 {"any_value_ref", false, [] {
77 return "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Eina.ValueMarshaler))]"; 82 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Eina.ValueMarshaler))";
78 }}, 83 }},
79 {"strbuf", true, [&] { 84 {"strbuf", true, [] {
80 return "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufPassOwnershipMarshaler))]"; 85 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufPassOwnershipMarshaler))";
81 }}, 86 }},
82 {"strbuf", false, [&] { 87 {"strbuf", false, [] {
83 return "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufKeepOwnershipMarshaler))]"; 88 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufKeepOwnershipMarshaler))";
84 }}, 89 }},
85 {"Value_Type", false, [&] { 90 {"Value_Type", false, [] {
86 return "[MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Eina.ValueTypeMarshaler))]"; 91 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Eina.ValueTypeMarshaler))";
87 }}, 92 }},
88 }; 93 };
89 match const return_match_table[] = 94 match const return_match_table[] =
90 { 95 {
91 // signed primitives 96 // signed primitives
92 {"bool", nullptr, [&] { return "[return: MarshalAs(UnmanagedType.U1)]"; }}, 97 {"bool", nullptr, [] { return "MarshalAs(UnmanagedType.U1)"; }},
93 {"string", true, [&] { 98 {"string", true, [] {
94 return "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))]"; 99 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))";
95 }}, 100 }},
96 {"string", nullptr, [&] { 101 {"string", false, [] {
97 return "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))]"; 102 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))";
98 }}, 103 }},
99 {"mstring", true, [&] { 104 {"mstring", true, [] {
100 return "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))]"; 105 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringPassOwnershipMarshaler))";
101 }}, 106 }},
102 {"mstring", false, [&] { 107 {"mstring", false, [] {
103 return "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))]"; 108 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringKeepOwnershipMarshaler))";
104 }}, 109 }},
105 {"stringshare", true, [&] { 110 {"stringshare", true, [] {
106 return "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringsharePassOwnershipMarshaler))]"; 111 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringsharePassOwnershipMarshaler))";
107 }}, 112 }},
108 {"stringshare", false, [&] { 113 {"stringshare", false, [] {
109 return "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringshareKeepOwnershipMarshaler))]"; 114 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StringshareKeepOwnershipMarshaler))";
110 }}, 115 }},
111 {"any_value_ref", true, [&] { 116 {"any_value_ref", true, [] {
112 return "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Eina.ValueMarshalerOwn))]"; 117 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Eina.ValueMarshalerOwn))";
113 }}, 118 }},
114 {"any_value_ref", false, [&] { 119 {"any_value_ref", false, [] {
115 return "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Eina.ValueMarshaler))]"; 120 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Eina.ValueMarshaler))";
116 }}, 121 }},
117 {"strbuf", true, [&] { 122 {"strbuf", true, [] {
118 return "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufPassOwnershipMarshaler))]"; 123 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufPassOwnershipMarshaler))";
119 }}, 124 }},
120 {"strbuf", false, [&] { 125 {"strbuf", false, [] {
121 return "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufKeepOwnershipMarshaler))]"; 126 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Efl.Eo.StrbufKeepOwnershipMarshaler))";
122 }}, 127 }},
123 {"Value_Type", false, [&] { 128 {"Value_Type", false, [] {
124 return "[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Eina.ValueTypeMarshaler))]"; 129 return "MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(Eina.ValueTypeMarshaler))";
125 }}, 130 }},
126 }; 131 };
127 132
128 if(eina::optional<bool> b = call_annotation_match 133 auto predicate = [&regular] (match const& m)
129 ((is_return ? return_match_table : parameter_match_table)
130 , [&] (match const& m)
131 { 134 {
132 return (!m.name || *m.name == regular.base_type) 135 return (!m.name || *m.name == regular.base_type)
133 && (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own)) 136 && (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own))
134 ; 137 ;
138 };
139
140 auto acceptCb = [this] (std::string const& marshalTag)
141 {
142 std::string prefix = is_return ? "return: " : "";
143 return as_generator("[" << prefix << marshalTag << "]").generate(sink, nullptr, *context);
144 };
145
146 const auto& match_table = is_return ? return_match_table : parameter_match_table;
147
148 if(eina::optional<bool> b = type_match::get_match(match_table, predicate, acceptCb))
149 {
150 return *b;
135 } 151 }
136 , [&] (std::string const& string) 152 else
137 { 153 {
138 std::copy(string.begin(), string.end(), sink); 154 return true;
139 return true; 155 }
140 }))
141 {
142 return *b;
143 }
144 else
145 {
146 return true;
147 }
148 } 156 }
149 bool operator()(attributes::klass_name const& klass_name) const 157 bool operator()(attributes::klass_name const& klass_name) const
150 { 158 {
@@ -157,8 +165,8 @@ struct marshall_annotation_visitor_generate
157 name = "Efl.Eo.MarshalEflClass"; 165 name = "Efl.Eo.MarshalEflClass";
158 else 166 else
159 { 167 {
160 std::string own = klass_name.base_qualifier & qualifier_info::is_own ? "OwnTag" : "NonOwnTag"; 168 std::string own = klass_name.base_qualifier & qualifier_info::is_own ? "Move" : "NoMove";
161 name = "Efl.Eo.MarshalEo<Efl.Eo." + own + ">"; 169 name = "Efl.Eo.MarshalEo" + own;
162 } 170 }
163 171
164 return as_generator( 172 return as_generator(
diff --git a/src/bin/eolian_mono/eolian/mono/marshall_type.hh b/src/bin/eolian_mono/eolian/mono/marshall_type.hh
index 2b05e63..c921431 100644
--- a/src/bin/eolian_mono/eolian/mono/marshall_type.hh
+++ b/src/bin/eolian_mono/eolian/mono/marshall_type.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_MARSHALL_TYPE_HH 16#ifndef EOLIAN_MONO_MARSHALL_TYPE_HH
2#define EOLIAN_MONO_MARSHALL_TYPE_HH 17#define EOLIAN_MONO_MARSHALL_TYPE_HH
3 18
diff --git a/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh b/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh
index 5ba68ab..4d1e188 100644
--- a/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh
+++ b/src/bin/eolian_mono/eolian/mono/marshall_type_impl.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_MARSHALL_TYPE_IMPL_HH 16#ifndef EOLIAN_MONO_MARSHALL_TYPE_IMPL_HH
2#define EOLIAN_MONO_MARSHALL_TYPE_IMPL_HH 17#define EOLIAN_MONO_MARSHALL_TYPE_IMPL_HH
3 18
@@ -6,6 +21,7 @@
6#include "grammar/case.hpp" 21#include "grammar/case.hpp"
7#include "helpers.hh" 22#include "helpers.hh"
8#include "name_helpers.hh" 23#include "name_helpers.hh"
24#include "type_match.hh"
9#include "type_impl.hh" 25#include "type_impl.hh"
10#include "generation_contexts.hh" 26#include "generation_contexts.hh"
11#include "blacklist.hh" 27#include "blacklist.hh"
@@ -177,7 +193,7 @@ struct marshall_type_visitor_generate
177 return as_generator(string << ".NativeStruct") 193 return as_generator(string << ".NativeStruct")
178 .generate(sink, name_helpers::type_full_managed_name(regular), *context); 194 .generate(sink, name_helpers::type_full_managed_name(regular), *context);
179 } 195 }
180 else if (eina::optional<bool> b = call_match 196 else if (eina::optional<bool> b = type_match::get_match
181 (match_table 197 (match_table
182 , [&] (match const& m) 198 , [&] (match const& m)
183 { 199 {
@@ -281,7 +297,7 @@ struct marshall_type_visitor_generate
281 && as_generator("<" << (type(false, false, true) % ", ") << ">").generate(sink, complex.subtypes, *context); 297 && as_generator("<" << (type(false, false, true) % ", ") << ">").generate(sink, complex.subtypes, *context);
282 }; 298 };
283 299
284 if(eina::optional<bool> b = call_match 300 if(eina::optional<bool> b = type_match::get_match
285 (matches 301 (matches
286 , [&] (match const& m) 302 , [&] (match const& m)
287 { 303 {
diff --git a/src/bin/eolian_mono/eolian/mono/name_helpers.hh b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
index df1405d..ae958ba 100644
--- a/src/bin/eolian_mono/eolian/mono/name_helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/name_helpers.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_NAME_HELPERS_HH 16#ifndef EOLIAN_MONO_NAME_HELPERS_HH
2#define EOLIAN_MONO_NAME_HELPERS_HH 17#define EOLIAN_MONO_NAME_HELPERS_HH
3 18
@@ -7,6 +22,7 @@
7#include <sstream> 22#include <sstream>
8#include <string> 23#include <string>
9#include <vector> 24#include <vector>
25#include <map>
10#include "utils.hh" 26#include "utils.hh"
11 27
12#include "grammar/integral.hpp" 28#include "grammar/integral.hpp"
@@ -158,7 +174,8 @@ static const std::vector<std::string> verbs =
158 "sync", 174 "sync",
159 "toggle", 175 "toggle",
160 "unbind", 176 "unbind",
161 "unregister" 177 "unregister",
178 "unselect"
162 }; 179 };
163 180
164const std::vector<std::string> not_verbs = 181const std::vector<std::string> not_verbs =
@@ -382,9 +399,7 @@ struct klass_full_interface_name_generator
382template<typename T> 399template<typename T>
383inline std::string klass_concrete_name(T const& klass) 400inline std::string klass_concrete_name(T const& klass)
384{ 401{
385 return utils::remove_all(klass.eolian_name, '_') + ((klass.type == attributes::class_type::mixin 402 return utils::remove_all(klass.eolian_name, '_');
386 || klass.type == attributes::class_type::interface_)
387 ? "Concrete" : "");
388} 403}
389 404
390template<typename T> 405template<typename T>
@@ -450,14 +465,19 @@ inline std::string klass_inherit_name(T const& klass)
450} 465}
451 466
452template<typename T> 467template<typename T>
453inline std::string klass_native_inherit_name(EINA_UNUSED T const& klass) 468inline std::string klass_native_inherit_name(T const& klass)
454{ 469{
455 return "NativeMethods"; 470 return ((klass.type == attributes::class_type::mixin
471 || klass.type == attributes::class_type::interface_) ? klass_interface_name(klass) : "") + "NativeMethods";
456} 472}
457 473
458template<typename T> 474template<typename T>
459inline std::string klass_full_native_inherit_name(T const& klass) 475inline std::string klass_full_native_inherit_name(T const& klass)
460{ 476{
477 if(klass.type == attributes::class_type::mixin
478 || klass.type == attributes::class_type::interface_)
479 return join_namespaces(klass.namespaces, '.', managed_namespace) + klass_native_inherit_name(klass);
480
461 return klass_full_concrete_name(klass) + "." + klass_native_inherit_name(klass); 481 return klass_full_concrete_name(klass) + "." + klass_native_inherit_name(klass);
462} 482}
463 483
@@ -470,6 +490,10 @@ inline std::string klass_get_name(T const& clsname)
470template<typename T> 490template<typename T>
471inline std::string klass_get_full_name(T const& clsname) 491inline std::string klass_get_full_name(T const& clsname)
472{ 492{
493 if(clsname.type == attributes::class_type::mixin
494 || clsname.type == attributes::class_type::interface_)
495 return klass_get_name(clsname);
496
473 return klass_full_concrete_name(clsname) + "." + klass_get_name(clsname); 497 return klass_full_concrete_name(clsname) + "." + klass_get_name(clsname);
474} 498}
475 499
@@ -522,6 +546,43 @@ std::string constructor_managed_name(std::string full_name)
522 return managed_name(tokens.at(tokens.size()-1)); 546 return managed_name(tokens.at(tokens.size()-1));
523} 547}
524 548
549std::string translate_value_type(std::string const& name)
550{
551 static std::map<std::string, std::string> table = {
552 {"sbyte", "SByte"},
553 {"byte","Byte"},
554 {"short","Int16"},
555 {"ushort","UInt16"},
556 {"int", "Int32"},
557 {"uint","UInt32"},
558 {"long","Int64"},
559 {"ulong","UInt64"},
560 {"char","Char"},
561 {"float","Single"},
562 {"double","Double"},
563 {"bool","Boolean"},
564 {"decimal","Decimal"},
565 };
566
567 auto found = table.find(name);
568
569 if (found != table.end())
570 return found->second;
571
572 return name;
573}
574
575
576// Field names //
577struct struct_field_name_generator
578{
579 template <typename OutputIterator, typename Context>
580 bool generate(OutputIterator sink, attributes::struct_field_def const& field, Context const& context) const
581 {
582 return as_generator(string).generate(sink, name_helpers::to_field_name(field.name), context);
583 }
584} const struct_field_name {};
585
525} // namespace name_helpers 586} // namespace name_helpers
526 587
527} // namespace eolian_mono 588} // namespace eolian_mono
@@ -549,9 +610,18 @@ struct is_eager_generator<eolian_mono::name_helpers::klass_full_concrete_name_ge
549template <> 610template <>
550struct is_generator<eolian_mono::name_helpers::klass_full_concrete_name_generator> : std::true_type {}; 611struct is_generator<eolian_mono::name_helpers::klass_full_concrete_name_generator> : std::true_type {};
551 612
613template <>
614struct is_eager_generator<eolian_mono::name_helpers::struct_field_name_generator> : std::true_type {};
615template <>
616struct is_generator< ::eolian_mono::name_helpers::struct_field_name_generator> : std::true_type {};
617
552namespace type_traits { 618namespace type_traits {
553template <> 619template <>
554struct attributes_needed<struct ::eolian_mono::name_helpers::klass_full_concrete_or_interface_name_generator> : std::integral_constant<int, 1> {}; 620struct attributes_needed<struct ::eolian_mono::name_helpers::klass_full_concrete_or_interface_name_generator> : std::integral_constant<int, 1> {};
621
622template <>
623struct attributes_needed< ::eolian_mono::name_helpers::struct_field_name_generator> : std::integral_constant<int, 1> {};
624
555} 625}
556 626
557} } } 627} } }
diff --git a/src/bin/eolian_mono/eolian/mono/parameter.hh b/src/bin/eolian_mono/eolian/mono/parameter.hh
index 4050c60..abd9464 100644
--- a/src/bin/eolian_mono/eolian/mono/parameter.hh
+++ b/src/bin/eolian_mono/eolian/mono/parameter.hh
@@ -1,3 +1,18 @@
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 */
1#ifndef EOLIAN_MONO_PARAMETER_HH 16#ifndef EOLIAN_MONO_PARAMETER_HH
2#define EOLIAN_MONO_PARAMETER_HH 17#define EOLIAN_MONO_PARAMETER_HH
3 18
@@ -479,7 +494,7 @@ struct marshall_parameter_generator
479 ).generate(sink, std::make_tuple(param, param_name), context); 494 ).generate(sink, std::make_tuple(param, param_name), context);
480 495
481 return as_generator( 496 return as_generator(
482 "IntPtr " << param_name << "_data, " << type << "Internal " << param_name << ", EinaFreeCb " 497 "IntPtr " << param_name << "_data, " << type << "Internal " << param_name << ", Eina.Callbacks.EinaFreeCb "
483 << param_name << "_free_cb" 498 << param_name << "_free_cb"
484 ).generate(sink, param, context); 499 ).generate(sink, param, context);
485 } 500 }
@@ -610,30 +625,44 @@ struct native_convert_in_variable_generator
610 << ");\n" 625 << ");\n"
611 ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context); 626 ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
612 } 627 }
613 else if (param.type.c_type == "Eina_Array *" || param.type.c_type == "const Eina_Array *" 628 else if (param.type.c_type == "Eina_List *" || param.type.c_type == "const Eina_List *")
614 || param.type.c_type == "Eina_List *" || param.type.c_type == "const Eina_List *"
615 )
616 { 629 {
617 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type); 630 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
618 if (!complex) 631 if (!complex)
619 return false; 632 return false;
620 return as_generator( 633 return as_generator(
621 "var " << string << " = new " << type << "(" << escape_keyword(param.param_name) 634 "var " << string << " = Efl.Eo.Globals.NativeListTo" << type << "(" << escape_keyword(param.param_name)
622 << ", " << (param.type.has_own ? "true" : "false")
623 << ", " << (complex->subtypes.front().is_value_type || complex->subtypes.front().has_own ? "true" : "false")
624 << ");\n" 635 << ");\n"
625 ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context); 636 ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
626 } 637 }
627 else if (param.type.c_type == "Eina_Iterator *" || param.type.c_type == "const Eina_Iterator *" 638 else if (param.type.c_type == "Eina_Array *" || param.type.c_type == "const Eina_Array *")
628 || param.type.c_type == "Eina_Accessor *" || param.type.c_type == "const Eina_Accessor *"
629 )
630 { 639 {
631 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type); 640 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
632 if (!complex) 641 if (!complex)
633 return false; 642 return false;
634 return as_generator( 643 return as_generator(
635 "var " << string << " = new " << type << "(" << escape_keyword(param.param_name) 644 "var " << string << " = Efl.Eo.Globals.NativeArrayTo" << type << "(" << escape_keyword(param.param_name)
636 << ", " << (param.type.has_own ? "true" : "false") 645 << ");\n"
646 ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
647 }
648
649 else if (param.type.c_type == "Eina_Iterator *" || param.type.c_type == "const Eina_Iterator *")
650 {
651 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
652 if (!complex)
653 return false;
654 return as_generator(
655 "var " << string << " = Efl.Eo.Globals.IteratorTo" << type << "(" << escape_keyword(param.param_name)
656 << ");\n"
657 ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
658 }
659 else if (param.type.c_type == "Eina_Accessor *" || param.type.c_type == "const Eina_Accessor *")
660 {
661 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
662 if (!complex)
663 return false;
664 return as_generator(
665 "var " << string << " = Efl.Eo.Globals.AccessorTo" << type << "(" << escape_keyword(param.param_name)
637 << ");\n" 666 << ");\n"
638 ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context); 667 ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.type), context);
639 } 668 }
@@ -671,10 +700,10 @@ struct convert_in_variable_generator
671 } 700 }
672 else if (param.type.c_type == "Eina_Binbuf *" || param.type.c_type == "const Eina_Binbuf *") 701 else if (param.type.c_type == "Eina_Binbuf *" || param.type.c_type == "const Eina_Binbuf *")
673 { 702 {
674 auto var_name = in_variable_name(param.param_name);
675 if (!as_generator( 703 if (!as_generator(
676 "var " << string << " = " << escape_keyword(param.param_name) << ".Handle;\n" 704 "Contract.Requires(" << string << " != null, nameof(" << string << "));\n"
677 ).generate(sink, var_name, context)) 705 << scope_tab(2) << "var " << string << " = " << string << ".Handle;\n"
706 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), escape_keyword(param.param_name), in_variable_name(param.param_name), escape_keyword(param.param_name)), context))
678 return false; 707 return false;
679 if (param.type.has_own) 708 if (param.type.has_own)
680 { 709 {
@@ -688,10 +717,10 @@ struct convert_in_variable_generator
688 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type); 717 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
689 if (!complex || complex->subtypes.size() != 2) 718 if (!complex || complex->subtypes.size() != 2)
690 return false; 719 return false;
691 auto var_name = in_variable_name(param.param_name);
692 if (!as_generator( 720 if (!as_generator(
693 "var " << string << " = " << escape_keyword(param.param_name) << ".Handle;\n" 721 "Contract.Requires(" << string << " != null, nameof(" << string << "));\n"
694 ).generate(sink, var_name, context)) 722 << scope_tab(2) << "var " << string << " = " << string << ".Handle;\n"
723 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), escape_keyword(param.param_name), in_variable_name(param.param_name), escape_keyword(param.param_name)), context))
695 return false; 724 return false;
696 if (param.type.has_own && !as_generator( 725 if (param.type.has_own && !as_generator(
697 escape_keyword(param.param_name) << ".SetOwn(false);\n" 726 escape_keyword(param.param_name) << ".SetOwn(false);\n"
@@ -707,42 +736,55 @@ struct convert_in_variable_generator
707 ).generate(sink, attributes::unused, context)) 736 ).generate(sink, attributes::unused, context))
708 return false; 737 return false;
709 } 738 }
710 else if (param.type.c_type == "Eina_Array *" || param.type.c_type == "const Eina_Array *" 739 else if (param.type.c_type == "Eina_Array *" || param.type.c_type == "const Eina_Array *")
711 || param.type.c_type == "Eina_List *" || param.type.c_type == "const Eina_List *" 740 {
712 || param.type.c_type == "Eina_Iterator *" || param.type.c_type == "const Eina_Iterator *" 741 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
713 || param.type.c_type == "Eina_Accessor *" || param.type.c_type == "const Eina_Accessor *" 742 if (!complex)
714 ) 743 return false;
744 if (!as_generator(
745 "var " << string << " = " << "Efl.Eo.Globals.IListToNativeArray(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false") << ");\n"
746 ).generate(sink, in_variable_name(param.param_name), context))
747 return false;
748 }
749 else if (param.type.c_type == "Eina_List *" || param.type.c_type == "const Eina_List *")
715 { 750 {
716 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type); 751 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
717 if (!complex) 752 if (!complex)
718 return false; 753 return false;
719 auto var_name = in_variable_name(param.param_name); 754 auto var_name = in_variable_name(param.param_name);
720 if (!as_generator( 755 if (!as_generator(
721 "var " << string << " = " << escape_keyword(param.param_name) << ".Handle;\n" 756 "var " << string << " = " << "Efl.Eo.Globals.IListToNativeList(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false") << ");\n"
722 ).generate(sink, var_name, context)) 757 ).generate(sink, var_name, context))
723 return false; 758 return false;
724 if (param.type.has_own && !as_generator( 759 }
725 escape_keyword(param.param_name) << ".Own = false;\n" 760 else if (param.type.c_type == "Eina_Iterator *" || param.type.c_type == "const Eina_Iterator *")
726 ).generate(sink, attributes::unused, context)) 761 {
762 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
763 if (!complex)
727 return false; 764 return false;
728 765 auto var_name = in_variable_name(param.param_name);
729 // Iterators and Accessors can't own their content. 766 if (!as_generator(
730 if (param.type.c_type == "Eina_Iterator *" || param.type.c_type == "const Eina_Iterator *" 767 "var " << string << " = Efl.Eo.Globals.IEnumerableToIterator(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
731 || param.type.c_type == "Eina_Accessor *" || param.type.c_type == "const Eina_Accessor *" 768 ).generate(sink, var_name, context))
732 ) 769 return false;
733 return true; 770 }
734 771 else if (param.type.c_type == "Eina_Accessor *" || param.type.c_type == "const Eina_Accessor *")
735 if (!complex->subtypes.front().is_value_type && complex->subtypes.front().has_own 772 {
736 && !as_generator( 773 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
737 escape_keyword(param.param_name) << ".OwnContent = false;\n" 774 if (!complex)
738 ).generate(sink, attributes::unused, context)) 775 return false;
776 auto var_name = in_variable_name(param.param_name);
777 if (!as_generator(
778 "var " << string << " = Efl.Eo.Globals.IEnumerableToAccessor(" << escape_keyword(param.param_name) << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
779 ).generate(sink, var_name, context))
739 return false; 780 return false;
740 } 781 }
741 else if (param.type.c_type == "Eina_Value") 782 else if (param.type.c_type == "Eina_Value")
742 { 783 {
743 return as_generator( 784 return as_generator(
744 "var " << string << " = " << string << ".GetNative();\n" 785 "Contract.Requires(" << string << " != null, nameof(" << string << "));\n"
745 ).generate(sink, std::make_tuple(in_variable_name(param.param_name), param.param_name), context); 786 "var " << string << " = " << string << ".GetNative();\n"
787 ).generate(sink, std::make_tuple(param.param_name, param.param_name, in_variable_name(param.param_name), param.param_name), context);
746 } 788 }
747 return true; 789 return true;
748 } 790 }
@@ -894,7 +936,7 @@ struct native_convert_out_variable_generator
894 // Assign a default value to the out variable in case we end up in the catch clause. 936 // Assign a default value to the out variable in case we end up in the catch clause.
895 return as_generator( 937 return as_generator(
896 string << " = default(" << type << ");" 938 string << " = default(" << type << ");"
897 ).generate(sink, std::make_tuple(param.param_name, param), context); 939 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param), context);
898 } 940 }
899 return true; 941 return true;
900 } 942 }
@@ -960,7 +1002,17 @@ struct convert_out_assign_generator
960 || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT) 1002 || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT)
961 || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT) 1003 || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT)
962 || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT) 1004 || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT)
963 || param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT) 1005 )
1006 {
1007 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
1008 if (!complex)
1009 return false;
1010 return as_generator(
1011 string << " = Efl.Eo.Globals.NativeArrayTo" << type << "(" << string
1012 << ");\n"
1013 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context);
1014 }
1015 else if (param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT)
964 || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT) 1016 || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT)
965 || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT) 1017 || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT)
966 || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT) 1018 || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT)
@@ -970,9 +1022,21 @@ struct convert_out_assign_generator
970 if (!complex) 1022 if (!complex)
971 return false; 1023 return false;
972 return as_generator( 1024 return as_generator(
973 string << " = new " << type << "(" << string 1025 string << " = Efl.Eo.Globals.NativeListTo" << type << "(" << string
974 << ", " << (param.type.has_own ? "true" : "false") 1026 << ");\n"
975 << ", " << (complex->subtypes.front().is_value_type || complex->subtypes.front().has_own ? "true" : "false") 1027 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context);
1028 }
1029 else if (param_is_acceptable(param, "Eina_Accessor *", WANT_OWN, WANT_OUT)
1030 || param_is_acceptable(param, "Eina_Accessor *", !WANT_OWN, WANT_OUT)
1031 || param_is_acceptable(param, "const Eina_Accessor *", WANT_OWN, WANT_OUT)
1032 || param_is_acceptable(param, "const Eina_Accessor *", !WANT_OWN, WANT_OUT)
1033 )
1034 {
1035 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
1036 if (!complex)
1037 return false;
1038 return as_generator(
1039 string << " = Efl.Eo.Globals.AccessorTo" << type << "(" << string
976 << ");\n" 1040 << ");\n"
977 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context); 1041 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context);
978 } 1042 }
@@ -980,18 +1044,13 @@ struct convert_out_assign_generator
980 || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT) 1044 || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT)
981 || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT) 1045 || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT)
982 || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT) 1046 || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT)
983 || param_is_acceptable(param, "Eina_Accessor *", WANT_OWN, WANT_OUT)
984 || param_is_acceptable(param, "Eina_Accessor *", !WANT_OWN, WANT_OUT)
985 || param_is_acceptable(param, "const Eina_Accessor *", WANT_OWN, WANT_OUT)
986 || param_is_acceptable(param, "const Eina_Accessor *", !WANT_OWN, WANT_OUT)
987 ) 1047 )
988 { 1048 {
989 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type); 1049 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
990 if (!complex) 1050 if (!complex)
991 return false; 1051 return false;
992 return as_generator( 1052 return as_generator(
993 string << " = new " << type << "(" << string 1053 string << " = Efl.Eo.Globals.IteratorTo" << type << "(" << string
994 << ", " << (param.type.has_own ? "true" : "false")
995 << ");\n" 1054 << ");\n"
996 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context); 1055 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), param.type, out_variable_name(param.param_name)), context);
997 } 1056 }
@@ -1036,6 +1095,17 @@ struct convert_in_ptr_assign_generator
1036 string << " = " << in_variable_name(param.param_name) << ";\n" 1095 string << " = " << in_variable_name(param.param_name) << ";\n"
1037 ).generate(sink, escape_keyword(param.param_name), context); 1096 ).generate(sink, escape_keyword(param.param_name), context);
1038 } 1097 }
1098 else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, !WANT_OUT)
1099 || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, !WANT_OUT)
1100 || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, !WANT_OUT)
1101 || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, !WANT_OUT)
1102 )
1103 {
1104 return as_generator(
1105 scope_tab(2) << lit("Efl.Eo.Globals.UpdateListFromNativeArray(") << escape_keyword(param.param_name) << ", " << in_variable_name(param.param_name) << ");\n"
1106 ).generate(sink, attributes::unused, context);
1107 }
1108
1039 1109
1040 return true; 1110 return true;
1041 } 1111 }
@@ -1093,27 +1163,40 @@ struct convert_return_generator
1093 .generate(sink, ret_type, context)) 1163 .generate(sink, ret_type, context))
1094 return false; 1164 return false;
1095 } 1165 }
1096 else if (ret_type.c_type == "Eina_Array *" || ret_type.c_type == "const Eina_Array *" 1166 else if (ret_type.c_type == "Eina_Array *" || ret_type.c_type == "const Eina_Array *")
1097 || ret_type.c_type == "Eina_List *" || ret_type.c_type == "const Eina_List *"
1098 )
1099 { 1167 {
1100 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type); 1168 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
1101 if (!complex) 1169 if (!complex)
1102 return false; 1170 return false;
1103 if (!as_generator("return new " << type << "(_ret_var, " << std::string{ret_type.has_own ? "true" : "false"} 1171
1104 << ", " << (complex->subtypes.front().is_value_type || complex->subtypes.front().has_own ? "true" : "false") 1172 if (!as_generator("return Efl.Eo.Globals.NativeArrayTo" << type << "(_ret_var);")
1105 << ");\n") 1173 .generate(sink, ret_type, context))
1106 .generate(sink, ret_type, context))
1107 return false; 1174 return false;
1108 } 1175 }
1109 else if(ret_type.c_type == "Eina_Iterator *" || ret_type.c_type == "const Eina_Iterator *" 1176 else if (ret_type.c_type == "Eina_List *" || ret_type.c_type == "const Eina_List *")
1110 || ret_type.c_type == "Eina_Accessor *" || ret_type.c_type == "const Eina_Accessor *"
1111 )
1112 { 1177 {
1113 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type); 1178 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
1114 if (!complex) 1179 if (!complex)
1115 return false; 1180 return false;
1116 if (!as_generator("return new " << type << "(_ret_var, " << std::string{ret_type.has_own ? "true" : "false"} << ");\n") 1181 if (!as_generator("return Efl.Eo.Globals.NativeListTo" << type << "(_ret_var);")
1182 .generate(sink, ret_type, context))
1183 return false;
1184 }
1185 else if (ret_type.c_type == "Eina_Accessor *" || ret_type.c_type == "const Eina_Accessor *")
1186 {
1187 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
1188 if (!complex)
1189 return false;
1190 if (!as_generator("return Efl.Eo.Globals.AccessorTo" << type << "(_ret_var);")
1191 .generate(sink, ret_type, context))
1192 return false;
1193 }
1194 else if (ret_type.c_type == "Eina_Iterator *" || ret_type.c_type == "const Eina_Iterator *")
1195 {
1196 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&ret_type.original_type);
1197 if (!complex)
1198 return false;
1199 if (!as_generator("return Efl.Eo.Globals.IteratorTo" << type << "(_ret_var);")
1117 .generate(sink, ret_type, context)) 1200 .generate(sink, ret_type, context))
1118 return false; 1201 return false;
1119 } 1202 }
@@ -1219,16 +1302,33 @@ struct native_convert_out_assign_generator
1219 else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT) 1302 else if (param_is_acceptable(param, "Eina_Array *", WANT_OWN, WANT_OUT)
1220 || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT) 1303 || param_is_acceptable(param, "Eina_Array *", !WANT_OWN, WANT_OUT)
1221 || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT) 1304 || param_is_acceptable(param, "const Eina_Array *", WANT_OWN, WANT_OUT)
1222 || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT) 1305 || param_is_acceptable(param, "const Eina_Array *", !WANT_OWN, WANT_OUT))
1223 || param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT) 1306 {
1307 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
1308 if (!complex)
1309 return false;
1310 auto outvar = out_variable_name(param.param_name);
1311 if (!as_generator(
1312 string << " = Efl.Eo.Globals.IListToNativeArray(" << string << ", " << (param.type.has_own ? "true" : "false")<< ");\n"
1313 ).generate(sink, std::make_tuple(escape_keyword(param.param_name), outvar), context))
1314 return false;
1315 }
1316 else if (param_is_acceptable(param, "Eina_List *", WANT_OWN, WANT_OUT)
1224 || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT) 1317 || param_is_acceptable(param, "Eina_List *", !WANT_OWN, WANT_OUT)
1225 || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT) 1318 || param_is_acceptable(param, "const Eina_List *", WANT_OWN, WANT_OUT)
1226 || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT) 1319 || param_is_acceptable(param, "const Eina_List *", !WANT_OWN, WANT_OUT))
1227 || param_is_acceptable(param, "Eina_Iterator *", WANT_OWN, WANT_OUT) 1320 {
1228 || param_is_acceptable(param, "Eina_Iterator *", !WANT_OWN, WANT_OUT) 1321 attributes::complex_type_def const* complex = efl::eina::get<attributes::complex_type_def>(&param.type.original_type);
1229 || param_is_acceptable(param, "const Eina_Iterator *", WANT_OWN, WANT_OUT) 1322 if (!complex)
1230 || param_is_acceptable(param, "const Eina_Iterator *", !WANT_OWN, WANT_OUT) 1323