[vala/wip/issue/871: 3/3] 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: 3/3] codegen: Set generic-type properties in Object.constructor()
- Date: Fri, 1 Nov 2019 18:54:25 +0000 (UTC)
commit cac2096f6c3a98c9563300af64be0cce9fa8bc99
Author: Rico Tzschichholz <ricotz ubuntu com>
Date: Thu Oct 31 15:10:46 2019 +0100
codegen: Set generic-type properties in Object.constructor()
Fixes https://gitlab.gnome.org/GNOME/vala/issues/871
codegen/valagobjectmodule.vala | 111 +++++++++++++++++++++++++++++++
tests/Makefile.am | 1 +
tests/generics/gobject-construction.vala | 15 +++++
vala/valaclass.vala | 7 +-
4 files changed, 133 insertions(+), 1 deletion(-)
---
diff --git a/codegen/valagobjectmodule.vala b/codegen/valagobjectmodule.vala
index 65726fe68..0f2b5ee35 100644
--- a/codegen/valagobjectmodule.vala
+++ b/codegen/valagobjectmodule.vala
@@ -522,6 +522,117 @@ 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
+ 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--"));
+
+ bool entered = false;
+ foreach (DataType base_type in cl.get_base_types ()) {
+ if (base_type.type_symbol is Class) {
+ var type_parameters = ((Class)
base_type.type_symbol).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.open_if (new CCodeBinaryExpression
(CCodeBinaryOperator.EQUALITY, new CCodeIdentifier ("_properties->pspec->owner_type"), get_type_id_expression
(base_type)));
+
+ 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++;
+ }
+ break;
+ }
+ }
+ 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 292eea0c7..61c49bbd6 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -500,6 +500,7 @@ TESTS = \
asynchronous/yield.vala \
generics/arrays-not-supported.test \
generics/constructor-chain-up.vala \
+ generics/gobject-construction.vala \
generics/inference-static-function.vala \
generics/parameter-sizeof-initializer.vala \
generics/bug640330.test \
diff --git a/tests/generics/gobject-construction.vala b/tests/generics/gobject-construction.vala
new file mode 100644
index 000000000..364dc92c1
--- /dev/null
+++ b/tests/generics/gobject-construction.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/vala/valaclass.vala b/vala/valaclass.vala
index 6cad8e00a..bc3cc0482 100644
--- a/vala/valaclass.vala
+++ b/vala/valaclass.vala
@@ -512,6 +512,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;
@@ -542,6 +544,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) {
@@ -563,7 +567,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]