forked from enlightenment/efl
eolian-mono: Make Get/Set protected for generated 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.
This commit is contained in:
parent
cf37047a7c
commit
cd72923bf1
|
@ -163,7 +163,7 @@ inline bool is_property_blacklisted(std::string const& name)
|
|||
// Will be bound manually
|
||||
, "Efl.Core.Env.Env"
|
||||
// Setter returns a future
|
||||
, "Efl.IModel.Property"
|
||||
//, "Efl.IModel.Property"
|
||||
// Protected
|
||||
, "Efl.Access.IAction.ActionName"
|
||||
, "Efl.Access.IAction.ActionLocalizedName"
|
||||
|
|
|
@ -118,13 +118,7 @@ struct documentation_generator
|
|||
name += name_helpers::managed_method_name({function, ftype, NULL, eolian_object_unit_get(EOLIAN_OBJECT(function))});
|
||||
break;
|
||||
case ::EOLIAN_PROP_SET:
|
||||
name += ".Set";
|
||||
name += name_helpers::property_managed_name(klass_d, eo_name);
|
||||
break;
|
||||
case ::EOLIAN_PROP_GET:
|
||||
name += ".Get";
|
||||
name += name_helpers::property_managed_name(klass_d, eo_name);
|
||||
break;
|
||||
case ::EOLIAN_PROPERTY:
|
||||
{
|
||||
std::string short_name = name_helpers::property_managed_name(klass_d, eo_name);
|
||||
|
@ -146,11 +140,16 @@ struct documentation_generator
|
|||
|
||||
auto has_wrapper = helpers::has_property_wrapper(prop, &klass_d, my_context);
|
||||
|
||||
if (has_wrapper == helpers::has_property_wrapper_bit::has_none)
|
||||
name += ".Get" + short_name;
|
||||
else if (name_tail == ".get") name += ".Get" + short_name;
|
||||
else if (name_tail == ".set") name += ".Set" + short_name;
|
||||
else name += "." + short_name;
|
||||
if (has_wrapper & helpers::has_property_wrapper_bit::has_getter
|
||||
// If there is no getter, there's no property.
|
||||
&&
|
||||
(
|
||||
(ftype == EOLIAN_PROP_GET || ftype == EOLIAN_PROPERTY)
|
||||
|| (has_wrapper & helpers::has_property_wrapper_bit::has_setter && ftype == EOLIAN_PROP_SET))
|
||||
)
|
||||
name += "." + short_name;
|
||||
else if (ftype == EOLIAN_PROP_GET || name_tail == ".get") name += ".Get" + short_name;
|
||||
else if (ftype == EOLIAN_PROP_SET || name_tail == ".set") name += ".Set" + short_name;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -159,18 +158,69 @@ struct documentation_generator
|
|||
return name;
|
||||
}
|
||||
|
||||
static std::string function_conversion(attributes::function_def const& func)
|
||||
template <typename Context>
|
||||
static std::string function_conversion(attributes::function_def const& func, Context const& context)
|
||||
{
|
||||
// This function is called only from the constructor reference conversion, so it does not
|
||||
// need to check whether this function non-public in a interface returning an empty reference (yet).
|
||||
std::string name = name_helpers::klass_full_concrete_or_interface_name(func.klass);
|
||||
switch (func.type)
|
||||
{
|
||||
// managed_method_name takes care of reordering the function name so the get/set goes first
|
||||
// for properties
|
||||
case attributes::function_type::method:
|
||||
case attributes::function_type::property:
|
||||
case attributes::function_type::prop_set:
|
||||
case attributes::function_type::prop_get:
|
||||
{
|
||||
auto unit = (const Eolian_Unit*) context_find_tag<eolian_state_context>(context).state;
|
||||
auto klass = get_klass(func.klass, unit);
|
||||
attributes::klass_def klass_d(klass, unit);
|
||||
|
||||
auto eo_name = func.name;
|
||||
auto prop_name = eo_name;
|
||||
if (prop_name.size () > 4
|
||||
&&
|
||||
( prop_name.substr(prop_name.size() - 4) == "_set"
|
||||
|| prop_name.substr(prop_name.size() - 4) == "_get"))
|
||||
{
|
||||
prop_name = prop_name.substr(0, prop_name.size() - 4);
|
||||
}
|
||||
std::string short_name = name_helpers::property_managed_name(klass_d, prop_name);
|
||||
assert (prop_name.size() <= 4 ||
|
||||
(prop_name.substr(prop_name.size() - 4) != "_set"
|
||||
&& prop_name.substr(prop_name.size() - 4) != "_get"));
|
||||
assert (short_name.size() <= 3 ||
|
||||
(short_name.substr(short_name.size() - 3) != "Set"
|
||||
&& short_name.substr(short_name.size() - 3) != "Get"));
|
||||
|
||||
// We need to replace the current class context with the context
|
||||
// from the class that originated this property.
|
||||
class_context::wrapper_kind klass_kind;
|
||||
if (helpers::is_managed_interface(klass_d))
|
||||
klass_kind = class_context::interface;
|
||||
else
|
||||
klass_kind = class_context::inherit;
|
||||
|
||||
auto my_context = grammar::context_replace_tag(class_context{klass_kind}, context);
|
||||
|
||||
auto function = eolian_class_function_by_name_get (klass, prop_name.c_str(), EOLIAN_PROPERTY);
|
||||
attributes::function_def getter_func{function, ::EOLIAN_PROP_GET, nullptr, unit};
|
||||
attributes::function_def setter_func{function, ::EOLIAN_PROP_SET, nullptr, unit};
|
||||
attributes::property_def prop{function, getter_func, setter_func, unit};
|
||||
|
||||
auto has_wrapper = helpers::has_property_wrapper(prop, &klass_d, my_context);
|
||||
|
||||
if (has_wrapper & helpers::has_property_wrapper_bit::has_getter
|
||||
// If there is no getter, there's no property.
|
||||
&&
|
||||
(
|
||||
(func.type == attributes::function_type::prop_get || func.type == attributes::function_type::property)
|
||||
|| (has_wrapper & helpers::has_property_wrapper_bit::has_setter && func.type == attributes::function_type::prop_set))
|
||||
)
|
||||
name += "." + short_name;
|
||||
else if (func.type == attributes::function_type::prop_get) name += ".Get" + short_name;
|
||||
else if (func.type == attributes::function_type::prop_set) name += ".Set" + short_name;
|
||||
}
|
||||
break;
|
||||
case attributes::function_type::method:
|
||||
if (blacklist::is_function_blacklisted(func.c_name))return "";
|
||||
if (!name.empty()) name += ".";
|
||||
name += name_helpers::managed_method_name(func);
|
||||
|
@ -218,8 +268,10 @@ struct documentation_generator
|
|||
is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2);
|
||||
break;
|
||||
case ::EOLIAN_OBJECT_FUNCTION:
|
||||
{
|
||||
ref += function_conversion(data, (const ::Eolian_Function *)data2, name_tail, context);
|
||||
is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2);
|
||||
}
|
||||
break;
|
||||
case ::EOLIAN_OBJECT_CONSTANT:
|
||||
{
|
||||
|
@ -634,7 +686,7 @@ struct documentation_generator
|
|||
|
||||
for (auto &¶m : ctor.function.parameters)
|
||||
{
|
||||
auto ref = function_conversion(func);
|
||||
auto ref = function_conversion(func, context);
|
||||
|
||||
if (!context_find_tag<options_context>(context).want_beta && func.is_beta)
|
||||
{
|
||||
|
|
|
@ -53,6 +53,63 @@ struct function_declaration_generator
|
|||
|
||||
function_declaration_generator const function_declaration = {};
|
||||
|
||||
struct property_declaration_generator
|
||||
{
|
||||
template <typename OutputIterator, typename Context>
|
||||
bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const
|
||||
{
|
||||
if(blacklist::is_property_blacklisted(property, *implementing_klass, context))
|
||||
return true;
|
||||
|
||||
auto has_wrapper = helpers::has_property_wrapper (property, implementing_klass, context);
|
||||
bool has_getter_wrapper = has_wrapper & helpers::has_property_wrapper_bit::has_getter;
|
||||
bool has_setter_wrapper = has_wrapper & helpers::has_property_wrapper_bit::has_setter;
|
||||
|
||||
auto gen = [&] (attributes::function_def const& f)
|
||||
{
|
||||
// C# interfaces can't have non-public members
|
||||
if(f.scope != attributes::member_scope::scope_public)
|
||||
return true;
|
||||
|
||||
if (f.is_static)
|
||||
return true;
|
||||
|
||||
if(!as_generator(documentation(1)).generate(sink, f, context))
|
||||
return false;
|
||||
|
||||
return as_generator
|
||||
(scope_tab << eolian_mono::type(true) << " " << string << "(" << (parameter % ", ") << ");\n\n")
|
||||
.generate(sink, std::make_tuple(f.return_type, name_helpers::managed_method_name(f), f.parameters), context);
|
||||
};
|
||||
bool r = true;
|
||||
if (property.getter)
|
||||
{
|
||||
if (!has_getter_wrapper)
|
||||
r &= gen (*property.getter);
|
||||
// else
|
||||
// r &= function_declaration.generate(sink, *property.getter, context);
|
||||
}
|
||||
if (r && property.setter)
|
||||
{
|
||||
if (!has_setter_wrapper)
|
||||
r &= gen (*property.setter);
|
||||
// else
|
||||
// r &= function_declaration.generate(sink, *property.setter, context);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
attributes::klass_def const* implementing_klass, *klass_from_property;
|
||||
};
|
||||
|
||||
struct property_declaration_parameterized
|
||||
{
|
||||
property_declaration_generator operator()(attributes::klass_def const& klass
|
||||
, attributes::klass_def const& prop_from_klass) const
|
||||
{
|
||||
return {&klass, &prop_from_klass};
|
||||
}
|
||||
} const property_declaration;
|
||||
|
||||
}
|
||||
|
||||
namespace efl { namespace eolian { namespace grammar {
|
||||
|
@ -60,11 +117,23 @@ namespace efl { namespace eolian { namespace grammar {
|
|||
template <>
|
||||
struct is_eager_generator< ::eolian_mono::function_declaration_generator> : std::true_type {};
|
||||
template <>
|
||||
struct is_eager_generator< ::eolian_mono::property_declaration_generator> : std::true_type {};
|
||||
template <>
|
||||
struct is_eager_generator< ::eolian_mono::property_declaration_parameterized> : std::true_type {};
|
||||
template <>
|
||||
struct is_generator< ::eolian_mono::function_declaration_generator> : std::true_type {};
|
||||
template <>
|
||||
struct is_generator< ::eolian_mono::property_declaration_generator> : std::true_type {};
|
||||
template <>
|
||||
struct is_generator< ::eolian_mono::property_declaration_parameterized> : std::true_type {};
|
||||
|
||||
namespace type_traits {
|
||||
template <>
|
||||
struct attributes_needed< ::eolian_mono::function_declaration_generator> : std::integral_constant<int, 1> {};
|
||||
template <>
|
||||
struct attributes_needed< ::eolian_mono::property_declaration_generator> : std::integral_constant<int, 1> {};
|
||||
template <>
|
||||
struct attributes_needed< ::eolian_mono::property_declaration_parameterized> : std::integral_constant<int, 1> {};
|
||||
}
|
||||
|
||||
} } }
|
||||
|
|
|
@ -50,6 +50,10 @@ struct native_function_definition_generator
|
|||
bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const
|
||||
{
|
||||
EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "native_function_definition_generator: " << f.c_name << std::endl;
|
||||
assert (!(f.type == attributes::function_type::property
|
||||
|| f.type == attributes::function_type::prop_set
|
||||
|| f.type == attributes::function_type::prop_get));
|
||||
|
||||
if(blacklist::is_function_blacklisted(f, context))
|
||||
return true;
|
||||
|
||||
|
@ -183,6 +187,203 @@ struct native_function_definition_generator
|
|||
}
|
||||
};
|
||||
|
||||
struct native_property_function_definition_generator
|
||||
{
|
||||
template <typename OutputIterator, typename Context>
|
||||
bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const
|
||||
{
|
||||
EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "native_property_function_definition_generator: " << property.name << std::endl;
|
||||
|
||||
if(blacklist::is_property_blacklisted(property, *implementing_klass, context))
|
||||
return true;
|
||||
|
||||
auto const& indent = current_indentation(context);
|
||||
|
||||
auto has_wrapper = helpers::has_property_wrapper (property, implementing_klass, context);
|
||||
bool has_wrapper_getter = has_wrapper & helpers::has_property_wrapper_bit::has_getter;
|
||||
bool has_wrapper_setter = has_wrapper & helpers::has_property_wrapper_bit::has_setter;
|
||||
|
||||
auto gen = [&] (attributes::function_def const& f, bool is_set)
|
||||
{
|
||||
// Delegate for the C# method we will export to EO as a method implementation.
|
||||
if(!as_generator
|
||||
(
|
||||
indent << eolian_mono::marshall_annotation(true) << "\n"
|
||||
<< indent << "private delegate "
|
||||
<< eolian_mono::marshall_type(true)
|
||||
<< " "
|
||||
<< string
|
||||
<< "_delegate(" << (f.is_static ? "" : "System.IntPtr obj, System.IntPtr pd")
|
||||
<< ((!f.is_static && f.parameters.size() > 0) ? ", " : "")
|
||||
<< (grammar::attribute_reorder<-1, -1>
|
||||
(
|
||||
(marshall_annotation << " " << marshall_parameter)
|
||||
) % ", ")
|
||||
<< ");\n\n")
|
||||
.generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
|
||||
return false;
|
||||
|
||||
// API delegate is the wrapper for the Eo methods exported from C that we will use from C#.
|
||||
if(!as_generator
|
||||
(
|
||||
indent << eolian_mono::marshall_annotation(true) << "\n"
|
||||
<< indent << "internal delegate "
|
||||
<< eolian_mono::marshall_type(true)
|
||||
<< " "
|
||||
<< string << "_api_delegate(" << (f.is_static ? "" : "System.IntPtr obj")
|
||||
<< ((!f.is_static && f.parameters.size() > 0) ? ", " : "")
|
||||
<< (grammar::attribute_reorder<-1, -1>
|
||||
(
|
||||
(marshall_annotation << " " << marshall_parameter)
|
||||
) % ", ")
|
||||
<< ");\n\n")
|
||||
.generate(sink, std::make_tuple(f.return_type, f.return_type, f.c_name, f.parameters), context))
|
||||
return false;
|
||||
|
||||
// Delegate holder (so it can't be collected).
|
||||
if(!as_generator
|
||||
(indent << "internal static readonly Efl.Eo.FunctionWrapper<" << string << "_api_delegate> " << string << "_ptr = new Efl.Eo.FunctionWrapper<"
|
||||
<< string << "_api_delegate>(Module, \"" << string << "\");\n\n")
|
||||
.generate(sink, std::make_tuple(f.c_name, f.c_name, f.c_name, f.c_name), context))
|
||||
return false;
|
||||
|
||||
// We do not generate the wrapper to be called from C for non public interface member directly.
|
||||
if (blacklist::is_non_public_interface_member(f, *implementing_klass))
|
||||
return true;
|
||||
|
||||
// Do not generate static method in interface
|
||||
if (((implementing_klass->type == attributes::class_type::interface_) ||
|
||||
(implementing_klass->type == attributes::class_type::mixin)) && f.is_static)
|
||||
return true;
|
||||
|
||||
// Actual method implementation to be called from C.
|
||||
std::string return_type;
|
||||
if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
|
||||
return false;
|
||||
|
||||
std::string klass_cast_name;
|
||||
if ((implementing_klass->type == attributes::class_type::interface_) ||
|
||||
((implementing_klass->type == attributes::class_type::mixin) && !f.is_static))
|
||||
klass_cast_name = name_helpers::klass_interface_name(*implementing_klass);
|
||||
else
|
||||
klass_cast_name = name_helpers::klass_inherit_name(*implementing_klass);
|
||||
|
||||
std::string self = "Efl.Eo.Globals.Super(obj, Efl.Eo.Globals.GetClass(obj))";
|
||||
|
||||
if (f.is_static)
|
||||
self = "";
|
||||
|
||||
if(!as_generator
|
||||
(indent << "[SuppressMessage(\"Microsoft.Reliability\", \"CA2000:DisposeObjectsBeforeLosingScope\", Justification = \"The instantiated objects can be stored in the called Managed API method.\")]\n"
|
||||
<< indent << "private static "
|
||||
<< eolian_mono::marshall_type(true) << " "
|
||||
<< string
|
||||
<< "(System.IntPtr obj, System.IntPtr pd"
|
||||
<< *(", " << marshall_parameter)
|
||||
<< ")\n"
|
||||
<< indent << "{\n"
|
||||
<< indent << scope_tab << "Eina.Log.Debug(\"function " << string << " was called\");\n"
|
||||
<< indent << scope_tab << "var ws = Efl.Eo.Globals.GetWrapperSupervisor(obj);\n"
|
||||
<< indent << scope_tab << "if (ws != null)\n"
|
||||
<< indent << scope_tab << "{\n"
|
||||
<< indent << scope_tab << scope_tab << eolian_mono::native_function_definition_preamble() << "\n"
|
||||
<< indent << scope_tab << scope_tab << "try\n"
|
||||
<< indent << scope_tab << scope_tab << "{\n"
|
||||
)
|
||||
.generate(sink, std::make_tuple(f.return_type, escape_keyword(f.name), f.parameters
|
||||
, /***/f.c_name/***/
|
||||
, f
|
||||
), context))
|
||||
return false;
|
||||
if (is_set && has_wrapper_setter)
|
||||
{
|
||||
if(!as_generator
|
||||
(
|
||||
indent << scope_tab << scope_tab << scope_tab << (return_type != "void" ? "_ret_var = " : "")
|
||||
<< (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")ws.Target).") << string
|
||||
)
|
||||
.generate(sink, std::make_tuple(name_helpers::property_managed_name(property), f.parameters), context))
|
||||
return false;
|
||||
|
||||
if(!f.keys.empty() && !as_generator(lit("[(") << (native_argument_invocation % ", ") << ")]").generate (sink, f.keys, context))
|
||||
return false;
|
||||
|
||||
if(!as_generator
|
||||
(" = ("
|
||||
<< (native_argument_invocation % ", ") << ");\n"
|
||||
)
|
||||
.generate(sink, f.values, context))
|
||||
return false;
|
||||
}
|
||||
else if (!is_set && has_wrapper_getter)
|
||||
{
|
||||
if(!as_generator
|
||||
(
|
||||
indent << scope_tab << scope_tab << scope_tab << "var ret = "
|
||||
<< (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")ws.Target).")
|
||||
<< string
|
||||
|
||||
)
|
||||
.generate(sink, std::make_tuple(name_helpers::property_managed_name(property)), context))
|
||||
return false;
|
||||
|
||||
if(!f.keys.empty() && !as_generator(lit("[(") << (native_argument_invocation % ", ") << ")]").generate (sink, f.keys, context))
|
||||
return false;
|
||||
|
||||
if (!as_generator(";\n").generate (sink, attributes::unused, context))
|
||||
return false;
|
||||
|
||||
}
|
||||
else if (!as_generator
|
||||
(indent << scope_tab << scope_tab << scope_tab << (return_type != "void" ? "_ret_var = " : "")
|
||||
<< (f.is_static ? "" : "((") << klass_cast_name << (f.is_static ? "." : ")ws.Target).") << string
|
||||
<< "(" << (native_argument_invocation % ", ") << ");\n"
|
||||
).generate(sink, std::make_tuple(name_helpers::managed_method_name(f), f.parameters), context))
|
||||
return false;
|
||||
|
||||
if(!as_generator
|
||||
(
|
||||
indent << scope_tab << scope_tab << "}\n"
|
||||
<< indent << scope_tab << scope_tab << "catch (Exception e)\n"
|
||||
<< indent << scope_tab << scope_tab << "{\n"
|
||||
<< indent << scope_tab << scope_tab << scope_tab << "Eina.Log.Warning($\"Callback error: {e.ToString()}\");\n"
|
||||
<< indent << scope_tab << scope_tab << scope_tab << "Eina.Error.Set(Eina.Error.UNHANDLED_EXCEPTION);\n"
|
||||
<< indent << scope_tab << scope_tab << "}\n\n"
|
||||
<< indent << eolian_mono::native_function_definition_epilogue(*implementing_klass) << "\n"
|
||||
<< indent << scope_tab << "}\n"
|
||||
<< indent << scope_tab << "else\n"
|
||||
<< indent << scope_tab << "{\n"
|
||||
<< indent << scope_tab << scope_tab << (return_type != "void" ? "return " : "") << string
|
||||
<< "_ptr.Value.Delegate(" << self << ((!f.is_static && f.parameters.size() > 0) ? ", " : "") << (argument % ", ") << ");\n"
|
||||
<< indent << scope_tab << "}\n"
|
||||
<< indent << "}\n\n"
|
||||
)
|
||||
.generate(sink, std::make_tuple(f, f.c_name, f.parameters), context))
|
||||
return false;
|
||||
|
||||
// Static functions do not need to be called from C
|
||||
if (f.is_static)
|
||||
return true;
|
||||
|
||||
// This is the delegate that will be passed to Eo to be called from C.
|
||||
// if(!as_generator(
|
||||
// indent << "private static " << f.c_name << "_delegate " << f.c_name << "_static_delegate;\n\n"
|
||||
// ).generate(sink, attributes::unused, context))
|
||||
// return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
bool r = true;
|
||||
if(r && property.getter)
|
||||
r &= gen (*property.getter, false);
|
||||
if(r && property.setter)
|
||||
r &= gen (*property.setter, true);
|
||||
return r;
|
||||
}
|
||||
|
||||
attributes::klass_def const* implementing_klass, *klass_from_property;
|
||||
};
|
||||
|
||||
struct function_definition_generator
|
||||
{
|
||||
function_definition_generator(bool do_super = false)
|
||||
|
@ -194,6 +395,10 @@ struct function_definition_generator
|
|||
{
|
||||
EINA_CXX_DOM_LOG_DBG(eolian_mono::domain) << "function_definition_generator: " << f.c_name << std::endl;
|
||||
|
||||
assert (!(f.type == attributes::function_type::property
|
||||
|| f.type == attributes::function_type::prop_set
|
||||
|| f.type == attributes::function_type::prop_get));
|
||||
|
||||
bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
|
||||
if(blacklist::is_function_blacklisted(f, context))
|
||||
return true;
|
||||
|
@ -256,6 +461,14 @@ struct native_function_definition_parameterized
|
|||
return {&klass};
|
||||
}
|
||||
} const native_function_definition;
|
||||
struct native_property_function_definition_parameterized
|
||||
{
|
||||
native_property_function_definition_generator operator()(attributes::klass_def const& klass
|
||||
, attributes::klass_def const& prop_from_klass) const
|
||||
{
|
||||
return {&klass, &prop_from_klass};
|
||||
}
|
||||
} const native_property_function_definition;
|
||||
|
||||
struct property_extension_method_definition_generator
|
||||
{
|
||||
|
@ -414,9 +627,9 @@ struct property_wrapper_definition_generator
|
|||
}
|
||||
assert (!get_keys.empty());
|
||||
|
||||
generate_get(sink, property, context, get_scope, get_keys, values, is_interface, "Self.");
|
||||
generate_get(sink, property, context, get_scope, get_keys, values, is_interface, "((" + name_helpers::klass_full_concrete_name (*implementing_klass) + ")Self).");
|
||||
if (has_setter)
|
||||
generate_set(sink, property, context, set_scope, get_keys, values, is_interface, "Self.");
|
||||
generate_set(sink, property, context, set_scope, get_keys, values, is_interface, "((" + name_helpers::klass_full_concrete_name (*implementing_klass) + ")Self).");
|
||||
|
||||
if (!as_generator
|
||||
(
|
||||
|
@ -648,13 +861,30 @@ struct property_wrapper_definition_generator
|
|||
std::string set_scope = has_setter ? eolian_mono::function_scope_get(*property.setter) : "";
|
||||
|
||||
// C# interface members are declared automatically as public
|
||||
if (is_interface)
|
||||
if (force_protected)
|
||||
{
|
||||
scope = "protected ";
|
||||
get_scope = "";
|
||||
set_scope = "";
|
||||
}
|
||||
else if (is_interface)
|
||||
{
|
||||
scope = "";
|
||||
get_scope = "";
|
||||
set_scope = "";
|
||||
}
|
||||
else if ((get_scope != "") && (get_scope == set_scope))
|
||||
else
|
||||
{
|
||||
auto want_beta = context_find_tag<options_context>(context).want_beta;
|
||||
if (!want_beta && property.getter->is_beta)
|
||||
{
|
||||
get_scope = "protected ";
|
||||
}
|
||||
if (property.setter && !want_beta && property.setter->is_beta)
|
||||
{
|
||||
set_scope = "protected ";
|
||||
}
|
||||
if ((get_scope != "") && (get_scope == set_scope))
|
||||
{
|
||||
scope = get_scope;
|
||||
get_scope = "";
|
||||
|
@ -665,6 +895,7 @@ struct property_wrapper_definition_generator
|
|||
scope = get_scope;
|
||||
get_scope = "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string virtual_mod = (is_static || is_interface || is_concrete) ? "" : "virtual ";
|
||||
|
||||
|
@ -735,6 +966,10 @@ struct property_wrapper_definition_generator
|
|||
if (has_indexer)
|
||||
{
|
||||
generate_get_indexer (sink, property, context, get_scope, is_interface);
|
||||
if (is_interface)
|
||||
as_generator(scope_tab(2) << "set;\n").generate (sink, attributes::unused, context);
|
||||
else
|
||||
as_generator(scope_tab(2) << "set {}\n").generate (sink, attributes::unused, context);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -751,18 +986,20 @@ struct property_wrapper_definition_generator
|
|||
return true;
|
||||
}
|
||||
attributes::klass_def const* implementing_klass, *klass_from_property;
|
||||
bool force_protected;
|
||||
};
|
||||
struct property_wrapper_definition_parameterized
|
||||
{
|
||||
property_wrapper_definition_generator operator()(attributes::klass_def const& klass
|
||||
, attributes::klass_def const& prop_from_klass) const
|
||||
, attributes::klass_def const& prop_from_klass
|
||||
, bool force_protected = false) const
|
||||
{
|
||||
return {&klass, &prop_from_klass};
|
||||
return {&klass, &prop_from_klass, force_protected};
|
||||
}
|
||||
} const property_wrapper_definition;
|
||||
property_wrapper_definition_generator as_generator(property_wrapper_definition_parameterized)
|
||||
{
|
||||
return {};
|
||||
return {nullptr, nullptr, false};
|
||||
}
|
||||
|
||||
struct interface_property_indexer_definition_generator
|
||||
|
@ -776,15 +1013,49 @@ struct interface_property_indexer_definition_generator
|
|||
using efl::eolian::grammar::attributes::parameter_def;
|
||||
|
||||
bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
|
||||
auto has_wrapper = helpers::has_property_wrapper (property, implementing_klass, context);
|
||||
bool has_wrapper_getter = has_wrapper & helpers::has_property_wrapper_bit::has_getter;
|
||||
bool has_wrapper_setter = has_wrapper & helpers::has_property_wrapper_bit::has_setter;
|
||||
|
||||
if (!has_wrapper_getter || !(has_wrapper & helpers::has_property_wrapper_bit::has_indexer))
|
||||
return true;
|
||||
|
||||
assert (is_interface);
|
||||
auto klass_name = name_helpers::klass_concrete_or_interface_name (*implementing_klass);
|
||||
std::string managed_name = name_helpers::property_managed_name(property);
|
||||
|
||||
if (!as_generator
|
||||
("public interface " << name_helpers::property_interface_indexer_short_name(property, *implementing_klass) << "\n"
|
||||
<< "{\n"
|
||||
<< "}\n"
|
||||
("public interface " << name_helpers::property_interface_indexer_short_name(property, *implementing_klass) << "\n{\n"
|
||||
).generate (sink, attributes::unused, context))
|
||||
return false;
|
||||
|
||||
auto size_not_one = [] (std::vector<attributes::parameter_def> k) { return k.size() != 1; };
|
||||
auto type_or_tuple
|
||||
=
|
||||
(
|
||||
(
|
||||
attribute_conditional(size_not_one)["("]
|
||||
<< (type(false) % ", ")
|
||||
<< ")"
|
||||
)
|
||||
| *type(false)
|
||||
)
|
||||
;
|
||||
auto keys = property.getter->keys;
|
||||
auto values = property.getter->values;
|
||||
if (!as_generator(scope_tab(2) << "public "
|
||||
<< type_or_tuple << " this[" << type_or_tuple <<" i]\n"
|
||||
<< scope_tab(2) << "{\n"
|
||||
).generate(sink, make_tuple(values, values, keys, keys), context))
|
||||
return false;
|
||||
|
||||
property_wrapper_definition_generator p {implementing_klass, implementing_klass};
|
||||
p.generate_get_indexer (sink, property, context, "", true);
|
||||
if (has_wrapper_setter)
|
||||
as_generator(scope_tab(3) << "set;\n").generate (sink, attributes::unused, context);
|
||||
|
||||
if (!as_generator
|
||||
(scope_tab(2) << "}\n}\n"
|
||||
).generate (sink, attributes::unused, context))
|
||||
return false;
|
||||
|
||||
|
@ -804,6 +1075,93 @@ interface_property_indexer_definition_generator as_generator(interface_property_
|
|||
return {};
|
||||
}
|
||||
|
||||
struct property_function_definition_generator
|
||||
{
|
||||
template<typename OutputIterator, typename Context>
|
||||
bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const
|
||||
{
|
||||
bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
|
||||
bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
|
||||
assert (!is_interface);
|
||||
if(blacklist::is_property_blacklisted(property, *implementing_klass, context))
|
||||
return true;
|
||||
|
||||
auto has_wrapper = helpers::has_property_wrapper (property, implementing_klass, context);
|
||||
bool has_wrapper_getter = has_wrapper & helpers::has_property_wrapper_bit::has_getter;
|
||||
bool has_wrapper_setter = has_wrapper & helpers::has_property_wrapper_bit::has_setter;
|
||||
|
||||
auto gen = [&] (attributes::function_def const& f, bool is_protected) -> bool
|
||||
{
|
||||
// Do not generate static function for concrete class
|
||||
if (is_concrete && f.is_static)
|
||||
return true;
|
||||
|
||||
std::string return_type;
|
||||
if(!as_generator(eolian_mono::type(true)).generate(std::back_inserter(return_type), f.return_type, context))
|
||||
return false;
|
||||
|
||||
if(!as_generator
|
||||
(documentation(1)).generate(sink, f, context))
|
||||
return false;
|
||||
|
||||
std::string self = "this.NativeHandle";
|
||||
|
||||
// IsGeneratedBindingClass is set in the constructor, true if this
|
||||
// instance is from a pure C# class (not generated).
|
||||
if (do_super && !f.is_static)
|
||||
self = "(IsGeneratedBindingClass ? " + self + " : Efl.Eo.Globals.Super(" + self + ", this.NativeClass))";
|
||||
else if (f.is_static)
|
||||
self = "";
|
||||
|
||||
auto scope = is_protected ? "protected " : eolian_mono::function_scope_get(f);
|
||||
|
||||
if(!as_generator
|
||||
(scope_tab << scope << ((do_super && !f.is_static) ? "virtual " : "") << (f.is_static ? "static " : "") << return_type << " " << string << "(" << (parameter % ", ")
|
||||
<< ") {\n"
|
||||
<< scope_tab(2) << eolian_mono::function_definition_preamble()
|
||||
<< klass_full_native_inherit_name(f.klass) << "." << string << "_ptr.Value.Delegate("
|
||||
<< self
|
||||
<< ((!f.is_static && (f.parameters.size() > 0)) ? ", " : "")
|
||||
<< (argument_invocation % ", ") << ");\n"
|
||||
<< scope_tab(2) << eolian_mono::function_definition_epilogue()
|
||||
<< scope_tab(1) << "}\n\n")
|
||||
.generate(sink, std::make_tuple(name_helpers::managed_method_name(f), f.parameters, f, f.c_name, f.parameters, f), context))
|
||||
return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
bool r = true;
|
||||
bool is_self_property = *implementing_klass == *klass_from_property;
|
||||
bool property_from_interface = (klass_from_property->type == attributes::class_type::interface_
|
||||
|| klass_from_property->type == attributes::class_type::mixin);
|
||||
//bool v = is_self_property && !is_concrete_for_interface;
|
||||
|
||||
if (r && property.getter)
|
||||
r &= gen ( *property.getter, always_public ? false : !property_from_interface && has_wrapper_getter);
|
||||
if (r && property.setter)
|
||||
r &= gen ( *property.setter, always_public ? false : !property_from_interface && has_wrapper_setter);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
attributes::klass_def const* implementing_klass, *klass_from_property;
|
||||
bool do_super, always_public;
|
||||
};
|
||||
struct property_function_definition_parameterized
|
||||
{
|
||||
property_function_definition_generator operator()(attributes::klass_def const& klass
|
||||
, attributes::klass_def const& prop_from_klass
|
||||
, bool do_super
|
||||
, bool always_public = false) const
|
||||
{
|
||||
return {&klass, &prop_from_klass, do_super, always_public};
|
||||
}
|
||||
} const property_function_definition;
|
||||
property_function_definition_generator as_generator(property_function_definition_parameterized)
|
||||
{
|
||||
return {nullptr, nullptr, false};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace efl { namespace eolian { namespace grammar {
|
||||
|
@ -813,12 +1171,18 @@ struct is_eager_generator< ::eolian_mono::function_definition_generator> : std::
|
|||
template <>
|
||||
struct is_eager_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {};
|
||||
template <>
|
||||
struct is_eager_generator< ::eolian_mono::native_property_function_definition_generator> : std::true_type {};
|
||||
template <>
|
||||
struct is_eager_generator< ::eolian_mono::property_extension_method_definition_generator> : std::true_type {};
|
||||
template <>
|
||||
struct is_eager_generator< ::eolian_mono::property_wrapper_definition_generator> : std::true_type {};
|
||||
template <>
|
||||
struct is_eager_generator< ::eolian_mono::property_wrapper_definition_parameterized> : std::true_type {};
|
||||
template <>
|
||||
struct is_eager_generator< ::eolian_mono::property_function_definition_generator> : std::true_type {};
|
||||
template <>
|
||||
struct is_eager_generator< ::eolian_mono::property_function_definition_parameterized> : std::true_type {};
|
||||
template <>
|
||||
struct is_eager_generator< ::eolian_mono::interface_property_indexer_definition_parameterized> : std::true_type {};
|
||||
template <>
|
||||
struct 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
|
|||
template <>
|
||||
struct is_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {};
|
||||
template <>
|
||||
struct is_generator< ::eolian_mono::native_property_function_definition_generator> : std::true_type {};
|
||||
template <>
|
||||
struct is_generator< ::eolian_mono::function_definition_parameterized> : std::true_type {};
|
||||
template <>
|
||||
struct 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
|
|||
template <>
|
||||
struct is_generator< ::eolian_mono::property_wrapper_definition_parameterized> : std::true_type {};
|
||||
template <>
|
||||
struct is_generator< ::eolian_mono::property_function_definition_generator> : std::true_type {};
|
||||
template <>
|
||||
struct is_generator< ::eolian_mono::property_function_definition_parameterized> : std::true_type {};
|
||||
template <>
|
||||
struct is_generator< ::eolian_mono::interface_property_indexer_definition_parameterized> : std::true_type {};
|
||||
template <>
|
||||
struct is_generator< ::eolian_mono::interface_property_indexer_definition_generator> : std::true_type {};
|
||||
|
@ -849,6 +1219,9 @@ struct attributes_needed< ::eolian_mono::function_definition_parameterized> : st
|
|||
template <>
|
||||
struct attributes_needed< ::eolian_mono::native_function_definition_generator> : std::integral_constant<int, 1> {};
|
||||
|
||||
template <>
|
||||
struct attributes_needed< ::eolian_mono::native_property_function_definition_generator> : std::integral_constant<int, 1> {};
|
||||
|
||||
template <>
|
||||
struct attributes_needed< ::eolian_mono::property_extension_method_definition_generator> : std::integral_constant<int, 1> {};
|
||||
|
||||
|
@ -857,6 +1230,11 @@ struct attributes_needed< ::eolian_mono::property_wrapper_definition_generator>
|
|||
template <>
|
||||
struct attributes_needed< ::eolian_mono::property_wrapper_definition_parameterized> : std::integral_constant<int, 1> {};
|
||||
|
||||
template <>
|
||||
struct attributes_needed< ::eolian_mono::property_function_definition_generator> : std::integral_constant<int, 1> {};
|
||||
template <>
|
||||
struct attributes_needed< ::eolian_mono::property_function_definition_parameterized> : std::integral_constant<int, 1> {};
|
||||
|
||||
template <>
|
||||
struct attributes_needed< ::eolian_mono::interface_property_indexer_definition_parameterized> : std::integral_constant<int, 1> {};
|
||||
template <>
|
||||
|
|
|
@ -55,6 +55,11 @@ struct function_registration_generator
|
|||
if(blacklist::is_non_public_interface_member(f, *klass))
|
||||
return true;
|
||||
|
||||
if (f.type == attributes::function_type::property
|
||||
|| f.type == attributes::function_type::prop_get
|
||||
|| f.type == attributes::function_type::prop_set)
|
||||
return true;
|
||||
|
||||
if(!as_generator(
|
||||
indent << "if (" << f.c_name << "_static_delegate == null)\n"
|
||||
<< indent << "{\n"
|
||||
|
|
|
@ -163,6 +163,50 @@ std::set<attributes::klass_name, attributes::compare_klass_name_by_name> non_imp
|
|||
return interfaces;
|
||||
}
|
||||
|
||||
// Returns the set of interfaces implemented by this type that haven't been implemented
|
||||
// by a regular parent class and beta path information
|
||||
template<typename Context>
|
||||
std::set<std::pair<attributes::klass_name, bool>, attributes::compare_klass_name_by_name>
|
||||
non_implemented_interfaces_and_beta(attributes::klass_def const& cls, Context const& context)
|
||||
{
|
||||
auto options = efl::eolian::grammar::context_find_tag<options_context>(context);
|
||||
std::set<std::pair<attributes::klass_name, bool>, attributes::compare_klass_name_by_name> implemented_interfaces;
|
||||
std::set<std::pair<attributes::klass_name, bool>, attributes::compare_klass_name_by_name> interfaces;
|
||||
|
||||
std::function<void(attributes::klass_name const&, bool, bool)> inherit_algo =
|
||||
[&] (attributes::klass_name const& klass, bool is_implemented, bool pbeta)
|
||||
{
|
||||
// TODO we could somehow cache klass_def instantiations
|
||||
attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
|
||||
for(auto&& inherit : c.immediate_inherits)
|
||||
{
|
||||
auto beta = pbeta | inherit.is_beta;
|
||||
switch(inherit.type)
|
||||
{
|
||||
case attributes::class_type::mixin:
|
||||
case attributes::class_type::interface_:
|
||||
interfaces.insert(std::make_pair(inherit, beta));
|
||||
if (is_implemented)
|
||||
implemented_interfaces.insert(std::make_pair(inherit, beta));
|
||||
inherit_algo(inherit, is_implemented, beta);
|
||||
break;
|
||||
case attributes::class_type::abstract_:
|
||||
case attributes::class_type::regular:
|
||||
inherit_algo(inherit, true, beta);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inherit_algo(get_klass_name(cls), false, cls.is_beta);
|
||||
|
||||
for (auto&& inherit : implemented_interfaces)
|
||||
interfaces.erase(inherit);
|
||||
|
||||
return interfaces;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Determines whether this class has any regular ancestor or not
|
||||
|
@ -195,18 +239,29 @@ bool inherits_from(attributes::klass_def const& cls, std::string const& name)
|
|||
* Gets all methods that this class should implement (i.e. that come from an unimplemented interface/mixin and the class itself)
|
||||
*/
|
||||
template<typename Context>
|
||||
std::vector<attributes::function_def> get_all_implementable_methods(attributes::klass_def const& cls, Context const& context)
|
||||
std::vector<attributes::function_def> get_all_implementable_methods(attributes::klass_def const& cls, Context const& context
|
||||
, bool insert_properties = false)
|
||||
{
|
||||
bool want_beta = efl::eolian::grammar::context_find_tag<options_context>(context).want_beta;
|
||||
std::vector<attributes::function_def> ret;
|
||||
auto filter_beta = [&want_beta](attributes::function_def const& func) {
|
||||
auto filter = [&](attributes::function_def const& func) {
|
||||
if (!want_beta)
|
||||
return !func.is_beta;
|
||||
return !func.is_beta
|
||||
&& (
|
||||
insert_properties
|
||||
? true
|
||||
:
|
||||
!(func.type == attributes::function_type::property
|
||||
|| func.type == attributes::function_type::prop_set
|
||||
|| func.type == attributes::function_type::prop_get));
|
||||
else
|
||||
return true;
|
||||
return insert_properties ? true
|
||||
: !(func.type == attributes::function_type::property
|
||||
|| func.type == attributes::function_type::prop_set
|
||||
|| func.type == attributes::function_type::prop_get);
|
||||
};
|
||||
|
||||
std::copy_if(cls.functions.begin(), cls.functions.end(), std::back_inserter(ret), filter_beta);
|
||||
std::copy_if(cls.functions.begin(), cls.functions.end(), std::back_inserter(ret), filter);
|
||||
|
||||
// Non implemented interfaces
|
||||
std::set<attributes::klass_name, attributes::compare_klass_name_by_name> implemented_interfaces;
|
||||
|
@ -243,7 +298,66 @@ std::vector<attributes::function_def> get_all_implementable_methods(attributes::
|
|||
for (auto&& inherit : interfaces)
|
||||
{
|
||||
attributes::klass_def klass(get_klass(inherit, cls.unit), cls.unit);
|
||||
std::copy_if(klass.functions.cbegin(), klass.functions.cend(), std::back_inserter(ret), filter_beta);
|
||||
std::copy_if(klass.functions.cbegin(), klass.functions.cend(), std::back_inserter(ret), filter);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets all methods that this class should implement (i.e. that come from an unimplemented interface/mixin and the class itself)
|
||||
*/
|
||||
template<typename Context>
|
||||
std::vector<attributes::property_def> get_all_implementable_properties(attributes::klass_def const& cls, Context const& context)
|
||||
{
|
||||
bool want_beta = efl::eolian::grammar::context_find_tag<options_context>(context).want_beta;
|
||||
std::vector<attributes::property_def> ret;
|
||||
auto filter_beta = [want_beta, cls](attributes::property_def const& prop) {
|
||||
if (!want_beta)
|
||||
return !cls.is_beta && (!prop.getter || !prop.getter->is_beta)
|
||||
&& (!prop.setter || !prop.setter->is_beta);
|
||||
else
|
||||
return true;
|
||||
};
|
||||
|
||||
std::copy_if(cls.properties.begin(), cls.properties.end(), std::back_inserter(ret), filter_beta);
|
||||
|
||||
// Non implemented interfaces
|
||||
std::set<attributes::klass_name, attributes::compare_klass_name_by_name> implemented_interfaces;
|
||||
std::set<attributes::klass_name, attributes::compare_klass_name_by_name> interfaces;
|
||||
std::function<void(attributes::klass_name const&, bool)> inherit_algo =
|
||||
[&] (attributes::klass_name const &klass, bool is_implemented)
|
||||
{
|
||||
attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
|
||||
for (auto&& inherit: c.immediate_inherits)
|
||||
{
|
||||
switch(inherit.type)
|
||||
{
|
||||
case attributes::class_type::mixin:
|
||||
case attributes::class_type::interface_:
|
||||
interfaces.insert(inherit);
|
||||
if (is_implemented)
|
||||
implemented_interfaces.insert(inherit);
|
||||
inherit_algo(inherit, is_implemented);
|
||||
break;
|
||||
case attributes::class_type::abstract_:
|
||||
case attributes::class_type::regular:
|
||||
inherit_algo(inherit, true);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inherit_algo(attributes::get_klass_name(cls), false);
|
||||
|
||||
for (auto&& inherit : implemented_interfaces)
|
||||
interfaces.erase(inherit);
|
||||
|
||||
for (auto&& inherit : interfaces)
|
||||
{
|
||||
attributes::klass_def klass(get_klass(inherit, cls.unit), cls.unit);
|
||||
std::copy_if(klass.properties.cbegin(), klass.properties.cend(), std::back_inserter(ret), filter_beta);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -273,6 +387,10 @@ std::vector<attributes::function_def> get_all_registerable_methods(attributes::k
|
|||
|
||||
if (cls == func.klass)
|
||||
return true;
|
||||
if (func.type == attributes::function_type::property
|
||||
|| func.type == attributes::function_type::prop_set
|
||||
|| func.type == attributes::function_type::prop_get)
|
||||
return false;
|
||||
|
||||
if (is_managed_interface(func.klass) && func.is_static)
|
||||
return true;
|
||||
|
|
|
@ -107,7 +107,7 @@ struct klass
|
|||
context);
|
||||
|
||||
// Property wrappers
|
||||
if (!as_generator(*(interface_property_indexer_definition(cls))).generate(sink, cls.properties, iface_cxt))
|
||||
if (!as_generator("\n\n" << *(interface_property_indexer_definition(cls))).generate(sink, cls.properties, iface_cxt))
|
||||
return false;
|
||||
|
||||
if(!as_generator(documentation).generate(sink, cls, iface_cxt))
|
||||
|
@ -146,7 +146,19 @@ struct klass
|
|||
if(!as_generator("\n{\n").generate(sink, attributes::unused, iface_cxt))
|
||||
return false;
|
||||
|
||||
if(!as_generator(*(function_declaration)).generate(sink, cls.functions, iface_cxt))
|
||||
if(!as_generator("\n\n" << *(property_declaration(cls, cls))).generate(sink, cls.properties, iface_cxt))
|
||||
return false;
|
||||
|
||||
std::vector<attributes::function_def> methods;
|
||||
std::copy_if (cls.functions.begin(), cls.functions.end()
|
||||
, std::back_inserter(methods)
|
||||
, [] (attributes::function_def const& f) -> bool
|
||||
{
|
||||
return !(f.type == attributes::function_type::property
|
||||
|| f.type == attributes::function_type::prop_set
|
||||
|| f.type == attributes::function_type::prop_get);
|
||||
});
|
||||
if(!as_generator("\n" << scope_tab << "//* Methods\n\n" << *(function_declaration)).generate(sink, methods, iface_cxt))
|
||||
return false;
|
||||
|
||||
if(!as_generator(*(async_function_declaration)).generate(sink, cls.functions, iface_cxt))
|
||||
|
@ -253,23 +265,32 @@ struct klass
|
|||
if(!as_generator(*(part_definition))
|
||||
.generate(sink, cls.parts, concrete_cxt)) return false;
|
||||
|
||||
// Concrete function definitions
|
||||
// Property concrete function definitions
|
||||
auto implemented_properties = helpers::get_all_implementable_properties(cls, concrete_cxt);
|
||||
if(!as_generator("\n\n"
|
||||
<< *(
|
||||
property_function_definition(cls, cls, false)
|
||||
))
|
||||
.generate(sink, implemented_properties, concrete_cxt)) return false;
|
||||
|
||||
auto implemented_methods = helpers::get_all_implementable_methods(cls, concrete_cxt);
|
||||
if(!as_generator(*(function_definition))
|
||||
if(!as_generator("\n" << scope_tab << "\n\n" << *(function_definition))
|
||||
.generate(sink, implemented_methods, concrete_cxt)) return false;
|
||||
|
||||
// Async wrappers
|
||||
if(!as_generator(*(async_function_definition)).generate(sink, implemented_methods, concrete_cxt))
|
||||
if(!as_generator(*(async_function_definition)).generate(sink, helpers::get_all_implementable_methods(cls, concrete_cxt, true), concrete_cxt))
|
||||
return false;
|
||||
|
||||
// Property wrappers
|
||||
if (!as_generator(*(property_wrapper_definition(cls, cls))).generate(sink, cls.properties, concrete_cxt))
|
||||
if (!as_generator(*(property_wrapper_definition(cls, cls)))
|
||||
.generate(sink, cls.properties, concrete_cxt))
|
||||
return false;
|
||||
|
||||
for (auto&& klass : helpers::non_implemented_interfaces(cls, concrete_cxt))
|
||||
for (auto&& klass : helpers::non_implemented_interfaces_and_beta(cls, concrete_cxt))
|
||||
{
|
||||
attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
|
||||
if (!as_generator(*(property_wrapper_definition(cls, c))).generate(sink, c.properties, concrete_cxt))
|
||||
attributes::klass_def c(get_klass(klass.first, cls.unit), cls.unit);
|
||||
bool force_protected = (!context_find_tag<options_context>(concrete_cxt).want_beta && klass.second);
|
||||
if (!as_generator(*(property_wrapper_definition(cls, c, force_protected))).generate(sink, c.properties, concrete_cxt))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -291,8 +312,9 @@ struct klass
|
|||
if(!as_generator("}\n").generate(sink, attributes::unused, concrete_cxt)) return false;
|
||||
}
|
||||
|
||||
// Inheritable class
|
||||
if(class_type == "class" || class_type == "abstract class")
|
||||
// // Inheritable class
|
||||
// if(class_type == "class" || class_type == "abstract class")
|
||||
else
|
||||
{
|
||||
auto inherit_cxt = context_add_tag(class_context{class_context::inherit,
|
||||
name_helpers::klass_full_concrete_or_interface_name(cls)},
|
||||
|
@ -337,23 +359,31 @@ struct klass
|
|||
if(!as_generator(*(part_definition))
|
||||
.generate(sink, cls.parts, inherit_cxt)) return false;
|
||||
|
||||
// Property concrete function definitions
|
||||
auto implemented_properties = helpers::get_all_implementable_properties(cls, inherit_cxt);
|
||||
if(!as_generator(*(property_function_definition(cls, cls, true, true)))
|
||||
.generate(sink, implemented_properties, inherit_cxt)) return false;
|
||||
|
||||
// Inherit function definitions
|
||||
auto implemented_methods = helpers::get_all_implementable_methods(cls, inherit_cxt);
|
||||
if(!as_generator(*(function_definition(true)))
|
||||
if(!as_generator("\n" << scope_tab << "//* Methods\n\n" << *(function_definition(true)))
|
||||
.generate(sink, implemented_methods, inherit_cxt)) return false;
|
||||
|
||||
// Async wrappers
|
||||
if(!as_generator(*(async_function_definition(true))).generate(sink, implemented_methods, inherit_cxt))
|
||||
if(!as_generator(*(async_function_definition(true))).generate(sink, helpers::get_all_implementable_methods(cls, inherit_cxt, true), inherit_cxt))
|
||||
return false;
|
||||
|
||||
// Property wrappers
|
||||
if (!as_generator(*(property_wrapper_definition(cls, cls))).generate(sink, cls.properties, inherit_cxt))
|
||||
if (!as_generator("\n\n" << *property_wrapper_definition(cls, cls)
|
||||
).generate(sink, cls.properties, inherit_cxt))
|
||||
return false;
|
||||
|
||||
for (auto&& klass : helpers::non_implemented_interfaces(cls, inherit_cxt))
|
||||
for (auto&& klass : helpers::non_implemented_interfaces_and_beta(cls, inherit_cxt))
|
||||
{
|
||||
attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
|
||||
if (!as_generator(*(property_wrapper_definition(cls, c))).generate(sink, c.properties, inherit_cxt))
|
||||
attributes::klass_def c(get_klass(klass.first, cls.unit), cls.unit);
|
||||
assert (c != cls);
|
||||
bool force_protected = (!context_find_tag<options_context>(inherit_cxt).want_beta && klass.second);
|
||||
if (!as_generator(*(property_wrapper_definition(cls, c, force_protected))).generate(sink, c.properties, inherit_cxt))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -424,6 +454,7 @@ struct klass
|
|||
auto native_inherit_name = name_helpers::klass_native_inherit_name(cls);
|
||||
auto inherit_name = name_helpers::klass_inherit_name(cls);
|
||||
auto implementable_methods = helpers::get_all_registerable_methods(cls, context);
|
||||
auto implementable_properties = helpers::get_all_implementable_properties(cls, inative_cxt);
|
||||
bool root = !helpers::has_regular_ancestor(cls);
|
||||
auto const& indent = current_indentation(inative_cxt);
|
||||
std::string klass_since;
|
||||
|
@ -450,7 +481,8 @@ struct klass
|
|||
).generate(sink, attributes::unused, inative_cxt))
|
||||
return false;
|
||||
|
||||
if(implementable_methods.size() >= 1)
|
||||
if(implementable_methods.size() >= 1
|
||||
|| implementable_properties.size() >= 1)
|
||||
{
|
||||
if(!as_generator(
|
||||
indent << scope_tab << "private static Efl.Eo.NativeModule Module = new Efl.Eo.NativeModule("
|
||||
|
@ -533,6 +565,12 @@ struct klass
|
|||
<< indent << scope_tab << "#pragma warning restore CA1707, CS1591, SA1300, SA1600\n\n")
|
||||
.generate(sink, implementable_methods, change_indentation(indent.inc(), inative_cxt))) return false;
|
||||
|
||||
if(!as_generator(
|
||||
indent << scope_tab << "#pragma warning disable CA1707, CS1591, SA1300, SA1600\n\n"
|
||||
<< *(native_property_function_definition(cls, cls))
|
||||
<< indent << scope_tab << "#pragma warning restore CA1707, CS1591, SA1300, SA1600\n\n")
|
||||
.generate(sink, implementable_properties, change_indentation(indent.inc(), inative_cxt))) return false;
|
||||
|
||||
if(!as_generator("}\n").generate(sink, attributes::unused, inative_cxt)) return false;
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -31,30 +31,30 @@ public class GenericModel<T> : Efl.Object, Efl.IModel
|
|||
}
|
||||
|
||||
/// <summary>The list of properties available in the wrapped model.</summary>
|
||||
/// <returns>The list of properties in the model.</returns>
|
||||
public IEnumerable<System.String> Properties
|
||||
{
|
||||
get { return GetProperties(); }
|
||||
get { return model.Properties; }
|
||||
}
|
||||
|
||||
/// <summary>The number of children in the wrapped model.</summary>
|
||||
|
||||
/// <summary>Returns the number of children in the wrapped model.</summary>
|
||||
/// <returns>The number of children.</returns>
|
||||
public uint ChildrenCount
|
||||
{
|
||||
get { return GetChildrenCount(); }
|
||||
}
|
||||
|
||||
/// <summary>The list of properties available in the wrapped model.</summary>
|
||||
/// <returns>The list of properties in the model.</returns>
|
||||
public IEnumerable<System.String> GetProperties()
|
||||
{
|
||||
return model.GetProperties();
|
||||
get { return model.ChildrenCount; }
|
||||
}
|
||||
|
||||
/// <summary>Gets the value of the given property in the wrapped model.</summary>
|
||||
/// <param name="property">The property of the model.</param>
|
||||
/// <returns>The value of the property.</returns>
|
||||
public Eina.Value GetProperty(System.String property)
|
||||
public Efl.IModelPropertyIndexer Property
|
||||
{
|
||||
return model.GetProperty(property);
|
||||
get
|
||||
{
|
||||
return model.Property;
|
||||
}
|
||||
set{}
|
||||
}
|
||||
|
||||
/// <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
|
|||
return model.SetProperty(property, value);
|
||||
}
|
||||
|
||||
/// <summary>Returns the number of children in the wrapped model.</summary>
|
||||
/// <returns>The number of children.</returns>
|
||||
public uint GetChildrenCount()
|
||||
{
|
||||
return model.GetChildrenCount();
|
||||
}
|
||||
|
||||
/// <summary>Returns an <see cref="Eina.Future" /> that will resolve when the property is ready to be read.</summary>
|
||||
/// <param name="property">The property of the model.</param>
|
||||
/// <returns>An <see cref="Eina.Future" /> that resolves when the property is ready.</returns>
|
||||
|
|
|
@ -42,7 +42,7 @@ internal class ModelHelper
|
|||
var properties = typeof(T).GetProperties();
|
||||
foreach (var prop in properties)
|
||||
{
|
||||
using (var v = child.GetProperty(prop.Name))
|
||||
using (var v = child.Property[prop.Name])
|
||||
{
|
||||
SetPropertyFromValue(o, prop, v);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<DocumentationFile>$(AssemblyName).xml</DocumentationFile>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<!-- TreatWarningsAsErrors>true</TreatWarningsAsErrors -->
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- <PropertyGroup Condition="'$(BuildType)'=='Beta'"> -->
|
||||
|
|
|
@ -227,7 +227,7 @@ public abstract class EoWrapper : IWrapper, IDisposable
|
|||
public void Del()
|
||||
{
|
||||
// FIXME Implement this
|
||||
((Efl.Object)this).SetParent(null);
|
||||
((Efl.Object)this).Parent = null;
|
||||
Dispose();
|
||||
}
|
||||
|
||||
|
|
|
@ -1082,6 +1082,52 @@ struct property_def
|
|||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct tuple_element<0ul, property_def>
|
||||
{
|
||||
typedef std::string type;
|
||||
static type& get(property_def& p) { return p.name; }
|
||||
static type const& get(property_def const& p) { return p.name; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct tuple_element<1ul, property_def>
|
||||
{
|
||||
typedef documentation_def type;
|
||||
static type& get(property_def& p) { return p.documentation; }
|
||||
static type const& get(property_def const& p) { return p.documentation; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct tuple_element<2ul, property_def>
|
||||
{
|
||||
typedef efl::eina::optional<function_def> type;
|
||||
static type& get(property_def& p) { return p.getter; }
|
||||
static type const& get(property_def const& p) { return p.getter; }
|
||||
};
|
||||
|
||||
template <>
|
||||
struct tuple_element<3ul, property_def>
|
||||
{
|
||||
typedef efl::eina::optional<function_def> type;
|
||||
static type& get(property_def& p) { return p.setter; }
|
||||
static type const& get(property_def const& p) { return p.setter; }
|
||||
};
|
||||
|
||||
template <std::size_t I>
|
||||
typename tuple_element<I, property_def>::type const&
|
||||
get(property_def const& f)
|
||||
{
|
||||
return tuple_element<I, property_def>::get(f);
|
||||
}
|
||||
|
||||
template <std::size_t I>
|
||||
typename tuple_element<I, property_def>::type&
|
||||
get(property_def& f)
|
||||
{
|
||||
return tuple_element<I, property_def>::get(f);
|
||||
}
|
||||
|
||||
struct constant_def
|
||||
{
|
||||
std::string name;
|
||||
|
@ -1165,6 +1211,18 @@ struct compare_klass_name_by_name
|
|||
return lhs.namespaces < rhs.namespaces
|
||||
|| (!(rhs.namespaces < lhs.namespaces) && lhs.eolian_name < rhs.eolian_name);
|
||||
}
|
||||
template <typename T>
|
||||
bool operator()(std::pair<klass_name, T> const& lhs, std::pair<klass_name, T> const& rhs) const
|
||||
{
|
||||
return lhs.first.namespaces < rhs.first.namespaces
|
||||
|| (!(rhs.first.namespaces < lhs.first.namespaces) && lhs.first.eolian_name < rhs.first.eolian_name);
|
||||
}
|
||||
template <typename T>
|
||||
bool operator()(std::pair<T, klass_name> const& lhs, std::pair<T, klass_name> const& rhs) const
|
||||
{
|
||||
return lhs.second.namespaces < rhs.second.namespaces
|
||||
|| (!(rhs.second.namespaces < lhs.second.namespaces) && lhs.second.eolian_name < rhs.second.eolian_name);
|
||||
}
|
||||
};
|
||||
|
||||
struct event_def
|
||||
|
@ -1816,6 +1874,10 @@ namespace type_traits {
|
|||
template <>
|
||||
struct is_tuple<attributes::parameter_def> : std::true_type {};
|
||||
template <>
|
||||
struct is_tuple<attributes::property_def> : std::true_type {};
|
||||
template <>
|
||||
struct is_tuple<attributes::function_def> : std::true_type {};
|
||||
template <>
|
||||
struct is_tuple<attributes::event_def> : std::true_type {};
|
||||
|
||||
}
|
||||
|
|
|
@ -699,16 +699,16 @@ class TestProtectedInterfaceMembers
|
|||
{
|
||||
var type = typeof(Dummy.ITestIface);
|
||||
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance);
|
||||
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||
|
||||
// Fully protected property
|
||||
Test.AssertNull(methods.SingleOrDefault(m => m.Name == "GetProtectedProp"));
|
||||
Test.AssertNull(methods.SingleOrDefault(m => m.Name == "SetProtectedProp"));
|
||||
|
||||
// Partially protected property
|
||||
Test.AssertNotNull(methods.SingleOrDefault(m => m.Name == "GetPublicGetterPrivateSetter"));
|
||||
Test.AssertNotNull(properties.SingleOrDefault(m => m.Name == "PublicGetterPrivateSetter"));
|
||||
Test.AssertNull(methods.SingleOrDefault(m => m.Name == "SetPublicGetterPrivateSetter"));
|
||||
|
||||
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
|
||||
Test.AssertNull(properties.SingleOrDefault(m => m.Name == "ProtectedProp"));
|
||||
Test.AssertNotNull(properties.SingleOrDefault(m => m.Name == "PublicGetterPrivateSetter"));
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ public static class TestModel {
|
|||
var veggies = CreateModel(loop);
|
||||
|
||||
var model = new Efl.GenericModel<VeggieViewModel>(veggies, loop);
|
||||
Test.AssertEquals(3, (int)model.GetChildrenCount());
|
||||
Test.AssertEquals(3, (int)model.ChildrenCount);
|
||||
|
||||
VeggieViewModel r2 = await model.GetAtAsync(1).ConfigureAwait(false);
|
||||
Test.AssertEquals(r2.Name, "Romaine Lettuce");
|
||||
|
|
Loading…
Reference in New Issue