[vala/wip/issue/871: 75/77] codegen: Set generic-type properties in Object.constructor()
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/wip/issue/871: 75/77] codegen: Set generic-type properties in Object.constructor()
- Date: Fri, 6 Dec 2019 14:21:48 +0000 (UTC)
commit 380dfb1a3430b4d07add579dd3b6bbd485b677f4
Author: Rico Tzschichholz <ricotz ubuntu com>
Date: Fri Dec 6 15:17:59 2019 +0100
codegen: Set generic-type properties in Object.constructor()
Fixes https://gitlab.gnome.org/GNOME/vala/issues/871
codegen/valagobjectmodule.vala | 113 +++++++++++++++++++++
tests/Makefile.am | 2 +
tests/generics/gobject-construction-class.vala | 15 +++
tests/generics/gobject-construction-interface.vala | 24 +++++
vala/valaclass.vala | 7 +-
5 files changed, 160 insertions(+), 1 deletion(-)
---
diff --git a/codegen/valagobjectmodule.vala b/codegen/valagobjectmodule.vala
index 674f18d8a..8a6c1fc3f 100644
--- a/codegen/valagobjectmodule.vala
+++ b/codegen/valagobjectmodule.vala
@@ -559,6 +559,119 @@ public class Vala.GObjectModule : GTypeModule {
ccast.add_argument (new CCodeIdentifier ("%s_parent_class".printf
(get_ccode_lower_case_name (cl, null))));
ccode.add_assignment (new CCodeIdentifier ("parent_class"), ccast);
+
+ // Set values of generic type properties with available information
+ bool entered = false;
+ foreach (DataType base_type in cl.get_base_types ()) {
+ unowned ObjectTypeSymbol? base_sym = base_type.type_symbol as
ObjectTypeSymbol;
+ if (base_sym == null || !base_sym.has_type_parameters ()) {
+ continue;
+ }
+
+ var type_parameters = base_sym.get_type_parameters ();
+ int type_param_index = 0;
+ foreach (var type_arg in base_type.get_type_arguments ()) {
+ if (type_arg is GenericType) {
+ type_param_index++;
+ continue;
+ }
+
+ var type_param_name = type_parameters.get
(type_param_index).name.down ().replace ("_", "-");
+
+ var cmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
+ cmp.add_argument (new CCodeIdentifier ("_property_name"));
+ cmp.add_argument (new CCodeIdentifier ("\"%s-type\"".printf
(type_param_name)));
+ var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY,
cmp, new CCodeConstant ("0"));
+
+ if (!entered) {
+ ccode.add_declaration ("guint", new CCodeVariableDeclarator
("_n_properties"));
+ ccode.add_declaration ("GObjectConstructParam *", new
CCodeVariableDeclarator ("_properties"));
+
+ ccode.add_assignment (new CCodeIdentifier ("_n_properties"),
new CCodeIdentifier ("n_construct_properties"));
+ ccode.add_assignment (new CCodeIdentifier ("_properties"),
new CCodeIdentifier ("construct_properties"));
+ ccode.open_if (new CCodeIdentifier ("_n_properties"));
+ ccode.open_while (new CCodeIdentifier ("_n_properties--"));
+
+ ccode.open_if (new CCodeBinaryExpression
(CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("_properties->pspec->owner_type"), get_type_id_expression
((base_sym is Class) ? base_type : new ClassType (cl))));
+
+ ccode.add_declaration ("const gchar *", new
CCodeVariableDeclarator ("_property_name"));
+ ccode.add_assignment (new CCodeIdentifier ("_property_name"),
new CCodeIdentifier ("_properties->pspec->name"));
+
+ ccode.open_if (cond);
+ entered = true;
+ } else {
+ ccode.else_if (cond);
+ }
+
+ var ccall = new CCodeFunctionCall (new CCodeIdentifier
("g_value_set_gtype"));
+ ccall.add_argument (new CCodeIdentifier ("_properties->value"));
+ ccall.add_argument (get_type_id_expression (type_arg));
+ ccode.add_statement (new CCodeExpressionStatement (ccall));
+
+ if (requires_copy (type_arg)) {
+ var dup_func = get_dup_func_expression (type_arg,
type_arg.source_reference);
+ if (dup_func == null) {
+ assert_not_reached ();
+ }
+
+ cmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
+ cmp.add_argument (new CCodeIdentifier ("_property_name"));
+ cmp.add_argument (new CCodeIdentifier
("\"%s-dup-func\"".printf (type_param_name)));
+ cond = new CCodeBinaryExpression
(CCodeBinaryOperator.EQUALITY, cmp, new CCodeConstant ("0"));
+ ccode.else_if (cond);
+
+ ccall = new CCodeFunctionCall (new CCodeIdentifier
("g_value_set_pointer"));
+ ccall.add_argument (new CCodeIdentifier
("_properties->value"));
+ ccall.add_argument (dup_func);
+ ccode.add_statement (new CCodeExpressionStatement (ccall));
+
+ cmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
+ cmp.add_argument (new CCodeIdentifier ("_property_name"));
+ cmp.add_argument (new CCodeIdentifier
("\"%s-destroy-func\"".printf (type_param_name)));
+ cond = new CCodeBinaryExpression
(CCodeBinaryOperator.EQUALITY, cmp, new CCodeConstant ("0"));
+ ccode.else_if (cond);
+
+ ccall = new CCodeFunctionCall (new CCodeIdentifier
("g_value_set_pointer"));
+ ccall.add_argument (new CCodeIdentifier
("_properties->value"));
+ ccall.add_argument (get_destroy_func_expression (type_arg));
+ ccode.add_statement (new CCodeExpressionStatement (ccall));
+ } else {
+ cmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
+ cmp.add_argument (new CCodeIdentifier ("_property_name"));
+ cmp.add_argument (new CCodeIdentifier
("\"%s-dup-func\"".printf (type_param_name)));
+ cond = new CCodeBinaryExpression
(CCodeBinaryOperator.EQUALITY, cmp, new CCodeConstant ("0"));
+ ccode.else_if (cond);
+
+ ccall = new CCodeFunctionCall (new CCodeIdentifier
("g_value_set_pointer"));
+ ccall.add_argument (new CCodeIdentifier
("_properties->value"));
+ ccall.add_argument (new CCodeConstant ("NULL"));
+ ccode.add_statement (new CCodeExpressionStatement (ccall));
+
+ cmp = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
+ cmp.add_argument (new CCodeIdentifier ("_property_name"));
+ cmp.add_argument (new CCodeIdentifier
("\"%s-destroy-func\"".printf (type_param_name)));
+ cond = new CCodeBinaryExpression
(CCodeBinaryOperator.EQUALITY, cmp, new CCodeConstant ("0"));
+ ccode.else_if (cond);
+
+ ccall = new CCodeFunctionCall (new CCodeIdentifier
("g_value_set_pointer"));
+ ccall.add_argument (new CCodeIdentifier
("_properties->value"));
+ ccall.add_argument (new CCodeConstant ("NULL"));
+ ccode.add_statement (new CCodeExpressionStatement (ccall));
+ }
+
+ type_param_index++;
+ }
+ }
+ if (entered) {
+ ccode.close ();
+ ccode.close ();
+
+ ccode.add_statement (new CCodeExpressionStatement (new CCodeIdentifier
("_properties++")));
+ ccode.close ();
+ ccode.close ();
+ }
+
+
var ccall = new CCodeFunctionCall (new CCodeMemberAccess.pointer (new CCodeIdentifier
("parent_class"), "constructor"));
ccall.add_argument (new CCodeIdentifier ("type"));
ccall.add_argument (new CCodeIdentifier ("n_construct_properties"));
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 21bfb431e..e7666114a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -510,6 +510,8 @@ TESTS = \
asynchronous/yield.vala \
generics/arrays-not-supported.test \
generics/constructor-chain-up.vala \
+ generics/gobject-construction-class.vala \
+ generics/gobject-construction-interface.vala \
generics/inference-argument-may-fail.vala \
generics/inference-static-function.vala \
generics/parameter-sizeof-initializer.vala \
diff --git a/tests/generics/gobject-construction-class.vala b/tests/generics/gobject-construction-class.vala
new file mode 100644
index 000000000..364dc92c1
--- /dev/null
+++ b/tests/generics/gobject-construction-class.vala
@@ -0,0 +1,15 @@
+abstract class Foo<T> : Object {
+ public T foo { get; set; }
+}
+
+class Bar : Foo<string> {
+}
+
+void main () {
+ Bar bar;
+ {
+ string foo = "foo";
+ bar = (Bar) Object.new (typeof (Bar), "foo", foo);
+ }
+ assert (bar.foo == "foo");
+}
diff --git a/tests/generics/gobject-construction-interface.vala
b/tests/generics/gobject-construction-interface.vala
new file mode 100644
index 000000000..28a59dbe6
--- /dev/null
+++ b/tests/generics/gobject-construction-interface.vala
@@ -0,0 +1,24 @@
+[GenericAccessors]
+interface IFoo<T> : Object {
+ public abstract T foo { get; set; }
+ public Type get_foo_type () {
+ return typeof (T);
+ }
+}
+
+abstract class Foo<T> : Object, IFoo<T> {
+ public T foo { get; set; }
+}
+
+class Bar : Foo<string> {
+}
+
+void main () {
+ Bar bar;
+ {
+ string foo = "foo";
+ bar = (Bar) Object.new (typeof (Bar), "foo", foo);
+ }
+ assert (bar.foo == "foo");
+ assert (bar.get_foo_type () == typeof (string));
+}
diff --git a/vala/valaclass.vala b/vala/valaclass.vala
index e9312c415..36e0ddf5a 100644
--- a/vala/valaclass.vala
+++ b/vala/valaclass.vala
@@ -525,6 +525,8 @@ public class Vala.Class : ObjectTypeSymbol {
}
context.analyzer.current_symbol = this;
+ bool has_type_arguments = false;
+
foreach (DataType base_type_reference in get_base_types ()) {
if (!base_type_reference.check (context)) {
error = true;
@@ -555,6 +557,8 @@ public class Vala.Class : ObjectTypeSymbol {
Report.error (base_type_reference.source_reference, "too many type
arguments");
return false;
}
+
+ has_type_arguments = (n_type_args > 0);
}
foreach (DataType type in base_types) {
@@ -576,7 +580,8 @@ public class Vala.Class : ObjectTypeSymbol {
}
/* singleton classes require an instance construtor */
- if (is_singleton && constructor == null) {
+ if (constructor == null
+ && (is_singleton || (is_subtype_of (context.analyzer.object_type) &&
has_type_arguments))) {
var c = new Constructor (source_reference);
c.body = new Block (source_reference);
add_constructor (c);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]