From 2f0a20b6887ee868f5a72ff38b9789b08e61630f Mon Sep 17 00:00:00 2001 From: Felipe Magno de Almeida Date: Fri, 23 Aug 2019 14:27:28 -0300 Subject: [PATCH] eolian-mono: Add support for partial classes Summary: Add the -p command to eolian to create a class as a partial class. Create a list in meson build of Eolian files that should be built with partial classes. This allows creating more specific method overloads for C#, manually, by generating the class as partial and adding in manual binding the partial class with the new methods and properties. T8034 Reviewers: segfaultxavi, lauromoura, woohyun, Jaehyun_Cho Reviewed By: lauromoura Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D9690 --- src/bin/eolian_mono/eolian/mono/klass.hh | 29 ++++++++++++++++++++---- src/bin/eolian_mono/eolian_mono.cc | 14 +++++++++--- src/bindings/mono/meson.build | 10 +++++++- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh index 819497a655..f1b89abc71 100644 --- a/src/bin/eolian_mono/eolian/mono/klass.hh +++ b/src/bin/eolian_mono/eolian/mono/klass.hh @@ -50,6 +50,11 @@ is_inherit_context(Context const& context) return context_find_tag(context).current_wrapper_kind == class_context::inherit; } +enum partial_class +{ + class_partial = 1 +}; + struct klass { template @@ -109,9 +114,11 @@ struct klass if(!as_generator("[Efl.Eo.BindingEntity]\n").generate(sink, attributes::unused, iface_cxt)) return false; + using efl::eolian::grammar::lit; if(!as_generator ( - "public " /*<< class_type*/ "interface" /*<<*/ " " << string << " : " + lit("public ") << (is_partial ? "partial ":"") + /*<< class_type*/ << "interface" /*<<*/ " " << string << " : " ) .generate(sink, name_helpers::klass_interface_name(cls), iface_cxt)) return false; @@ -191,7 +198,7 @@ struct klass if(!as_generator ( documentation - << "sealed public class " << concrete_name << " :\n" + << "sealed public " << (is_partial ? "partial ":"") << " class " << concrete_name << " :\n" << scope_tab << (root ? "Efl.Eo.EoWrapper" : "") << (klass_full_concrete_or_interface_name % "") << "\n" << scope_tab << ", " << interface_name << "\n" << scope_tab << *(", " << name_helpers::klass_full_concrete_or_interface_name) << "\n" @@ -284,7 +291,14 @@ struct klass documentation << "[" << name_helpers::klass_full_native_inherit_name(cls) << "]\n" << "[Efl.Eo.BindingEntity]\n" - << "public " << class_type << " " << name_helpers::klass_concrete_name(cls) << " : " + << "public " + << (is_partial + ? class_type == "class" + ? "partial class" + : "abstract partial class" + : class_type + ) + << " " << name_helpers::klass_concrete_name(cls) << " : " << (klass_full_concrete_or_interface_name % ",") // classes << (root ? "Efl.Eo.EoWrapper" : "") // ... or root << (inherit_interfaces.empty() ? "" : ", ") @@ -600,9 +614,16 @@ struct klass } return true; } + + bool is_partial; + + klass const operator()(partial_class) const + { + return klass{true}; + } }; -struct klass const klass = {}; +struct klass const klass = {false}; } diff --git a/src/bin/eolian_mono/eolian_mono.cc b/src/bin/eolian_mono/eolian_mono.cc index e22acb9ce1..42f8034a03 100644 --- a/src/bin/eolian_mono/eolian_mono.cc +++ b/src/bin/eolian_mono/eolian_mono.cc @@ -50,6 +50,7 @@ struct options_type int v_major; int v_minor; bool want_beta; + bool want_partial; std::map references_map; }; @@ -192,8 +193,9 @@ run(options_type const& opts) efl::eolian::grammar::attributes::klass_def klass_def(klass, opts.unit); std::vector klasses{klass_def}; - if (!eolian_mono::klass - .generate(iterator, klass_def, context)) + auto klass_gen = !opts.want_partial ? eolian_mono::klass + : eolian_mono::klass(eolian_mono::class_partial); + if (!klass_gen.generate(iterator, klass_def, context)) { throw std::runtime_error("Failed to generate class"); } @@ -297,6 +299,7 @@ _usage(const char *progname) << " -v, --version Print the version." << std::endl << " -b, --beta Enable @beta methods." << std::endl << " -e, --example-dir Folder to search for example files." << std::endl + << " -p, --partial Create class as a partial class" << std::endl << " -h, --help Print this help." << std::endl; exit(EXIT_FAILURE); } @@ -328,9 +331,10 @@ opts_get(int argc, char **argv) { "references", required_argument, 0, 'r'}, { "beta", no_argument, 0, 'b'}, { "example-dir", required_argument, 0, 'e' }, + { "partial", no_argument, 0, 'p' }, { 0, 0, 0, 0 } }; - const char* options = "I:D:o:c:M:m:ar:vhbe:"; + const char* options = "I:D:o:c:M:m:ar:vhbpe:"; int c, idx; while ( (c = getopt_long(argc, argv, options, long_options, &idx)) != -1) @@ -391,6 +395,10 @@ opts_get(int argc, char **argv) opts.examples_dir = optarg; if (!opts.examples_dir.empty() && opts.examples_dir.back() != '/') opts.examples_dir += "/"; } + else if (c == 'p') + { + opts.want_partial = true; + } } if (optind == argc-1) { diff --git a/src/bindings/mono/meson.build b/src/bindings/mono/meson.build index 8a87da9572..c0f04c3b37 100644 --- a/src/bindings/mono/meson.build +++ b/src/bindings/mono/meson.build @@ -82,6 +82,10 @@ blacklisted_files = [ 'elm_atspi_app_object.eo', ] +manual_inheritance_files = [ + 'efl_object.eo' +] + beta_option = [] if (get_option('mono-beta')) beta_option = '-b' @@ -105,13 +109,17 @@ foreach lib : mono_sublibs subdir_file_location = join_paths(file_location, eo_file_subdir) foreach mono_gen_file : mono_pub_eo_files if not blacklisted_files.contains(mono_gen_file) + partial = [] + if manual_inheritance_files.contains(mono_gen_file) + partial = '-p' + endif mono_generator_target += custom_target('eolian_mono_gen_'+mono_gen_file.underscorify()+'', input : join_paths(subdir_file_location, mono_gen_file), output : [mono_gen_file + '.cs'], command : [eolian_mono_gen, beta_option, '-I', meson.current_source_dir(), eolian_include_directories, '--dllimport', package_name, '-o', join_paths(meson.current_build_dir(), mono_gen_file + '.cs'), - '-e', get_option('mono-examples-dir'), + '-e', get_option('mono-examples-dir'), partial, '@INPUT@']) endif endforeach