forked from enlightenment/efl
csharp: Property Indexer implementation
Use Indexers to use brackets, eg [i], syntax. Keys now can be used as following: var someVal = obj.SomeProperty[key]; obj.SomeProperty[key] = someNewVal; And for multiple keys: var someVal = obj.SomeProperty[(key1, key2)]; obj.SomeProperty[(key1, key2)] = someNewVal; T8384 Reviewed-by: WooHyun Jung <wh0705.jung@samsung.com> Differential Revision: https://phab.enlightenment.org/D10791
This commit is contained in:
parent
ed0572a33a
commit
0954e501fd
|
@ -150,9 +150,34 @@ inline bool is_alias_blacklisted(attributes::alias_def const& alias, Context con
|
||||||
return name_helpers::alias_full_eolian_name(alias) == "Eina.Error";
|
return name_helpers::alias_full_eolian_name(alias) == "Eina.Error";
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool is_property_blacklisted(std::string const&)
|
inline bool is_property_blacklisted(std::string const& name)
|
||||||
{
|
{
|
||||||
return false;
|
auto properties = std::vector<std::string>{
|
||||||
|
// These properties encode (void* arr, int len) arrays
|
||||||
|
"Efl.Gfx.IGradient.Stop"
|
||||||
|
, "Efl.Gfx.GradientConcrete.Stop"
|
||||||
|
, "Efl.Gfx.IShape.StrokeDash"
|
||||||
|
, "Efl.Gfx.ShapeConcrete.StrokeDash"
|
||||||
|
, "Efl.Gfx.Vg.ValueProvider.Transform"
|
||||||
|
, "Efl.Canvas.Vg.Node.Transformation"
|
||||||
|
// Will be bound manually
|
||||||
|
, "Efl.Core.Env.Env"
|
||||||
|
// Setter returns a future
|
||||||
|
, "Efl.IModel.Property"
|
||||||
|
// Protected
|
||||||
|
, "Efl.Access.IAction.ActionName"
|
||||||
|
, "Efl.Access.IAction.ActionLocalizedName"
|
||||||
|
, "Efl.Access.IComponent.Extents"
|
||||||
|
, "Efl.Access.IText.AccessSelection"
|
||||||
|
, "Efl.Access.IText.AccessText"
|
||||||
|
, "Efl.Access.IText.BoundedRanges"
|
||||||
|
, "Efl.Access.IText.Character"
|
||||||
|
, "Efl.Access.IText.OffsetAtPoint"
|
||||||
|
, "Efl.Access.IText.String"
|
||||||
|
, "Efl.Access.IText.TextAttributes"
|
||||||
|
};
|
||||||
|
|
||||||
|
return std::find(std::begin(properties), std::end(properties), name) != std::end(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Context>
|
template<typename Context>
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "grammar/html_escaped_string.hpp"
|
#include "grammar/html_escaped_string.hpp"
|
||||||
#include "using_decl.hh"
|
#include "using_decl.hh"
|
||||||
#include "name_helpers.hh"
|
#include "name_helpers.hh"
|
||||||
|
#include "helpers.hh"
|
||||||
#include "generation_contexts.hh"
|
#include "generation_contexts.hh"
|
||||||
#include "blacklist.hh"
|
#include "blacklist.hh"
|
||||||
|
|
||||||
|
@ -76,7 +77,11 @@ struct documentation_generator
|
||||||
// The name_tail parameter is the last 4 chars of the original string, which
|
// The name_tail parameter is the last 4 chars of the original string, which
|
||||||
// could be ".set" or ".get" and in this case they are ignored by Eolian.
|
// could be ".set" or ".get" and in this case they are ignored by Eolian.
|
||||||
// We want them to know what the documentation intended to reference.
|
// We want them to know what the documentation intended to reference.
|
||||||
static std::string function_conversion(const ::Eolian_Object *klass, const ::Eolian_Function *function, std::string name_tail)
|
template<typename Context>
|
||||||
|
static std::string function_conversion(const ::Eolian_Object *klass
|
||||||
|
, const ::Eolian_Function *function
|
||||||
|
, std::string name_tail
|
||||||
|
, Context const& context)
|
||||||
{
|
{
|
||||||
::Eolian_Function_Type ftype = ::eolian_function_type_get(function);
|
::Eolian_Function_Type ftype = ::eolian_function_type_get(function);
|
||||||
const char* eo_name = ::eolian_function_name_get(function);
|
const char* eo_name = ::eolian_function_name_get(function);
|
||||||
|
@ -122,13 +127,27 @@ struct documentation_generator
|
||||||
break;
|
break;
|
||||||
case ::EOLIAN_PROPERTY:
|
case ::EOLIAN_PROPERTY:
|
||||||
{
|
{
|
||||||
int getter_nkeys = property_num_keys(function, ::EOLIAN_PROP_GET);
|
|
||||||
int setter_nkeys = property_num_keys(function, ::EOLIAN_PROP_SET);
|
|
||||||
std::string short_name = name_helpers::property_managed_name(klass_d, eo_name);
|
std::string short_name = name_helpers::property_managed_name(klass_d, eo_name);
|
||||||
bool blacklisted = blacklist::is_property_blacklisted(name + "." + short_name);
|
|
||||||
// EO properties with keys or blacklisted are not converted into C# properties.
|
// We need to replace the current class context with the context
|
||||||
// In these cases we refer to the getter method instead of the property.
|
// from the class that originated this property.
|
||||||
if ((getter_nkeys > 0) || (setter_nkeys > 0) || (blacklisted)) name += ".Get" + short_name;
|
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 unit = eolian_object_unit_get((const Eolian_Object*)function);
|
||||||
|
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_none)
|
||||||
|
name += ".Get" + short_name;
|
||||||
else if (name_tail == ".get") name += ".Get" + short_name;
|
else if (name_tail == ".get") name += ".Get" + short_name;
|
||||||
else if (name_tail == ".set") name += ".Set" + short_name;
|
else if (name_tail == ".set") name += ".Set" + short_name;
|
||||||
else name += "." + short_name;
|
else name += "." + short_name;
|
||||||
|
@ -165,9 +184,13 @@ struct documentation_generator
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turns an Eolian reference like @Efl.Input.Pointer.tool into a <see> tag
|
// Turns an Eolian reference like @Efl.Input.Pointer.tool into a <see> tag
|
||||||
static std::string ref_conversion(const ::Eolian_Doc_Token *token, const Eolian_State *state, std::string name_tail,
|
template<typename Context>
|
||||||
bool want_beta)
|
static std::string ref_conversion(const ::Eolian_Doc_Token *token
|
||||||
|
, const Eolian_State *state
|
||||||
|
, std::string name_tail
|
||||||
|
, Context const& context)
|
||||||
{
|
{
|
||||||
|
bool want_beta = context_want_beta(context);
|
||||||
const Eolian_Object *data, *data2;
|
const Eolian_Object *data, *data2;
|
||||||
::Eolian_Object_Type type =
|
::Eolian_Object_Type type =
|
||||||
::eolian_doc_token_ref_resolve(token, state, &data, &data2);
|
::eolian_doc_token_ref_resolve(token, state, &data, &data2);
|
||||||
|
@ -195,7 +218,7 @@ struct documentation_generator
|
||||||
is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2);
|
is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2);
|
||||||
break;
|
break;
|
||||||
case ::EOLIAN_OBJECT_FUNCTION:
|
case ::EOLIAN_OBJECT_FUNCTION:
|
||||||
ref += function_conversion(data, (const ::Eolian_Function *)data2, name_tail);
|
ref += function_conversion(data, (const ::Eolian_Function *)data2, name_tail, context);
|
||||||
is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2);
|
is_beta = eolian_object_is_beta(data) || eolian_object_is_beta(data2);
|
||||||
break;
|
break;
|
||||||
case ::EOLIAN_OBJECT_CONSTANT:
|
case ::EOLIAN_OBJECT_CONSTANT:
|
||||||
|
@ -227,7 +250,8 @@ struct documentation_generator
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turns EO documentation syntax into C# triple-slash XML comment syntax
|
// Turns EO documentation syntax into C# triple-slash XML comment syntax
|
||||||
static std::string syntax_conversion(std::string text, const Eolian_State *state, bool want_beta)
|
template<typename Context>
|
||||||
|
static std::string syntax_conversion(std::string text, const Eolian_State *state, Context const& context)
|
||||||
{
|
{
|
||||||
std::string new_text, ref;
|
std::string new_text, ref;
|
||||||
::Eolian_Doc_Token_Type previous_token_type = ::EOLIAN_DOC_TOKEN_UNKNOWN;
|
::Eolian_Doc_Token_Type previous_token_type = ::EOLIAN_DOC_TOKEN_UNKNOWN;
|
||||||
|
@ -266,7 +290,7 @@ struct documentation_generator
|
||||||
new_text += token_text;
|
new_text += token_text;
|
||||||
break;
|
break;
|
||||||
case ::EOLIAN_DOC_TOKEN_REF:
|
case ::EOLIAN_DOC_TOKEN_REF:
|
||||||
ref = ref_conversion(&token, state, name_tail, want_beta);
|
ref = ref_conversion(&token, state, name_tail, context);
|
||||||
if (ref != "")
|
if (ref != "")
|
||||||
{
|
{
|
||||||
if (utils::ends_with(ref, BETA_REF_SUFFIX))
|
if (utils::ends_with(ref, BETA_REF_SUFFIX))
|
||||||
|
@ -331,7 +355,7 @@ struct documentation_generator
|
||||||
if (!as_generator(html_escaped_string).generate(std::back_inserter(new_text), text, context))
|
if (!as_generator(html_escaped_string).generate(std::back_inserter(new_text), text, context))
|
||||||
return false;
|
return false;
|
||||||
auto options = context_find_tag<options_context>(context);
|
auto options = context_find_tag<options_context>(context);
|
||||||
new_text = syntax_conversion( new_text, context_find_tag<eolian_state_context>(context).state, options.want_beta);
|
new_text = syntax_conversion( new_text, context_find_tag<eolian_state_context>(context).state, context);
|
||||||
|
|
||||||
std::string tabs;
|
std::string tabs;
|
||||||
as_generator(scope_tab(scope_size) << "/// ").generate (std::back_inserter(tabs), attributes::unused, context);
|
as_generator(scope_tab(scope_size) << "/// ").generate (std::back_inserter(tabs), attributes::unused, context);
|
||||||
|
@ -653,7 +677,7 @@ struct documentation_string_generator
|
||||||
|
|
||||||
auto options = context_find_tag<options_context>(context);
|
auto options = context_find_tag<options_context>(context);
|
||||||
auto state = context_find_tag<eolian_state_context>(context).state;
|
auto state = context_find_tag<eolian_state_context>(context).state;
|
||||||
if (!as_generator(string).generate(sink, documentation_generator::syntax_conversion(escaped, state, options.want_beta), context))
|
if (!as_generator(string).generate(sink, documentation_generator::syntax_conversion(escaped, state, context), context))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "grammar/list.hpp"
|
#include "grammar/list.hpp"
|
||||||
#include "grammar/alternative.hpp"
|
#include "grammar/alternative.hpp"
|
||||||
#include "grammar/attribute_reorder.hpp"
|
#include "grammar/attribute_reorder.hpp"
|
||||||
|
#include "grammar/eps.hpp"
|
||||||
#include "grammar/counter.hpp"
|
#include "grammar/counter.hpp"
|
||||||
#include "logging.hh"
|
#include "logging.hh"
|
||||||
#include "type.hh"
|
#include "type.hh"
|
||||||
|
@ -323,6 +324,199 @@ property_extension_method_definition_generator property_extension_method_definit
|
||||||
|
|
||||||
struct property_wrapper_definition_generator
|
struct property_wrapper_definition_generator
|
||||||
{
|
{
|
||||||
|
template <typename OutputIterator, typename Context>
|
||||||
|
bool generate_get_indexer(OutputIterator sink, attributes::property_def const& property, Context const& context
|
||||||
|
, std::string get_scope
|
||||||
|
, bool is_interface) const
|
||||||
|
{
|
||||||
|
if (is_interface)
|
||||||
|
{
|
||||||
|
if (!as_generator(scope_tab << scope_tab << get_scope << "get;\n"
|
||||||
|
).generate(sink, attributes::unused, context))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!as_generator(scope_tab << scope_tab << get_scope << "get\n"
|
||||||
|
<< scope_tab << scope_tab << "{\n"
|
||||||
|
<< scope_tab << scope_tab(2) << "var i = new "
|
||||||
|
<< name_helpers::property_concrete_indexer_name(property) << "();\n"
|
||||||
|
<< scope_tab << scope_tab(2) << "i.Self = this;\n"
|
||||||
|
<< scope_tab << scope_tab(2) << "return i;\n"
|
||||||
|
<< scope_tab << scope_tab << "}\n"
|
||||||
|
).generate(sink, attributes::unused, context))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename OutputIterator, typename Context, typename C1, typename C2>
|
||||||
|
bool generate_indexer(OutputIterator sink
|
||||||
|
, 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
|
||||||
|
, bool has_setter) const
|
||||||
|
{
|
||||||
|
if (is_interface)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
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)
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
std::string parentship = "\n";
|
||||||
|
|
||||||
|
bool is_self_property = *implementing_klass == *klass_from_property;
|
||||||
|
|
||||||
|
if (!(is_self_property && !is_concrete_for_interface))
|
||||||
|
parentship = " : " + name_helpers::property_interface_indexer_name(property, *klass_from_property) + "\n";
|
||||||
|
|
||||||
|
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 "
|
||||||
|
<< type_or_tuple << " this[" << type_or_tuple <<" i]\n"
|
||||||
|
<< scope_tab(2) << "{\n"
|
||||||
|
).generate(sink, make_tuple(values, values, keys, keys), context))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
assert (!keys.empty());
|
||||||
|
std::vector<std::string> get_keys;
|
||||||
|
if(keys.size() != 1)
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
for (auto&& key : keys)
|
||||||
|
{
|
||||||
|
static_cast<void>(key);
|
||||||
|
++i;
|
||||||
|
get_keys.push_back("i.Item" + std::to_string(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
get_keys.push_back ("i");
|
||||||
|
}
|
||||||
|
assert (!get_keys.empty());
|
||||||
|
|
||||||
|
generate_get(sink, property, context, get_scope, get_keys, values, is_interface, "Self.");
|
||||||
|
if (has_setter)
|
||||||
|
generate_set(sink, property, context, set_scope, get_keys, values, is_interface, "Self.");
|
||||||
|
|
||||||
|
if (!as_generator
|
||||||
|
(
|
||||||
|
scope_tab(2) << "}\n"
|
||||||
|
<< scope_tab << "};\n"
|
||||||
|
).generate(sink, attributes::unused, context))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
template <typename OutputIterator, typename Context, typename CK, typename CV>
|
||||||
|
bool generate_set(OutputIterator sink, attributes::property_def const& property, Context const& context
|
||||||
|
, std::string set_scope
|
||||||
|
, CK keys, CV values
|
||||||
|
, bool is_interface
|
||||||
|
, std::string name_prefix = "") const
|
||||||
|
{
|
||||||
|
using efl::eolian::grammar::counter;
|
||||||
|
if (is_interface)
|
||||||
|
{
|
||||||
|
if (!as_generator(scope_tab << scope_tab << set_scope << "set;\n"
|
||||||
|
).generate(sink, attributes::unused, context))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (values.size() == 1)
|
||||||
|
{
|
||||||
|
if (!as_generator(scope_tab << scope_tab << set_scope << "set " << "{ " << name_prefix << name_helpers::managed_method_name(*property.setter) + "(" << *(string << ",") << "value); }\n"
|
||||||
|
).generate(sink, keys, context))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (values.size() > 1)
|
||||||
|
{
|
||||||
|
if (!as_generator(
|
||||||
|
scope_tab << scope_tab << set_scope << "set "
|
||||||
|
<< ("{ " << name_prefix << name_helpers::managed_method_name(*property.setter) + "(")
|
||||||
|
<< *(string << ",") << ((" value.Item" << counter(1)) % ", ")
|
||||||
|
<< "); }\n"
|
||||||
|
).generate(sink, std::make_tuple(keys, values), context))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
template <typename OutputIterator, typename Context, typename CK, typename CV>
|
||||||
|
bool generate_get(OutputIterator sink, attributes::property_def const& property, Context const& context
|
||||||
|
, std::string get_scope
|
||||||
|
, CK keys, CV values
|
||||||
|
, bool is_interface
|
||||||
|
, std::string name_prefix = "") const
|
||||||
|
{
|
||||||
|
using efl::eolian::grammar::attribute_reorder;
|
||||||
|
using efl::eolian::grammar::attributes::parameter_direction;
|
||||||
|
using efl::eolian::grammar::attributes::parameter_def;
|
||||||
|
|
||||||
|
if (is_interface) // only declaration
|
||||||
|
{
|
||||||
|
if (!as_generator(scope_tab << scope_tab << get_scope << "get;\n"
|
||||||
|
).generate(sink, attributes::unused, context))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (/*has_getter && */values.size() == 1)
|
||||||
|
{
|
||||||
|
if (!as_generator
|
||||||
|
(scope_tab << scope_tab << get_scope
|
||||||
|
<< "get " << "{ return " << name_prefix << name_helpers::managed_method_name(*property.getter)
|
||||||
|
<< "(" << (string % ",") << "); }\n"
|
||||||
|
).generate(sink, keys, context))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (/*has_getter && */values.size() > 1)
|
||||||
|
{
|
||||||
|
if (!as_generator
|
||||||
|
(scope_tab << scope_tab << get_scope << "get "
|
||||||
|
<< "{\n"
|
||||||
|
<< *attribute_reorder<1, -1, 1>
|
||||||
|
(scope_tab(3) << type(true) << " _out_"
|
||||||
|
<< argument(false) << " = default(" << type(true) << ");\n"
|
||||||
|
)
|
||||||
|
<< scope_tab(3) << name_prefix << name_helpers::managed_method_name(*property.getter)
|
||||||
|
<< "(" << *(string << ",") << (("out _out_" << argument(false)) % ", ") << ");\n"
|
||||||
|
<< scope_tab(3) << "return (" << (("_out_"<< argument(false)) % ", ") << ");\n"
|
||||||
|
<< scope_tab(2) << "}" << "\n"
|
||||||
|
).generate(sink, std::make_tuple(values, keys, values, values), context))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// else if (values.size() == 1)
|
||||||
|
// {
|
||||||
|
// if (!as_generator
|
||||||
|
// (scope_tab << scope_tab << get_scope << "get "
|
||||||
|
// << "{\n"
|
||||||
|
// << *attribute_reorder<1, -1, 1>(scope_tab(3) << type(true) << " _out_" << argument(false) << " = default(" << type(true) << ");\n")
|
||||||
|
// << scope_tab(3) << name_prefix << name_helpers::managed_method_name(*property.getter)
|
||||||
|
// << "(" << *(string << ",") << (("out _out_" << argument(false)) % ",") << ");\n"
|
||||||
|
// << scope_tab(3) << "return " << (("_out_"<< argument(false)) % ",") << ";\n"
|
||||||
|
// << scope_tab(2) << "}" << "\n"
|
||||||
|
// ).generate(sink, std::make_tuple(values, keys, values, values), context))
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename OutputIterator, typename Context>
|
template<typename OutputIterator, typename Context>
|
||||||
bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const
|
bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const
|
||||||
{
|
{
|
||||||
|
@ -331,103 +525,127 @@ struct property_wrapper_definition_generator
|
||||||
using efl::eolian::grammar::attributes::parameter_direction;
|
using efl::eolian::grammar::attributes::parameter_direction;
|
||||||
using efl::eolian::grammar::attributes::parameter_def;
|
using efl::eolian::grammar::attributes::parameter_def;
|
||||||
|
|
||||||
if (blacklist::is_property_blacklisted(property, *implementing_klass, context))
|
/// C(k) = keys count, C(v) = values count
|
||||||
return true;
|
/// /------------\ /------\.
|
||||||
|
/// |blacklisted?|---yes-----| skip |--------------\.
|
||||||
|
/// \------------/ \------/ |
|
||||||
|
/// | | |
|
||||||
|
/// no yes |
|
||||||
|
/// | | |
|
||||||
|
/// /---------\ /------------\ |
|
||||||
|
/// |is-static|----yes-----|is-interface| |
|
||||||
|
/// \---------/ \------------/ |
|
||||||
|
/// | | |
|
||||||
|
/// no no |
|
||||||
|
/// | | |
|
||||||
|
/// /--------\ /-----------\ |
|
||||||
|
/// |has-get?|---no-conc---|is-concrete|-----yes---/
|
||||||
|
/// \--------/ \-----------/
|
||||||
|
/// / \.
|
||||||
|
/// no yes
|
||||||
|
/// / \.
|
||||||
|
/// /----\ /--------------------------------------\.
|
||||||
|
/// |skip|-yes-|explicit return != Eina.Error or void |
|
||||||
|
/// \----/ \--------------------------------------/
|
||||||
|
/// |
|
||||||
|
/// no
|
||||||
|
/// |
|
||||||
|
/// /--------\.
|
||||||
|
/// |has-set?|
|
||||||
|
/// \--------/
|
||||||
|
/// / \.
|
||||||
|
/// no yes
|
||||||
|
/// / \.
|
||||||
|
/// /------\ /--------------------------------------\.
|
||||||
|
/// /------------------|no-set| |explicit return != Eina.Error or void |---- yes --\.
|
||||||
|
/// | \------/ \--------------------------------------/ |
|
||||||
|
/// | \------------|----------------------------------------------/
|
||||||
|
/// | no
|
||||||
|
/// | |
|
||||||
|
/// | /--------\.
|
||||||
|
/// | |has-both|
|
||||||
|
/// | \--------/
|
||||||
|
/// | |
|
||||||
|
/// | /-------------------\.
|
||||||
|
/// | |set-keys = get-keys|
|
||||||
|
/// | \-------------------/
|
||||||
|
/// | / |
|
||||||
|
/// | no |
|
||||||
|
/// | / |
|
||||||
|
/// | /----\ /-----------------------\.
|
||||||
|
/// | |skip|--no---|set-values = get-values|
|
||||||
|
/// | \----/ \-----------------------/
|
||||||
|
/// | /
|
||||||
|
/// | yes
|
||||||
|
/// | /
|
||||||
|
/// | /--------\.
|
||||||
|
/// \-------------------------| keys |
|
||||||
|
/// \--------/
|
||||||
|
/// / \.
|
||||||
|
/// 0 >0
|
||||||
|
/// / \.
|
||||||
|
/// /----------\ /----------\.
|
||||||
|
/// |no-indexer| | keys > 1 |
|
||||||
|
/// \----------/ \----------/
|
||||||
|
/// | / |
|
||||||
|
/// | no yes
|
||||||
|
/// | / |
|
||||||
|
/// | / |
|
||||||
|
/// | /---------\ /-------------------\.
|
||||||
|
/// | | indexer | | indexer tuple key |
|
||||||
|
/// | \---------/ \-------------------/
|
||||||
|
/// | / |
|
||||||
|
/// /--------\ |
|
||||||
|
/// | values |----------/
|
||||||
|
/// \--------/
|
||||||
|
/// / \.
|
||||||
|
/// 1 >1
|
||||||
|
/// / \.
|
||||||
|
/// /----------------\ /-------------\.
|
||||||
|
/// | no tuple value | | tuple value |
|
||||||
|
/// \----------------/ \-------------/
|
||||||
|
///
|
||||||
|
|
||||||
|
auto has_wrapper = helpers::has_property_wrapper (property, implementing_klass, context);
|
||||||
|
bool has_getter = has_wrapper & helpers::has_property_wrapper_bit::has_getter;
|
||||||
|
if (!has_getter) return true;
|
||||||
|
bool has_setter = has_wrapper & helpers::has_property_wrapper_bit::has_setter;
|
||||||
|
bool has_indexer = has_wrapper & helpers::has_property_wrapper_bit::has_indexer;
|
||||||
|
|
||||||
bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
|
bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
|
||||||
bool is_static = (property.getter.is_engaged() && property.getter->is_static)
|
bool is_static = (property.getter.is_engaged() && property.getter->is_static)
|
||||||
|| (property.setter.is_engaged() && property.setter->is_static);
|
|| (property.setter.is_engaged() && property.setter->is_static);
|
||||||
bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
|
bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
|
||||||
|
bool is_concrete_for_interface = is_concrete
|
||||||
|
&& (implementing_klass->type == attributes::class_type::interface_
|
||||||
|
|| implementing_klass->type == attributes::class_type::mixin);
|
||||||
|
|
||||||
|
//if (name_helpers::klass_concrete_or_interface_name (*implementing_klass) == "IMapping")
|
||||||
if ((is_concrete || is_interface) && is_static)
|
if (false)
|
||||||
return true;
|
|
||||||
|
|
||||||
auto get_params = property.getter.is_engaged() ? property.getter->parameters.size() : 0;
|
|
||||||
//auto set_params = property.setter.is_engaged() ? property.setter->parameters.size() : 0;
|
|
||||||
|
|
||||||
// C# properties must have a single value.
|
|
||||||
//
|
|
||||||
// Single values in getters are automatically converted to return_type,
|
|
||||||
// meaning they should have 0 parameters.
|
|
||||||
//
|
|
||||||
// For setters, we ignore the return type - usually boolean.
|
|
||||||
// if (get_params > 0 || set_params > 1)
|
|
||||||
// return true;
|
|
||||||
|
|
||||||
if (property.getter
|
|
||||||
&& std::find_if (property.getter->parameters.begin()
|
|
||||||
, property.getter->parameters.end()
|
|
||||||
, [] (parameter_def const& p)
|
|
||||||
{
|
|
||||||
return p.direction != parameter_direction::out;
|
|
||||||
}) != property.getter->parameters.end())
|
|
||||||
return true;
|
|
||||||
if (property.setter
|
|
||||||
&& std::find_if (property.setter->parameters.begin()
|
|
||||||
, property.setter->parameters.end()
|
|
||||||
, [] (parameter_def const& p)
|
|
||||||
{
|
|
||||||
return p.direction != parameter_direction::in;
|
|
||||||
}) != property.setter->parameters.end())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (property.getter && property.setter)
|
|
||||||
{
|
{
|
||||||
if (get_params != 0 && property.setter->parameters.size() != property.getter->parameters.size())
|
if (!as_generator(grammar::lit("/// is interface ") << (int)is_interface
|
||||||
return true;
|
<< " is static " << (int)is_static
|
||||||
|
<< " is concrete " << (int)is_concrete
|
||||||
|
<< " is concrete_for_interface " << (int)is_concrete_for_interface
|
||||||
|
<< " klass_from_property->type " << (int)klass_from_property->type
|
||||||
|
<< " has_setter " << (int)has_setter
|
||||||
|
<< " property.setter->explicit_return_type != attributes::void_ " << (property.setter && property.setter->explicit_return_type != attributes::void_)
|
||||||
|
<< " property.setter->keys != property.getter->keys " << (property.setter && property.setter->keys != property.getter->keys)
|
||||||
|
<< " property.setter->values != property.getter->values " << (property.setter && property.setter->values != property.getter->values)
|
||||||
|
<< " has_setter && property.setter->scope != attributes::member_scope::scope_public " << (property.setter && property.setter->scope != attributes::member_scope::scope_public)
|
||||||
|
<< "\n")
|
||||||
|
.generate (sink, attributes::unused, context))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<attributes::parameter_def> parameters;
|
if (blacklist::is_property_blacklisted(property, context))
|
||||||
|
return true;
|
||||||
if (property.setter.is_engaged())
|
|
||||||
{
|
|
||||||
std::transform (property.setter->parameters.begin(), property.setter->parameters.end()
|
|
||||||
, std::back_inserter(parameters)
|
|
||||||
, [] (parameter_def p) -> parameter_def
|
|
||||||
{
|
|
||||||
//p.direction = efl::eolian::attributes::parameter_direction::in;
|
|
||||||
return p;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (property.getter.is_engaged())
|
|
||||||
{
|
|
||||||
// if getter has parameters, then we ignore return type, otherwise
|
|
||||||
// we use the return type.
|
|
||||||
if (get_params == 0)
|
|
||||||
parameters.push_back({parameter_direction::in
|
|
||||||
, property.getter->return_type, "propertyResult", {}
|
|
||||||
, property.getter->unit});
|
|
||||||
else
|
|
||||||
std::transform (property.getter->parameters.begin(), property.getter->parameters.end()
|
|
||||||
, std::back_inserter(parameters)
|
|
||||||
, [] (parameter_def p) -> parameter_def
|
|
||||||
{
|
|
||||||
p.direction = parameter_direction::in;
|
|
||||||
return p;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EINA_CXX_DOM_LOG_ERR(eolian_mono::domain) << "Property must have either a getter or a setter." << std::endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string dir_mod;
|
|
||||||
if (property.setter.is_engaged())
|
|
||||||
dir_mod = direction_modifier(property.setter->parameters[0]);
|
|
||||||
|
|
||||||
std::string managed_name = name_helpers::property_managed_name(property);
|
std::string managed_name = name_helpers::property_managed_name(property);
|
||||||
|
|
||||||
std::string scope = "public ";
|
std::string scope = "public ";
|
||||||
std::string get_scope = property.getter.is_engaged() ? eolian_mono::function_scope_get(*property.getter) : "";
|
std::string get_scope = eolian_mono::function_scope_get(*property.getter);
|
||||||
bool is_get_public = get_scope == "public ";
|
std::string set_scope = has_setter ? eolian_mono::function_scope_get(*property.setter) : "";
|
||||||
std::string set_scope = property.setter.is_engaged() ? eolian_mono::function_scope_get(*property.setter) : "";
|
|
||||||
bool is_set_public = set_scope == "public ";
|
|
||||||
|
|
||||||
// No need to generate this wrapper as no accessor is public.
|
|
||||||
if (is_interface && (!is_get_public && !is_set_public))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// C# interface members are declared automatically as public
|
// C# interface members are declared automatically as public
|
||||||
if (is_interface)
|
if (is_interface)
|
||||||
|
@ -442,23 +660,64 @@ struct property_wrapper_definition_generator
|
||||||
get_scope = "";
|
get_scope = "";
|
||||||
set_scope = "";
|
set_scope = "";
|
||||||
}
|
}
|
||||||
else if (!property.setter.is_engaged() || (get_scope == scope))
|
else if (!has_setter || (get_scope == scope))
|
||||||
{
|
{
|
||||||
scope = get_scope;
|
scope = get_scope;
|
||||||
get_scope = "";
|
get_scope = "";
|
||||||
}
|
}
|
||||||
else if (!property.getter.is_engaged() || (set_scope == scope))
|
|
||||||
{
|
|
||||||
scope = set_scope;
|
|
||||||
set_scope = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parameters.size() == 1)
|
std::string virtual_mod = (is_static || is_interface || is_concrete) ? "" : "virtual ";
|
||||||
|
|
||||||
|
auto keys = property.getter->keys;
|
||||||
|
auto values = property.getter->values;
|
||||||
|
auto generated_values = values;
|
||||||
|
auto klass_name = name_helpers::klass_concrete_or_interface_name (*implementing_klass);
|
||||||
|
|
||||||
|
if (has_indexer)
|
||||||
|
{
|
||||||
|
assert (!!implementing_klass);
|
||||||
|
generate_indexer (sink, property, context, scope, get_scope, set_scope
|
||||||
|
, klass_name, keys, values
|
||||||
|
, is_interface, is_concrete_for_interface, has_setter);
|
||||||
|
|
||||||
|
generated_values.clear();
|
||||||
|
if (!is_interface && *implementing_klass == *klass_from_property
|
||||||
|
&& !is_concrete_for_interface)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
, false, false, false, ""
|
||||||
|
}
|
||||||
|
, "indexer", {}, nullptr
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (generated_values.size() == 1)
|
||||||
{
|
{
|
||||||
if (!as_generator(
|
if (!as_generator(
|
||||||
documentation(1)
|
documentation(1)
|
||||||
<< scope_tab << scope << (is_static ? "static " : "") << type(true) << " " << managed_name << " {\n"
|
<< scope_tab << scope << (is_static ? "static " : virtual_mod) << type(true) << " " << managed_name << " {\n"
|
||||||
).generate(sink, std::make_tuple(property, parameters[0].type), context))
|
).generate(sink, std::make_tuple(property, generated_values[0].type), context))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -469,73 +728,21 @@ struct property_wrapper_definition_generator
|
||||||
<< scope_tab << scope << (is_static ? "static (" : "(")
|
<< scope_tab << scope << (is_static ? "static (" : "(")
|
||||||
<< (attribute_reorder<1, -1>(type(true) /*<< " " << argument*/) % ", ") << ") "
|
<< (attribute_reorder<1, -1>(type(true) /*<< " " << argument*/) % ", ") << ") "
|
||||||
<< managed_name << " {\n"
|
<< managed_name << " {\n"
|
||||||
).generate(sink, std::make_tuple(property, parameters), context))
|
).generate(sink, std::make_tuple(property, generated_values), context))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property.getter.is_engaged() && is_interface)
|
if (has_indexer)
|
||||||
{
|
{
|
||||||
if (is_get_public)
|
generate_get_indexer (sink, property, context, get_scope, is_interface);
|
||||||
if (!as_generator(scope_tab << scope_tab << set_scope << "get;\n"
|
|
||||||
).generate(sink, attributes::unused, context))
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
else if (property.getter.is_engaged() && get_params == 0/*parameters.size() == 1 && property.getter.is_engaged()*/)
|
else
|
||||||
{
|
{
|
||||||
if (!as_generator
|
std::vector<std::string> empty_keys;
|
||||||
(scope_tab << scope_tab << get_scope
|
generate_get(sink, property, context, get_scope, empty_keys, values, is_interface);
|
||||||
<< "get " << "{ return " + name_helpers::managed_method_name(*property.getter) + "(); }\n"
|
|
||||||
).generate(sink, attributes::unused, context))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (parameters.size() >= 1 && property.getter)
|
|
||||||
{
|
|
||||||
if (!as_generator
|
|
||||||
(scope_tab << scope_tab << get_scope << "get "
|
|
||||||
<< "{\n"
|
|
||||||
<< *attribute_reorder<1, -1, 1>
|
|
||||||
(scope_tab(3) << type(true) << " _out_"
|
|
||||||
<< argument(false) << " = default(" << type(true) << ");\n"
|
|
||||||
)
|
|
||||||
<< scope_tab(3) << name_helpers::managed_method_name(*property.getter)
|
|
||||||
<< "(" << (("out _out_" << argument(false)) % ", ") << ");\n"
|
|
||||||
<< scope_tab(3) << "return (" << (("_out_"<< argument(false)) % ", ") << ");\n"
|
|
||||||
<< scope_tab(2) << "}" << "\n"
|
|
||||||
).generate(sink, std::make_tuple(parameters, parameters, parameters), context))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// else if (parameters.size() == 1)
|
|
||||||
// {
|
|
||||||
// if (!as_generator
|
|
||||||
// (scope_tab << scope_tab << get_scope << "get "
|
|
||||||
// << "{\n"
|
|
||||||
// << *attribute_reorder<1, -1, 1>(scope_tab(3) << type(true) << " _out_" << argument(false) << " = default(" << type(true) << ");\n")
|
|
||||||
// << scope_tab(3) << name_helpers::managed_method_name(*property.getter)
|
|
||||||
// << "(" << (("out _out_" << argument(false)) % ",") << ");\n"
|
|
||||||
// << scope_tab(3) << "return " << (("_out_"<< argument(false)) % ",") << ";\n"
|
|
||||||
// << scope_tab(2) << "}" << "\n"
|
|
||||||
// ).generate(sink, std::make_tuple(parameters, parameters, parameters), context))
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (property.setter.is_engaged() && is_interface)
|
if (has_setter)
|
||||||
{
|
generate_set (sink, property, context, set_scope, empty_keys, values, is_interface);
|
||||||
if (is_set_public)
|
|
||||||
if (!as_generator(scope_tab << scope_tab << set_scope << "set;\n"
|
|
||||||
).generate(sink, attributes::unused, context))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (parameters.size() == 1 && property.setter.is_engaged())
|
|
||||||
{
|
|
||||||
if (!as_generator(scope_tab << scope_tab << set_scope << "set " << "{ " + name_helpers::managed_method_name(*property.setter) + "(" + dir_mod + "value); }\n"
|
|
||||||
).generate(sink, attributes::unused, context))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if (parameters.size() > 1 && property.setter.is_engaged())
|
|
||||||
{
|
|
||||||
if (!as_generator(scope_tab << scope_tab << set_scope << "set " << ("{ " + name_helpers::managed_method_name(*property.setter) + "(" + dir_mod) << ((" value.Item" << counter(1)) % ", ") << "); }" << "\n"
|
|
||||||
).generate(sink, parameters, context))
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!as_generator(scope_tab << "}\n\n").generate(sink, attributes::unused, context))
|
if (!as_generator(scope_tab << "}\n\n").generate(sink, attributes::unused, context))
|
||||||
|
@ -543,13 +750,14 @@ struct property_wrapper_definition_generator
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
attributes::klass_def const* implementing_klass;
|
attributes::klass_def const* implementing_klass, *klass_from_property;
|
||||||
};
|
};
|
||||||
struct property_wrapper_definition_parameterized
|
struct property_wrapper_definition_parameterized
|
||||||
{
|
{
|
||||||
property_wrapper_definition_generator operator()(attributes::klass_def const& klass) const
|
property_wrapper_definition_generator operator()(attributes::klass_def const& klass
|
||||||
|
, attributes::klass_def const& prop_from_klass) const
|
||||||
{
|
{
|
||||||
return {&klass};
|
return {&klass, &prop_from_klass};
|
||||||
}
|
}
|
||||||
} const property_wrapper_definition;
|
} const property_wrapper_definition;
|
||||||
property_wrapper_definition_generator as_generator(property_wrapper_definition_parameterized)
|
property_wrapper_definition_generator as_generator(property_wrapper_definition_parameterized)
|
||||||
|
@ -557,6 +765,45 @@ property_wrapper_definition_generator as_generator(property_wrapper_definition_p
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct interface_property_indexer_definition_generator
|
||||||
|
{
|
||||||
|
template<typename OutputIterator, typename Context>
|
||||||
|
bool generate(OutputIterator sink, attributes::property_def const& property, Context const& context) const
|
||||||
|
{
|
||||||
|
using efl::eolian::grammar::attribute_reorder;
|
||||||
|
using efl::eolian::grammar::counter;
|
||||||
|
using efl::eolian::grammar::attributes::parameter_direction;
|
||||||
|
using efl::eolian::grammar::attributes::parameter_def;
|
||||||
|
|
||||||
|
bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
|
||||||
|
|
||||||
|
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"
|
||||||
|
).generate (sink, attributes::unused, context))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
attributes::klass_def const* implementing_klass;
|
||||||
|
};
|
||||||
|
struct interface_property_indexer_definition_parameterized
|
||||||
|
{
|
||||||
|
interface_property_indexer_definition_generator operator()(attributes::klass_def const& klass) const
|
||||||
|
{
|
||||||
|
return {&klass};
|
||||||
|
}
|
||||||
|
} const interface_property_indexer_definition;
|
||||||
|
interface_property_indexer_definition_generator as_generator(interface_property_indexer_definition_parameterized)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace efl { namespace eolian { namespace grammar {
|
namespace efl { namespace eolian { namespace grammar {
|
||||||
|
@ -572,6 +819,10 @@ struct is_eager_generator< ::eolian_mono::property_wrapper_definition_generator>
|
||||||
template <>
|
template <>
|
||||||
struct is_eager_generator< ::eolian_mono::property_wrapper_definition_parameterized> : std::true_type {};
|
struct is_eager_generator< ::eolian_mono::property_wrapper_definition_parameterized> : std::true_type {};
|
||||||
template <>
|
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 {};
|
||||||
|
template <>
|
||||||
struct is_generator< ::eolian_mono::function_definition_generator> : std::true_type {};
|
struct is_generator< ::eolian_mono::function_definition_generator> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
struct is_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {};
|
struct is_generator< ::eolian_mono::native_function_definition_generator> : std::true_type {};
|
||||||
|
@ -583,6 +834,10 @@ template <>
|
||||||
struct is_generator< ::eolian_mono::property_wrapper_definition_generator> : std::true_type {};
|
struct is_generator< ::eolian_mono::property_wrapper_definition_generator> : std::true_type {};
|
||||||
template <>
|
template <>
|
||||||
struct is_generator< ::eolian_mono::property_wrapper_definition_parameterized> : std::true_type {};
|
struct is_generator< ::eolian_mono::property_wrapper_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 {};
|
||||||
|
|
||||||
namespace type_traits {
|
namespace type_traits {
|
||||||
template <>
|
template <>
|
||||||
|
@ -601,6 +856,11 @@ template <>
|
||||||
struct attributes_needed< ::eolian_mono::property_wrapper_definition_generator> : std::integral_constant<int, 1> {};
|
struct attributes_needed< ::eolian_mono::property_wrapper_definition_generator> : std::integral_constant<int, 1> {};
|
||||||
template <>
|
template <>
|
||||||
struct attributes_needed< ::eolian_mono::property_wrapper_definition_parameterized> : std::integral_constant<int, 1> {};
|
struct attributes_needed< ::eolian_mono::property_wrapper_definition_parameterized> : std::integral_constant<int, 1> {};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct attributes_needed< ::eolian_mono::interface_property_indexer_definition_parameterized> : std::integral_constant<int, 1> {};
|
||||||
|
template <>
|
||||||
|
struct attributes_needed< ::eolian_mono::interface_property_indexer_definition_generator> : std::integral_constant<int, 1> {};
|
||||||
}
|
}
|
||||||
|
|
||||||
} } }
|
} } }
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace eolian_mono {
|
||||||
struct class_context
|
struct class_context
|
||||||
{
|
{
|
||||||
enum wrapper_kind {
|
enum wrapper_kind {
|
||||||
|
none,
|
||||||
interface,
|
interface,
|
||||||
concrete,
|
concrete,
|
||||||
inherit,
|
inherit,
|
||||||
|
@ -109,6 +110,12 @@ struct options_context {
|
||||||
std::string examples_dir;
|
std::string examples_dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename Context>
|
||||||
|
bool context_want_beta(Context const& context)
|
||||||
|
{
|
||||||
|
return efl::eolian::grammar::context_find_tag<options_context>(context).want_beta;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#define EOLIAN_MONO_HELPERS_HH
|
#define EOLIAN_MONO_HELPERS_HH
|
||||||
|
|
||||||
#include "grammar/klass_def.hpp"
|
#include "grammar/klass_def.hpp"
|
||||||
|
#include "grammar/context.hpp"
|
||||||
#include "blacklist.hh"
|
#include "blacklist.hh"
|
||||||
#include "generation_contexts.hh"
|
#include "generation_contexts.hh"
|
||||||
#include "name_helpers.hh"
|
#include "name_helpers.hh"
|
||||||
|
@ -305,6 +306,106 @@ inline std::vector<attributes::constructor_def> reorder_constructors(std::vector
|
||||||
return constructors;
|
return constructors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class has_property_wrapper_bit
|
||||||
|
{
|
||||||
|
has_none = 0
|
||||||
|
, has_getter = 1 << 0
|
||||||
|
, has_setter = 1 << 1
|
||||||
|
, has_indexer = 1 << 2
|
||||||
|
, has_key_tuple = 1 << 3
|
||||||
|
, has_value_tuple = 1 << 4
|
||||||
|
, has_set_error_check = 1 << 5
|
||||||
|
, has_get_error_check = 1 << 6
|
||||||
|
};
|
||||||
|
|
||||||
|
has_property_wrapper_bit& operator|=(has_property_wrapper_bit& self, has_property_wrapper_bit bit)
|
||||||
|
{
|
||||||
|
self = static_cast<has_property_wrapper_bit>(static_cast<int>(self) | static_cast<int>(bit));
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator&(has_property_wrapper_bit self, has_property_wrapper_bit bit)
|
||||||
|
{
|
||||||
|
return static_cast<int>(self) & static_cast<int>(bit);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Context>
|
||||||
|
has_property_wrapper_bit has_property_wrapper(attributes::property_def const& property, attributes::klass_def const* implementing_klass
|
||||||
|
, Context const& context)
|
||||||
|
{
|
||||||
|
using efl::eolian::grammar::context_find_tag;
|
||||||
|
has_property_wrapper_bit r = has_property_wrapper_bit::has_none;
|
||||||
|
|
||||||
|
if (blacklist::is_property_blacklisted(property, *implementing_klass, context))
|
||||||
|
return r;
|
||||||
|
|
||||||
|
bool has_getter = property.getter.is_engaged();
|
||||||
|
bool has_setter = property.setter.is_engaged();
|
||||||
|
|
||||||
|
bool is_interface = context_find_tag<class_context>(context).current_wrapper_kind == class_context::interface;
|
||||||
|
bool is_static = (property.getter.is_engaged() && property.getter->is_static)
|
||||||
|
|| (has_setter && property.setter->is_static);
|
||||||
|
bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
|
||||||
|
|
||||||
|
if (is_static)
|
||||||
|
{
|
||||||
|
if (is_interface) return r;
|
||||||
|
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
|
||||||
|
if (is_interface)
|
||||||
|
{
|
||||||
|
has_getter = has_getter && property.getter->scope == attributes::member_scope:: scope_public;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!has_getter)
|
||||||
|
{
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property.getter->explicit_return_type != attributes::void_)
|
||||||
|
{
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
else if (has_setter)
|
||||||
|
{
|
||||||
|
if (property.setter->explicit_return_type != attributes::void_)
|
||||||
|
has_setter = false; // do not generate setter
|
||||||
|
else if (property.setter->keys != property.getter->keys)
|
||||||
|
has_setter = false;
|
||||||
|
else if (property.setter->values != property.getter->values)
|
||||||
|
has_setter = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_interface)
|
||||||
|
{
|
||||||
|
if (property.getter->scope != attributes::member_scope::scope_public)
|
||||||
|
return r;
|
||||||
|
else if (has_setter && property.setter->scope != attributes::member_scope::scope_public)
|
||||||
|
has_setter = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_getter)
|
||||||
|
r |= has_property_wrapper_bit::has_getter;
|
||||||
|
if (has_setter)
|
||||||
|
r |= has_property_wrapper_bit::has_setter;
|
||||||
|
|
||||||
|
if (property.getter->keys.size() == 1)
|
||||||
|
r |= has_property_wrapper_bit::has_indexer;
|
||||||
|
else if (property.getter->keys.size() > 1)
|
||||||
|
{
|
||||||
|
r |= has_property_wrapper_bit::has_indexer;
|
||||||
|
r |= has_property_wrapper_bit::has_key_tuple;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property.getter->values.size() > 1)
|
||||||
|
r |= has_property_wrapper_bit::has_value_tuple;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace helpers
|
} // namespace helpers
|
||||||
|
|
||||||
} // namespace eolian_mono
|
} // namespace eolian_mono
|
||||||
|
|
|
@ -106,6 +106,10 @@ struct klass
|
||||||
name_helpers::klass_full_concrete_or_interface_name(cls)},
|
name_helpers::klass_full_concrete_or_interface_name(cls)},
|
||||||
context);
|
context);
|
||||||
|
|
||||||
|
// Property wrappers
|
||||||
|
if (!as_generator(*(interface_property_indexer_definition(cls))).generate(sink, cls.properties, iface_cxt))
|
||||||
|
return false;
|
||||||
|
|
||||||
if(!as_generator(documentation).generate(sink, cls, iface_cxt))
|
if(!as_generator(documentation).generate(sink, cls, iface_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -158,7 +162,7 @@ struct klass
|
||||||
).generate(sink, p, iface_cxt))
|
).generate(sink, p, iface_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, cls.properties, iface_cxt))
|
if (!as_generator(*(property_wrapper_definition(cls, cls))).generate(sink, cls.properties, iface_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// End of interface declaration
|
// End of interface declaration
|
||||||
|
@ -259,13 +263,13 @@ struct klass
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Property wrappers
|
// Property wrappers
|
||||||
if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, cls.properties, concrete_cxt))
|
if (!as_generator(*(property_wrapper_definition(cls, cls))).generate(sink, cls.properties, concrete_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (auto&& klass : helpers::non_implemented_interfaces(cls, concrete_cxt))
|
for (auto&& klass : helpers::non_implemented_interfaces(cls, concrete_cxt))
|
||||||
{
|
{
|
||||||
attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
|
attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
|
||||||
if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, c.properties, concrete_cxt))
|
if (!as_generator(*(property_wrapper_definition(cls, c))).generate(sink, c.properties, concrete_cxt))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,13 +347,13 @@ struct klass
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Property wrappers
|
// Property wrappers
|
||||||
if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, cls.properties, inherit_cxt))
|
if (!as_generator(*(property_wrapper_definition(cls, cls))).generate(sink, cls.properties, inherit_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (auto&& klass : helpers::non_implemented_interfaces(cls, inherit_cxt))
|
for (auto&& klass : helpers::non_implemented_interfaces(cls, inherit_cxt))
|
||||||
{
|
{
|
||||||
attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
|
attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
|
||||||
if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, c.properties, inherit_cxt))
|
if (!as_generator(*(property_wrapper_definition(cls, c))).generate(sink, c.properties, inherit_cxt))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -334,28 +334,6 @@ inline std::string to_field_name(std::string const& in)
|
||||||
return utils::capitalize(in);
|
return utils::capitalize(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline std::string property_managed_name(T const& klass, std::string const& name)
|
|
||||||
{
|
|
||||||
auto names = utils::split(name, '_');
|
|
||||||
// No need to escape keyword here as it will be capitalized and already
|
|
||||||
// namespaced inside the owner class.
|
|
||||||
auto managed_name = utils::to_pascal_case(names);
|
|
||||||
auto managed_klass_name = klass_concrete_or_interface_name(klass);
|
|
||||||
|
|
||||||
if (managed_name == "Type")
|
|
||||||
managed_name = managed_klass_name + managed_name;
|
|
||||||
|
|
||||||
return managed_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string property_managed_name(attributes::property_def const& property)
|
|
||||||
{
|
|
||||||
return property_managed_name(property.klass, property.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::string managed_part_name(attributes::part_def const& part)
|
inline std::string managed_part_name(attributes::part_def const& part)
|
||||||
{
|
{
|
||||||
std::vector<std::string> names = utils::split(part.name, '_');
|
std::vector<std::string> names = utils::split(part.name, '_');
|
||||||
|
@ -512,6 +490,45 @@ inline std::string translate_inherited_event_name(const attributes::event_def &e
|
||||||
return join_namespaces(klass.namespaces, '_') + klass_interface_name(klass) + "_" + managed_event_name(evt.name);
|
return join_namespaces(klass.namespaces, '_') + klass_interface_name(klass) + "_" + managed_event_name(evt.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline std::string property_managed_name(T const& klass, std::string const& name)
|
||||||
|
{
|
||||||
|
auto names = utils::split(name, '_');
|
||||||
|
// No need to escape keyword here as it will be capitalized and already
|
||||||
|
// namespaced inside the owner class.
|
||||||
|
auto managed_name = utils::to_pascal_case(names);
|
||||||
|
auto managed_klass_name = klass_concrete_or_interface_name(klass);
|
||||||
|
|
||||||
|
if (managed_name == "Type")
|
||||||
|
managed_name = managed_klass_name + managed_name;
|
||||||
|
|
||||||
|
return managed_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string property_managed_name(attributes::property_def const& property)
|
||||||
|
{
|
||||||
|
return property_managed_name(property.klass, property.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string property_concrete_indexer_name(attributes::property_def const& property)
|
||||||
|
{
|
||||||
|
return property_managed_name(property) + "Indexer";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline std::string property_interface_indexer_name(attributes::property_def const& property, T const& current_klass)
|
||||||
|
{
|
||||||
|
return name_helpers::klass_full_interface_name(current_klass) + property_concrete_indexer_name(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline std::string property_interface_indexer_short_name(attributes::property_def const& property, T const& current_klass)
|
||||||
|
{
|
||||||
|
return name_helpers::klass_interface_name(current_klass) + property_concrete_indexer_name(property);
|
||||||
|
}
|
||||||
|
|
||||||
// Open/close namespaces
|
// Open/close namespaces
|
||||||
template<typename OutputIterator, typename Context>
|
template<typename OutputIterator, typename Context>
|
||||||
bool open_namespaces(OutputIterator sink, std::vector<std::string> namespaces, Context const& context)
|
bool open_namespaces(OutputIterator sink, std::vector<std::string> namespaces, Context const& context)
|
||||||
|
|
|
@ -182,13 +182,14 @@ run(options_type const& opts)
|
||||||
|
|
||||||
auto context = context_add_tag(eolian_mono::indentation_context{0},
|
auto context = context_add_tag(eolian_mono::indentation_context{0},
|
||||||
context_add_tag(eolian_mono::eolian_state_context{opts.state},
|
context_add_tag(eolian_mono::eolian_state_context{opts.state},
|
||||||
|
context_add_tag(eolian_mono::class_context{eolian_mono::class_context::none},
|
||||||
context_add_tag(eolian_mono::options_context{opts.want_beta,
|
context_add_tag(eolian_mono::options_context{opts.want_beta,
|
||||||
opts.examples_dir},
|
opts.examples_dir},
|
||||||
context_add_tag(eolian_mono::library_context{opts.dllimport,
|
context_add_tag(eolian_mono::library_context{opts.dllimport,
|
||||||
opts.v_major,
|
opts.v_major,
|
||||||
opts.v_minor,
|
opts.v_minor,
|
||||||
opts.references_map},
|
opts.references_map},
|
||||||
efl::eolian::grammar::context_null()))));
|
efl::eolian::grammar::context_null())))));
|
||||||
|
|
||||||
EINA_ITERATOR_FOREACH(aliases, tp)
|
EINA_ITERATOR_FOREACH(aliases, tp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -52,7 +52,7 @@ public class GenericModel<T> : Efl.Object, Efl.IModel
|
||||||
/// <summary>Gets the value of the given property in the wrapped model.</summary>
|
/// <summary>Gets the value of the given property in the wrapped model.</summary>
|
||||||
/// <param name="property">The property of the model.</param>
|
/// <param name="property">The property of the model.</param>
|
||||||
/// <returns>The value of the property.</returns>
|
/// <returns>The value of the property.</returns>
|
||||||
public Eina.Value GetProperty( System.String property)
|
public Eina.Value GetProperty(System.String property)
|
||||||
{
|
{
|
||||||
return model.GetProperty(property);
|
return model.GetProperty(property);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ public class GenericModel<T> : Efl.Object, Efl.IModel
|
||||||
/// <param name="value">The value of the property.</param>
|
/// <param name="value">The value of the property.</param>
|
||||||
/// <returns>An <see cref="Eina.Future" /> that resolves when the property has
|
/// <returns>An <see cref="Eina.Future" /> that resolves when the property has
|
||||||
/// been set or reports an error if it could not be set.</returns>
|
/// been set or reports an error if it could not be set.</returns>
|
||||||
public Eina.Future SetProperty( System.String property, Eina.Value value)
|
public Eina.Future SetProperty(System.String property, Eina.Value value)
|
||||||
{
|
{
|
||||||
return model.SetProperty(property, value);
|
return model.SetProperty(property, value);
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ public class GenericModel<T> : Efl.Object, Efl.IModel
|
||||||
/// <summary>Returns an <see cref="Eina.Future" /> that will resolve when the property is ready to be read.</summary>
|
/// <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>
|
/// <param name="property">The property of the model.</param>
|
||||||
/// <returns>An <see cref="Eina.Future" /> that resolves when the property is ready.</returns>
|
/// <returns>An <see cref="Eina.Future" /> that resolves when the property is ready.</returns>
|
||||||
public Eina.Future GetPropertyReady( System.String property)
|
public Eina.Future GetPropertyReady(System.String property)
|
||||||
{
|
{
|
||||||
return model.GetPropertyReady(property);
|
return model.GetPropertyReady(property);
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ public class GenericModel<T> : Efl.Object, Efl.IModel
|
||||||
/// <param name="count">The size of the range.</param>
|
/// <param name="count">The size of the range.</param>
|
||||||
/// <returns>An <see cref="Eina.Future" /> that resolves to an
|
/// <returns>An <see cref="Eina.Future" /> that resolves to an
|
||||||
/// <see cref="Eina.Array<T>" /> of children models.</returns>
|
/// <see cref="Eina.Array<T>" /> of children models.</returns>
|
||||||
public Eina.Future GetChildrenSlice( uint start, uint count)
|
public Eina.Future GetChildrenSlice(uint start, uint count)
|
||||||
{
|
{
|
||||||
return model.GetChildrenSlice(start, count);
|
return model.GetChildrenSlice(start, count);
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ public class GenericModel<T> : Efl.Object, Efl.IModel
|
||||||
/// <param name="token">The token for the task's cancellation.</param>
|
/// <param name="token">The token for the task's cancellation.</param>
|
||||||
/// <returns>Task that resolves when the property has been set or could not
|
/// <returns>Task that resolves when the property has been set or could not
|
||||||
/// be set.</returns>
|
/// be set.</returns>
|
||||||
public System.Threading.Tasks.Task<Eina.Value> SetPropertyAsync( System.String property, Eina.Value value, System.Threading.CancellationToken token=default(System.Threading.CancellationToken))
|
public System.Threading.Tasks.Task<Eina.Value> SetPropertyAsync(System.String property, Eina.Value value, System.Threading.CancellationToken token=default(System.Threading.CancellationToken))
|
||||||
{
|
{
|
||||||
return model.SetPropertyAsync(property, value, token);
|
return model.SetPropertyAsync(property, value, token);
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ public class GenericModel<T> : Efl.Object, Efl.IModel
|
||||||
/// <param name="token">The token for the task's cancellation.</param>
|
/// <param name="token">The token for the task's cancellation.</param>
|
||||||
/// <returns>Task that resolves when the given property is ready to be
|
/// <returns>Task that resolves when the given property is ready to be
|
||||||
/// read.</returns>
|
/// read.</returns>
|
||||||
public System.Threading.Tasks.Task<Eina.Value> GetPropertyReadyAsync( System.String property, System.Threading.CancellationToken token=default(System.Threading.CancellationToken))
|
public System.Threading.Tasks.Task<Eina.Value> GetPropertyReadyAsync(System.String property, System.Threading.CancellationToken token=default(System.Threading.CancellationToken))
|
||||||
{
|
{
|
||||||
return model.GetPropertyReadyAsync(property, token);
|
return model.GetPropertyReadyAsync(property, token);
|
||||||
}
|
}
|
||||||
|
@ -162,7 +162,7 @@ public class GenericModel<T> : Efl.Object, Efl.IModel
|
||||||
/// <param name="token">Token to notify the async operation of external request to cancel.</param>
|
/// <param name="token">Token to notify the async operation of external request to cancel.</param>
|
||||||
/// <returns>Task that resolves when the desired <see cref="Eina.Array<T>" /> of
|
/// <returns>Task that resolves when the desired <see cref="Eina.Array<T>" /> of
|
||||||
/// children models is ready.</returns>
|
/// children models is ready.</returns>
|
||||||
public System.Threading.Tasks.Task<Eina.Value> GetChildrenSliceAsync( uint start, uint count, System.Threading.CancellationToken token=default(System.Threading.CancellationToken))
|
public System.Threading.Tasks.Task<Eina.Value> GetChildrenSliceAsync(uint start, uint count, System.Threading.CancellationToken token=default(System.Threading.CancellationToken))
|
||||||
{
|
{
|
||||||
return model.GetChildrenSliceAsync(start, count, token);
|
return model.GetChildrenSliceAsync(start, count, token);
|
||||||
}
|
}
|
||||||
|
|
|
@ -897,7 +897,7 @@ struct function_def
|
||||||
}
|
}
|
||||||
else if(type == EOLIAN_PROP_GET)
|
else if(type == EOLIAN_PROP_GET)
|
||||||
{
|
{
|
||||||
for(auto&& v : values)
|
for(auto v : values)
|
||||||
{
|
{
|
||||||
v.direction = parameter_direction::out;
|
v.direction = parameter_direction::out;
|
||||||
parameters.push_back(v);
|
parameters.push_back(v);
|
||||||
|
|
|
@ -402,15 +402,15 @@ class TestCsharpProperties
|
||||||
obj.Dispose();
|
obj.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void test_setter_only()
|
// public static void test_setter_only()
|
||||||
{
|
// {
|
||||||
var obj = new Dummy.TestObject();
|
// var obj = new Dummy.TestObject();
|
||||||
int val = -1984;
|
// int val = -1984;
|
||||||
|
|
||||||
obj.SetterOnly = val;
|
// obj.SetterOnly = val;
|
||||||
Test.AssertEquals(val, obj.GetSetterOnly());
|
// Test.AssertEquals(val, obj.GetSetterOnly());
|
||||||
obj.Dispose();
|
// obj.Dispose();
|
||||||
}
|
// }
|
||||||
|
|
||||||
public static void test_class_property()
|
public static void test_class_property()
|
||||||
{
|
{
|
||||||
|
@ -436,6 +436,52 @@ class TestCsharpProperties
|
||||||
Test.AssertEquals(ret, (1, 2));
|
Test.AssertEquals(ret, (1, 2));
|
||||||
obj.Dispose();
|
obj.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void test_csharp_keyed_multi_valued_prop()
|
||||||
|
{
|
||||||
|
var obj = new Dummy.TestObject();
|
||||||
|
obj.KeyedMultiValuedProp[100] = (1, 2);
|
||||||
|
Test.AssertEquals(obj.KeyedMultiValuedProp[100], (1, 2));
|
||||||
|
obj.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void test_csharp_multi_keyed_multi_valued_prop()
|
||||||
|
{
|
||||||
|
var obj = new Dummy.TestObject();
|
||||||
|
obj.MultiKeyedMultiValuedProp[(100, 101)] = (1, 2);
|
||||||
|
Test.AssertEquals(obj.MultiKeyedMultiValuedProp[(100, 101)], (1, 2));
|
||||||
|
obj.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void test_csharp_multi_prop()
|
||||||
|
{
|
||||||
|
var obj = new Dummy.TestObject();
|
||||||
|
obj.MultiKeyedMultiValuedProp[(100, 101)] = (1, 2);
|
||||||
|
obj.KeyedMultiValuedProp[100] = (1, 2);
|
||||||
|
Test.AssertEquals(obj.KeyedMultiValuedProp[100],
|
||||||
|
obj.MultiKeyedMultiValuedProp[(100, 101)]);
|
||||||
|
int a1, b1, a2, b2;
|
||||||
|
#if __MonoCS__
|
||||||
|
(int a, int b) t1 = obj.MultiKeyedMultiValuedProp[(100, 101)];
|
||||||
|
(a1, b1) = (t1.Item1, t1.Item2);
|
||||||
|
(int a, int b) t2 = obj.KeyedMultiValuedProp[100];
|
||||||
|
(a2, b2) = (t2.Item1, t2.Item2);
|
||||||
|
#else
|
||||||
|
(a1, b1) = obj.MultiKeyedMultiValuedProp[(100, 101)];
|
||||||
|
(a2, b2) = obj.KeyedMultiValuedProp[100];
|
||||||
|
#endif
|
||||||
|
Test.AssertEquals(a1, a2);
|
||||||
|
Test.AssertEquals(b1, b2);
|
||||||
|
var i = (100, 101);
|
||||||
|
var j = 100;
|
||||||
|
Test.AssertEquals(obj.KeyedMultiValuedProp[j],
|
||||||
|
obj.MultiKeyedMultiValuedProp[i]);
|
||||||
|
obj.MultiKeyedMultiValuedProp[i] = (1, 3);
|
||||||
|
obj.KeyedMultiValuedProp[j] = obj.MultiKeyedMultiValuedProp[i];
|
||||||
|
Test.AssertEquals(obj.KeyedMultiValuedProp[j],
|
||||||
|
obj.MultiKeyedMultiValuedProp[i]);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestEoGrandChildrenFinalize
|
class TestEoGrandChildrenFinalize
|
||||||
|
|
|
@ -43,6 +43,12 @@ _dummy_event_manager_emitter_set(EINA_UNUSED Eo *obj, Dummy_Event_Manager_Data *
|
||||||
pd->emitter = emitter;
|
pd->emitter = emitter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Efl_Object*
|
||||||
|
_dummy_event_manager_emitter_get(EINA_UNUSED Eo const *obj, Dummy_Event_Manager_Data *pd)
|
||||||
|
{
|
||||||
|
return pd->emitter;
|
||||||
|
}
|
||||||
|
|
||||||
static Eina_Bool
|
static Eina_Bool
|
||||||
_dummy_event_manager_emit_with_int(EINA_UNUSED Eo *obj, Dummy_Event_Manager_Data *pd, int data)
|
_dummy_event_manager_emit_with_int(EINA_UNUSED Eo *obj, Dummy_Event_Manager_Data *pd, int data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,8 +4,6 @@ class Dummy.Event_Manager extends Efl.Object {
|
||||||
|
|
||||||
methods {
|
methods {
|
||||||
@property emitter {
|
@property emitter {
|
||||||
set {
|
|
||||||
}
|
|
||||||
values {
|
values {
|
||||||
emitter: Efl.Object @move;
|
emitter: Efl.Object @move;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#define DUMMY_TEST_IFACE_PROTECTED
|
#define DUMMY_TEST_IFACE_PROTECTED
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include "libefl_mono_native_test.h"
|
#include "libefl_mono_native_test.h"
|
||||||
|
|
||||||
typedef struct Dummy_Test_Object_Data
|
typedef struct Dummy_Test_Object_Data
|
||||||
|
@ -4612,6 +4613,36 @@ void _dummy_test_object_multi_valued_prop_set(Eo* obj EINA_UNUSED, Dummy_Test_Ob
|
||||||
pd->prop2 = prop2;
|
pd->prop2 = prop2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _dummy_test_object_keyed_multi_valued_prop_get(Eo const* obj EINA_UNUSED, Dummy_Test_Object_Data* pd, int prop_key1, int* prop1, int* prop2)
|
||||||
|
{
|
||||||
|
assert (prop_key1 == 100);
|
||||||
|
*prop1 = pd->prop1;
|
||||||
|
*prop2 = pd->prop2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _dummy_test_object_keyed_multi_valued_prop_set(Eo* obj EINA_UNUSED, Dummy_Test_Object_Data* pd, int prop_key1, int prop1, int prop2)
|
||||||
|
{
|
||||||
|
assert (prop_key1 == 100);
|
||||||
|
pd->prop1 = prop1;
|
||||||
|
pd->prop2 = prop2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _dummy_test_object_multi_keyed_multi_valued_prop_get(Eo const* obj EINA_UNUSED, Dummy_Test_Object_Data* pd, int prop_key1, int prop_key2, int* prop1, int* prop2)
|
||||||
|
{
|
||||||
|
assert (prop_key1 == 100);
|
||||||
|
assert (prop_key2 == 101);
|
||||||
|
*prop1 = pd->prop1;
|
||||||
|
*prop2 = pd->prop2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _dummy_test_object_multi_keyed_multi_valued_prop_set(Eo* obj EINA_UNUSED, Dummy_Test_Object_Data* pd, int prop_key1, int prop_key2, int prop1, int prop2)
|
||||||
|
{
|
||||||
|
assert (prop_key1 == 100);
|
||||||
|
assert (prop_key2 == 101);
|
||||||
|
pd->prop1 = prop1;
|
||||||
|
pd->prop2 = prop2;
|
||||||
|
}
|
||||||
|
|
||||||
/* Class Properties */
|
/* Class Properties */
|
||||||
static int _dummy_test_object_klass_prop = 0;
|
static int _dummy_test_object_klass_prop = 0;
|
||||||
|
|
||||||
|
|
|
@ -1581,6 +1581,31 @@ class Dummy.Test_Object extends Efl.Object implements Dummy.Test_Iface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@property keyed_multi_valued_prop {
|
||||||
|
get {}
|
||||||
|
set {}
|
||||||
|
keys {
|
||||||
|
key1: int;
|
||||||
|
}
|
||||||
|
values {
|
||||||
|
prop1: int;
|
||||||
|
prop2: int;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@property multi_keyed_multi_valued_prop {
|
||||||
|
get {}
|
||||||
|
set {}
|
||||||
|
keys {
|
||||||
|
key1: int;
|
||||||
|
key2: int;
|
||||||
|
}
|
||||||
|
values {
|
||||||
|
prop1: int;
|
||||||
|
prop2: int;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@property klass_prop @static {
|
@property klass_prop @static {
|
||||||
get {}
|
get {}
|
||||||
set {}
|
set {}
|
||||||
|
|
Loading…
Reference in New Issue