From: Rico Tzschichholz Date: Thu, 4 Nov 2021 21:34:47 +0000 (+0100) Subject: genie: Properly handle plain "get" or "set" property accessors X-Git-Tag: 0.55.1~90 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c0970d0cbc0b592b95d7d29b4a2b20ad40818e9b;p=thirdparty%2Fvala.git genie: Properly handle plain "get" or "set" property accessors Fixes https://gitlab.gnome.org/GNOME/vala/issues/1248 --- diff --git a/tests/Makefile.am b/tests/Makefile.am index d5ddb4917..022c91cd7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1234,6 +1234,7 @@ TESTS = \ version/since-method.test \ version/since-parameter.test \ genie/class.gs \ + genie/class-property.gs \ genie/control-flow-if-do.gs \ genie/control-flow-if-else.gs \ genie/control-flow-if-else-if.gs \ diff --git a/tests/genie/class-property.c-expected b/tests/genie/class-property.c-expected new file mode 100644 index 000000000..4f66b3bfa --- /dev/null +++ b/tests/genie/class-property.c-expected @@ -0,0 +1,307 @@ +/* genie_class_property.c generated by valac, the Vala compiler + * generated from genie_class_property.gs, do not modify */ + +#include +#include +#include +#include + +#if !defined(VALA_EXTERN) +#if defined(_MSC_VER) +#define VALA_EXTERN __declspec(dllexport) extern +#elif __GNUC__ >= 4 +#define VALA_EXTERN __attribute__((visibility("default"))) extern +#else +#define VALA_EXTERN extern +#endif +#endif + +#define TYPE_TEST (test_get_type ()) +#define TEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TEST, Test)) +#define TEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TEST, TestClass)) +#define IS_TEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_TEST)) +#define IS_TEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_TEST)) +#define TEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_TEST, TestClass)) + +typedef struct _Test Test; +typedef struct _TestClass TestClass; +#define _g_free0(var) (var = (g_free (var), NULL)) +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) +typedef struct _TestPrivate TestPrivate; +enum { + TEST_0_PROPERTY, + TEST_FOO_PROPERTY, + TEST_BAR_PROPERTY, + TEST_MANAM_PROPERTY, + TEST_NUM_PROPERTIES +}; +static GParamSpec* test_properties[TEST_NUM_PROPERTIES]; +#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg); +#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; } +#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; } +#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg); + +struct _Test { + GObject parent_instance; + TestPrivate * priv; +}; + +struct _TestClass { + GObjectClass parent_class; +}; + +struct _TestPrivate { + gchar* _foo; + gchar* _manam; +}; + +static gint Test_private_offset; +static gpointer test_parent_class = NULL; + +static void _vala_main (gchar** args, + gint args_length1); +VALA_EXTERN GType test_get_type (void) G_GNUC_CONST ; +G_DEFINE_AUTOPTR_CLEANUP_FUNC (Test, g_object_unref) +VALA_EXTERN Test* test_new (void); +VALA_EXTERN Test* test_construct (GType object_type); +VALA_EXTERN void test_set_foo (Test* self, + const gchar* value); +VALA_EXTERN const gchar* test_get_foo (Test* self); +VALA_EXTERN const gchar* test_get_bar (Test* self); +VALA_EXTERN void test_set_manam (Test* self, + const gchar* value); +VALA_EXTERN gchar* test_get_manam (Test* self); +static void test_finalize (GObject * obj); +static GType test_get_type_once (void); +static void _vala_test_get_property (GObject * object, + guint property_id, + GValue * value, + GParamSpec * pspec); +static void _vala_test_set_property (GObject * object, + guint property_id, + const GValue * value, + GParamSpec * pspec); + +static void +_vala_main (gchar** args, + gint args_length1) +{ + Test* a = NULL; + Test* _tmp0_; + const gchar* _tmp1_; + const gchar* _tmp2_; + const gchar* _tmp3_; + const gchar* _tmp4_; + gchar* _tmp5_; + gchar* _tmp6_; + gchar* _tmp7_; + _tmp0_ = test_new (); + a = _tmp0_; + test_set_foo (a, "foo"); + _tmp1_ = test_get_foo (a); + _tmp2_ = _tmp1_; + _vala_assert (g_strcmp0 (_tmp2_, "foo") == 0, "a.foo == \"foo\""); + _tmp3_ = test_get_bar (a); + _tmp4_ = _tmp3_; + _vala_assert (g_strcmp0 (_tmp4_, "bar") == 0, "a.bar == \"bar\""); + test_set_manam (a, "manam"); + _tmp5_ = test_get_manam (a); + _tmp6_ = _tmp5_; + _tmp7_ = _tmp6_; + _vala_assert (g_strcmp0 (_tmp7_, "manam") == 0, "a.manam == \"manam\""); + _g_free0 (_tmp7_); + _g_object_unref0 (a); +} + +int +main (int argc, + char ** argv) +{ + _vala_main (argv, argc); + return 0; +} + +static inline gpointer +test_get_instance_private (Test* self) +{ + return G_STRUCT_MEMBER_P (self, Test_private_offset); +} + +Test* +test_construct (GType object_type) +{ + Test * self = NULL; + self = (Test*) g_object_new (object_type, NULL); + return self; +} + +Test* +test_new (void) +{ + return test_construct (TYPE_TEST); +} + +const gchar* +test_get_foo (Test* self) +{ + const gchar* result; + const gchar* _tmp0_; + g_return_val_if_fail (IS_TEST (self), NULL); + _tmp0_ = self->priv->_foo; + result = _tmp0_; + return result; +} + +void +test_set_foo (Test* self, + const gchar* value) +{ + gchar* old_value; + g_return_if_fail (IS_TEST (self)); + old_value = test_get_foo (self); + if (g_strcmp0 (value, old_value) != 0) { + gchar* _tmp0_; + _tmp0_ = g_strdup (value); + _g_free0 (self->priv->_foo); + self->priv->_foo = _tmp0_; + g_object_notify_by_pspec ((GObject *) self, test_properties[TEST_FOO_PROPERTY]); + } +} + +const gchar* +test_get_bar (Test* self) +{ + const gchar* result; + g_return_val_if_fail (IS_TEST (self), NULL); + result = "bar"; + return result; +} + +gchar* +test_get_manam (Test* self) +{ + gchar* result; + const gchar* _tmp0_; + gchar* _tmp1_; + g_return_val_if_fail (IS_TEST (self), NULL); + _tmp0_ = self->priv->_manam; + _tmp1_ = g_strdup (_tmp0_); + result = _tmp1_; + return result; +} + +void +test_set_manam (Test* self, + const gchar* value) +{ + gchar* old_value; + g_return_if_fail (IS_TEST (self)); + old_value = test_get_manam (self); + if (g_strcmp0 (value, old_value) != 0) { + gchar* _tmp0_; + _tmp0_ = g_strdup (value); + _g_free0 (self->priv->_manam); + self->priv->_manam = _tmp0_; + g_object_notify_by_pspec ((GObject *) self, test_properties[TEST_MANAM_PROPERTY]); + } + _g_free0 (old_value); +} + +static void +test_class_init (TestClass * klass, + gpointer klass_data) +{ + test_parent_class = g_type_class_peek_parent (klass); + g_type_class_adjust_private_offset (klass, &Test_private_offset); + G_OBJECT_CLASS (klass)->get_property = _vala_test_get_property; + G_OBJECT_CLASS (klass)->set_property = _vala_test_set_property; + G_OBJECT_CLASS (klass)->finalize = test_finalize; + g_object_class_install_property (G_OBJECT_CLASS (klass), TEST_FOO_PROPERTY, test_properties[TEST_FOO_PROPERTY] = g_param_spec_string ("foo", "foo", "foo", NULL, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), TEST_BAR_PROPERTY, test_properties[TEST_BAR_PROPERTY] = g_param_spec_string ("bar", "bar", "bar", NULL, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE)); + g_object_class_install_property (G_OBJECT_CLASS (klass), TEST_MANAM_PROPERTY, test_properties[TEST_MANAM_PROPERTY] = g_param_spec_string ("manam", "manam", "manam", NULL, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); +} + +static void +test_instance_init (Test * self, + gpointer klass) +{ + self->priv = test_get_instance_private (self); +} + +static void +test_finalize (GObject * obj) +{ + Test * self; + self = G_TYPE_CHECK_INSTANCE_CAST (obj, TYPE_TEST, Test); + _g_free0 (self->priv->_foo); + _g_free0 (self->priv->_manam); + G_OBJECT_CLASS (test_parent_class)->finalize (obj); +} + +static GType +test_get_type_once (void) +{ + static const GTypeInfo g_define_type_info = { sizeof (TestClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) test_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Test), 0, (GInstanceInitFunc) test_instance_init, NULL }; + GType test_type_id; + test_type_id = g_type_register_static (G_TYPE_OBJECT, "Test", &g_define_type_info, 0); + Test_private_offset = g_type_add_instance_private (test_type_id, sizeof (TestPrivate)); + return test_type_id; +} + +GType +test_get_type (void) +{ + static volatile gsize test_type_id__volatile = 0; + if (g_once_init_enter (&test_type_id__volatile)) { + GType test_type_id; + test_type_id = test_get_type_once (); + g_once_init_leave (&test_type_id__volatile, test_type_id); + } + return test_type_id__volatile; +} + +static void +_vala_test_get_property (GObject * object, + guint property_id, + GValue * value, + GParamSpec * pspec) +{ + Test * self; + self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_TEST, Test); + switch (property_id) { + case TEST_FOO_PROPERTY: + g_value_set_string (value, test_get_foo (self)); + break; + case TEST_BAR_PROPERTY: + g_value_set_string (value, test_get_bar (self)); + break; + case TEST_MANAM_PROPERTY: + g_value_take_string (value, test_get_manam (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +_vala_test_set_property (GObject * object, + guint property_id, + const GValue * value, + GParamSpec * pspec) +{ + Test * self; + self = G_TYPE_CHECK_INSTANCE_CAST (object, TYPE_TEST, Test); + switch (property_id) { + case TEST_FOO_PROPERTY: + test_set_foo (self, g_value_get_string (value)); + break; + case TEST_MANAM_PROPERTY: + test_set_manam (self, g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + diff --git a/tests/genie/class-property.gs b/tests/genie/class-property.gs new file mode 100644 index 000000000..d536a7bf5 --- /dev/null +++ b/tests/genie/class-property.gs @@ -0,0 +1,16 @@ +init + var a = new Test() + a.foo = "foo" + assert( a.foo == "foo" ) + assert( a.bar == "bar" ) + a.manam = "manam" + assert( a.manam == "manam" ) + +class Test:Object + prop foo:string + prop readonly bar:string + get + return "bar" + prop manam:string + owned get + set construct diff --git a/vala/valagenieparser.vala b/vala/valagenieparser.vala index a9ef56513..d7f95cda9 100644 --- a/vala/valagenieparser.vala +++ b/vala/valagenieparser.vala @@ -3142,6 +3142,8 @@ public class Vala.Genie.Parser : CodeVisitor { if (accept_block ()) { block = parse_block (); prop.external = false; + } else { + accept (TokenType.EOL); } prop.get_accessor = new PropertyAccessor (true, false, false, value_type, block, get_src (accessor_begin)); set_attributes (prop.get_accessor, attribs); @@ -3167,6 +3169,8 @@ public class Vala.Genie.Parser : CodeVisitor { if (accept_block ()) { block = parse_block (); prop.external = false; + } else { + accept (TokenType.EOL); } prop.set_accessor = new PropertyAccessor (false, !readonly, _construct, value_type, block, get_src (accessor_begin)); set_attributes (prop.set_accessor, attribs);