summaryrefslogtreecommitdiff
path: root/src/bin/eolian_mono/eolian/mono/property_definition.hh
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2020-01-30 16:49:04 -0300
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2020-02-18 16:47:38 -0300
commit595cb754b3aa280cdbebcb5fa0c51f287099b713 (patch)
tree49ce2ed6e0e25b7268267d8255dddf46266dfe71 /src/bin/eolian_mono/eolian/mono/property_definition.hh
parentd00dadb79ab1c216ecc0519716ca25a1f92c3632 (diff)
eolian-mono: Make Get/Set internal for generated properties
Make Get and Set methods internal for properties that get the property syntax generated. Reviewed-by: João Paulo Taylor Ienczak Zanette <joao.tiz@expertisesolutions.com.br> Differential Revision: https://phab.enlightenment.org/D11252
Diffstat (limited to '')
-rw-r--r--src/bin/eolian_mono/eolian/mono/property_definition.hh383
1 files changed, 383 insertions, 0 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/property_definition.hh b/src/bin/eolian_mono/eolian/mono/property_definition.hh
new file mode 100644
index 0000000000..df94fc36e8
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/property_definition.hh
@@ -0,0 +1,383 @@
1/*
2 * Copyright 2019 by its authors. See AUTHORS.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16#ifndef EOLIAN_MONO_PROPERTY_DEFINITION_HH
17#define EOLIAN_MONO_PROPERTY_DEFINITION_HH
18
19#include "grammar/generator.hpp"
20#include "grammar/klass_def.hpp"
21
22#include "grammar/indentation.hpp"
23#include "grammar/list.hpp"
24#include "grammar/alternative.hpp"
25#include "type.hh"
26#include "parameter.hh"
27#include "name_helpers.hh"
28#include "using_decl.hh"
29#include "blacklist.hh"
30
31#include <eina_variant.hh>
32
33namespace eolian_mono {
34
35struct compare_get_and_set_value_type
36{
37 inline bool operator () (attributes::parameter_def const& get, attributes::parameter_def const& set) const;
38 inline bool operator () (attributes::type_def const& get, attributes::type_def const& set) const;
39};
40
41struct compare_get_and_set_value_type_overload
42{
43 template <typename T, typename U>
44 bool operator()(T const& /*left*/, U const& /*right*/) const
45 {
46 return false;
47 }
48 bool operator()(attributes::regular_type_def const& left, attributes::regular_type_def const& right) const
49 {
50 return left.base_type == right.base_type
51 && left.namespaces == right.namespaces;
52 }
53 bool operator()(attributes::complex_type_def const& left, attributes::complex_type_def const& right) const
54 {
55 return (*this)(left.outer, right.outer)
56 && std::equal (left.subtypes.begin(), left.subtypes.end(), right.subtypes.begin()
57 , compare_get_and_set_value_type{});
58 }
59 bool operator()(attributes::klass_name const& left, attributes::klass_name const& right) const
60 {
61 return left.namespaces == right.namespaces
62 && left.eolian_name == right.eolian_name;
63 }
64
65 typedef bool result_type;
66};
67
68inline bool compare_get_and_set_value_type::operator () (attributes::parameter_def const& get, attributes::parameter_def const& set) const
69{
70 return efl::eina::visit(compare_get_and_set_value_type_overload{}, get.type.original_type, set.type.original_type);
71}
72inline bool compare_get_and_set_value_type::operator () (attributes::type_def const& get, attributes::type_def const& set) const
73{
74 return efl::eina::visit(compare_get_and_set_value_type_overload{}, get.original_type, set.original_type);
75}
76
77template <typename Context>
78bool property_generate_wrapper_both_check(attributes::property_def const& property, Context const& context)
79{
80 if (blacklist::is_property_blacklisted(property, context))
81 return false;
82
83 bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
84 bool is_static = (property.getter.is_engaged() && property.getter->is_static)
85 || (property.setter.is_engaged() && property.setter->is_static);
86 bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
87
88 if ((is_concrete || is_interface) && is_static)
89 return false;
90
91 if (!property.getter)
92 return false;
93
94 if (property.setter)
95 {
96 if (property.getter->values.size() == property.setter->values.size())
97 {
98 if (!std::equal (property.getter->values.begin(), property.getter->values.end(), property.setter->values.begin()
99 , compare_get_and_set_value_type{}))
100 return false;
101 }
102 else
103 return false;
104 }
105
106 return true;
107}
108
109template <typename Context>
110bool property_generate_wrapper_getter(attributes::property_def const& property, Context const& context)
111{
112 if (!property_generate_wrapper_both_check (property, context))
113 return false;
114
115 if (!property.getter->keys.empty())
116 return false;
117
118 if (property.getter->explicit_return_type != attributes::void_)
119 return false;
120
121 assert (!!property.getter.is_engaged());
122
123 bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
124 if (is_interface)
125 {
126 std::string get_scope = property.getter.is_engaged() ? eolian_mono::function_scope_get(*property.getter) : "";
127 bool is_get_public = get_scope == "public ";
128 if (!is_get_public)
129 return false;
130 }
131 return true;
132}
133
134template <typename Context>
135bool property_generate_wrapper_setter (attributes::property_def const& property, Context const& context)
136{
137 if (!property_generate_wrapper_both_check (property, context))
138 return false;
139 if (!property.setter)
140 return false;
141
142 if (property.setter->explicit_return_type != attributes::void_)
143 return false;
144
145 if (!property.setter->keys.empty())
146 return false;
147
148 bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
149 if (property.setter.is_engaged() && is_interface)
150 {
151 std::string set_scope = property.setter.is_engaged() ? eolian_mono::function_scope_get(*property.setter) : "";
152 bool is_set_public = set_scope == "public ";
153 if (!is_set_public)
154 return false;
155 }
156
157 return true;
158}
159
160struct native_property_function_definition_generator
161{
162 template <typename OutputIterator, typename Context>
163 bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const
164 {
165 EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "native_property_function_definition_generator: " << property.name << std::endl;
166
167 if(blacklist::is_property_blacklisted(property, context))
168 return true;
169
170 auto const& indent = current_indentation(context);
171
172 bool has_wrapper_getter = property_generate_wrapper_getter (property, context);
173 bool has_wrapper_setter = property_generate_wrapper_setter (property, context);
174
175 auto gen = [&] (attributes::function_def const& f, bool is_set)
176 {
177 // Delegate for the C# method we will export to EO as a method implementation.
178 if(!as_generator
179 (
180 indent << eolian_mono::marshall_annotation(true) << "\n"
181 << indent << "private delegate "
182 << eolian_mono::marshall_type(true)
183 << " "
184 << string
185 << "_delegate(" << (f.is_static ? "" : "System.IntPtr obj, System.IntPtr pd")
186 << ((!f.is_static && f.parameters.size() > 0) ? ", " : "")
187 << (grammar::attribute_reorder<-1, -1>
188 (
189 (marshall_annotation << " " << marshall_parameter)
190 ) % ", ")
191 << ");\n\n")
192 .generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
193 return false;
194
195 // API delegate is the wrapper for the Eo methods exported from C that we will use from C#.
196 if(!as_generator
197 (
198 indent << eolian_mono::marshall_annotation(true) << "\n"
199 << indent << "internal delegate "
200 << eolian_mono::marshall_type(true)
201 << " "
202 << string << "_api_delegate(" << (f.is_static ? "" : "System.IntPtr obj")
203 << ((!f.is_static && f.parameters.size() > 0) ? ", " : "")
204 << (grammar::attribute_reorder<-1, -1>
205 (
206 (marshall_annotation << " " << marshall_parameter)
207 ) % ", ")
208 << ");\n\n")
209 .generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
210 return false;
211
212 // Delegate holder (so it can't be collected).
213 if(!as_generator
214 (indent << "internal static readonly Efl.Eo.FunctionWrapper<" << string << "_api_delegate> " << string << "_ptr = new Efl.Eo.FunctionWrapper<"
215 << string << "_api_delegate>(Module, \"" << string << "\");\n\n")
216 .generate(sink, std::make_tuple(f.c_name, f.c_name, f.c_name, f.c_name), context))
217 return false;
218
219 // We do not generate the wrapper to be called from C for non public interface member directly.
220 if (blacklist::is_non_public_interface_member(f, *implementing_klass))
221 return true;
222
223 // Do not generate static method in interface
224 if (((implementing_klass->type == attributes::class_type::interface_) ||
225 (implementing_klass->type == attributes::class_type::mixin)) && f.is_static)
226 return true;
227
228 // Actual method implementation to be called from C.
229 std::string return_type;
230 if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
231 return false;
232
233 std::string klass_cast_name;
234 if ((implementing_klass->type == attributes::class_type::interface_) ||
235 ((implementing_klass->type == attributes::class_type::mixin) && !f.is_static))
236 klass_cast_name = name_helpers::klass_interface_name(*implementing_klass);
237 else
238 klass_cast_name = name_helpers::klass_inherit_name(*implementing_klass);
239
240 std::string self = "Efl.Eo.Globals.Super(obj, Efl.Eo.Globals.GetClass(obj))";
241
242 if (f.is_static)
243 self = "";
244
245 if(!as_generator
246 (indent << "[SuppressMessage(\"Microsoft.Reliability\", \"CA2000:DisposeObjectsBeforeLosingScope\", Justification = \"The instantiated objects can be stored in the called Managed API method.\")]\n"
247 << indent << "private static "
248 << eolian_mono::marshall_type(true) << " "
249 << string
250 << "(System.IntPtr obj, System.IntPtr pd"
251 << *(", " << marshall_parameter)
252 << ")\n"
253 << indent << "{\n"
254 << indent << scope_tab << "Eina.Log.Debug(\"function " << string << " was called\");\n"
255 << indent << scope_tab << "var ws = Efl.Eo.Globals.GetWrapperSupervisor(obj);\n"
256 << indent << scope_tab << "if (ws != null)\n"
257 << indent << scope_tab << "{\n"
258 << indent << scope_tab << scope_tab << eolian_mono::native_function_definition_preamble() << "\n"
259 << indent << scope_tab << scope_tab << "try\n"
260 << indent << scope_tab << scope_tab << "{\n"
261 )
262 .generate(sink, std::make_tuple(f.return_type, escape_keyword(f.name), f.parameters
263 , /***/f.c_name/***/
264 , f
265 ), context))
266 return false;
267 if (is_set/* && has_wrapper_setter*/)
268 {
269 if(!as_generator
270 (
271 indent << scope_tab << scope_tab << scope_tab << (return_type != "void" ? "_ret_var = " : "")
272 << (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")ws.Target).") << string
273 )
274 .generate(sink, std::make_tuple(name_helpers::property_managed_name(property), f.parameters), context))
275 return false;
276
277 if(!f.keys.empty() && !as_generator(lit("[(") << (native_argument_invocation % ", ") << ")]").generate (sink, f.keys, context))
278 return false;
279
280 if(!as_generator
281 (" = ("
282 << (native_tuple_argument_invocation % ", ") << ");\n"
283 )
284 .generate(sink, f.values, context))
285 return false;
286 }
287 else if (!is_set/* && has_wrapper_getter*/)
288 {
289 if(!as_generator
290 (
291 indent << scope_tab << scope_tab << scope_tab << "var ret = "
292 << (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")ws.Target).")
293 << string
294
295 )
296 .generate(sink, std::make_tuple(name_helpers::property_managed_name(property)), context))
297 return false;
298
299 if(!f.keys.empty() && !as_generator(lit("[(") << (native_argument_invocation % ", ") << ")]").generate (sink, f.keys, context))
300 return false;
301
302 if (!as_generator(";\n").generate (sink, attributes::unused, context))
303 return false;
304
305 }
306 // else if (!as_generator
307 // (indent << scope_tab << scope_tab << scope_tab << (return_type != "void" ? "_ret_var = " : "")
308 // << (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")ws.Target).") << string
309 // << "(" << (native_argument_invocation % ", ") << ");\n"
310 // ).generate(sink, std::make_tuple(name_helpers::managed_method_name(f), f.parameters), context))
311 // return false;
312
313 if(!as_generator
314 (
315 indent << scope_tab << scope_tab << "}\n"
316 << indent << scope_tab << scope_tab << "catch (Exception e)\n"
317 << indent << scope_tab << scope_tab << "{\n"
318 << indent << scope_tab << scope_tab << scope_tab << "Eina.Log.Warning($\"Callback error: {e.ToString()}\");\n"
319 << indent << scope_tab << scope_tab << scope_tab << "Eina.Error.Set(Eina.Error.UNHANDLED_EXCEPTION);\n"
320 << indent << scope_tab << scope_tab << "}\n\n"
321 << indent << eolian_mono::native_function_definition_epilogue(*implementing_klass) << "\n"
322 << indent << scope_tab << "}\n"
323 << indent << scope_tab << "else\n"
324 << indent << scope_tab << "{\n"
325 << indent << scope_tab << scope_tab << (return_type != "void" ? "return " : "") << string
326 << "_ptr.Value.Delegate(" << self << ((!f.is_static && f.parameters.size() > 0) ? ", " : "") << (argument % ", ") << ");\n"
327 << indent << scope_tab << "}\n"
328 << indent << "}\n\n"
329 )
330 .generate(sink, std::make_tuple(f, f.c_name, f.parameters), context))
331 return false;
332
333 // Static functions do not need to be called from C
334 if (f.is_static)
335 return true;
336
337 // This is the delegate that will be passed to Eo to be called from C.
338 if(!as_generator(
339 indent << "private static " << f.c_name << "_delegate " << f.c_name << "_static_delegate;\n\n"
340 ).generate(sink, attributes::unused, context))
341 return false;
342 return true;
343 };
344
345 bool r = true;
346 if(r && property.getter && has_wrapper_getter
347 && helpers::is_function_registerable (*property.getter, *implementing_klass))
348 r &= gen (*property.getter, false);
349 if(r && property.setter && has_wrapper_setter
350 && helpers::is_function_registerable (*property.setter, *implementing_klass))
351 r &= gen (*property.setter, true);
352 return r;
353 }
354
355 attributes::klass_def const* implementing_klass, *klass_from_property;
356};
357
358struct native_property_function_definition_parameterized
359{
360 native_property_function_definition_generator operator()(attributes::klass_def const& klass
361 , attributes::klass_def const& prop_from_klass) const
362 {
363 return {&klass, &prop_from_klass};
364 }
365} const native_property_function_definition;
366
367}
368
369namespace efl { namespace eolian { namespace grammar {
370
371template <>
372struct is_eager_generator< ::eolian_mono::native_property_function_definition_generator> : std::true_type {};
373template <>
374struct is_generator< ::eolian_mono::native_property_function_definition_generator> : std::true_type {};
375
376namespace type_traits {
377
378template <>
379struct attributes_needed< ::eolian_mono::native_property_function_definition_generator> : std::integral_constant<int, 1> {};
380
381} } } }
382
383#endif