summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2019-12-26 23:50:20 -0300
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2020-01-07 16:56:12 -0300
commitcd72923bf178cca1a0418ed55956769add2732d8 (patch)
tree12d84c4e2e117890e2e78054cca3c022b9e91a63
parentcf37047a7c77e4ce7d76bbbfd93a042d59ac2771 (diff)
eolian-mono: Make Get/Set protected for generated propertiesdevs/felipealmeida/hide-properties
Make Get and Set methods protected for properties that get the property syntax generated. This is still a work in progress and fails compilation. Native calls should use the property-syntax instead of the method, which may not be available in some interfaces.
-rw-r--r--src/bin/eolian_mono/eolian/mono/blacklist.hh2
-rw-r--r--src/bin/eolian_mono/eolian/mono/documentation.hh88
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_declaration.hh69
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_definition.hh412
-rw-r--r--src/bin/eolian_mono/eolian/mono/function_registration.hh5
-rw-r--r--src/bin/eolian_mono/eolian/mono/helpers.hh128
-rw-r--r--src/bin/eolian_mono/eolian/mono/klass.hh76
-rw-r--r--src/bindings/mono/efl_mono/GenericModel.cs31
-rw-r--r--src/bindings/mono/efl_mono/UserModel.cs2
-rw-r--r--src/bindings/mono/efl_sharp.csproj.in2
-rw-r--r--src/bindings/mono/eo_mono/EoWrapper.cs2
-rw-r--r--src/lib/eolian_cxx/grammar/klass_def.hpp62
-rw-r--r--src/tests/efl_mono/Eo.cs4
-rw-r--r--src/tests/efl_mono/Model.cs2
14 files changed, 800 insertions, 85 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/blacklist.hh b/src/bin/eolian_mono/eolian/mono/blacklist.hh
index 70bc34a..6e73d80 100644
--- a/src/bin/eolian_mono/eolian/mono/blacklist.hh
+++ b/src/bin/eolian_mono/eolian/mono/blacklist.hh
@@ -163,7 +163,7 @@ inline bool is_property_blacklisted(std::string const& name)
163 // Will be bound manually 163 // Will be bound manually
164 , "Efl.Core.Env.Env" 164 , "Efl.Core.Env.Env"
165 // Setter returns a future 165 // Setter returns a future
166 , "Efl.IModel.Property" 166 //, "Efl.IModel.Property"
167 // Protected 167 // Protected
168 , "Efl.Access.IAction.ActionName" 168 , "Efl.Access.IAction.ActionName"
169 , "Efl.Access.IAction.ActionLocalizedName" 169 , "Efl.Access.IAction.ActionLocalizedName"
diff --git a/src/bin/eolian_mono/eolian/mono/documentation.hh b/src/bin/eolian_mono/eolian/mono/documentation.hh
index db00ba8..1c7c1e5 100644
--- a/src/bin/eolian_mono/eolian/mono/documentation.hh
+++ b/src/bin/eolian_mono/eolian/mono/documentation.hh
@@ -118,13 +118,7 @@ struct documentation_generator
118 name += name_helpers::managed_method_name({function, ftype, NULL, eolian_object_unit_get(EOLIAN_OBJECT(function))}); 118 name += name_helpers::managed_method_name({function, ftype, NULL, eolian_object_unit_get(EOLIAN_OBJECT(function))});
119 break; 119 break;
120 case ::EOLIAN_PROP_SET: 120 case ::EOLIAN_PROP_SET:
121 name += ".Set";
122 name += name_helpers::property_managed_name(klass_d, eo_name);
123 break;
124 case ::EOLIAN_PROP_GET: 121 case ::EOLIAN_PROP_GET:
125 name += ".Get";
126 name += name_helpers::property_managed_name(klass_d, eo_name);
127 break;
128 case ::EOLIAN_PROPERTY: 122 case ::EOLIAN_PROPERTY:
129 { 123 {
130 std::string short_name = name_helpers::property_managed_name(klass_d, eo_name); 124 std::string short_name = name_helpers::property_managed_name(klass_d, eo_name);
@@ -146,11 +140,16 @@ struct documentation_generator
146 140
147 auto has_wrapper = helpers::has_property_wrapper(prop, &klass_d, my_context); 141 auto has_wrapper = helpers::has_property_wrapper(prop, &klass_d, my_context);
148 142
149 if (has_wrapper == helpers::has_property_wrapper_bit::has_none) 143 if (has_wrapper & helpers::has_property_wrapper_bit::has_getter
150 name += ".Get" + short_name; 144 // If there is no getter, there's no property.
151 else if (name_tail == ".get") name += ".Get" + short_name; 145 &&
152 else if (name_tail == ".set") name += ".Set" + short_name; 146 (
153 else name += "." + short_name; 147 (ftype == EOLIAN_PROP_GET || ftype == EOLIAN_PROPERTY)
148 || (has_wrapper & helpers::has_property_wrapper_bit::has_setter && ftype == EOLIAN_PROP_SET))
149 )
150 name += "." + short_name;
151 else if (ftype == EOLIAN_PROP_GET || name_tail == ".get") name += ".Get" + short_name;
152 else if (ftype == EOLIAN_PROP_SET || name_tail == ".set") name += ".Set" + short_name;
154 } 153 }
155 break; 154 break;
156 default: 155 default:
@@ -159,18 +158,69 @@ struct documentation_generator
159 return name; 158 return name;
160 } 159 }
161 160
162 static std::string function_conversion(attributes::function_def const& func) 161 template <typename Context>
162 static std::string function_conversion(attributes::function_def const& func, Context const& context)
163 { 163 {
164 // This function is called only from the constructor reference conversion, so it does not 164 // This function is called only from the constructor reference conversion, so it does not
165 // need to check whether this function non-public in a interface returning an empty reference (yet). 165 // need to check whether this function non-public in a interface returning an empty reference (yet).
166 std::string name = name_helpers::klass_full_concrete_or_interface_name(func.klass); 166 std::string name = name_helpers::klass_full_concrete_or_interface_name(func.klass);
167 switch (func.type) 167 switch (func.type)
168 { 168 {
169 // managed_method_name takes care of reordering the function name so the get/set goes first 169 case attributes::function_type::property:
170 // for properties
171 case attributes::function_type::method:
172 case attributes::function_type::prop_set: 170 case attributes::function_type::prop_set:
173 case attributes::function_type::prop_get: 171 case attributes::function_type::prop_get:
172 {
173 auto unit = (const Eolian_Unit*) context_find_tag<eolian_state_context>(context).state;
174 auto klass = get_klass(func.klass, unit);
175 attributes::klass_def klass_d(klass, unit);
176
177 auto eo_name = func.name;
178 auto prop_name = eo_name;
179 if (prop_name.size () > 4
180 &&
181 ( prop_name.substr(prop_name.size() - 4) == "_set"
182 || prop_name.substr(prop_name.size() - 4) == "_get"))
183 {
184 prop_name = prop_name.substr(0, prop_name.size() - 4);
185 }
186 std::string short_name = name_helpers::property_managed_name(klass_d, prop_name);
187 assert (prop_name.size() <= 4 ||
188 (prop_name.substr(prop_name.size() - 4) != "_set"
189 && prop_name.substr(prop_name.size() - 4) != "_get"));
190 assert (short_name.size() <= 3 ||
191 (short_name.substr(short_name.size() - 3) != "Set"
192 && short_name.substr(short_name.size() - 3) != "Get"));
193
194 // We need to replace the current class context with the context
195 // from the class that originated this property.
196 class_context::wrapper_kind klass_kind;
197 if (helpers::is_managed_interface(klass_d))
198 klass_kind = class_context::interface;
199 else
200 klass_kind = class_context::inherit;
201
202 auto my_context = grammar::context_replace_tag(class_context{klass_kind}, context);
203
204 auto function = eolian_class_function_by_name_get (klass, prop_name.c_str(), EOLIAN_PROPERTY);
205 attributes::function_def getter_func{function, ::EOLIAN_PROP_GET, nullptr, unit};
206 attributes::function_def setter_func{function, ::EOLIAN_PROP_SET, nullptr, unit};
207 attributes::property_def prop{function, getter_func, setter_func, unit};
208
209 auto has_wrapper = helpers::has_property_wrapper(prop, &klass_d, my_context);
210
211 if (has_wrapper & helpers::has_property_wrapper_bit::has_getter
212 // If there is no getter, there's no property.
213 &&
214 (
215 (func.type == attributes::function_type::prop_get || func.type == attributes::function_type::property)
216 || (has_wrapper & helpers::has_property_wrapper_bit::has_setter && func.type == attributes::function_type::prop_set))
217 )
218 name += "." + short_name;
219 else if (func.type == attributes::function_type::prop_get) name += ".Get" + short_name;
220 else if (func.type == attributes::function_type::prop_set) name += ".Set" + short_name;
221 }
222 break;
223 case attributes::function_type::method:
174 if (blacklist::is_function_blacklisted(func.c_name))return ""; 224 if (blacklist::is_function_blacklisted(func.c_name))return "";
175 if (!name.empty()) name += "."; 225 if (!name.empty()) name += ".";
176 name += name_helpers::managed_method_name(func); 226 name += name_helpers::managed_method_name(func);
@@ -218,8 +268,10 @@ struct documentation_generator
218 is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2); 268 is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2);
219 break; 269 break;
220 case ::EOLIAN_OBJECT_FUNCTION: 270 case ::EOLIAN_OBJECT_FUNCTION:
221 ref += function_conversion(data, (const ::Eolian_Function *)data2, name_tail, context); 271 {
222 is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2); 272 ref += function_conversion(data, (const ::Eolian_Function *)data2, name_tail, context);
273 is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2);
274 }
223 break; 275 break;
224 case ::EOLIAN_OBJECT_CONSTANT: 276 case ::EOLIAN_OBJECT_CONSTANT:
225 { 277 {
@@ -634,7 +686,7 @@ struct documentation_generator
634 686
635 for (auto &&param : ctor.function.parameters) 687 for (auto &&param : ctor.function.parameters)
636 { 688 {
637 auto ref = function_conversion(func); 689 auto ref = function_conversion(func, context);
638 690
639 if (!context_find_tag<options_context>(context).want_beta && func.is_beta) 691 if (!context_find_tag<options_context>(context).want_beta && func.is_beta)
640 { 692 {
diff --git a/src/bin/eolian_mono/eolian/mono/function_declaration.hh b/src/bin/eolian_mono/eolian/mono/function_declaration.hh
index b71ffb1..ab59b85 100644
--- a/src/bin/eolian_mono/eolian/mono/function_declaration.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_declaration.hh
@@ -53,6 +53,63 @@ struct function_declaration_generator
53 53
54function_declaration_generator const function_declaration = {}; 54function_declaration_generator const function_declaration = {};
55 55
56struct property_declaration_generator
57{
58 template <typename OutputIterator, typename Context>
59 bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const
60 {
61 if(blacklist::is_property_blacklisted(property, *implementing_klass, context))
62 return true;
63
64 auto has_wrapper = helpers::has_property_wrapper (property, implementing_klass, context);
65 bool has_getter_wrapper = has_wrapper & helpers::has_property_wrapper_bit::has_getter;
66 bool has_setter_wrapper = has_wrapper & helpers::has_property_wrapper_bit::has_setter;
67
68 auto gen = [&] (attributes::function_def const& f)
69 {
70 // C# interfaces can't have non-public members
71 if(f.scope != attributes::member_scope::scope_public)
72 return true;
73
74 if (f.is_static)
75 return true;
76
77 if(!as_generator(documentation(1)).generate(sink, f, context))
78 return false;
79
80 return as_generator
81 (scope_tab << eolian_mono::type(true) << " " << string << "(" << (parameter % ", ") << ");\n\n")
82 .generate(sink, std::make_tuple(f.return_type, name_helpers::managed_method_name(f), f.parameters), context);
83 };
84 bool r = true;
85 if (property.getter)
86 {
87 if (!has_getter_wrapper)
88 r &= gen (*property.getter);
89 // else
90 // r &= function_declaration.generate(sink, *property.getter, context);
91 }
92 if (r && property.setter)
93 {
94 if (!has_setter_wrapper)
95 r &= gen (*property.setter);
96 // else
97 // r &= function_declaration.generate(sink, *property.setter, context);
98 }
99 return r;
100 }
101 attributes::klass_def const* implementing_klass, *klass_from_property;
102};
103
104struct property_declaration_parameterized
105{
106 property_declaration_generator operator()(attributes::klass_def const& klass
107 , attributes::klass_def const& prop_from_klass) const
108 {
109 return {&klass, &prop_from_klass};
110 }
111} const property_declaration;
112
56} 113}
57 114
58namespace efl { namespace eolian { namespace grammar { 115namespace efl { namespace eolian { namespace grammar {
@@ -60,11 +117,23 @@ namespace efl { namespace eolian { namespace grammar {
60template <> 117template <>
61struct is_eager_generator< ::eolian_mono::function_declaration_generator> : std::true_type {}; 118struct is_eager_generator< ::eolian_mono::function_declaration_generator> : std::true_type {};
62template <> 119template <>
120struct is_eager_generator< ::eolian_mono::property_declaration_generator> : std::true_type {};
121template <>
122struct is_eager_generator< ::eolian_mono::property_declaration_parameterized> : std::true_type {};
123template <>
63struct is_generator< ::eolian_mono::function_declaration_generator> : std::true_type {}; 124struct is_generator< ::eolian_mono::function_declaration_generator> : std::true_type {};
125template <>
126struct is_generator< ::eolian_mono::property_declaration_generator> : std::true_type {};
127template <>
128struct is_generator< ::eolian_mono::property_declaration_parameterized> : std::true_type {};
64 129
65namespace type_traits { 130namespace type_traits {
66template <> 131template <>
67struct attributes_needed< ::eolian_mono::function_declaration_generator> : std::integral_constant<int, 1> {}; 132struct attributes_needed< ::eolian_mono::function_declaration_generator> : std::integral_constant<int, 1> {};
133template <>
134struct attributes_needed< ::eolian_mono::property_declaration_generator> : std::integral_constant<int, 1> {};
135template <>
136struct attributes_needed< ::eolian_mono::property_declaration_parameterized> : std::integral_constant<int, 1> {};
68} 137}
69 138
70} } } 139} } }
diff --git a/src/bin/eolian_mono/eolian/mono/function_definition.hh b/src/bin/eolian_mono/eolian/mono/function_definition.hh
index 86eb2db..cbf2e2b 100644
--- a/src/bin/eolian_mono/eolian/mono/function_definition.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_definition.hh
@@ -50,6 +50,10 @@ struct native_function_definition_generator
50 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const 50 bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
51 { 51 {
52 EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "native_function_definition_generator: " << f.c_name << std::endl; 52 EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "native_function_definition_generator: " << f.c_name << std::endl;
53 assert (!(f.type == attributes::function_type::property
54 || f.type == attributes::function_type::prop_set
55 || f.type == attributes::function_type::prop_get));
56
53 if(blacklist::is_function_blacklisted(f, context)) 57 if(blacklist::is_function_blacklisted(f, context))
54 return true; 58 return true;
55 59
@@ -183,6 +187,203 @@ struct native_function_definition_generator
183 } 187 }
184}; 188};
185 189
190struct native_property_function_definition_generator
191{
192 template <typename OutputIterator, typename Context>
193 bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const
194 {
195 EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "native_property_function_definition_generator: " << property.name << std::endl;
196
197 if(blacklist::is_property_blacklisted(property, *implementing_klass, context))
198 return true;
199
200 auto const& indent = current_indentation(context);
201
202 auto has_wrapper = helpers::has_property_wrapper (property, implementing_klass, context);
203 bool has_wrapper_getter = has_wrapper & helpers::has_property_wrapper_bit::has_getter;
204 bool has_wrapper_setter = has_wrapper & helpers::has_property_wrapper_bit::has_setter;
205
206 auto gen = [&] (attributes::function_def const& f, bool is_set)
207 {
208 // Delegate for the C# method we will export to EO as a method implementation.
209 if(!as_generator
210 (
211 indent << eolian_mono::marshall_annotation(true) << "\n"
212 << indent << "private delegate "
213 << eolian_mono::marshall_type(true)
214 << " "
215 << string
216 << "_delegate(" << (f.is_static ? "" : "System.IntPtr obj, System.IntPtr pd")
217 << ((!f.is_static && f.parameters.size() > 0) ? ", " : "")
218 << (grammar::attribute_reorder<-1, -1>
219 (
220 (marshall_annotation << " " << marshall_parameter)
221 ) % ", ")
222 << ");\n\n")
223 .generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
224 return false;
225
226 // API delegate is the wrapper for the Eo methods exported from C that we will use from C#.
227 if(!as_generator
228 (
229 indent << eolian_mono::marshall_annotation(true) << "\n"
230 << indent << "internal delegate "
231 << eolian_mono::marshall_type(true)
232 << " "
233 << string << "_api_delegate(" << (f.is_static ? "" : "System.IntPtr obj")
234 << ((!f.is_static && f.parameters.size() > 0) ? ", " : "")
235 << (grammar::attribute_reorder<-1, -1>
236 (
237 (marshall_annotation << " " << marshall_parameter)
238 ) % ", ")
239 << ");\n\n")
240 .generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
241 return false;
242
243 // Delegate holder (so it can't be collected).
244 if(!as_generator
245 (indent << "internal static readonly Efl.Eo.FunctionWrapper<" << string << "_api_delegate> " << string << "_ptr = new Efl.Eo.FunctionWrapper<"
246 << string << "_api_delegate>(Module, \"" << string << "\");\n\n")
247 .generate(sink, std::make_tuple(f.c_name, f.c_name, f.c_name, f.c_name), context))
248 return false;
249
250 // We do not generate the wrapper to be called from C for non public interface member directly.
251 if (blacklist::is_non_public_interface_member(f, *implementing_klass))
252 return true;
253
254 // Do not generate static method in interface
255 if (((implementing_klass->type == attributes::class_type::interface_) ||
256 (implementing_klass->type == attributes::class_type::mixin)) && f.is_static)
257 return true;
258
259 // Actual method implementation to be called from C.
260 std::string return_type;
261 if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
262 return false;
263
264 std::string klass_cast_name;
265 if ((implementing_klass->type == attributes::class_type::interface_) ||
266 ((implementing_klass->type == attributes::class_type::mixin) && !f.is_static))
267 klass_cast_name = name_helpers::klass_interface_name(*implementing_klass);
268 else
269 klass_cast_name = name_helpers::klass_inherit_name(*implementing_klass);
270
271 std::string self = "Efl.Eo.Globals.Super(obj, Efl.Eo.Globals.GetClass(obj))";
272
273 if (f.is_static)
274 self = "";
275
276 if(!as_generator
277 (indent << "[SuppressMessage(\"Microsoft.Reliability\", \"CA2000:DisposeObjectsBeforeLosingScope\", Justification = \"The instantiated objects can be stored in the called Managed API method.\")]\n"
278 << indent << "private static "
279 << eolian_mono::marshall_type(true) << " "
280 << string
281 << "(System.IntPtr obj, System.IntPtr pd"
282 << *(", " << marshall_parameter)
283 << ")\n"
284 << indent << "{\n"
285 << indent << scope_tab << "Eina.Log.Debug(\"function " << string << " was called\");\n"
286 << indent << scope_tab << "var ws = Efl.Eo.Globals.GetWrapperSupervisor(obj);\n"
287 << indent << scope_tab << "if (ws != null)\n"
288 << indent << scope_tab << "{\n"
289 << indent << scope_tab << scope_tab << eolian_mono::native_function_definition_preamble() << "\n"
290 << indent << scope_tab << scope_tab << "try\n"
291 << indent << scope_tab << scope_tab << "{\n"
292 )
293 .generate(sink, std::make_tuple(f.return_type, escape_keyword(f.name), f.parameters
294 , /***/f.c_name/***/
295 , f
296 ), context))
297 return false;
298 if (is_set && has_wrapper_setter)
299 {
300 if(!as_generator
301 (
302 indent << scope_tab << scope_tab << scope_tab << (return_type != "void" ? "_ret_var = " : "")
303 << (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")ws.Target).") << string
304 )
305 .generate(sink, std::make_tuple(name_helpers::property_managed_name(property), f.parameters), context))
306 return false;
307
308 if(!f.keys.empty() && !as_generator(lit("[(") << (native_argument_invocation % ", ") << ")]").generate (sink, f.keys, context))
309 return false;
310
311 if(!as_generator
312 (" = ("
313 << (native_argument_invocation % ", ") << ");\n"
314 )
315 .generate(sink, f.values, context))
316 return false;
317 }
318 else if (!is_set && has_wrapper_getter)
319 {
320 if(!as_generator
321 (
322 indent << scope_tab << scope_tab << scope_tab << "var ret = "
323 << (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")ws.Target).")
324 << string
325
326 )
327 .generate(sink, std::make_tuple(name_helpers::property_managed_name(property)), context))
328 return false;
329
330 if(!f.keys.empty() && !as_generator(lit("[(") << (native_argument_invocation % ", ") << ")]").generate (sink, f.keys, context))
331 return false;
332
333 if (!as_generator(";\n").generate (sink, attributes::unused, context))
334 return false;
335
336 }
337 else if (!as_generator
338 (indent << scope_tab << scope_tab << scope_tab << (return_type != "void" ? "_ret_var = " : "")
339 << (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")ws.Target).") << string
340 << "(" << (native_argument_invocation % ", ") << ");\n"
341 ).generate(sink, std::make_tuple(name_helpers::managed_method_name(f), f.parameters), context))
342 return false;
343
344 if(!as_generator
345 (
346 indent << scope_tab << scope_tab << "}\n"
347 << indent << scope_tab << scope_tab << "catch (Exception e)\n"
348 << indent << scope_tab << scope_tab << "{\n"
349 << indent << scope_tab << scope_tab << scope_tab << "Eina.Log.Warning($\"Callback error: {e.ToString()}\");\n"
350 << indent << scope_tab << scope_tab << scope_tab << "Eina.Error.Set(Eina.Error.UNHANDLED_EXCEPTION);\n"
351 << indent << scope_tab << scope_tab << "}\n\n"
352 << indent << eolian_mono::native_function_definition_epilogue(*implementing_klass) << "\n"
353 << indent << scope_tab << "}\n"
354 << indent << scope_tab << "else\n"
355 << indent << scope_tab << "{\n"
356 << indent << scope_tab << scope_tab << (return_type != "void" ? "return " : "") << string
357 << "_ptr.Value.Delegate(" << self << ((!f.is_static && f.parameters.size() > 0) ? ", " : "") << (argument % ", ") << ");\n"
358 << indent << scope_tab << "}\n"
359 << indent << "}\n\n"
360 )
361 .generate(sink, std::make_tuple(f, f.c_name, f.parameters), context))
362 return false;
363
364 // Static functions do not need to be called from C
365 if (f.is_static)
366 return true;
367
368 // This is the delegate that will be passed to Eo to be called from C.
369 // if(!as_generator(
370 // indent << "private static " << f.c_name << "_delegate " << f.c_name << "_static_delegate;\n\n"
371 // ).generate(sink, attributes::unused, context))
372 // return false;
373 return true;
374 };
375
376 bool r = true;
377 if(r && property.getter)
378 r &= gen (*property.getter, false);
379 if(r && property.setter)
380 r &= gen (*property.setter, true);
381 return r;
382 }
383
384 attributes::klass_def const* implementing_klass, *klass_from_property;
385};
386
186struct function_definition_generator 387struct function_definition_generator
187{ 388{
188 function_definition_generator(bool do_super = false) 389 function_definition_generator(bool do_super = false)
@@ -194,6 +395,10 @@ struct function_definition_generator
194 { 395 {
195 EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "function_definition_generator: " << f.c_name << std::endl; 396 EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "function_definition_generator: " << f.c_name << std::endl;
196 397
398 assert (!(f.type == attributes::function_type::property
399 || f.type == attributes::function_type::prop_set
400 || f.type == attributes::function_type::prop_get));
401
197 bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete; 402 bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
198 if(blacklist::is_function_blacklisted(f, context)) 403 if(blacklist::is_function_blacklisted(f, context))
199 return true; 404 return true;
@@ -256,6 +461,14 @@ struct native_function_definition_parameterized
256 return {&klass}; 461 return {&klass};
257 } 462 }
258} const native_function_definition; 463} const native_function_definition;
464struct native_property_function_definition_parameterized
465{
466 native_property_function_definition_generator operator()(attributes::klass_def const& klass
467 , attributes::klass_def const& prop_from_klass) const
468 {
469 return {&klass, &prop_from_klass};
470 }
471} const native_property_function_definition;
259 472
260struct property_extension_method_definition_generator 473struct property_extension_method_definition_generator
261{ 474{
@@ -414,9 +627,9 @@ struct property_wrapper_definition_generator
414 } 627 }
415 assert (!get_keys.empty()); 628 assert (!get_keys.empty());
416 629
417 generate_get(sink, property, context, get_scope, get_keys, values, is_interface, "Self."); 630 generate_get(sink, property, context, get_scope, get_keys, values, is_interface, "((" + name_helpers::klass_full_concrete_name (*implementing_klass) + ")Self).");
418 if (has_setter) 631 if (has_setter)
419 generate_set(sink, property, context, set_scope, get_keys, values, is_interface, "Self."); 632 generate_set(sink, property, context, set_scope, get_keys, values, is_interface, "((" + name_helpers::klass_full_concrete_name (*implementing_klass) + ")Self).");
420 633
421 if (!as_generator 634 if (!as_generator
422 ( 635 (
@@ -648,22 +861,40 @@ struct property_wrapper_definition_generator
648 std::string set_scope = has_setter ? eolian_mono::function_scope_get(*property.setter) : ""; 861 std::string set_scope = has_setter ? eolian_mono::function_scope_get(*property.setter) : "";
649 862
650 // C# interface members are declared automatically as public 863 // C# interface members are declared automatically as public
651 if (is_interface) 864 if (force_protected)
652 { 865 {
653 scope = ""; 866 scope = "protected ";
654 get_scope = ""; 867 get_scope = "";
655 set_scope = ""; 868 set_scope = "";
656 } 869 }
657 else if ((get_scope != "") && (get_scope == set_scope)) 870 else if (is_interface)
658 { 871 {
659 scope = get_scope; 872 scope = "";
660 get_scope = ""; 873 get_scope = "";
661 set_scope = ""; 874 set_scope = "";
662 } 875 }
663 else if (!has_setter || (get_scope == scope)) 876 else
664 { 877 {
665 scope = get_scope; 878 auto want_beta = context_find_tag<options_context>(context).want_beta;
666 get_scope = ""; 879 if (!want_beta && property.getter->is_beta)
880 {
881 get_scope = "protected ";
882 }
883 if (property.setter && !want_beta && property.setter->is_beta)
884 {
885 set_scope = "protected ";
886 }
887 if ((get_scope != "") && (get_scope == set_scope))
888 {
889 scope = get_scope;
890 get_scope = "";
891 set_scope = "";
892 }
893 else if (!has_setter || (get_scope == scope))
894 {
895 scope = get_scope;
896 get_scope = "";
897 }
667 } 898 }
668 899
669 std::string virtual_mod = (is_static || is_interface || is_concrete) ? "" : "virtual "; 900 std::string virtual_mod = (is_static || is_interface || is_concrete) ? "" : "virtual ";
@@ -735,6 +966,10 @@ struct property_wrapper_definition_generator
735 if (has_indexer) 966 if (has_indexer)
736 { 967 {
737 generate_get_indexer (sink, property, context, get_scope, is_interface); 968 generate_get_indexer (sink, property, context, get_scope, is_interface);
969 if (is_interface)
970 as_generator(scope_tab(2) << "set;\n").generate (sink, attributes::unused, context);
971 else
972 as_generator(scope_tab(2) << "set {}\n").generate (sink, attributes::unused, context);
738 } 973 }
739 else 974 else
740 { 975 {
@@ -751,18 +986,20 @@ struct property_wrapper_definition_generator
751 return true; 986 return true;
752 } 987 }
753 attributes::klass_def const* implementing_klass, *klass_from_property; 988 attributes::klass_def const* implementing_klass, *klass_from_property;
989 bool force_protected;
754}; 990};
755struct property_wrapper_definition_parameterized 991struct property_wrapper_definition_parameterized
756{ 992{
757 property_wrapper_definition_generator operator()(attributes::klass_def const& klass 993 property_wrapper_definition_generator operator()(attributes::klass_def const& klass
758 , attributes::klass_def const& prop_from_klass) const 994 , attributes::klass_def const& prop_from_klass
995 , bool force_protected = false) const
759 { 996 {
760 return {&klass, &prop_from_klass}; 997 return {&klass, &prop_from_klass, force_protected};
761 } 998 }
762} const property_wrapper_definition; 999} const property_wrapper_definition;
763property_wrapper_definition_generator as_generator(property_wrapper_definition_parameterized) 1000property_wrapper_definition_generator as_generator(property_wrapper_definition_parameterized)
764{ 1001{
765 return {}; 1002 return {nullptr, nullptr, false};
766} 1003}
767 1004
768struct interface_property_indexer_definition_generator 1005struct interface_property_indexer_definition_generator
@@ -776,18 +1013,52 @@ struct interface_property_indexer_definition_generator
776 using efl::eolian::grammar::attributes::parameter_def; 1013 using efl::eolian::grammar::attributes::parameter_def;
777 1014
778 bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface; 1015 bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
1016 auto has_wrapper = helpers::has_property_wrapper (property, implementing_klass, context);
1017 bool has_wrapper_getter = has_wrapper & helpers::has_property_wrapper_bit::has_getter;
1018 bool has_wrapper_setter = has_wrapper & helpers::has_property_wrapper_bit::has_setter;
779 1019
1020 if (!has_wrapper_getter || !(has_wrapper & helpers::has_property_wrapper_bit::has_indexer))
1021 return true;
1022
780 assert (is_interface); 1023 assert (is_interface);
781 auto klass_name = name_helpers::klass_concrete_or_interface_name (*implementing_klass); 1024 auto klass_name = name_helpers::klass_concrete_or_interface_name (*implementing_klass);
782 std::string managed_name = name_helpers::property_managed_name(property); 1025 std::string managed_name = name_helpers::property_managed_name(property);
783 1026
784 if (!as_generator 1027 if (!as_generator
785 ("public interface " << name_helpers::property_interface_indexer_short_name(property, *implementing_klass) << "\n" 1028 ("public interface " << name_helpers::property_interface_indexer_short_name(property, *implementing_klass) << "\n{\n"
786 << "{\n"
787 << "}\n"
788 ).generate (sink, attributes::unused, context)) 1029 ).generate (sink, attributes::unused, context))
789 return false; 1030 return false;
790 1031
1032 auto size_not_one = [] (std::vector<attributes::parameter_def> k) { return k.size() != 1; };
1033 auto type_or_tuple
1034 =
1035 (
1036 (
1037 attribute_conditional(size_not_one)["("]
1038 << (type(false) % ", ")
1039 << ")"
1040 )
1041 | *type(false)
1042 )
1043 ;
1044 auto keys = property.getter->keys;
1045 auto values = property.getter->values;
1046 if (!as_generator(scope_tab(2) << "public "
1047 << type_or_tuple << " this[" << type_or_tuple <<" i]\n"
1048 << scope_tab(2) << "{\n"
1049 ).generate(sink, make_tuple(values, values, keys, keys), context))
1050 return false;
1051
1052 property_wrapper_definition_generator p {implementing_klass, implementing_klass};
1053 p.generate_get_indexer (sink, property, context, "", true);
1054 if (has_wrapper_setter)
1055 as_generator(scope_tab(3) << "set;\n").generate (sink, attributes::unused, context);
1056
1057 if (!as_generator
1058 (scope_tab(2) << "}\n}\n"
1059 ).generate (sink, attributes::unused, context))
1060 return false;
1061
791 return true; 1062 return true;
792 } 1063 }
793 attributes::klass_def const* implementing_klass; 1064 attributes::klass_def const* implementing_klass;
@@ -804,6 +1075,93 @@ interface_property_indexer_definition_generator as_generator(interface_property_
804 return {}; 1075 return {};
805} 1076}
806 1077
1078struct property_function_definition_generator
1079{
1080 template<typename OutputIterator, typename Context>
1081 bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const
1082 {
1083 bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
1084 bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
1085 assert (!is_interface);
1086 if(blacklist::is_property_blacklisted(property, *implementing_klass, context))
1087 return true;
1088
1089 auto has_wrapper = helpers::has_property_wrapper (property, implementing_klass, context);
1090 bool has_wrapper_getter = has_wrapper & helpers::has_property_wrapper_bit::has_getter;
1091 bool has_wrapper_setter = has_wrapper & helpers::has_property_wrapper_bit::has_setter;
1092
1093 auto gen = [&] (attributes::function_def const& f, bool is_protected) -> bool
1094 {
1095 // Do not generate static function for concrete class
1096 if (is_concrete && f.is_static)
1097 return true;
1098
1099 std::string return_type;
1100 if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
1101 return false;
1102
1103 if(!as_generator
1104 (documentation(1)).generate(sink, f, context))
1105 return false;
1106
1107 std::string self = "this.NativeHandle";
1108
1109 // IsGeneratedBindingClass is set in the constructor, true if this
1110 // instance is from a pure C# class (not generated).
1111 if (do_super && !f.is_static)
1112 self = "(IsGeneratedBindingClass ? " + self + " : Efl.Eo.Globals.Super(" + self + ", this.NativeClass))";
1113 else if (f.is_static)
1114 self = "";
1115
1116 auto scope = is_protected ? "protected " : eolian_mono::function_scope_get(f);
1117
1118 if(!as_generator
1119 (scope_tab << scope << ((do_super && !f.is_static) ? "virtual " : "") << (f.is_static ? "static " : "") << return_type << " " << string << "(" << (parameter % ", ")
1120 << ") {\n"
1121 << scope_tab(2) << eolian_mono::function_definition_preamble()
1122 << klass_full_native_inherit_name(f.klass) << "." << string << "_ptr.Value.Delegate("
1123 << self
1124 << ((!f.is_static && (f.parameters.size() > 0)) ? ", " : "")
1125 << (argument_invocation % ", ") << ");\n"
1126 << scope_tab(2) << eolian_mono::function_definition_epilogue()
1127 << scope_tab(1) << "}\n\n")
1128 .generate(sink, std::make_tuple(name_helpers::managed_method_name(f), f.parameters, f, f.c_name, f.parameters, f), context))
1129 return false;
1130 return true;
1131 };
1132
1133 bool r = true;
1134 bool is_self_property = *implementing_klass == *klass_from_property;
1135 bool property_from_interface = (klass_from_property->type == attributes::class_type::interface_
1136 || klass_from_property->type == attributes::class_type::mixin);
1137 //bool v = is_self_property && !is_concrete_for_interface;
1138
1139 if (r && property.getter)
1140 r &= gen ( *property.getter, always_public ? false : !property_from_interface && has_wrapper_getter);
1141 if (r && property.setter)
1142 r &= gen ( *property.setter, always_public ? false : !property_from_interface && has_wrapper_setter);
1143
1144 return r;
1145 }
1146
1147 attributes::klass_def const* implementing_klass, *klass_from_property;
1148 bool do_super, always_public;
1149};
1150struct property_function_definition_parameterized
1151{
1152 property_function_definition_generator operator()(attributes::klass_def const& klass
1153 , attributes::klass_def const& prop_from_klass
1154 , bool do_super
1155 , bool always_public = false) const
1156 {
1157 return {&klass, &prop_from_klass, do_super, always_public};
1158 }
1159} const property_function_definition;
1160property_function_definition_generator as_generator(property_function_definition_parameterized)
1161{
1162 return {nullptr, nullptr, false};
1163}
1164
807} 1165}
808 1166
809namespace efl { namespace eolian { namespace grammar { 1167namespace efl { namespace eolian { namespace grammar {
@@ -813,12 +1171,18 @@ struct is_eager_generator< ::eolian_mono::function_definition_generator> : std::
813template <> 1171template <>
814struct is_eager_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {}; 1172struct is_eager_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {};
815template <> 1173template <>
1174struct is_eager_generator< ::eolian_mono::native_property_function_definition_generator> : std::true_type {};
1175template <>
816struct is_eager_generator< ::eolian_mono::property_extension_method_definition_generator> : std::true_type {}; 1176struct is_eager_generator< ::eolian_mono::property_extension_method_definition_generator> : std::true_type {};
817template <> 1177template <>
818struct is_eager_generator< ::eolian_mono::property_wrapper_definition_generator> : std::true_type {}; 1178struct is_eager_generator< ::eolian_mono::property_wrapper_definition_generator> : std::true_type {};
819template <> 1179template <>
820struct is_eager_generator< ::eolian_mono::property_wrapper_definition_parameterized> : std::true_type {}; 1180struct is_eager_generator< ::eolian_mono::property_wrapper_definition_parameterized> : std::true_type {};
821template <> 1181template <>
1182struct is_eager_generator< ::eolian_mono::property_function_definition_generator> : std::true_type {};
1183template <>
1184struct is_eager_generator< ::eolian_mono::property_function_definition_parameterized> : std::true_type {};
1185template <>
822struct is_eager_generator< ::eolian_mono::interface_property_indexer_definition_parameterized> : std::true_type {}; 1186struct is_eager_generator< ::eolian_mono::interface_property_indexer_definition_parameterized> : std::true_type {};
823template <> 1187template <>
824struct is_eager_generator< ::eolian_mono::interface_property_indexer_definition_generator> : std::true_type {}; 1188struct is_eager_generator< ::eolian_mono::interface_property_indexer_definition_generator> : std::true_type {};
@@ -827,6 +1191,8 @@ struct is_generator< ::eolian_mono::function_definition_generator> : std::true_t
827template <> 1191template <>
828struct is_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {}; 1192struct is_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {};
829template <> 1193template <>
1194struct is_generator< ::eolian_mono::native_property_function_definition_generator> : std::true_type {};
1195template <>
830struct is_generator< ::eolian_mono::function_definition_parameterized> : std::true_type {}; 1196struct is_generator< ::eolian_mono::function_definition_parameterized> : std::true_type {};
831template <> 1197template <>
832struct is_generator< ::eolian_mono::property_extension_method_definition_generator> : std::true_type {}; 1198struct is_generator< ::eolian_mono::property_extension_method_definition_generator> : std::true_type {};
@@ -835,6 +1201,10 @@ struct is_generator< ::eolian_mono::property_wrapper_definition_generator> : std
835template <> 1201template <>
836struct is_generator< ::eolian_mono::property_wrapper_definition_parameterized> : std::true_type {}; 1202struct is_generator< ::eolian_mono::property_wrapper_definition_parameterized> : std::true_type {};
837template <> 1203template <>
1204struct is_generator< ::eolian_mono::property_function_definition_generator> : std::true_type {};
1205template <>
1206struct is_generator< ::eolian_mono::property_function_definition_parameterized> : std::true_type {};
1207template <>
838struct is_generator< ::eolian_mono::interface_property_indexer_definition_parameterized> : std::true_type {}; 1208struct is_generator< ::eolian_mono::interface_property_indexer_definition_parameterized> : std::true_type {};
839template <> 1209template <>
840struct is_generator< ::eolian_mono::interface_property_indexer_definition_generator> : std::true_type {}; 1210struct is_generator< ::eolian_mono::interface_property_indexer_definition_generator> : std::true_type {};
@@ -850,6 +1220,9 @@ template <>
850struct attributes_needed< ::eolian_mono::native_function_definition_generator> : std::integral_constant<int, 1> {}; 1220struct attributes_needed< ::eolian_mono::native_function_definition_generator> : std::integral_constant<int, 1> {};
851 1221
852template <> 1222template <>
1223struct attributes_needed< ::eolian_mono::native_property_function_definition_generator> : std::integral_constant<int, 1> {};
1224
1225template <>
853struct attributes_needed< ::eolian_mono::property_extension_method_definition_generator> : std::integral_constant<int, 1> {}; 1226struct attributes_needed< ::eolian_mono::property_extension_method_definition_generator> : std::integral_constant<int, 1> {};
854 1227
855template <> 1228template <>
@@ -858,6 +1231,11 @@ template <>
858struct attributes_needed< ::eolian_mono::property_wrapper_definition_parameterized> : std::integral_constant<int, 1> {}; 1231struct attributes_needed< ::eolian_mono::property_wrapper_definition_parameterized> : std::integral_constant<int, 1> {};
859 1232
860template <> 1233template <>
1234struct attributes_needed< ::eolian_mono::property_function_definition_generator> : std::integral_constant<int, 1> {};
1235template <>
1236struct attributes_needed< ::eolian_mono::property_function_definition_parameterized> : std::integral_constant<int, 1> {};
1237
1238template <>
861struct attributes_needed< ::eolian_mono::interface_property_indexer_definition_parameterized> : std::integral_constant<int, 1> {}; 1239struct attributes_needed< ::eolian_mono::interface_property_indexer_definition_parameterized> : std::integral_constant<int, 1> {};
862template <> 1240template <>
863struct attributes_needed< ::eolian_mono::interface_property_indexer_definition_generator> : std::integral_constant<int, 1> {}; 1241struct attributes_needed< ::eolian_mono::interface_property_indexer_definition_generator> : std::integral_constant<int, 1> {};
diff --git a/src/bin/eolian_mono/eolian/mono/function_registration.hh b/src/bin/eolian_mono/eolian/mono/function_registration.hh
index bef9e21..f614c26 100644
--- a/src/bin/eolian_mono/eolian/mono/function_registration.hh
+++ b/src/bin/eolian_mono/eolian/mono/function_registration.hh
@@ -55,6 +55,11 @@ struct function_registration_generator
55 if(blacklist::is_non_public_interface_member(f, *klass)) 55 if(blacklist::is_non_public_interface_member(f, *klass))
56 return true; 56 return true;
57 57
58 if (f.type == attributes::function_type::property
59 || f.type == attributes::function_type::prop_get
60 || f.type == attributes::function_type::prop_set)
61 return true;
62
58 if(!as_generator( 63 if(!as_generator(
59 indent << "if (" << f.c_name << "_static_delegate == null)\n" 64 indent << "if (" << f.c_name << "_static_delegate == null)\n"
60 << indent << "{\n" 65 << indent << "{\n"
diff --git a/src/bin/eolian_mono/eolian/mono/helpers.hh b/src/bin/eolian_mono/eolian/mono/helpers.hh
index 049f263..31f8592 100644
--- a/src/bin/eolian_mono/eolian/mono/helpers.hh
+++ b/src/bin/eolian_mono/eolian/mono/helpers.hh
@@ -163,6 +163,50 @@ std::set<attributes::klass_name, attributes::compare_klass_name_by_name> non_imp
163 return interfaces; 163 return interfaces;
164} 164}
165 165
166// Returns the set of interfaces implemented by this type that haven't been implemented
167// by a regular parent class and beta path information
168template<typename Context>
169std::set<std::pair<attributes::klass_name, bool>, attributes::compare_klass_name_by_name>
170 non_implemented_interfaces_and_beta(attributes::klass_def const& cls, Context const& context)
171{
172 auto options = efl::eolian::grammar::context_find_tag<options_context>(context);
173 std::set<std::pair<attributes::klass_name, bool>, attributes::compare_klass_name_by_name> implemented_interfaces;
174 std::set<std::pair<attributes::klass_name, bool>, attributes::compare_klass_name_by_name> interfaces;
175
176 std::function<void(attributes::klass_name const&, bool, bool)> inherit_algo =
177 [&] (attributes::klass_name const& klass, bool is_implemented, bool pbeta)
178 {
179 // TODO we could somehow cache klass_def instantiations
180 attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
181 for(auto&& inherit : c.immediate_inherits)
182 {
183 auto beta = pbeta | inherit.is_beta;
184 switch(inherit.type)
185 {
186 case attributes::class_type::mixin:
187 case attributes::class_type::interface_:
188 interfaces.insert(std::make_pair(inherit, beta));
189 if (is_implemented)
190 implemented_interfaces.insert(std::make_pair(inherit, beta));
191 inherit_algo(inherit, is_implemented, beta);
192 break;
193 case attributes::class_type::abstract_:
194 case attributes::class_type::regular:
195 inherit_algo(inherit, true, beta);
196 default:
197 break;
198 }
199 }
200 };
201
202 inherit_algo(get_klass_name(cls), false, cls.is_beta);
203
204 for (auto&& inherit : implemented_interfaces)
205 interfaces.erase(inherit);
206
207 return interfaces;
208}
209
166 210
167/* 211/*
168 * Determines whether this class has any regular ancestor or not 212 * Determines whether this class has any regular ancestor or not
@@ -195,18 +239,88 @@ bool inherits_from(attributes::klass_def const& cls, std::string const& name)
195 * Gets all methods that this class should implement (i.e. that come from an unimplemented interface/mixin and the class itself) 239 * Gets all methods that this class should implement (i.e. that come from an unimplemented interface/mixin and the class itself)
196 */ 240 */
197template<typename Context> 241template<typename Context>
198std::vector<attributes::function_def> get_all_implementable_methods(attributes::klass_def const& cls, Context const& context) 242std::vector<attributes::function_def> get_all_implementable_methods(attributes::klass_def const& cls, Context const& context
243 , bool insert_properties = false)
199{ 244{
200 bool want_beta = efl::eolian::grammar::context_find_tag<options_context>(context).want_beta; 245 bool want_beta = efl::eolian::grammar::context_find_tag<options_context>(context).want_beta;
201 std::vector<attributes::function_def> ret; 246 std::vector<attributes::function_def> ret;
202 auto filter_beta = [&want_beta](attributes::function_def const& func) { 247 auto filter = [&](attributes::function_def const& func) {
248 if (!want_beta)
249 return !func.is_beta
250 && (
251 insert_properties
252 ? true
253 :
254 !(func.type == attributes::function_type::property
255 || func.type == attributes::function_type::prop_set
256 || func.type == attributes::function_type::prop_get));
257 else
258 return insert_properties ? true
259 : !(func.type == attributes::function_type::property
260 || func.type == attributes::function_type::prop_set
261 || func.type == attributes::function_type::prop_get);
262 };
263
264 std::copy_if(cls.functions.begin(), cls.functions.end(), std::back_inserter(ret), filter);
265
266 // Non implemented interfaces
267 std::set<attributes::klass_name, attributes::compare_klass_name_by_name> implemented_interfaces;
268 std::set<attributes::klass_name, attributes::compare_klass_name_by_name> interfaces;
269 std::function<void(attributes::klass_name const&, bool)> inherit_algo =
270 [&] (attributes::klass_name const &klass, bool is_implemented)
271 {
272 attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
273 for (auto&& inherit: c.immediate_inherits)
274 {
275 switch(inherit.type)
276 {
277 case attributes::class_type::mixin:
278 case attributes::class_type::interface_:
279 interfaces.insert(inherit);
280 if (is_implemented)
281 implemented_interfaces.insert(inherit);
282 inherit_algo(inherit, is_implemented);
283 break;
284 case attributes::class_type::abstract_:
285 case attributes::class_type::regular:
286 inherit_algo(inherit, true);
287 default:
288 break;
289 }
290 }
291 };
292
293 inherit_algo(attributes::get_klass_name(cls), false);
294
295 for (auto&& inherit : implemented_interfaces)
296 interfaces.erase(inherit);
297
298 for (auto&& inherit : interfaces)
299 {
300 attributes::klass_def klass(get_klass(inherit, cls.unit), cls.unit);
301 std::copy_if(klass.functions.cbegin(), klass.functions.cend(), std::back_inserter(ret), filter);
302 }
303
304 return ret;
305}
306
307/*
308 * Gets all methods that this class should implement (i.e. that come from an unimplemented interface/mixin and the class itself)
309 */
310template<typename Context>
311std::vector<attributes::property_def> get_all_implementable_properties(attributes::klass_def const& cls, Context const& context)
312{
313 bool want_beta = efl::eolian::grammar::context_find_tag<options_context>(context).want_beta;
314 std::vector<attributes::property_def> ret;
315 auto filter_beta = [want_beta, cls](attributes::property_def const& prop) {
203 if (!want_beta) 316 if (!want_beta)
204 return !func.is_beta; 317 return !cls.is_beta && (!prop.getter || !prop.getter->is_beta)
318 && (!prop.setter || !prop.setter->is_beta);
205 else 319 else
206 return true; 320 return true;
207 }; 321 };
208 322
209 std::copy_if(cls.functions.begin(), cls.functions.end(), std::back_inserter(ret), filter_beta); 323 std::copy_if(cls.properties.begin(), cls.properties.end(), std::back_inserter(ret), filter_beta);
210 324
211 // Non implemented interfaces 325 // Non implemented interfaces
212 std::set<attributes::klass_name, attributes::compare_klass_name_by_name> implemented_interfaces; 326 std::set<attributes::klass_name, attributes::compare_klass_name_by_name> implemented_interfaces;
@@ -243,7 +357,7 @@ std::vector<attributes::function_def> get_all_implementable_methods(attributes::
243 for (auto&& inherit : interfaces) 357 for (auto&& inherit : interfaces)
244 { 358 {
245 attributes::klass_def klass(get_klass(inherit, cls.unit), cls.unit); 359 attributes::klass_def klass(get_klass(inherit, cls.unit), cls.unit);
246 std::copy_if(klass.functions.cbegin(), klass.functions.cend(), std::back_inserter(ret), filter_beta); 360 std::copy_if(klass.properties.cbegin(), klass.properties.cend(), std::back_inserter(ret), filter_beta);
247 } 361 }
248 362
249 return ret; 363 return ret;
@@ -273,6 +387,10 @@ std::vector<attributes::function_def> get_all_registerable_methods(attributes::k
273 387
274 if (cls == func.klass) 388 if (cls == func.klass)
275 return true; 389 return true;
390 if (func.type == attributes::function_type::property
391 || func.type == attributes::function_type::prop_set
392 || func.type == attributes::function_type::prop_get)
393 return false;
276 394
277 if (is_managed_interface(func.klass) && func.is_static) 395 if (is_managed_interface(func.klass) && func.is_static)
278 return true; 396 return true;
diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh
index 478c6a9..f2ea802 100644
--- a/src/bin/eolian_mono/eolian/mono/klass.hh
+++ b/src/bin/eolian_mono/eolian/mono/klass.hh
@@ -107,7 +107,7 @@ struct klass
107 context); 107 context);
108 108
109 // Property wrappers 109 // Property wrappers
110 if (!as_generator(*(interface_property_indexer_definition(cls))).generate(sink, cls.properties, iface_cxt)) 110 if (!as_generator("\n\n" << *(interface_property_indexer_definition(cls))).generate(sink, cls.properties, iface_cxt))
111 return false; 111 return false;
112 112
113 if(!as_generator(documentation).generate(sink, cls, iface_cxt)) 113 if(!as_generator(documentation).generate(sink, cls, iface_cxt))
@@ -146,7 +146,19 @@ struct klass
146 if(!as_generator("\n{\n").generate(sink, attributes::unused, iface_cxt)) 146 if(!as_generator("\n{\n").generate(sink, attributes::unused, iface_cxt))
147 return false; 147 return false;
148 148
149 if(!as_generator(*(function_declaration)).generate(sink, cls.functions, iface_cxt)) 149 if(!as_generator("\n\n" << *(property_declaration(cls, cls))).generate(sink, cls.properties, iface_cxt))
150 return false;
151
152 std::vector<attributes::function_def> methods;
153 std::copy_if (cls.functions.begin(), cls.functions.end()
154 , std::back_inserter(methods)
155 , [] (attributes::function_def const& f) -> bool
156 {
157 return !(f.type == attributes::function_type::property
158 || f.type == attributes::function_type::prop_set
159 || f.type == attributes::function_type::prop_get);
160 });
161 if(!as_generator("\n" << scope_tab << "//* Methods\n\n" << *(function_declaration)).generate(sink, methods, iface_cxt))
150 return false; 162 return false;
151 163
152 if(!as_generator(*(async_function_declaration)).generate(sink, cls.functions, iface_cxt)) 164 if(!as_generator(*(async_function_declaration)).generate(sink, cls.functions, iface_cxt))
@@ -253,23 +265,32 @@ struct klass
253 if(!as_generator(*(part_definition)) 265 if(!as_generator(*(part_definition))
254 .generate(sink, cls.parts, concrete_cxt)) return false; 266 .generate(sink, cls.parts, concrete_cxt)) return false;
255 267
256 // Concrete function definitions 268 // Property concrete function definitions
269 auto implemented_properties = helpers::get_all_implementable_properties(cls, concrete_cxt);
270 if(!as_generator("\n\n"
271 << *(
272 property_function_definition(cls, cls, false)
273 ))
274 .generate(sink, implemented_properties, concrete_cxt)) return false;
275
257 auto implemented_methods = helpers::get_all_implementable_methods(cls, concrete_cxt); 276 auto implemented_methods = helpers::get_all_implementable_methods(cls, concrete_cxt);
258 if(!as_generator(*(function_definition)) 277 if(!as_generator("\n" << scope_tab << "\n\n" << *(function_definition))
259 .generate(sink, implemented_methods, concrete_cxt)) return false; 278 .generate(sink, implemented_methods, concrete_cxt)) return false;
260 279
261 // Async wrappers 280 // Async wrappers
262 if(!as_generator(*(async_function_definition)).generate(sink, implemented_methods, concrete_cxt)) 281 if(!as_generator(*(async_function_definition)).generate(sink, helpers::get_all_implementable_methods(cls, concrete_cxt, true), concrete_cxt))
263 return false; 282 return false;
264 283
265 // Property wrappers 284 // Property wrappers
266 if (!as_generator(*(property_wrapper_definition(cls, cls))).generate(sink, cls.properties, concrete_cxt)) 285 if (!as_generator(*(property_wrapper_definition(cls, cls)))
286 .generate(sink, cls.properties, concrete_cxt))
267 return false; 287 return false;
268 288
269 for (auto&& klass : helpers::non_implemented_interfaces(cls, concrete_cxt)) 289 for (auto&& klass : helpers::non_implemented_interfaces_and_beta(cls, concrete_cxt))
270 { 290 {
271 attributes::klass_def c(get_klass(klass, cls.unit), cls.unit); 291 attributes::klass_def c(get_klass(klass.first, cls.unit), cls.unit);
272 if (!as_generator(*(property_wrapper_definition(cls, c))).generate(sink, c.properties, concrete_cxt)) 292 bool force_protected = (!context_find_tag<options_context>(concrete_cxt).want_beta && klass.second);
293 if (!as_generator(*(property_wrapper_definition(cls, c, force_protected))).generate(sink, c.properties, concrete_cxt))
273 return false; 294 return false;
274 } 295 }
275 296
@@ -291,8 +312,9 @@ struct klass
291 if(!as_generator("}\n").generate(sink, attributes::unused, concrete_cxt)) return false; 312 if(!as_generator("}\n").generate(sink, attributes::unused, concrete_cxt)) return false;
292 } 313 }
293 314
294 // Inheritable class 315 // // Inheritable class
295 if(class_type == "class" || class_type == "abstract class") 316 // if(class_type == "class" || class_type == "abstract class")
317 else
296 { 318 {
297 auto inherit_cxt = context_add_tag(class_context{class_context::inherit, 319 auto inherit_cxt = context_add_tag(class_context{class_context::inherit,
298 name_helpers::klass_full_concrete_or_interface_name(cls)}, 320 name_helpers::klass_full_concrete_or_interface_name(cls)},
@@ -337,23 +359,31 @@ struct klass
337 if(!as_generator(*(part_definition)) 359 if(!as_generator(*(part_definition))
338 .generate(sink, cls.parts, inherit_cxt)) return false; 360 .generate(sink, cls.parts, inherit_cxt)) return false;
339 361
362 // Property concrete function definitions
363 auto implemented_properties = helpers::get_all_implementable_properties(cls, inherit_cxt);
364 if(!as_generator(*(property_function_definition(cls, cls, true, true)))
365 .generate(sink, implemented_properties, inherit_cxt)) return false;
366
340 // Inherit function definitions 367 // Inherit function definitions
341 auto implemented_methods = helpers::get_all_implementable_methods(cls, inherit_cxt); 368 auto implemented_methods = helpers::get_all_implementable_methods(cls, inherit_cxt);
342 if(!as_generator(*(function_definition(true))) 369 if(!as_generator("\n" << scope_tab << "//* Methods\n\n" << *(function_definition(true)))
343 .generate(sink, implemented_methods, inherit_cxt)) return false; 370 .generate(sink, implemented_methods, inherit_cxt)) return false;
344 371
345 // Async wrappers 372 // Async wrappers
346 if(!as_generator(*(async_function_definition(true))).generate(sink, implemented_methods, inherit_cxt)) 373 if(!as_generator(*(async_function_definition(true))).generate(sink, helpers::get_all_implementable_methods(cls, inherit_cxt, true), inherit_cxt))
347 return false; 374 return false;
348 375
349 // Property wrappers 376 // Property wrappers
350 if (!as_generator(*(property_wrapper_definition(cls, cls))).generate(sink, cls.properties, inherit_cxt)) 377 if (!as_generator("\n\n" << *property_wrapper_definition(cls, cls)
378 ).generate(sink, cls.properties, inherit_cxt))
351 return false; 379 return false;
352 380
353 for (auto&& klass : helpers::non_implemented_interfaces(cls, inherit_cxt)) 381 for (auto&& klass : helpers::non_implemented_interfaces_and_beta(cls, inherit_cxt))
354 { 382 {
355 attributes::klass_def c(get_klass(klass, cls.unit), cls.unit); 383 attributes::klass_def c(get_klass(klass.first, cls.unit), cls.unit);
356 if (!as_generator(*(property_wrapper_definition(cls, c))).generate(sink, c.properties, inherit_cxt)) 384 assert (c != cls);
385 bool force_protected = (!context_find_tag<options_context>(inherit_cxt).want_beta && klass.second);
386 if (!as_generator(*(property_wrapper_definition(cls, c, force_protected))).generate(sink, c.properties, inherit_cxt))
357 return false; 387 return false;
358 } 388 }
359 389
@@ -424,6 +454,7 @@ struct klass
424 auto native_inherit_name = name_helpers::klass_native_inherit_name(cls); 454 auto native_inherit_name = name_helpers::klass_native_inherit_name(cls);
425 auto inherit_name = name_helpers::klass_inherit_name(cls); 455 auto inherit_name = name_helpers::klass_inherit_name(cls);
426 auto implementable_methods = helpers::get_all_registerable_methods(cls, context); 456 auto implementable_methods = helpers::get_all_registerable_methods(cls, context);
457 auto implementable_properties = helpers::get_all_implementable_properties(cls, inative_cxt);
427 bool root = !helpers::has_regular_ancestor(cls); 458 bool root = !helpers::has_regular_ancestor(cls);
428 auto const& indent = current_indentation(inative_cxt); 459 auto const& indent = current_indentation(inative_cxt);
429 std::string klass_since; 460 std::string klass_since;
@@ -450,7 +481,8 @@ struct klass
450 ).generate(sink, attributes::unused, inative_cxt)) 481 ).generate(sink, attributes::unused, inative_cxt))
451 return false; 482 return false;
452 483
453 if(implementable_methods.size() >= 1) 484 if(implementable_methods.size() >= 1
485 || implementable_properties.size() >= 1)
454 { 486 {
455 if(!as_generator( 487 if(!as_generator(
456 indent << scope_tab << "private static Efl.Eo.NativeModule Module = new Efl.Eo.NativeModule(" 488 indent << scope_tab << "private static Efl.Eo.NativeModule Module = new Efl.Eo.NativeModule("
@@ -533,6 +565,12 @@ struct klass
533 << indent << scope_tab << "#pragma warning restore CA1707, CS1591, SA1300, SA1600\n\n") 565 << indent << scope_tab << "#pragma warning restore CA1707, CS1591, SA1300, SA1600\n\n")
534 .generate(sink, implementable_methods, change_indentation(indent.inc(), inative_cxt))) return false; 566 .generate(sink, implementable_methods, change_indentation(indent.inc(), inative_cxt))) return false;
535 567
568 if(!as_generator(
569 indent << scope_tab << "#pragma warning disable CA1707, CS1591, SA1300, SA1600\n\n"
570 << *(native_property_function_definition(cls, cls))
571 << indent << scope_tab << "#pragma warning restore CA1707, CS1591, SA1300, SA1600\n\n")
572 .generate(sink, implementable_properties, change_indentation(indent.inc(), inative_cxt))) return false;
573
536 if(!as_generator("}\n").generate(sink, attributes::unused, inative_cxt)) return false; 574 if(!as_generator("}\n").generate(sink, attributes::unused, inative_cxt)) return false;
537 } 575 }
538 return true; 576 return true;
diff --git a/src/bindings/mono/efl_mono/GenericModel.cs b/src/bindings/mono/efl_mono/GenericModel.cs
index faa2a2f..7df833c 100644
--- a/src/bindings/mono/efl_mono/GenericModel.cs
+++ b/src/bindings/mono/efl_mono/GenericModel.cs
@@ -31,30 +31,30 @@ public class GenericModel<T> : Efl.Object, Efl.IModel
31 } 31 }
32 32
33 /// <summary>The list of properties available in the wrapped model.</summary> 33 /// <summary>The list of properties available in the wrapped model.</summary>
34 /// <returns>The list of properties in the model.</returns>
34 public IEnumerable<System.String> Properties 35 public IEnumerable<System.String> Properties
35 { 36 {
36 get { return GetProperties(); } 37 get { return model.Properties; }
37 } 38 }
38 39
39 /// <summary>The number of children in the wrapped model.</summary>
40 public uint ChildrenCount
41 {
42 get { return GetChildrenCount(); }
43 }
44 40
45 /// <summary>The list of properties available in the wrapped model.</summary> 41 /// <summary>Returns the number of children in the wrapped model.</summary>
46 /// <returns>The list of properties in the model.</returns> 42 /// <returns>The number of children.</returns>
47 public IEnumerable<System.String> GetProperties() 43 public uint ChildrenCount
48 { 44 {
49 return model.GetProperties(); 45 get { return model.ChildrenCount; }
50 } 46 }
51 47
52 /// <summary>Gets the value of the given property in the wrapped model.</summary> 48 /// <summary>Gets the value of the given property in the wrapped model.</summary>
53 /// <param name="property">The property of the model.</param> 49 /// <param name="property">The property of the model.</param>
54 /// <returns>The value of the property.</returns> 50 /// <returns>The value of the property.</returns>
55 public Eina.Value GetProperty(System.String property) 51 public Efl.IModelPropertyIndexer Property
56 { 52 {
57 return model.GetProperty(property); 53 get
54 {
55 return model.Property;
56 }
57 set{}
58 } 58 }
59 59
60 /// <summary>Sets the value of the given property in the given model.</summary> 60 /// <summary>Sets the value of the given property in the given model.</summary>
@@ -67,13 +67,6 @@ public class GenericModel<T> : Efl.Object, Efl.IModel
67 return model.SetProperty(property, value); 67 return model.SetProperty(property, value);
68 } 68 }
69 69
70 /// <summary>Returns the number of children in the wrapped model.</summary>
71 /// <returns>The number of children.</returns>
72 public uint GetChildrenCount()
73 {
74 return model.GetChildrenCount();
75 }
76
77 /// <summary>Returns an <see cref="Eina.Future" /> that will resolve when the property is ready to be read.</summary> 70 /// <summary>Returns an <see cref="Eina.Future" /> that will resolve when the property is ready to be read.</summary>
78 /// <param name="property">The property of the model.</param> 71 /// <param name="property">The property of the model.</param>
79 /// <returns>An <see cref="Eina.Future" /> that resolves when the property is ready.</returns> 72 /// <returns>An <see cref="Eina.Future" /> that resolves when the property is ready.</returns>
diff --git a/src/bindings/mono/efl_mono/UserModel.cs b/src/bindings/mono/efl_mono/UserModel.cs
index 99350b1..33c3eaf 100644
--- a/src/bindings/mono/efl_mono/UserModel.cs
+++ b/src/bindings/mono/efl_mono/UserModel.cs
@@ -42,7 +42,7 @@ internal class ModelHelper
42 var properties = typeof(T).GetProperties(); 42 var properties = typeof(T).GetProperties();
43 foreach (var prop in properties) 43 foreach (var prop in properties)
44 { 44 {
45 using (var v = child.GetProperty(prop.Name)) 45 using (var v = child.Property[prop.Name])
46 { 46 {
47 SetPropertyFromValue(o, prop, v); 47 SetPropertyFromValue(o, prop, v);
48 } 48 }
diff --git a/src/bindings/mono/efl_sharp.csproj.in b/src/bindings/mono/efl_sharp.csproj.in
index ce6a9e4..d0ddbca 100644
--- a/src/bindings/mono/efl_sharp.csproj.in
+++ b/src/bindings/mono/efl_sharp.csproj.in
@@ -14,7 +14,7 @@
14 14
15 <PropertyGroup> 15 <PropertyGroup>
16 <DocumentationFile>$(AssemblyName).xml</DocumentationFile> 16 <DocumentationFile>$(AssemblyName).xml</DocumentationFile>
17 <TreatWarningsAsErrors>true</TreatWarningsAsErrors> 17 <!-- TreatWarningsAsErrors>true</TreatWarningsAsErrors -->
18 </PropertyGroup> 18 </PropertyGroup>
19 19
20 <!-- <PropertyGroup Condition="'$(BuildType)'=='Beta'"> --> 20 <!-- <PropertyGroup Condition="'$(BuildType)'=='Beta'"> -->
diff --git a/src/bindings/mono/eo_mono/EoWrapper.cs b/src/bindings/mono/eo_mono/EoWrapper.cs
index 99e60b1..dc18c0d 100644
--- a/src/bindings/mono/eo_mono/EoWrapper.cs
+++ b/src/bindings/mono/eo_mono/EoWrapper.cs
@@ -227,7 +227,7 @@ public abstract class EoWrapper : IWrapper, IDisposable
227 public void Del() 227 public void Del()
228 { 228 {
229 // FIXME Implement this 229 // FIXME Implement this
230 ((Efl.Object)this).SetParent(null); 230 ((Efl.Object)this).Parent = null;
231 Dispose(); 231 Dispose();
232 } 232 }
233 233
diff --git a/src/lib/eolian_cxx/grammar/klass_def.hpp b/src/lib/eolian_cxx/grammar/klass_def.hpp
index 48b8b52..47a8ac6 100644
--- a/src/lib/eolian_cxx/grammar/klass_def.hpp
+++ b/src/lib/eolian_cxx/grammar/klass_def.hpp
@@ -1082,6 +1082,52 @@ struct property_def
1082 } 1082 }
1083}; 1083};
1084 1084
1085template <>
1086struct tuple_element<0ul, property_def>
1087{
1088 typedef std::string type;
1089 static type& get(property_def& p) { return p.name; }
1090 static type const& get(property_def const& p) { return p.name; }
1091};
1092
1093template <>
1094struct tuple_element<1ul, property_def>
1095{
1096 typedef documentation_def type;
1097 static type& get(property_def& p) { return p.documentation; }
1098 static type const& get(property_def const& p) { return p.documentation; }
1099};
1100
1101template <>
1102struct tuple_element<2ul, property_def>
1103{
1104 typedef efl::eina::optional<function_def> type;
1105 static type& get(property_def& p) { return p.getter; }
1106 static type const& get(property_def const& p) { return p.getter; }
1107};
1108
1109template <>
1110struct tuple_element<3ul, property_def>
1111{
1112 typedef efl::eina::optional<function_def> type;
1113 static type& get(property_def& p) { return p.setter; }
1114 static type const& get(property_def const& p) { return p.setter; }
1115};
1116
1117template <std::size_t I>
1118typename tuple_element<I, property_def>::type const&
1119get(property_def const& f)
1120{
1121 return tuple_element<I, property_def>::get(f);
1122}
1123
1124template <std::size_t I>
1125typename tuple_element<I, property_def>::type&
1126get(property_def& f)
1127{
1128 return tuple_element<I, property_def>::get(f);
1129}
1130
1085struct constant_def 1131struct constant_def
1086{ 1132{
1087 std::string name; 1133 std::string name;
@@ -1165,6 +1211,18 @@ struct compare_klass_name_by_name
1165 return lhs.namespaces < rhs.namespaces 1211 return lhs.namespaces < rhs.namespaces
1166 || (!(rhs.namespaces < lhs.namespaces) && lhs.eolian_name < rhs.eolian_name); 1212 || (!(rhs.namespaces < lhs.namespaces) && lhs.eolian_name < rhs.eolian_name);
1167 } 1213 }
1214 template <typename T>
1215 bool operator()(std::pair<klass_name, T> const& lhs, std::pair<klass_name, T> const& rhs) const
1216 {
1217 return lhs.first.namespaces < rhs.first.namespaces
1218 || (!(rhs.first.namespaces < lhs.first.namespaces) && lhs.first.eolian_name < rhs.first.eolian_name);
1219 }
1220 template <typename T>
1221 bool operator()(std::pair<T, klass_name> const& lhs, std::pair<T, klass_name> const& rhs) const
1222 {
1223 return lhs.second.namespaces < rhs.second.namespaces
1224 || (!(rhs.second.namespaces < lhs.second.namespaces) && lhs.second.eolian_name < rhs.second.eolian_name);
1225 }
1168}; 1226};
1169 1227
1170struct event_def 1228struct event_def
@@ -1816,6 +1874,10 @@ namespace type_traits {
1816template <> 1874template <>
1817struct is_tuple<attributes::parameter_def> : std::true_type {}; 1875struct is_tuple<attributes::parameter_def> : std::true_type {};
1818template <> 1876template <>
1877struct is_tuple<attributes::property_def> : std::true_type {};
1878template <>
1879struct is_tuple<attributes::function_def> : std::true_type {};
1880template <>
1819struct is_tuple<attributes::event_def> : std::true_type {}; 1881struct is_tuple<attributes::event_def> : std::true_type {};
1820 1882
1821} 1883}
diff --git a/src/tests/efl_mono/Eo.cs b/src/tests/efl_mono/Eo.cs
index af40bf1..a9d0d3f 100644
--- a/src/tests/efl_mono/Eo.cs
+++ b/src/tests/efl_mono/Eo.cs
@@ -699,16 +699,16 @@ class TestProtectedInterfaceMembers
699 { 699 {
700 var type = typeof(Dummy.ITestIface); 700 var type = typeof(Dummy.ITestIface);
701 var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance); 701 var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance);
702 var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
702 703
703 // Fully protected property 704 // Fully protected property
704 Test.AssertNull(methods.SingleOrDefault(m => m.Name == "GetProtectedProp")); 705 Test.AssertNull(methods.SingleOrDefault(m => m.Name == "GetProtectedProp"));
705 Test.AssertNull(methods.SingleOrDefault(m => m.Name == "SetProtectedProp")); 706 Test.AssertNull(methods.SingleOrDefault(m => m.Name == "SetProtectedProp"));
706 707
707 // Partially protected property 708 // Partially protected property
708 Test.AssertNotNull(methods.SingleOrDefault(m => m.Name == "GetPublicGetterPrivateSetter")); 709 Test.AssertNotNull(properties.SingleOrDefault(m => m.Name == "PublicGetterPrivateSetter"));
709 Test.AssertNull(methods.SingleOrDefault(m => m.Name == "SetPublicGetterPrivateSetter")); 710 Test.AssertNull(methods.SingleOrDefault(m => m.Name == "SetPublicGetterPrivateSetter"));
710 711
711 var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
712 Test.AssertNull(properties.SingleOrDefault(m => m.Name == "ProtectedProp")); 712 Test.AssertNull(properties.SingleOrDefault(m => m.Name == "ProtectedProp"));
713 Test.AssertNotNull(properties.SingleOrDefault(m => m.Name == "PublicGetterPrivateSetter")); 713 Test.AssertNotNull(properties.SingleOrDefault(m => m.Name == "PublicGetterPrivateSetter"));
714 } 714 }
diff --git a/src/tests/efl_mono/Model.cs b/src/tests/efl_mono/Model.cs
index bb6ba3b..cb668db 100644
--- a/src/tests/efl_mono/Model.cs
+++ b/src/tests/efl_mono/Model.cs
@@ -41,7 +41,7 @@ public static class TestModel {
41 var veggies = CreateModel(loop); 41 var veggies = CreateModel(loop);
42 42
43 var model = new Efl.GenericModel<VeggieViewModel>(veggies, loop); 43 var model = new Efl.GenericModel<VeggieViewModel>(veggies, loop);
44 Test.AssertEquals(3, (int)model.GetChildrenCount()); 44 Test.AssertEquals(3, (int)model.ChildrenCount);
45 45
46 VeggieViewModel r2 = await model.GetAtAsync(1).ConfigureAwait(false); 46 VeggieViewModel r2 = await model.GetAtAsync(1).ConfigureAwait(false);
47 Test.AssertEquals(r2.Name, "Romaine Lettuce"); 47 Test.AssertEquals(r2.Name, "Romaine Lettuce");