csharp: cleanup concrete class
Summary: Concrete class is only used to call static member of NativeMethod. they don't need any inheritance and implementation of c functions. Depends on D9893 Test Plan: ninja test Reviewers: lauromoura, felipealmeida Subscribers: Jaehyun_Cho, woohyun, segfaultxavi, cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D9894
This commit is contained in:
parent
5137f6d143
commit
97098dcc50
|
@ -131,7 +131,7 @@ struct unpack_event_args_visitor
|
||||||
}
|
}
|
||||||
bool operator()(grammar::attributes::klass_name const& cls) const
|
bool operator()(grammar::attributes::klass_name const& cls) const
|
||||||
{
|
{
|
||||||
return as_generator("(Efl.Eo.Globals.CreateWrapperFor(info) as " + name_helpers::klass_full_concrete_name(cls) + ")").generate(sink, attributes::unused, *context);
|
return as_generator("(Efl.Eo.Globals.CreateWrapperFor(info) as " + name_helpers::klass_full_interface_name(cls) + ")").generate(sink, attributes::unused, *context);
|
||||||
}
|
}
|
||||||
bool operator()(attributes::complex_type_def const& types) const
|
bool operator()(attributes::complex_type_def const& types) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -193,98 +193,9 @@ struct klass
|
||||||
auto concrete_cxt = context_add_tag(class_context{class_context::concrete,
|
auto concrete_cxt = context_add_tag(class_context{class_context::concrete,
|
||||||
name_helpers::klass_full_concrete_or_interface_name(cls)},
|
name_helpers::klass_full_concrete_or_interface_name(cls)},
|
||||||
context);
|
context);
|
||||||
auto concrete_name = name_helpers::klass_concrete_name(cls);
|
|
||||||
auto interface_name = name_helpers::klass_interface_name(cls);
|
|
||||||
|
|
||||||
// We can't make these internal yet as they have methods that are used by
|
if(!generate_native_inherit_class(sink, cls, change_indentation(indent, concrete_cxt)))
|
||||||
// other classes that implement the interface.
|
|
||||||
if(!as_generator
|
|
||||||
(
|
|
||||||
documentation(1)
|
|
||||||
<< scope_tab << "public sealed " << (is_partial ? "partial ":"") << "class " << concrete_name << " :\n"
|
|
||||||
<< scope_tab(2) << (root ? "Efl.Eo.EoWrapper" : "") << (klass_full_concrete_or_interface_name % "")
|
|
||||||
<< ",\n" << scope_tab(2) << interface_name
|
|
||||||
<< *(",\n" << scope_tab(2) << name_helpers::klass_full_concrete_or_interface_name) << "\n"
|
|
||||||
<< scope_tab << "{\n"
|
|
||||||
).generate(sink, std::make_tuple(cls, inherit_classes, inherit_interfaces), concrete_cxt))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!generate_fields(sink, cls, concrete_cxt))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!as_generator
|
|
||||||
(
|
|
||||||
scope_tab(2) << "/// <summary>Subclasses should override this constructor if they are expected to be instantiated from native code.\n"
|
|
||||||
<< scope_tab(2) << "/// Do not call this constructor directly.</summary>\n"
|
|
||||||
<< scope_tab(2) << "/// <param name=\"ch\">Tag struct storing the native handle of the object being constructed.</param>\n"
|
|
||||||
<< scope_tab(2) << "private " << concrete_name << "(ConstructingHandle ch) : base(ch)\n"
|
|
||||||
<< scope_tab(2) << "{\n"
|
|
||||||
<< scope_tab(2) << "}\n\n"
|
|
||||||
)
|
|
||||||
.generate(sink, attributes::unused, concrete_cxt))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!as_generator
|
|
||||||
(
|
|
||||||
scope_tab(2) << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(concrete_cxt).actual_library_name(cls.filename)
|
|
||||||
<< ")] internal static extern System.IntPtr\n"
|
|
||||||
<< scope_tab(2) << scope_tab << name_helpers::klass_get_name(cls) << "();\n\n"
|
|
||||||
<< scope_tab(2) << "/// <summary>Initializes a new instance of the <see cref=\"" << interface_name << "\"/> class.\n"
|
|
||||||
<< scope_tab(2) << "/// Internal usage: This is used when interacting with C code and should not be used directly.</summary>\n"
|
|
||||||
<< scope_tab(2) << "/// <param name=\"wh\">The native pointer to be wrapped.</param>\n"
|
|
||||||
<< scope_tab(2) << "private " << concrete_name << "(Efl.Eo.WrappingHandle wh) : base(wh)\n"
|
|
||||||
<< scope_tab(2) << "{\n"
|
|
||||||
<< scope_tab(2) << "}\n\n"
|
|
||||||
)
|
|
||||||
.generate(sink, attributes::unused, concrete_cxt))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!generate_events(sink, cls, concrete_cxt))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (!as_generator(lit("#pragma warning disable CS0628\n")).generate(sink, attributes::unused, concrete_cxt))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Parts
|
|
||||||
if(!as_generator(*(part_definition))
|
|
||||||
.generate(sink, cls.parts, concrete_cxt)) return false;
|
|
||||||
|
|
||||||
// Concrete function definitions
|
|
||||||
auto implemented_methods = helpers::get_all_implementable_methods(cls, concrete_cxt);
|
|
||||||
if(!as_generator(*(function_definition))
|
|
||||||
.generate(sink, implemented_methods, concrete_cxt)) return false;
|
|
||||||
|
|
||||||
// Async wrappers
|
|
||||||
if(!as_generator(*(async_function_definition)).generate(sink, implemented_methods, concrete_cxt))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Property wrappers
|
|
||||||
if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, cls.properties, concrete_cxt))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (auto&& klass : helpers::non_implemented_interfaces(cls, concrete_cxt))
|
|
||||||
{
|
|
||||||
attributes::klass_def c(get_klass(klass, cls.unit), cls.unit);
|
|
||||||
if (!as_generator(*(property_wrapper_definition(cls))).generate(sink, c.properties, concrete_cxt))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!as_generator(lit("#pragma warning restore CS0628\n")).generate(sink, attributes::unused, concrete_cxt))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Copied from nativeinherit class, used when setting up providers.
|
|
||||||
if(!as_generator(
|
|
||||||
scope_tab(2) << "private static IntPtr GetEflClassStatic()\n"
|
|
||||||
<< scope_tab(2) << "{\n"
|
|
||||||
<< scope_tab(2) << scope_tab << "return " << name_helpers::klass_get_full_name(cls) << "();\n"
|
|
||||||
<< scope_tab(2) << "}\n\n"
|
|
||||||
).generate(sink, attributes::unused, concrete_cxt))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(!generate_native_inherit_class(sink, cls, change_indentation(indent.inc(), concrete_cxt)))
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if(!as_generator(scope_tab << "}\n").generate(sink, attributes::unused, concrete_cxt)) return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inheritable class
|
// Inheritable class
|
||||||
|
@ -427,6 +338,7 @@ struct klass
|
||||||
auto inherit_name = name_helpers::klass_inherit_name(cls);
|
auto inherit_name = name_helpers::klass_inherit_name(cls);
|
||||||
auto implementable_methods = helpers::get_all_registerable_methods(cls, context);
|
auto implementable_methods = helpers::get_all_registerable_methods(cls, context);
|
||||||
bool root = !helpers::has_regular_ancestor(cls);
|
bool root = !helpers::has_regular_ancestor(cls);
|
||||||
|
bool is_concrete = context_find_tag<class_context>(context).current_wrapper_kind == class_context::concrete;
|
||||||
auto const& indent = current_indentation(inative_cxt).inc();
|
auto const& indent = current_indentation(inative_cxt).inc();
|
||||||
std::string klass_since;
|
std::string klass_since;
|
||||||
|
|
||||||
|
@ -447,11 +359,23 @@ struct klass
|
||||||
<< klass_since
|
<< klass_since
|
||||||
<< indent << "/// </summary>\n"
|
<< indent << "/// </summary>\n"
|
||||||
<< indent << "[EditorBrowsable(EditorBrowsableState.Never)]\n"
|
<< indent << "[EditorBrowsable(EditorBrowsableState.Never)]\n"
|
||||||
<< indent << "internal new class " << native_inherit_name << " : " << (root ? "Efl.Eo.EoWrapper.NativeMethods" : base_name) << "\n"
|
<< indent << "internal " << (is_concrete ? "" : "new ") << "class " << native_inherit_name << " : " << (root ? "Efl.Eo.EoWrapper.NativeMethods" : base_name) << "\n"
|
||||||
<< indent << "{\n"
|
<< indent << "{\n"
|
||||||
).generate(sink, attributes::unused, inative_cxt))
|
).generate(sink, attributes::unused, inative_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if(is_concrete)
|
||||||
|
{
|
||||||
|
if (!as_generator
|
||||||
|
(
|
||||||
|
scope_tab(2) << "[System.Runtime.InteropServices.DllImport(" << context_find_tag<library_context>(context).actual_library_name(cls.filename)
|
||||||
|
<< ")] internal static extern System.IntPtr\n"
|
||||||
|
<< scope_tab(2) << scope_tab << name_helpers::klass_get_name(cls) << "();\n"
|
||||||
|
)
|
||||||
|
.generate(sink, attributes::unused, inative_cxt))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(implementable_methods.size() >= 1)
|
if(implementable_methods.size() >= 1)
|
||||||
{
|
{
|
||||||
if(!as_generator(
|
if(!as_generator(
|
||||||
|
@ -502,7 +426,7 @@ struct klass
|
||||||
).generate(sink, attributes::unused, inative_cxt))
|
).generate(sink, attributes::unused, inative_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!root || context_find_tag<class_context>(context).current_wrapper_kind != class_context::concrete)
|
if (!root || !is_concrete)
|
||||||
if(!as_generator(indent << scope_tab << scope_tab << "descs.AddRange(base.GetEoOps(type, false));\n").generate(sink, attributes::unused, inative_cxt))
|
if(!as_generator(indent << scope_tab << scope_tab << "descs.AddRange(base.GetEoOps(type, false));\n").generate(sink, attributes::unused, inative_cxt))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
|
@ -399,9 +399,7 @@ struct klass_full_interface_name_generator
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline std::string klass_concrete_name(T const& klass)
|
inline std::string klass_concrete_name(T const& klass)
|
||||||
{
|
{
|
||||||
return utils::remove_all(klass.eolian_name, '_') + ((klass.type == attributes::class_type::mixin
|
return utils::remove_all(klass.eolian_name, '_');
|
||||||
|| klass.type == attributes::class_type::interface_)
|
|
||||||
? "Concrete" : "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -467,14 +465,19 @@ inline std::string klass_inherit_name(T const& klass)
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline std::string klass_native_inherit_name(EINA_UNUSED T const& klass)
|
inline std::string klass_native_inherit_name(T const& klass)
|
||||||
{
|
{
|
||||||
return "NativeMethods";
|
return ((klass.type == attributes::class_type::mixin
|
||||||
|
|| klass.type == attributes::class_type::interface_) ? klass_interface_name(klass) : "") + "NativeMethods";
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline std::string klass_full_native_inherit_name(T const& klass)
|
inline std::string klass_full_native_inherit_name(T const& klass)
|
||||||
{
|
{
|
||||||
|
if(klass.type == attributes::class_type::mixin
|
||||||
|
|| klass.type == attributes::class_type::interface_)
|
||||||
|
return join_namespaces(klass.namespaces, '.', managed_namespace) + klass_native_inherit_name(klass);
|
||||||
|
|
||||||
return klass_full_concrete_name(klass) + "." + klass_native_inherit_name(klass);
|
return klass_full_concrete_name(klass) + "." + klass_native_inherit_name(klass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -487,6 +490,10 @@ inline std::string klass_get_name(T const& clsname)
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline std::string klass_get_full_name(T const& clsname)
|
inline std::string klass_get_full_name(T const& clsname)
|
||||||
{
|
{
|
||||||
|
if(clsname.type == attributes::class_type::mixin
|
||||||
|
|| clsname.type == attributes::class_type::interface_)
|
||||||
|
return klass_get_name(clsname);
|
||||||
|
|
||||||
return klass_full_concrete_name(clsname) + "." + klass_get_name(clsname);
|
return klass_full_concrete_name(clsname) + "." + klass_get_name(clsname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -190,11 +190,10 @@ struct to_external_field_convert_generator
|
||||||
if (klass)
|
if (klass)
|
||||||
{
|
{
|
||||||
auto interface_name = name_helpers::klass_full_interface_name(*klass);
|
auto interface_name = name_helpers::klass_full_interface_name(*klass);
|
||||||
auto concrete_name = name_helpers::klass_full_concrete_name(*klass);
|
|
||||||
if (!as_generator(
|
if (!as_generator(
|
||||||
"\n"
|
"\n"
|
||||||
<< indent << scope_tab << scope_tab << "_external_struct." << string
|
<< indent << scope_tab << scope_tab << "_external_struct." << string
|
||||||
<< " = (" << concrete_name << ") Efl.Eo.Globals.CreateWrapperFor(_internal_struct." << string << ");\n"
|
<< " = (" << interface_name << ") Efl.Eo.Globals.CreateWrapperFor(_internal_struct." << string << ");\n"
|
||||||
).generate(sink, std::make_tuple(field_name, field_name), context))
|
).generate(sink, std::make_tuple(field_name, field_name), context))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1003,22 +1003,6 @@ internal static class TraitFunctions
|
||||||
|
|
||||||
private static IDictionary<System.Type, object> register = new Dictionary<System.Type, object>();
|
private static IDictionary<System.Type, object> register = new Dictionary<System.Type, object>();
|
||||||
|
|
||||||
private static System.Type AsEflInstantiableType(System.Type type)
|
|
||||||
{
|
|
||||||
if (!IsEflObject(type))
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type.IsInterface)
|
|
||||||
{
|
|
||||||
string fullName = type.FullName + "Concrete";
|
|
||||||
return type.Assembly.GetType(fullName); // That was our best guess...
|
|
||||||
}
|
|
||||||
|
|
||||||
return type; // Not interface, so it should be a concrete.
|
|
||||||
}
|
|
||||||
|
|
||||||
public static object RegisterTypeTraits<T>()
|
public static object RegisterTypeTraits<T>()
|
||||||
{
|
{
|
||||||
Eina.Log.Debug($"Finding TypeTraits for {typeof(T).Name}");
|
Eina.Log.Debug($"Finding TypeTraits for {typeof(T).Name}");
|
||||||
|
@ -1026,14 +1010,6 @@ internal static class TraitFunctions
|
||||||
var type = typeof(T);
|
var type = typeof(T);
|
||||||
if (IsEflObject(type))
|
if (IsEflObject(type))
|
||||||
{
|
{
|
||||||
System.Type concrete = AsEflInstantiableType(type);
|
|
||||||
if (concrete == null || !type.IsAssignableFrom(concrete))
|
|
||||||
{
|
|
||||||
throw new Exception("Failed to get a suitable concrete class for this type.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// No need to pass concrete as the traits class will use reflection to get the actually most
|
|
||||||
// derived type returned.
|
|
||||||
traits = new EflObjectElementTraits<T>();
|
traits = new EflObjectElementTraits<T>();
|
||||||
}
|
}
|
||||||
else if (IsString(type))
|
else if (IsString(type))
|
||||||
|
|
|
@ -1221,14 +1221,12 @@ internal static class ClassRegister
|
||||||
|
|
||||||
if (objectType.IsInterface)
|
if (objectType.IsInterface)
|
||||||
{
|
{
|
||||||
// Try to get the *Concrete class
|
// Try to get the *NativeMethods class
|
||||||
var assembly = objectType.Assembly;
|
var nativeMethods = (Efl.Eo.NativeClass)System.Attribute.GetCustomAttributes(objectType)?.FirstOrDefault(attr => attr is Efl.Eo.NativeClass);
|
||||||
objectType = assembly.GetType(objectType.FullName + "Concrete");
|
if (nativeMethods == null)
|
||||||
|
|
||||||
if (objectType == null)
|
|
||||||
{
|
|
||||||
return IntPtr.Zero;
|
return IntPtr.Zero;
|
||||||
}
|
|
||||||
|
return nativeMethods.GetEflClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
var method = objectType.GetMethod("GetEflClassStatic",
|
var method = objectType.GetMethod("GetEflClassStatic",
|
||||||
|
|
|
@ -385,6 +385,16 @@ class TestEoMultipleChildClasses
|
||||||
|
|
||||||
class TestCsharpProperties
|
class TestCsharpProperties
|
||||||
{
|
{
|
||||||
|
|
||||||
|
private class MyObject : Dummy.TestObject
|
||||||
|
{
|
||||||
|
public MyObject(Efl.Object parent = null) : base(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
private MyObject(ConstructingHandle ch) : base(ch)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
public static void test_csharp_properties()
|
public static void test_csharp_properties()
|
||||||
{
|
{
|
||||||
var obj = new Dummy.TestObject();
|
var obj = new Dummy.TestObject();
|
||||||
|
@ -428,6 +438,28 @@ class TestCsharpProperties
|
||||||
iface.Dispose();
|
iface.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void test_iface_value_property()
|
||||||
|
{
|
||||||
|
var obj = new Dummy.TestObject();
|
||||||
|
var prop = new MyObject();
|
||||||
|
|
||||||
|
obj.IfaceValueProp = prop;
|
||||||
|
Test.AssertEquals(obj.IfaceValueProp, prop);
|
||||||
|
|
||||||
|
obj.Dispose();
|
||||||
|
prop.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void test_iface_value_from_c()
|
||||||
|
{
|
||||||
|
var obj = new Dummy.TestObject();
|
||||||
|
|
||||||
|
obj.SetIfaceKlassProp(typeof(MyObject));
|
||||||
|
Test.AssertEquals(obj.IfaceValueFromC.GetType(), typeof(MyObject));
|
||||||
|
|
||||||
|
obj.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
public static void test_csharp_multi_valued_prop()
|
public static void test_csharp_multi_valued_prop()
|
||||||
{
|
{
|
||||||
var obj = new Dummy.TestObject();
|
var obj = new Dummy.TestObject();
|
||||||
|
|
|
@ -38,6 +38,8 @@ typedef struct Dummy_Test_Object_Data
|
||||||
int prop1;
|
int prop1;
|
||||||
int prop2;
|
int prop2;
|
||||||
Eo *hidden_object;
|
Eo *hidden_object;
|
||||||
|
Dummy_Test_Iface *iface_value_prop;
|
||||||
|
Efl_Class *iface_klass;
|
||||||
|
|
||||||
// Containers passed to C# as iterator/accessors
|
// Containers passed to C# as iterator/accessors
|
||||||
Eina_Array *out_array;
|
Eina_Array *out_array;
|
||||||
|
@ -4784,6 +4786,26 @@ Eo *_dummy_test_object_hidden_object_get(EINA_UNUSED const Eo *obj, Dummy_Test_O
|
||||||
return pd->hidden_object;
|
return pd->hidden_object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dummy_Test_Iface *_dummy_test_object_iface_value_prop_get(EINA_UNUSED const Eo *obj, Dummy_Test_Object_Data *pd)
|
||||||
|
{
|
||||||
|
return pd->iface_value_prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _dummy_test_object_iface_value_prop_set(EINA_UNUSED Eo *obj, Dummy_Test_Object_Data *pd, Dummy_Test_Iface *prop)
|
||||||
|
{
|
||||||
|
pd->iface_value_prop = prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _dummy_test_object_iface_klass_prop_set(EINA_UNUSED Eo *obj, Dummy_Test_Object_Data *pd, Efl_Class *klass)
|
||||||
|
{
|
||||||
|
pd->iface_klass = klass;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dummy_Test_Iface *_dummy_test_object_iface_value_from_c_get(const Eo *obj, Dummy_Test_Object_Data *pd)
|
||||||
|
{
|
||||||
|
return efl_add(pd->iface_klass, (Eo*)obj);
|
||||||
|
}
|
||||||
|
|
||||||
// Inherit
|
// Inherit
|
||||||
int _dummy_inherit_helper_receive_dummy_and_call_int_out(Dummy_Test_Object *x)
|
int _dummy_inherit_helper_receive_dummy_and_call_int_out(Dummy_Test_Object *x)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1664,6 +1664,23 @@ class Dummy.Test_Object extends Efl.Object implements Dummy.Test_Iface {
|
||||||
obj: Efl.Object;
|
obj: Efl.Object;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@property iface_value_prop {
|
||||||
|
values {
|
||||||
|
prop: Dummy.Test_Iface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@property iface_klass_prop {
|
||||||
|
set {}
|
||||||
|
values {
|
||||||
|
klass: Efl.Class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@property iface_value_from_c {
|
||||||
|
get {}
|
||||||
|
values {
|
||||||
|
prop: Dummy.Test_Iface;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
implements {
|
implements {
|
||||||
Efl.Object.constructor;
|
Efl.Object.constructor;
|
||||||
|
|
Loading…
Reference in New Issue