csharp: Implement Deconstruct for structs.

Summary:
Usage example:

```
var (x, y) = somePos2D;
```

Not available on Mono environment due to [`mcs` not implementing
it](a3de0304a1/mcs/mcs/tuples.cs (L590)).
To keep tests from breaking because of it, a `MONO` preprocessor variable is
defined and checked during test compilation.

Ref T8489.

Reviewers: brunobelo, lauromoura, segfaultxavi

Reviewed By: lauromoura

Subscribers: cedric, #reviewers, #committers

Tags: #efl

Maniphest Tasks: T8489

Differential Revision: https://phab.enlightenment.org/D10809
This commit is contained in:
João Paulo Taylor Ienczak Zanette 2019-12-12 18:32:31 -03:00 committed by Lauro Moura
parent 4c77ee6843
commit ca3a913375
3 changed files with 70 additions and 1 deletions

View File

@ -463,6 +463,61 @@ struct struct_definition_generator
return true;
}
template <typename OutputIterator, typename Context>
bool generate_deconstruct_method(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const
{
auto const& indent = current_indentation(context);
auto struct_name = binding_struct_name(struct_);
if (!as_generator(
indent << scope_tab << "/// <summary>Unpacks " << struct_name << " into tuple.\n"
<< indent << scope_tab << "/// <para>Since EFL 1.24.</para>\n"
<< indent << scope_tab << "/// </summary>\n"
<< indent << scope_tab << "public void Deconstruct(\n"
).generate(sink, attributes::unused, context))
return false;
// parameters
{
auto i = 0u;
for (auto const& field : struct_.fields)
{
auto field_name = name_helpers::to_field_name(field.name);
auto suffix = i == struct_.fields.size() - 1 ? "\n" : ",\n";
if (!as_generator(
indent << scope_tab << scope_tab << "out " << type << " " << field_name << suffix
).generate(sink, std::make_tuple(field.type), context))
return false;
++i;
}
}
if (!as_generator(
indent << scope_tab << ")\n"
<< indent << scope_tab << "{\n"
).generate(sink, attributes::unused, context))
return false;
// assigments
for (auto const& field : struct_.fields)
{
auto field_name = name_helpers::to_field_name(field.name);
if (!as_generator(
indent << scope_tab << scope_tab << field_name << " = this." << field_name << ";\n"
).generate(sink, attributes::unused, context))
return false;
}
// the end
return as_generator(
indent << scope_tab << "}\n"
).generate(sink, attributes::unused, context);
}
template <typename OutputIterator, typename Context>
bool generate(OutputIterator sink, attributes::struct_def const& struct_, Context const& context) const
{
@ -537,6 +592,9 @@ struct struct_definition_generator
if (!generate_implicit_operator(struct_, sink, context))
return false;
if (!generate_deconstruct_method(sink, struct_, context))
return false;
}
std::string since_line;

View File

@ -199,12 +199,13 @@ if (get_option('dotnet'))
)
else
extra_cs_args += '-d:MONO'
efl_mono = library('efl_mono',
mono_generator_target + mono_files + [efl_src],
install : true,
install_dir : efl_mono_install_dir,
cs_args : extra_cs_args + ['-doc:' + efl_mono_xml_doc, '-warnaserror+']
cs_args : extra_cs_args + ['-doc:' + efl_mono_xml_doc, '-warnaserror+'],
)
meson.add_install_script(join_paths(meson.source_root(), 'meson', 'meson_csharp_docs.sh'),

View File

@ -419,6 +419,16 @@ internal class TestStructEquality
Test.AssertNotEquals(a.GetHashCode(), c.GetHashCode());
Test.AssertNotEquals(a.GetHashCode(), singleDifferentField.GetHashCode());
}
#if !MONO
public static void test_deconstruct() {
var p = new Eina.Position2D(1, 2);
var (x, y) = p;
Test.AssertEquals(x, 1);
Test.AssertEquals(y, 2);
}
#endif
}
internal class TestStructTuples