WIP: Generating fields in interface indexers

Needs to sort out the generation of indexer types for the fields of
non-public interface properties that are generated in concrete classes.

(Mainly the if/else around function_definition.hh 690)
This commit is contained in:
Lauro Moura 2019-12-17 22:36:33 -03:00
parent 28271776d8
commit 518a6cc57d
4 changed files with 77 additions and 27 deletions

View File

@ -165,7 +165,7 @@ inline bool is_property_blacklisted(std::string const& name)
// Setter returns a future
, "Efl.IModel.Property"
// Protected
, "Efl.Access.IAction.ActionName"
// , "Efl.Access.IAction.ActionName"
, "Efl.Access.IAction.ActionLocalizedName"
, "Efl.Access.IComponent.Extents"
, "Efl.Access.IText.AccessSelection"

View File

@ -356,7 +356,6 @@ struct property_wrapper_definition_generator
, attributes::property_def const& property
, Context const& context
, std::string scope, std::string get_scope, std::string set_scope
, std::string class_name
, C1 keys, C2 values
, bool is_interface
, bool is_concrete_for_interface
@ -380,16 +379,15 @@ struct property_wrapper_definition_generator
std::string parentship = "\n";
bool is_self_property = *implementing_klass == *klass_from_property;
if (!(is_self_property && !is_concrete_for_interface))
if (helpers::is_impl_of_interface_property_indexer(property, *klass_from_property, *implementing_klass, context))
parentship = " : " + name_helpers::property_interface_indexer_name(property, *klass_from_property) + "\n";
auto klass_from_property_name = name_helpers::klass_full_concrete_or_interface_name(*klass_from_property);
if (!as_generator
(
scope_tab << scope << "class " << name_helpers::property_concrete_indexer_name(property) << parentship
<< scope_tab << "{\n"
<< scope_tab(2) << "public " << class_name << " Self {get; set;}\n"
<< scope_tab(2) << "public " << klass_from_property_name << " Self {get; set;}\n"
<< scope_tab(2) << "public "
<< type_or_tuple << " this[" << type_or_tuple <<" i]\n"
<< scope_tab(2) << "{\n"
@ -675,41 +673,44 @@ struct property_wrapper_definition_generator
if (has_indexer)
{
// The generated indexer wraps the actual property values inside the indexer, so a call like
// `obj.IndexedProperty[key] = value` calls the `[key]` indexer method in the indexer class.
// That said, we need to replace the property values with the indexer.
assert (!!implementing_klass);
generate_indexer (sink, property, context, scope, get_scope, set_scope
, klass_name, keys, values
generate_indexer (sink, property, context
, scope, get_scope, set_scope
, keys, values
, is_interface, is_concrete_for_interface, has_setter);
generated_values.clear();
std::string base_type_name;
std::string c_type;
// FIXME this selection needs to be sorted out.
if (!is_interface && *implementing_klass == *klass_from_property
&& !is_concrete_for_interface)
// if (!is_interface && !helpers::is_impl_of_interface_property_indexer(property, *klass_from_property, *implementing_klass, context))
{
generated_values.push_back
(attributes::parameter_def
{parameter_direction::in
, attributes::type_def
{
attributes::regular_type_def{name_helpers::property_concrete_indexer_name(property), {attributes::qualifier_info::is_none, ""}, {}}
, name_helpers::property_concrete_indexer_name(property)
, false, false, false, ""
}
, "indexer", {}, nullptr
});
base_type_name = name_helpers::property_concrete_indexer_name(property);
c_type = name_helpers::property_concrete_indexer_name(property);
}
else
{
generated_values.push_back
base_type_name = name_helpers::property_interface_indexer_name(property, *klass_from_property);
c_type = name_helpers::property_interface_indexer_name(property, *klass_from_property);
}
generated_values.push_back
(attributes::parameter_def
{parameter_direction::in
, attributes::type_def
{
attributes::regular_type_def{name_helpers::klass_full_concrete_or_interface_name (*klass_from_property) + managed_name + "Indexer", {attributes::qualifier_info::is_none, ""}, {}}
, name_helpers::property_interface_indexer_name(property, *klass_from_property)
attributes::regular_type_def{base_type_name, {attributes::qualifier_info::is_none, ""}, {}}
, c_type
, false, false, false, ""
}
, "indexer", {}, nullptr
});
}
}
if (generated_values.size() == 1)
@ -781,11 +782,42 @@ struct interface_property_indexer_definition_generator
auto klass_name = name_helpers::klass_concrete_or_interface_name (*implementing_klass);
std::string managed_name = name_helpers::property_managed_name(property);
auto has_wrapper = helpers::has_property_wrapper(property, implementing_klass, context);
// EINA_LOG_ERR("Wrapper bit for property %s of implementing class %s is 0x%X", managed_name.c_str(),
// implementing_klass->eolian_name.c_str(), (unsigned int) has_wrapper);
if (!(has_wrapper & helpers::has_property_wrapper_bit::has_getter))
return true;
if (!(has_wrapper & helpers::has_property_wrapper_bit::has_indexer))
return true;
auto keys = property.getter->keys;
auto values = property.getter->values;
// Helper generator expressions
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)
)
;
if (!as_generator
("public interface " << name_helpers::property_interface_indexer_short_name(property, *implementing_klass) << "\n"
<< "{\n"
<< scope_tab << klass_name << " Self {get; set;}\n"
<< scope_tab << type_or_tuple << " this[" << type_or_tuple << " i]\n"
<< scope_tab << "{\n"
<< scope_tab(2) << "get;\n"
<< scope_tab << "}\n"
<< "}\n"
).generate (sink, attributes::unused, context))
).generate (sink, std::make_tuple(values, values, keys, keys), context))
return false;
return true;

