From 3d71dcaa646128b5f71484ec33651664120ce913 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sun, 12 Jan 2025 14:58:34 -0800 Subject: [PATCH 1/4] gicallableinfo: Fix inaccuracy in is_method docs The docs say that gi_callable_info_is_method() on a GICallbackInfo always returns TRUE. But the source code says it always returns FALSE. --- girepository/gicallableinfo.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/girepository/gicallableinfo.c b/girepository/gicallableinfo.c index f85192fdb..bcb37a792 100644 --- a/girepository/gicallableinfo.c +++ b/girepository/gicallableinfo.c @@ -135,9 +135,10 @@ gi_callable_info_can_throw_gerror (GICallableInfo *info) * * Determines if the callable info is a method. * - * For [class@GIRepository.VFuncInfo]s, [class@GIRepository.CallbackInfo]s, and - * [class@GIRepository.SignalInfo]s, this is always true. Otherwise, this looks - * at the `GI_FUNCTION_IS_METHOD` flag on the [class@GIRepository.FunctionInfo]. + * For [class@GIRepository.VFuncInfo]s and [class@GIRepository.SignalInfo]s, + * this is always true, and for [class@GIRepository.CallbackInfo]s always false. + * Otherwise, this looks at the `GI_FUNCTION_IS_METHOD` flag on the + * [class@GIRepository.FunctionInfo]. * * Concretely, this function returns whether * [method@GIRepository.CallableInfo.get_n_args] matches the number of arguments From fe142e3b320e123e4dd1789a1e53f0e7812faeb3 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sun, 12 Jan 2025 14:59:20 -0800 Subject: [PATCH 2/4] girepository: Add baseline tests for gi_callable_info_is_method() This tests existing functionality. --- girepository/tests/callable-info.c | 61 ++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/girepository/tests/callable-info.c b/girepository/tests/callable-info.c index 97b9e6183..4bf251fcf 100644 --- a/girepository/tests/callable-info.c +++ b/girepository/tests/callable-info.c @@ -124,6 +124,65 @@ test_callable_get_async_function_for_sync_function (RepositoryFixture *fx, gi_base_info_unref (info); } +static void +test_callable_info_is_method (RepositoryFixture *fx, + const void *unused) +{ + GIBaseInfo *info; + GIFunctionInfo *func_info; + GIVFuncInfo *vfunc_info; + GISignalInfo *sig_info; + GIBaseInfo *cb_info; + + info = gi_repository_find_by_name (fx->repository, "Gio", "ActionGroup"); + g_assert_nonnull (info); + + func_info = gi_interface_info_find_method (GI_INTERFACE_INFO (info), "action_added"); + g_assert_nonnull (func_info); + + g_assert_true (gi_callable_info_is_method (GI_CALLABLE_INFO (func_info))); + + vfunc_info = gi_interface_info_find_vfunc (GI_INTERFACE_INFO (info), "action_added"); + g_assert_nonnull (vfunc_info); + + g_assert_true (gi_callable_info_is_method (GI_CALLABLE_INFO (vfunc_info))); + + sig_info = gi_interface_info_find_signal (GI_INTERFACE_INFO (info), "action-added"); + g_assert_nonnull (sig_info); + + g_assert_true (gi_callable_info_is_method (GI_CALLABLE_INFO (sig_info))); + + cb_info = gi_repository_find_by_name (fx->repository, "Gio", "AsyncReadyCallback"); + g_assert_nonnull (cb_info); + + g_assert_false (gi_callable_info_is_method (GI_CALLABLE_INFO (cb_info))); + + gi_base_info_unref (info); + gi_base_info_unref ((GIBaseInfo *) func_info); + gi_base_info_unref ((GIBaseInfo *) vfunc_info); + gi_base_info_unref ((GIBaseInfo *) sig_info); + gi_base_info_unref (cb_info); +} + +static void +test_callable_info_static_method (RepositoryFixture *fx, + const void *unused) +{ + GIBaseInfo *info; + GIFunctionInfo *func_info; + + info = gi_repository_find_by_name (fx->repository, "Gio", "Application"); + g_assert_nonnull (info); + + func_info = gi_object_info_find_method (GI_OBJECT_INFO (info), "get_default"); + g_assert_nonnull (func_info); + + g_assert_false (gi_callable_info_is_method (GI_CALLABLE_INFO (func_info))); + + gi_base_info_unref (info); + gi_base_info_unref ((GIBaseInfo *) func_info); +} + int main (int argc, char **argv) { @@ -131,6 +190,8 @@ main (int argc, char **argv) ADD_REPOSITORY_TEST ("/callable-info/sync-function", test_callable_get_sync_function_for_async_function, &typelib_load_spec_gio); ADD_REPOSITORY_TEST ("/callable-info/async-function", test_callable_get_async_function_for_sync_function, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/callable-info/is-method", test_callable_info_is_method, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/callable-info/static-method", test_callable_info_static_method, &typelib_load_spec_gio); return g_test_run (); } From 7ea9840cf4ba6be3dbf7a9b7749485b52a07b1aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 5 Oct 2022 17:55:54 -0700 Subject: [PATCH 3/4] girepository: Read static vfunc attribute exposing via callable is_method() Read the static attribute for virtual functions, and make sure that g_callable_info_is_method() returns false for such cases. --- girepository/gicallableinfo.c | 15 +++++++++++---- girepository/girnode-private.h | 2 ++ girepository/girnode.c | 1 + girepository/girparser.c | 7 +++++++ girepository/gitypelib-internal.h | 4 +++- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/girepository/gicallableinfo.c b/girepository/gicallableinfo.c index bcb37a792..551fe961d 100644 --- a/girepository/gicallableinfo.c +++ b/girepository/gicallableinfo.c @@ -135,10 +135,12 @@ gi_callable_info_can_throw_gerror (GICallableInfo *info) * * Determines if the callable info is a method. * - * For [class@GIRepository.VFuncInfo]s and [class@GIRepository.SignalInfo]s, - * this is always true, and for [class@GIRepository.CallbackInfo]s always false. - * Otherwise, this looks at the `GI_FUNCTION_IS_METHOD` flag on the - * [class@GIRepository.FunctionInfo]. + * For [class@GIRepository.SignalInfo]s, this is always true, and for + * [class@GIRepository.CallbackInfo]s always false. + * For [class@GIRepository.FunctionInfo]s this looks at the + * `GI_FUNCTION_IS_METHOD` flag on the [class@GIRepository.FunctionInfo]. + * For [class@GIRepository.VFuncInfo]s this is true when the virtual function + * has an instance parameter. * * Concretely, this function returns whether * [method@GIRepository.CallableInfo.get_n_args] matches the number of arguments @@ -160,6 +162,11 @@ gi_callable_info_is_method (GICallableInfo *info) return (!blob->constructor && !blob->is_static); } case GI_INFO_TYPE_VFUNC: + { + VFuncBlob *blob; + blob = (VFuncBlob *) &rinfo->typelib->data[rinfo->offset]; + return !blob->is_static; + } case GI_INFO_TYPE_SIGNAL: return TRUE; case GI_INFO_TYPE_CALLBACK: diff --git a/girepository/girnode-private.h b/girepository/girnode-private.h index 652eb92a0..6bb814e38 100644 --- a/girepository/girnode-private.h +++ b/girepository/girnode-private.h @@ -243,6 +243,8 @@ struct _GIIrNodeVFunc uint8_t instance_transfer_full : 1; uint8_t is_async : 1; + uint8_t is_static : 1; + char *invoker; /* (owned) */ char *finish_func; /* (owned) */ char *sync_func; /* (owned) */ diff --git a/girepository/girnode.c b/girepository/girnode.c index 15084ceba..65641625d 100644 --- a/girepository/girnode.c +++ b/girepository/girnode.c @@ -2029,6 +2029,7 @@ gi_ir_node_build_typelib (GIIrNode *node, blob->struct_offset = vfunc->offset; blob->reserved2 = 0; blob->signature = signature; + blob->is_static = vfunc->is_static; gi_ir_node_build_typelib ((GIIrNode *)vfunc->result->type, node, build, &signature, offset2, NULL); diff --git a/girepository/girparser.c b/girepository/girparser.c index 7a111f0d9..0cf341533 100644 --- a/girepository/girparser.c +++ b/girepository/girparser.c @@ -2660,6 +2660,7 @@ start_vfunc (GMarkupParseContext *context, const char *offset; const char *invoker; const char *throws; + const char *is_static; const char *finish_func; const char *async_func; const char *sync_func; @@ -2682,6 +2683,7 @@ start_vfunc (GMarkupParseContext *context, offset = find_attribute ("offset", attribute_names, attribute_values); invoker = find_attribute ("invoker", attribute_names, attribute_values); throws = find_attribute ("throws", attribute_names, attribute_values); + is_static = find_attribute ("glib:static", attribute_names, attribute_values); finish_func = find_attribute ("glib:finish-func", attribute_names, attribute_values); sync_func = find_attribute ("glib:sync-func", attribute_names, attribute_values); async_func = find_attribute ("glib:async-func", attribute_names, attribute_values); @@ -2728,6 +2730,11 @@ start_vfunc (GMarkupParseContext *context, else vfunc->throws = FALSE; + if (is_static && strcmp (is_static, "1") == 0) + vfunc->is_static = TRUE; + else + vfunc->is_static = FALSE; + if (offset == NULL) vfunc->offset = 0xFFFF; else if (g_ascii_string_to_unsigned (offset, 10, 0, G_MAXSIZE, &parsed_offset, error)) diff --git a/girepository/gitypelib-internal.h b/girepository/gitypelib-internal.h index cb5610ef6..74cf1b4dc 100644 --- a/girepository/gitypelib-internal.h +++ b/girepository/gitypelib-internal.h @@ -1117,6 +1117,7 @@ typedef struct { * @invoker: If a method invoker for this virtual exists, this is the offset * in the class structure of the method. If no method is known, this value * will be 0x3ff. + * @is_static: True if the vfunc has no instance parameter. * @reserved: Reserved for future use. * @finish: The index of the finish function if is_async is TRUE, otherwise ASYNC_SENTINEL * @reserved2: Reserved for future use. @@ -1142,7 +1143,8 @@ typedef struct { uint16_t struct_offset; uint16_t invoker : 10; /* Number of bits matches @index in FunctionBlob */ - uint16_t reserved : 6; + uint16_t is_static : 1; + uint16_t reserved : 5; uint16_t finish : 10; uint16_t reserved2 : 6; From 7471ab20d1f40fe4fbb167567461928d3bd94bb0 Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Sun, 12 Jan 2025 15:13:20 -0800 Subject: [PATCH 4/4] girepository: Add test for static vfunc info This is a test for the functionality in the previous commit. It depends on g-ir-scanner being able to scan static vfuncs, and is otherwise skipped. The g-ir-scanner functionality is in https://gitlab.gnome.org/GNOME/gobject-introspection/-/merge_requests/361 --- girepository/tests/callable-info.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/girepository/tests/callable-info.c b/girepository/tests/callable-info.c index 4bf251fcf..ee23d2e62 100644 --- a/girepository/tests/callable-info.c +++ b/girepository/tests/callable-info.c @@ -183,6 +183,32 @@ test_callable_info_static_method (RepositoryFixture *fx, gi_base_info_unref ((GIBaseInfo *) func_info); } +static void +test_callable_info_static_vfunc (RepositoryFixture *fx, + const void *unused) +{ + GIBaseInfo *info; + GIVFuncInfo *vfunc_info; + + g_test_bug ("https://gitlab.gnome.org/GNOME/gobject-introspection/-/merge_requests/361"); + + info = gi_repository_find_by_name (fx->repository, "Gio", "Icon"); + g_assert_nonnull (info); + + vfunc_info = gi_interface_info_find_vfunc (GI_INTERFACE_INFO (info), "from_tokens"); + if (!vfunc_info) + { + g_test_skip ("g-ir-scanner is not new enough"); + return; + } + g_assert_nonnull (vfunc_info); + + g_assert_false (gi_callable_info_is_method (GI_CALLABLE_INFO (vfunc_info))); + + gi_base_info_unref (info); + gi_base_info_unref ((GIBaseInfo *) vfunc_info); +} + int main (int argc, char **argv) { @@ -192,6 +218,7 @@ main (int argc, char **argv) ADD_REPOSITORY_TEST ("/callable-info/async-function", test_callable_get_async_function_for_sync_function, &typelib_load_spec_gio); ADD_REPOSITORY_TEST ("/callable-info/is-method", test_callable_info_is_method, &typelib_load_spec_gio); ADD_REPOSITORY_TEST ("/callable-info/static-method", test_callable_info_static_method, &typelib_load_spec_gio); + ADD_REPOSITORY_TEST ("/callable-info/static-vfunc", test_callable_info_static_vfunc, &typelib_load_spec_gio); return g_test_run (); }