From: Rico Tzschichholz Date: Sat, 18 Dec 2021 21:25:54 +0000 (+0100) Subject: parser: Improve partial classes support X-Git-Tag: 0.55.1~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=73cd47c7c474d4601766a10e413e4e7512b810f2;p=thirdparty%2Fvala.git parser: Improve partial classes support Fixes https://gitlab.gnome.org/GNOME/vala/issues/370 --- diff --git a/tests/Makefile.am b/tests/Makefile.am index b3e51dc7b..788d9e474 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -471,6 +471,7 @@ TESTS = \ objects/class-partial-conflict-access.test \ objects/class-partial-conflict-partial.test \ objects/class-partial-conflict-sealed.test \ + objects/class-partial-nested.vala \ objects/class-vfunc-base-access.vala \ objects/classes.vala \ objects/classes-interfaces.vala \ diff --git a/tests/objects/class-partial-nested.c-expected b/tests/objects/class-partial-nested.c-expected new file mode 100644 index 000000000..32b00c14e --- /dev/null +++ b/tests/objects/class-partial-nested.c-expected @@ -0,0 +1,440 @@ +/* objects_class_partial_nested.c generated by valac, the Vala compiler + * generated from objects_class_partial_nested.vala, do not modify */ + +#include +#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 MANAM_FOO_BAR_TYPE_BAZ (manam_foo_bar_baz_get_type ()) +#define MANAM_FOO_BAR_BAZ(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MANAM_FOO_BAR_TYPE_BAZ, ManamFooBarBaz)) +#define MANAM_FOO_BAR_BAZ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MANAM_FOO_BAR_TYPE_BAZ, ManamFooBarBazClass)) +#define MANAM_FOO_BAR_IS_BAZ(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MANAM_FOO_BAR_TYPE_BAZ)) +#define MANAM_FOO_BAR_IS_BAZ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MANAM_FOO_BAR_TYPE_BAZ)) +#define MANAM_FOO_BAR_BAZ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MANAM_FOO_BAR_TYPE_BAZ, ManamFooBarBazClass)) + +typedef struct _ManamFooBarBaz ManamFooBarBaz; +typedef struct _ManamFooBarBazClass ManamFooBarBazClass; +typedef struct _ManamFooBarBazPrivate ManamFooBarBazPrivate; +#define _g_free0(var) (var = (g_free (var), NULL)) +#define _manam_foo_bar_baz_unref0(var) ((var == NULL) ? NULL : (var = (manam_foo_bar_baz_unref (var), NULL))) +typedef struct _ManamFooBarParamSpecBaz ManamFooBarParamSpecBaz; + +struct _ManamFooBarBaz { + GTypeInstance parent_instance; + volatile int ref_count; + ManamFooBarBazPrivate * priv; + gchar* f0; + gchar* f1; +}; + +struct _ManamFooBarBazClass { + GTypeClass parent_class; + void (*finalize) (ManamFooBarBaz *self); + void (*v0) (ManamFooBarBaz* self); + void (*v1) (ManamFooBarBaz* self); +}; + +struct _ManamFooBarBazPrivate { + gchar* _p0; + gchar* _p1; +}; + +struct _ManamFooBarParamSpecBaz { + GParamSpec parent_instance; +}; + +static gint ManamFooBarBaz_private_offset; +static gpointer manam_foo_bar_baz_parent_class = NULL; + +static void _vala_main (void); +VALA_EXTERN gpointer manam_foo_bar_baz_ref (gpointer instance); +VALA_EXTERN void manam_foo_bar_baz_unref (gpointer instance); +VALA_EXTERN GParamSpec* manam_foo_bar_param_spec_baz (const gchar* name, + const gchar* nick, + const gchar* blurb, + GType object_type, + GParamFlags flags); +VALA_EXTERN void manam_foo_bar_value_set_baz (GValue* value, + gpointer v_object); +VALA_EXTERN void manam_foo_bar_value_take_baz (GValue* value, + gpointer v_object); +VALA_EXTERN gpointer manam_foo_bar_value_get_baz (const GValue* value); +VALA_EXTERN GType manam_foo_bar_baz_get_type (void) G_GNUC_CONST ; +G_DEFINE_AUTOPTR_CLEANUP_FUNC (ManamFooBarBaz, manam_foo_bar_baz_unref) +VALA_EXTERN ManamFooBarBaz* manam_foo_bar_baz_new (void); +VALA_EXTERN ManamFooBarBaz* manam_foo_bar_baz_construct (GType object_type); +VALA_EXTERN void manam_foo_bar_baz_set_p0 (ManamFooBarBaz* self, + const gchar* value); +VALA_EXTERN void manam_foo_bar_baz_m0 (ManamFooBarBaz* self); +VALA_EXTERN void manam_foo_bar_baz_v0 (ManamFooBarBaz* self); +VALA_EXTERN void manam_foo_bar_baz_set_p1 (ManamFooBarBaz* self, + const gchar* value); +VALA_EXTERN void manam_foo_bar_baz_m1 (ManamFooBarBaz* self); +VALA_EXTERN void manam_foo_bar_baz_v1 (ManamFooBarBaz* self); +static void manam_foo_bar_baz_real_v0 (ManamFooBarBaz* self); +static void manam_foo_bar_baz_real_v1 (ManamFooBarBaz* self); +VALA_EXTERN const gchar* manam_foo_bar_baz_get_p0 (ManamFooBarBaz* self); +VALA_EXTERN const gchar* manam_foo_bar_baz_get_p1 (ManamFooBarBaz* self); +static void manam_foo_bar_baz_finalize (ManamFooBarBaz * obj); +static GType manam_foo_bar_baz_get_type_once (void); + +static void +_vala_main (void) +{ + ManamFooBarBaz* baz = NULL; + ManamFooBarBaz* _tmp0_; + gchar* _tmp1_; + gchar* _tmp2_; + _tmp0_ = manam_foo_bar_baz_new (); + baz = _tmp0_; + manam_foo_bar_baz_set_p0 (baz, "p0"); + _tmp1_ = g_strdup ("f0"); + _g_free0 (baz->f0); + baz->f0 = _tmp1_; + manam_foo_bar_baz_m0 (baz); + manam_foo_bar_baz_v0 (baz); + manam_foo_bar_baz_set_p1 (baz, "p1"); + _tmp2_ = g_strdup ("f1"); + _g_free0 (baz->f1); + baz->f1 = _tmp2_; + manam_foo_bar_baz_m1 (baz); + manam_foo_bar_baz_v1 (baz); + _manam_foo_bar_baz_unref0 (baz); +} + +int +main (int argc, + char ** argv) +{ + _vala_main (); + return 0; +} + +static inline gpointer +manam_foo_bar_baz_get_instance_private (ManamFooBarBaz* self) +{ + return G_STRUCT_MEMBER_P (self, ManamFooBarBaz_private_offset); +} + +void +manam_foo_bar_baz_m0 (ManamFooBarBaz* self) +{ + g_return_if_fail (MANAM_FOO_BAR_IS_BAZ (self)); +} + +static void +manam_foo_bar_baz_real_v0 (ManamFooBarBaz* self) +{ +} + +void +manam_foo_bar_baz_v0 (ManamFooBarBaz* self) +{ + ManamFooBarBazClass* _klass_; + g_return_if_fail (MANAM_FOO_BAR_IS_BAZ (self)); + _klass_ = MANAM_FOO_BAR_BAZ_GET_CLASS (self); + if (_klass_->v0) { + _klass_->v0 (self); + } +} + +ManamFooBarBaz* +manam_foo_bar_baz_construct (GType object_type) +{ + ManamFooBarBaz* self = NULL; + self = (ManamFooBarBaz*) g_type_create_instance (object_type); + return self; +} + +ManamFooBarBaz* +manam_foo_bar_baz_new (void) +{ + return manam_foo_bar_baz_construct (MANAM_FOO_BAR_TYPE_BAZ); +} + +void +manam_foo_bar_baz_m1 (ManamFooBarBaz* self) +{ + g_return_if_fail (MANAM_FOO_BAR_IS_BAZ (self)); +} + +static void +manam_foo_bar_baz_real_v1 (ManamFooBarBaz* self) +{ +} + +void +manam_foo_bar_baz_v1 (ManamFooBarBaz* self) +{ + ManamFooBarBazClass* _klass_; + g_return_if_fail (MANAM_FOO_BAR_IS_BAZ (self)); + _klass_ = MANAM_FOO_BAR_BAZ_GET_CLASS (self); + if (_klass_->v1) { + _klass_->v1 (self); + } +} + +const gchar* +manam_foo_bar_baz_get_p0 (ManamFooBarBaz* self) +{ + const gchar* result; + const gchar* _tmp0_; + g_return_val_if_fail (MANAM_FOO_BAR_IS_BAZ (self), NULL); + _tmp0_ = self->priv->_p0; + result = _tmp0_; + return result; +} + +void +manam_foo_bar_baz_set_p0 (ManamFooBarBaz* self, + const gchar* value) +{ + gchar* _tmp0_; + g_return_if_fail (MANAM_FOO_BAR_IS_BAZ (self)); + _tmp0_ = g_strdup (value); + _g_free0 (self->priv->_p0); + self->priv->_p0 = _tmp0_; +} + +const gchar* +manam_foo_bar_baz_get_p1 (ManamFooBarBaz* self) +{ + const gchar* result; + const gchar* _tmp0_; + g_return_val_if_fail (MANAM_FOO_BAR_IS_BAZ (self), NULL); + _tmp0_ = self->priv->_p1; + result = _tmp0_; + return result; +} + +void +manam_foo_bar_baz_set_p1 (ManamFooBarBaz* self, + const gchar* value) +{ + gchar* _tmp0_; + g_return_if_fail (MANAM_FOO_BAR_IS_BAZ (self)); + _tmp0_ = g_strdup (value); + _g_free0 (self->priv->_p1); + self->priv->_p1 = _tmp0_; +} + +static void +manam_foo_bar_value_baz_init (GValue* value) +{ + value->data[0].v_pointer = NULL; +} + +static void +manam_foo_bar_value_baz_free_value (GValue* value) +{ + if (value->data[0].v_pointer) { + manam_foo_bar_baz_unref (value->data[0].v_pointer); + } +} + +static void +manam_foo_bar_value_baz_copy_value (const GValue* src_value, + GValue* dest_value) +{ + if (src_value->data[0].v_pointer) { + dest_value->data[0].v_pointer = manam_foo_bar_baz_ref (src_value->data[0].v_pointer); + } else { + dest_value->data[0].v_pointer = NULL; + } +} + +static gpointer +manam_foo_bar_value_baz_peek_pointer (const GValue* value) +{ + return value->data[0].v_pointer; +} + +static gchar* +manam_foo_bar_value_baz_collect_value (GValue* value, + guint n_collect_values, + GTypeCValue* collect_values, + guint collect_flags) +{ + if (collect_values[0].v_pointer) { + ManamFooBarBaz * object; + object = collect_values[0].v_pointer; + if (object->parent_instance.g_class == NULL) { + return g_strconcat ("invalid unclassed object pointer for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } else if (!g_value_type_compatible (G_TYPE_FROM_INSTANCE (object), G_VALUE_TYPE (value))) { + return g_strconcat ("invalid object type `", g_type_name (G_TYPE_FROM_INSTANCE (object)), "' for value type `", G_VALUE_TYPE_NAME (value), "'", NULL); + } + value->data[0].v_pointer = manam_foo_bar_baz_ref (object); + } else { + value->data[0].v_pointer = NULL; + } + return NULL; +} + +static gchar* +manam_foo_bar_value_baz_lcopy_value (const GValue* value, + guint n_collect_values, + GTypeCValue* collect_values, + guint collect_flags) +{ + ManamFooBarBaz ** object_p; + object_p = collect_values[0].v_pointer; + if (!object_p) { + return g_strdup_printf ("value location for `%s' passed as NULL", G_VALUE_TYPE_NAME (value)); + } + if (!value->data[0].v_pointer) { + *object_p = NULL; + } else if (collect_flags & G_VALUE_NOCOPY_CONTENTS) { + *object_p = value->data[0].v_pointer; + } else { + *object_p = manam_foo_bar_baz_ref (value->data[0].v_pointer); + } + return NULL; +} + +GParamSpec* +manam_foo_bar_param_spec_baz (const gchar* name, + const gchar* nick, + const gchar* blurb, + GType object_type, + GParamFlags flags) +{ + ManamFooBarParamSpecBaz* spec; + g_return_val_if_fail (g_type_is_a (object_type, MANAM_FOO_BAR_TYPE_BAZ), NULL); + spec = g_param_spec_internal (G_TYPE_PARAM_OBJECT, name, nick, blurb, flags); + G_PARAM_SPEC (spec)->value_type = object_type; + return G_PARAM_SPEC (spec); +} + +gpointer +manam_foo_bar_value_get_baz (const GValue* value) +{ + g_return_val_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, MANAM_FOO_BAR_TYPE_BAZ), NULL); + return value->data[0].v_pointer; +} + +void +manam_foo_bar_value_set_baz (GValue* value, + gpointer v_object) +{ + ManamFooBarBaz * old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, MANAM_FOO_BAR_TYPE_BAZ)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, MANAM_FOO_BAR_TYPE_BAZ)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + manam_foo_bar_baz_ref (value->data[0].v_pointer); + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + manam_foo_bar_baz_unref (old); + } +} + +void +manam_foo_bar_value_take_baz (GValue* value, + gpointer v_object) +{ + ManamFooBarBaz * old; + g_return_if_fail (G_TYPE_CHECK_VALUE_TYPE (value, MANAM_FOO_BAR_TYPE_BAZ)); + old = value->data[0].v_pointer; + if (v_object) { + g_return_if_fail (G_TYPE_CHECK_INSTANCE_TYPE (v_object, MANAM_FOO_BAR_TYPE_BAZ)); + g_return_if_fail (g_value_type_compatible (G_TYPE_FROM_INSTANCE (v_object), G_VALUE_TYPE (value))); + value->data[0].v_pointer = v_object; + } else { + value->data[0].v_pointer = NULL; + } + if (old) { + manam_foo_bar_baz_unref (old); + } +} + +static void +manam_foo_bar_baz_class_init (ManamFooBarBazClass * klass, + gpointer klass_data) +{ + manam_foo_bar_baz_parent_class = g_type_class_peek_parent (klass); + ((ManamFooBarBazClass *) klass)->finalize = manam_foo_bar_baz_finalize; + g_type_class_adjust_private_offset (klass, &ManamFooBarBaz_private_offset); + ((ManamFooBarBazClass *) klass)->v0 = (void (*) (ManamFooBarBaz*)) manam_foo_bar_baz_real_v0; + ((ManamFooBarBazClass *) klass)->v1 = (void (*) (ManamFooBarBaz*)) manam_foo_bar_baz_real_v1; +} + +static void +manam_foo_bar_baz_instance_init (ManamFooBarBaz * self, + gpointer klass) +{ + self->priv = manam_foo_bar_baz_get_instance_private (self); + self->ref_count = 1; +} + +static void +manam_foo_bar_baz_finalize (ManamFooBarBaz * obj) +{ + ManamFooBarBaz * self; + self = G_TYPE_CHECK_INSTANCE_CAST (obj, MANAM_FOO_BAR_TYPE_BAZ, ManamFooBarBaz); + g_signal_handlers_destroy (self); + _g_free0 (self->priv->_p0); + _g_free0 (self->f0); + _g_free0 (self->priv->_p1); + _g_free0 (self->f1); +} + +static GType +manam_foo_bar_baz_get_type_once (void) +{ + static const GTypeValueTable g_define_type_value_table = { manam_foo_bar_value_baz_init, manam_foo_bar_value_baz_free_value, manam_foo_bar_value_baz_copy_value, manam_foo_bar_value_baz_peek_pointer, "p", manam_foo_bar_value_baz_collect_value, "p", manam_foo_bar_value_baz_lcopy_value }; + static const GTypeInfo g_define_type_info = { sizeof (ManamFooBarBazClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) manam_foo_bar_baz_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (ManamFooBarBaz), 0, (GInstanceInitFunc) manam_foo_bar_baz_instance_init, &g_define_type_value_table }; + static const GTypeFundamentalInfo g_define_type_fundamental_info = { (G_TYPE_FLAG_CLASSED | G_TYPE_FLAG_INSTANTIATABLE | G_TYPE_FLAG_DERIVABLE | G_TYPE_FLAG_DEEP_DERIVABLE) }; + GType manam_foo_bar_baz_type_id; + manam_foo_bar_baz_type_id = g_type_register_fundamental (g_type_fundamental_next (), "ManamFooBarBaz", &g_define_type_info, &g_define_type_fundamental_info, 0); + ManamFooBarBaz_private_offset = g_type_add_instance_private (manam_foo_bar_baz_type_id, sizeof (ManamFooBarBazPrivate)); + return manam_foo_bar_baz_type_id; +} + +GType +manam_foo_bar_baz_get_type (void) +{ + static volatile gsize manam_foo_bar_baz_type_id__volatile = 0; + if (g_once_init_enter (&manam_foo_bar_baz_type_id__volatile)) { + GType manam_foo_bar_baz_type_id; + manam_foo_bar_baz_type_id = manam_foo_bar_baz_get_type_once (); + g_once_init_leave (&manam_foo_bar_baz_type_id__volatile, manam_foo_bar_baz_type_id); + } + return manam_foo_bar_baz_type_id__volatile; +} + +gpointer +manam_foo_bar_baz_ref (gpointer instance) +{ + ManamFooBarBaz * self; + self = instance; + g_atomic_int_inc (&self->ref_count); + return instance; +} + +void +manam_foo_bar_baz_unref (gpointer instance) +{ + ManamFooBarBaz * self; + self = instance; + if (g_atomic_int_dec_and_test (&self->ref_count)) { + MANAM_FOO_BAR_BAZ_GET_CLASS (self)->finalize (self); + g_type_free_instance ((GTypeInstance *) self); + } +} + diff --git a/tests/objects/class-partial-nested.vala b/tests/objects/class-partial-nested.vala new file mode 100644 index 000000000..03298ea4f --- /dev/null +++ b/tests/objects/class-partial-nested.vala @@ -0,0 +1,34 @@ +namespace Manam.Foo { + public partial class Bar.Baz { + public string p0 { get; set; } + public string f0; + public void m0 () { + } + public virtual void v0 () { + } + } +} + +namespace Manam.Foo { + public partial class Bar.Baz { + public string p1 { get; set; } + public string f1; + public void m1 () { + } + public virtual void v1 () { + } + } +} + +void main () { + var baz = new Manam.Foo.Bar.Baz (); + baz.p0 = "p0"; + baz.f0 = "f0"; + baz.m0 (); + baz.v0 (); + + baz.p1 = "p1"; + baz.f1 = "f1"; + baz.m1 (); + baz.v1 (); +} diff --git a/tests/objects/class-partial.c-expected b/tests/objects/class-partial.c-expected index 0cf36ee73..ccc2533d7 100644 --- a/tests/objects/class-partial.c-expected +++ b/tests/objects/class-partial.c-expected @@ -42,6 +42,8 @@ typedef struct _IBarIface IBarIface; typedef struct _Foo Foo; typedef struct _FooClass FooClass; typedef struct _FooPrivate FooPrivate; +#define _g_free0(var) (var = (g_free (var), NULL)) +#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) enum { FOO_0_PROPERTY, FOO_P0_PROPERTY, @@ -50,7 +52,6 @@ enum { FOO_NUM_PROPERTIES }; static GParamSpec* foo_properties[FOO_NUM_PROPERTIES]; -#define _g_free0(var) (var = (g_free (var), NULL)) enum { FOO_S0_SIGNAL, FOO_S1_SIGNAL, @@ -58,7 +59,6 @@ enum { FOO_NUM_SIGNALS }; static guint foo_signals[FOO_NUM_SIGNALS] = {0}; -#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL))) #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; } @@ -109,30 +109,31 @@ static GType ifoo_get_type_once (void); VALA_EXTERN GType ibar_get_type (void) G_GNUC_CONST ; VALA_EXTERN void ibar_i2 (IBar* self); static GType ibar_get_type_once (void); +static void _vala_main (void); VALA_EXTERN GType foo_get_type (void) G_GNUC_CONST ; G_DEFINE_AUTOPTR_CLEANUP_FUNC (Foo, g_object_unref) +VALA_EXTERN Foo* foo_new (void); +VALA_EXTERN Foo* foo_construct (GType object_type); +VALA_EXTERN void foo_set_p0 (Foo* self, + const gchar* value); +VALA_EXTERN void foo_m0 (Foo* self); VALA_EXTERN void foo_v0 (Foo* self); +VALA_EXTERN void foo_set_p1 (Foo* self, + const gchar* value); +VALA_EXTERN void foo_m1 (Foo* self); VALA_EXTERN void foo_v1 (Foo* self); +VALA_EXTERN void foo_set_p2 (Foo* self, + const gchar* value); +VALA_EXTERN void foo_m2 (Foo* self); VALA_EXTERN void foo_v2 (Foo* self); -VALA_EXTERN void foo_m0 (Foo* self); static void foo_real_v0 (Foo* self); -VALA_EXTERN Foo* foo_new (void); -VALA_EXTERN Foo* foo_construct (GType object_type); -VALA_EXTERN void foo_m1 (Foo* self); static void foo_real_v1 (Foo* self); static void foo_real_i1 (IFoo* base); -VALA_EXTERN void foo_m2 (Foo* self); static void foo_real_v2 (Foo* self); static void foo_real_i2 (IBar* base); VALA_EXTERN const gchar* foo_get_p0 (Foo* self); -VALA_EXTERN void foo_set_p0 (Foo* self, - const gchar* value); VALA_EXTERN const gchar* foo_get_p1 (Foo* self); -VALA_EXTERN void foo_set_p1 (Foo* self, - const gchar* value); VALA_EXTERN const gchar* foo_get_p2 (Foo* self); -VALA_EXTERN void foo_set_p2 (Foo* self, - const gchar* value); static void foo_real_s0 (Foo* self); static void foo_real_s1 (Foo* self); static void foo_real_s2 (Foo* self); @@ -146,7 +147,6 @@ static void _vala_foo_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec); -static void _vala_main (void); void ifoo_i1 (IFoo* self) @@ -224,6 +224,52 @@ ibar_get_type (void) return ibar_type_id__volatile; } +static void +_vala_main (void) +{ + Foo* foo = NULL; + Foo* _tmp0_; + gchar* _tmp1_; + gchar* _tmp2_; + gchar* _tmp3_; + _tmp0_ = foo_new (); + foo = _tmp0_; + foo_set_p0 (foo, "p0"); + _tmp1_ = g_strdup ("f0"); + _g_free0 (foo->f0); + foo->f0 = _tmp1_; + foo_m0 (foo); + foo_v0 (foo); + g_signal_emit (foo, foo_signals[FOO_S0_SIGNAL], 0); + foo_set_p1 (foo, "p1"); + _tmp2_ = g_strdup ("f1"); + _g_free0 (foo->f1); + foo->f1 = _tmp2_; + foo_m1 (foo); + foo_v1 (foo); + g_signal_emit (foo, foo_signals[FOO_S1_SIGNAL], 0); + foo_set_p2 (foo, "p2"); + _tmp3_ = g_strdup ("f2"); + _g_free0 (foo->f2); + foo->f2 = _tmp3_; + foo_m2 (foo); + foo_v2 (foo); + g_signal_emit (foo, foo_signals[FOO_S2_SIGNAL], 0); + _vala_assert (IS_IFOO (foo), "foo is IFoo"); + ifoo_i1 (G_TYPE_CHECK_INSTANCE_CAST (foo, TYPE_IFOO, IFoo)); + _vala_assert (IS_IBAR (foo), "foo is IBar"); + ibar_i2 (G_TYPE_CHECK_INSTANCE_CAST (foo, TYPE_IBAR, IBar)); + _g_object_unref0 (foo); +} + +int +main (int argc, + char ** argv) +{ + _vala_main (); + return 0; +} + static inline gpointer foo_get_instance_private (Foo* self) { @@ -554,49 +600,3 @@ _vala_foo_set_property (GObject * object, } } -static void -_vala_main (void) -{ - Foo* foo = NULL; - Foo* _tmp0_; - gchar* _tmp1_; - gchar* _tmp2_; - gchar* _tmp3_; - _tmp0_ = foo_new (); - foo = _tmp0_; - foo_set_p0 (foo, "p0"); - _tmp1_ = g_strdup ("f0"); - _g_free0 (foo->f0); - foo->f0 = _tmp1_; - foo_m0 (foo); - foo_v0 (foo); - g_signal_emit (foo, foo_signals[FOO_S0_SIGNAL], 0); - foo_set_p1 (foo, "p1"); - _tmp2_ = g_strdup ("f1"); - _g_free0 (foo->f1); - foo->f1 = _tmp2_; - foo_m1 (foo); - foo_v1 (foo); - g_signal_emit (foo, foo_signals[FOO_S1_SIGNAL], 0); - foo_set_p2 (foo, "p2"); - _tmp3_ = g_strdup ("f2"); - _g_free0 (foo->f2); - foo->f2 = _tmp3_; - foo_m2 (foo); - foo_v2 (foo); - g_signal_emit (foo, foo_signals[FOO_S2_SIGNAL], 0); - _vala_assert (IS_IFOO (foo), "foo is IFoo"); - ifoo_i1 (G_TYPE_CHECK_INSTANCE_CAST (foo, TYPE_IFOO, IFoo)); - _vala_assert (IS_IBAR (foo), "foo is IBar"); - ibar_i2 (G_TYPE_CHECK_INSTANCE_CAST (foo, TYPE_IBAR, IBar)); - _g_object_unref0 (foo); -} - -int -main (int argc, - char ** argv) -{ - _vala_main (); - return 0; -} - diff --git a/vala/valaparser.vala b/vala/valaparser.vala index d61a581e0..112a0d04d 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -44,12 +44,20 @@ public class Vala.Parser : CodeVisitor { static List _empty_type_parameter_list; static int next_local_func_id = 0; + PartialInfo[] partials; + struct TokenInfo { public TokenType type; public SourceLocation begin; public SourceLocation end; } + struct PartialInfo { + public Symbol parent; + public SourceLocation begin; + public List? attributes; + } + [Flags] enum ModifierFlags { NONE = 0, @@ -211,6 +219,20 @@ public class Vala.Parser : CodeVisitor { } } + void jump (SourceLocation location) { + while (tokens[index].begin.pos != location.pos) { + index = (index + 1) % BUFFER_SIZE; + size--; + if (size <= 0) { + scanner.seek (location); + size = 0; + index = 0; + + next (); + } + } + } + void skip_identifier () throws ParseError { // also accept keywords as identifiers where there is no conflict switch (current ()) { @@ -386,6 +408,8 @@ public class Vala.Parser : CodeVisitor { try { + partials = new PartialInfo[] {}; + var begin = get_location (); parse_using_directives (context.root); parse_declarations (context.root, true); if (accept (TokenType.CLOSE_BRACE)) { @@ -394,6 +418,14 @@ public class Vala.Parser : CodeVisitor { Report.error (get_last_src (), "unexpected `}'"); } } + if (partials.length > 0) { + rollback (begin); + foreach (var info in partials) { + jump (info.begin); + parse_class_declaration (info.parent, info.attributes, true); + } + } + partials = null; } catch (ParseError e) { report_parse_error (e); } @@ -2903,7 +2935,7 @@ public class Vala.Parser : CodeVisitor { } } - void parse_class_declaration (Symbol parent, List? attrs) throws ParseError { + void parse_class_declaration (Symbol parent, List? attrs, bool partial_reparse = false) throws ParseError { var begin = get_location (); var access = parse_access_modifier (); var flags = parse_type_declaration_modifiers (); @@ -2935,7 +2967,30 @@ public class Vala.Parser : CodeVisitor { cl.is_extern = true; } - var old_cl = parent.scope.lookup (cl.name) as Class; + Class? old_cl = null; + if (partial_reparse) { + var names = new ArrayList (); + while (sym.inner != null) { + sym = sym.inner; + names.insert (0, sym.name); + } + Symbol p = parent; + while (p != null && p != context.root) { + names.insert (0, p.name); + p = p.parent_symbol; + } + p = context.root; + foreach (var name in names) { + p = p.scope.lookup (name); + if (p == null) { + break; + } + } + if (p != null) { + old_cl = p.scope.lookup (cl.name) as Class; + parent = p; + } + } if (old_cl != null && old_cl.is_partial) { if (cl.is_partial != old_cl.is_partial) { Report.error (cl.source_reference, "conflicting partial and not partial declarations of `%s'".printf (cl.name)); @@ -2984,6 +3039,11 @@ public class Vala.Parser : CodeVisitor { cl.add_method (m); } + if (partial_reparse) { + parent.add_class (cl); + return; + } + Symbol result = cl; while (sym != null) { sym = sym.inner; @@ -2991,7 +3051,10 @@ public class Vala.Parser : CodeVisitor { Symbol next = (sym != null ? new Namespace (sym.name, cl.source_reference) : parent); if (result is Namespace) { next.add_namespace ((Namespace) result); - } else { + } else if (!partial_reparse && cl.is_partial) { + PartialInfo info = { parent, begin, attrs }; + partials += info; + } else if (!cl.is_partial) { next.add_class ((Class) result); } result = next;