View File

@ -29,6 +29,7 @@ namespace helpers {
/* General helpers, not related directly with generating strings (those go in the name_helpers.hh). */
namespace attributes = efl::eolian::grammar::attributes;
namespace grammar = efl::eolian::grammar;
inline bool need_struct_conversion(attributes::regular_type_def const* regular)
{
@ -353,8 +354,7 @@ has_property_wrapper_bit has_property_wrapper(attributes::property_def const& pr
else if (is_concrete) return r;
}
// EINA_LOG_ERR("Generating property %s", name_helpers::property_managed_name(property).c_str());
// C# interface can have only
// C# interface can have only public methods.
if (is_interface)
{
has_getter = has_getter && property.getter->scope == attributes::member_scope:: scope_public;
@ -406,6 +406,24 @@ has_property_wrapper_bit has_property_wrapper(attributes::property_def const& pr
return r;
}
template<typename Context>
bool is_impl_of_interface_property_indexer(attributes::property_def const& property
, attributes::klass_def const& klass_from_property
, attributes::klass_def const& implementing_klass
, Context const& context)
{
bool is_self_property = implementing_klass == klass_from_property;
// EINA_LOG_ERR("Generating indexer for property %s", name_helpers::property_managed_name(property).c_str());
if (is_self_property)
return false;
bool original_klass_is_interface = helpers::is_managed_interface(klass_from_property);
auto iface_context = grammar::context_add_tag(class_context{class_context::interface}, context);
auto wrapper_bit = helpers::has_property_wrapper(property, &klass_from_property, iface_context);
return wrapper_bit & helpers::has_property_wrapper_bit::has_indexer;
}
} // namespace helpers
} // namespace eolian_mono

View File

@ -40,7 +40,7 @@ public static class Timeout
/// <summary>
/// The path to an object.
/// <para>Since EFL 1.23.</para>
/// </summary>
/// /// </summary>
[StructLayout(LayoutKind.Sequential)]
public struct ObjectPath : IEquatable<ObjectPath>
{