From 9cec3ba0bf977472be18d290de53dbdc6dd78f18 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Thu, 25 Jun 2026 22:23:30 +0100 Subject: [PATCH 1/2] Extract native handle graph helper --- ext/rubydex/declaration.c | 85 ++++++++------------------------------- ext/rubydex/definition.c | 65 ++++++------------------------ ext/rubydex/document.c | 25 +++--------- ext/rubydex/handle.h | 13 ++++++ ext/rubydex/reference.c | 30 +++----------- 5 files changed, 54 insertions(+), 164 deletions(-) diff --git a/ext/rubydex/declaration.c b/ext/rubydex/declaration.c index 3f8366fee..b3a856791 100644 --- a/ext/rubydex/declaration.c +++ b/ext/rubydex/declaration.c @@ -59,10 +59,7 @@ VALUE rdxi_declaration_class_for_kind(CDeclarationKind kind) { */ static VALUE rdxr_declaration_name(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); const char *name = rdx_declaration_name(graph, data->id); if (name == NULL) { @@ -83,10 +80,7 @@ static VALUE rdxr_declaration_name(VALUE self) { */ static VALUE rdxr_declaration_unqualified_name(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); const char *name = rdx_declaration_unqualified_name(graph, data->id); if (name == NULL) { @@ -130,10 +124,7 @@ static VALUE declaration_definitions_ensure(VALUE args) { // Size function for the Declaration#definitions enumerator static VALUE declaration_definitions_size(VALUE self, VALUE _args, VALUE _eobj) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); struct DefinitionsIter *iter = rdx_declaration_definitions_iter_new(graph, data->id); size_t len = rdx_definitions_iter_len(iter); rdx_definitions_iter_free(iter); @@ -153,10 +144,7 @@ static VALUE rdxr_declaration_definitions(VALUE self) { } HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); void *iter = rdx_declaration_definitions_iter_new(graph, data->id); VALUE args = rb_ary_new_from_args(2, self, ULL2NUM((uintptr_t)iter)); @@ -173,10 +161,7 @@ static VALUE rdxr_declaration_definitions(VALUE self) { */ static VALUE rdxr_declaration_member(VALUE self, VALUE name) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); if (TYPE(name) != T_STRING) { rb_raise(rb_eTypeError, "expected String"); @@ -217,10 +202,7 @@ static VALUE rdxr_declaration_find_member(int argc, VALUE *argv, VALUE self) { } HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); const CDeclaration *decl = rdx_declaration_find_member(graph, data->id, StringValueCStr(member), only_inherited); if (decl == NULL) { @@ -242,10 +224,7 @@ static VALUE rdxr_declaration_find_member(int argc, VALUE *argv, VALUE self) { */ static VALUE rdxr_declaration_singleton_class(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); const CDeclaration *decl = rdx_declaration_singleton_class(graph, data->id); if (decl == NULL) { @@ -267,10 +246,7 @@ static VALUE rdxr_declaration_singleton_class(VALUE self) { */ static VALUE rdxr_declaration_owner(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); const CDeclaration *decl = rdx_declaration_owner(graph, data->id); if (decl == NULL) { @@ -296,10 +272,7 @@ static VALUE rdxr_declaration_ancestors(VALUE self) { } HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); void *iter = rdx_declaration_ancestors(graph, data->id); if (iter == NULL) { @@ -324,10 +297,7 @@ static VALUE rdxr_declaration_descendants(VALUE self) { } HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); void *iter = rdx_declaration_descendants(graph, data->id); if (iter == NULL) { @@ -352,10 +322,7 @@ static VALUE rdxr_declaration_members(VALUE self) { } HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); void *iter = rdx_declaration_members(graph, data->id); if (iter == NULL) { @@ -371,10 +338,7 @@ static VALUE rdxr_declaration_members(VALUE self) { // Size function for constant declaration references enumerator static VALUE constant_declaration_references_size(VALUE self, VALUE _args, VALUE _eobj) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); struct ConstantReferencesIter *iter = rdx_declaration_constant_references_iter_new(graph, data->id); if (iter == NULL) { @@ -399,10 +363,7 @@ static VALUE rdxr_constant_declaration_references(VALUE self) { } HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); void *iter = rdx_declaration_constant_references_iter_new(graph, data->id); if (iter == NULL) { @@ -418,10 +379,7 @@ static VALUE rdxr_constant_declaration_references(VALUE self) { // Size function for method declaration references enumerator static VALUE method_declaration_references_size(VALUE self, VALUE _args, VALUE _eobj) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); struct MethodReferencesIter *iter = rdx_declaration_method_references_iter_new(graph, data->id); if (iter == NULL) { @@ -446,10 +404,7 @@ static VALUE rdxr_method_declaration_references(VALUE self) { } HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); void *iter = rdx_declaration_method_references_iter_new(graph, data->id); if (iter == NULL) { @@ -493,10 +448,7 @@ static VALUE rdxi_visibility_to_symbol(CVisibility visibility) { */ static VALUE rdxr_declaration_visibility(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); const CVisibility *visibility = rdx_graph_visibility(graph, data->id); if (visibility == NULL) { @@ -518,10 +470,7 @@ static VALUE rdxr_declaration_visibility(VALUE self) { */ static VALUE rdxr_constant_alias_target(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); const CDeclaration *decl = rdx_constant_alias_target(graph, data->id); if (decl == NULL) { diff --git a/ext/rubydex/definition.c b/ext/rubydex/definition.c index 58bd4ac71..23d73eb10 100644 --- a/ext/rubydex/definition.c +++ b/ext/rubydex/definition.c @@ -84,10 +84,7 @@ VALUE rdxi_definition_class_for_kind(DefinitionKind kind) { */ static VALUE rdxr_definition_location(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); Location *loc = rdx_definition_location(graph, data->id); VALUE location = rdxi_build_location_value(loc); @@ -104,10 +101,7 @@ static VALUE rdxr_definition_location(VALUE self) { */ static VALUE rdxr_definition_comments(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); CommentArray *arr = rdx_definition_comments(graph, data->id); if (arr == NULL || arr->len == 0) { @@ -147,10 +141,7 @@ static VALUE rdxr_definition_comments(VALUE self) { */ static VALUE rdxr_definition_name(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); const char *name = rdx_definition_name(graph, data->id); if (name == NULL) { @@ -169,10 +160,7 @@ static VALUE rdxr_definition_name(VALUE self) { */ static VALUE rdxr_definition_deprecated(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); bool deprecated = rdx_definition_is_deprecated(graph, data->id); return deprecated ? Qtrue : Qfalse; @@ -187,10 +175,7 @@ static VALUE rdxr_definition_deprecated(VALUE self) { */ static VALUE rdxr_definition_name_location(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); Location *loc = rdx_definition_name_location(graph, data->id); if (loc == NULL) { @@ -210,10 +195,7 @@ static VALUE rdxr_definition_name_location(VALUE self) { */ static VALUE rdxr_definition_declaration(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); const struct CDeclaration *decl = rdx_definition_declaration(graph, data->id); if (decl == NULL) { @@ -243,10 +225,7 @@ static VALUE rdxi_build_definition(VALUE graph_obj, void *graph, uint64_t defini */ static VALUE rdxr_definition_lexical_owner(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); const uint64_t *owner_id = rdx_definition_lexical_nesting_id(graph, data->id); if (owner_id == NULL) { @@ -267,10 +246,7 @@ static VALUE rdxr_definition_lexical_owner(VALUE self) { */ static VALUE rdxr_definition_lexical_nesting(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); VALUE nesting = rb_ary_new(); uint64_t definition_id = data->id; @@ -306,10 +282,7 @@ static VALUE rdxi_build_constant_reference(VALUE graph_obj, const CConstantRefer */ static VALUE rdxr_class_definition_superclass(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); const CConstantReference *ref = rdx_class_definition_superclass(graph, data->id); if (ref == NULL) { @@ -342,10 +315,7 @@ static VALUE rdxi_mixin_class_for_kind(MixinKind kind) { */ static VALUE rdxr_definition_mixins(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); MixinsIter *iter = rdx_definition_mixins(graph, data->id); if (iter == NULL) { @@ -375,10 +345,7 @@ static VALUE rdxr_definition_mixins(VALUE self) { */ static VALUE rdxr_method_definition_signatures(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); SignatureArray *arr = rdx_definition_signatures(graph, data->id); return rdxi_signatures_to_ruby(arr); @@ -392,10 +359,7 @@ static VALUE rdxr_method_definition_signatures(VALUE self) { */ static VALUE rdxr_method_alias_definition_signatures(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); SignatureArray *arr = rdx_method_alias_definition_signatures(graph, data->id); return rdxi_signatures_to_ruby(arr); @@ -410,10 +374,7 @@ static VALUE rdxr_method_alias_definition_signatures(VALUE self) { */ static VALUE rdxr_method_alias_definition_target(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); CMethodAliasTargetResult result = rdx_method_alias_definition_target(graph, data->id); diff --git a/ext/rubydex/document.c b/ext/rubydex/document.c index 615463c15..78b7ab47f 100644 --- a/ext/rubydex/document.c +++ b/ext/rubydex/document.c @@ -20,10 +20,7 @@ VALUE cDocument; */ static VALUE rdxr_document_uri(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); const char *uri = rdx_document_uri(graph, data->id); if (uri == NULL) { @@ -66,10 +63,7 @@ static VALUE document_definitions_ensure(VALUE args) { // Size function for the Document#definitions enumerator static VALUE document_definitions_size(VALUE self, VALUE _args, VALUE _eobj) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); struct DefinitionsIter *iter = rdx_document_definitions_iter_new(graph, data->id); size_t len = rdx_definitions_iter_len(iter); rdx_definitions_iter_free(iter); @@ -89,10 +83,7 @@ static VALUE rdxr_document_definitions(VALUE self) { } HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); void *iter = rdx_document_definitions_iter_new(graph, data->id); VALUE args = rb_ary_new_from_args(2, self, ULL2NUM((uintptr_t)iter)); rb_ensure(document_definitions_yield, args, document_definitions_ensure, args); @@ -103,10 +94,7 @@ static VALUE rdxr_document_definitions(VALUE self) { // Size function for the Document#method_references enumerator static VALUE document_method_references_size(VALUE self, VALUE _args, VALUE _eobj) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); struct MethodReferencesIter *iter = rdx_document_method_references_iter_new(graph, data->id); size_t len = rdx_method_references_iter_len(iter); rdx_method_references_iter_free(iter); @@ -123,10 +111,7 @@ static VALUE rdxr_document_method_references(VALUE self) { } HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); void *iter = rdx_document_method_references_iter_new(graph, data->id); VALUE args = rb_ary_new_from_args(2, data->graph_obj, ULL2NUM((uintptr_t)iter)); rb_ensure(rdxi_method_references_yield, args, rdxi_method_references_ensure, args); diff --git a/ext/rubydex/handle.h b/ext/rubydex/handle.h index dba57acd5..cfd82c196 100644 --- a/ext/rubydex/handle.h +++ b/ext/rubydex/handle.h @@ -1,6 +1,7 @@ #ifndef RUBYDEX_HANDLE_H #define RUBYDEX_HANDLE_H +#include "graph.h" #include "ruby.h" typedef struct { @@ -34,6 +35,18 @@ static const rb_data_type_t handle_type = { .flags = RUBY_TYPED_FREE_IMMEDIATELY, }; +static inline void *rdxi_graph_from_handle(VALUE self, HandleData **out_data) { + HandleData *data; + TypedData_Get_Struct(self, HandleData, &handle_type, data); + + void *graph; + TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + + *out_data = data; + + return graph; +} + static VALUE rdxr_handle_alloc(VALUE klass) { HandleData *data = ALLOC(HandleData); diff --git a/ext/rubydex/reference.c b/ext/rubydex/reference.c index bf0a656af..825f12697 100644 --- a/ext/rubydex/reference.c +++ b/ext/rubydex/reference.c @@ -24,10 +24,7 @@ VALUE cMethodReference; */ static VALUE rdxr_constant_reference_name(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); const char *name = rdx_constant_reference_name(graph, data->id); if (name == NULL) { @@ -47,10 +44,7 @@ static VALUE rdxr_constant_reference_name(VALUE self) { */ static VALUE rdxr_constant_reference_location(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); Location *loc = rdx_constant_reference_location(graph, data->id); VALUE location = rdxi_build_location_value(loc); @@ -66,10 +60,7 @@ static VALUE rdxr_constant_reference_location(VALUE self) { */ static VALUE rdxr_method_reference_name(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); const char *name = rdx_method_reference_name(graph, data->id); if (name == NULL) { @@ -89,10 +80,7 @@ static VALUE rdxr_method_reference_name(VALUE self) { */ static VALUE rdxr_method_reference_location(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); Location *loc = rdx_method_reference_location(graph, data->id); VALUE location = rdxi_build_location_value(loc); @@ -109,10 +97,7 @@ static VALUE rdxr_method_reference_location(VALUE self) { */ static VALUE rdxr_method_reference_receiver(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); const struct CDeclaration *decl = rdx_method_reference_receiver_declaration(graph, data->id); if (decl == NULL) { @@ -134,10 +119,7 @@ static VALUE rdxr_method_reference_receiver(VALUE self) { */ static VALUE rdxr_resolved_constant_reference_declaration(VALUE self) { HandleData *data; - TypedData_Get_Struct(self, HandleData, &handle_type, data); - - void *graph; - TypedData_Get_Struct(data->graph_obj, void *, &graph_type, graph); + void *graph = rdxi_graph_from_handle(self, &data); const struct CDeclaration *decl = rdx_resolved_constant_reference_declaration(graph, data->id); if (decl == NULL) { From 84a78f95bbb2e9ac1ab433fdb19c7a8b16244d56 Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Thu, 25 Jun 2026 22:23:53 +0100 Subject: [PATCH 2/2] Extract owned C string conversion helper --- ext/rubydex/declaration.c | 18 ++---------------- ext/rubydex/definition.c | 8 ++------ ext/rubydex/document.c | 9 +-------- ext/rubydex/graph.c | 3 +-- ext/rubydex/reference.c | 17 +++-------------- ext/rubydex/utils.c | 13 +++++++++++++ ext/rubydex/utils.h | 4 ++++ 7 files changed, 26 insertions(+), 46 deletions(-) diff --git a/ext/rubydex/declaration.c b/ext/rubydex/declaration.c index b3a856791..e36e70c1d 100644 --- a/ext/rubydex/declaration.c +++ b/ext/rubydex/declaration.c @@ -62,14 +62,7 @@ static VALUE rdxr_declaration_name(VALUE self) { void *graph = rdxi_graph_from_handle(self, &data); const char *name = rdx_declaration_name(graph, data->id); - if (name == NULL) { - return Qnil; - } - - VALUE str = rb_utf8_str_new_cstr(name); - free_c_string(name); - - return str; + return rdxi_owned_c_string_to_ruby(name); } /* @@ -83,14 +76,7 @@ static VALUE rdxr_declaration_unqualified_name(VALUE self) { void *graph = rdxi_graph_from_handle(self, &data); const char *name = rdx_declaration_unqualified_name(graph, data->id); - if (name == NULL) { - return Qnil; - } - - VALUE str = rb_utf8_str_new_cstr(name); - free_c_string(name); - - return str; + return rdxi_owned_c_string_to_ruby(name); } // Body function for rb_ensure in Declaration#definitions diff --git a/ext/rubydex/definition.c b/ext/rubydex/definition.c index 23d73eb10..a302083c4 100644 --- a/ext/rubydex/definition.c +++ b/ext/rubydex/definition.c @@ -7,6 +7,7 @@ #include "signature.h" #include "ruby/internal/scan_args.h" #include "rustbindings.h" +#include "utils.h" /* * RDoc parser workaround for https://github.com/ruby/rdoc/issues/1744: @@ -144,12 +145,7 @@ static VALUE rdxr_definition_name(VALUE self) { void *graph = rdxi_graph_from_handle(self, &data); const char *name = rdx_definition_name(graph, data->id); - if (name == NULL) { - return Qnil; - } - VALUE str = rb_utf8_str_new_cstr(name); - free_c_string(name); - return str; + return rdxi_owned_c_string_to_ruby(name); } /* diff --git a/ext/rubydex/document.c b/ext/rubydex/document.c index 78b7ab47f..8a7e5c937 100644 --- a/ext/rubydex/document.c +++ b/ext/rubydex/document.c @@ -23,14 +23,7 @@ static VALUE rdxr_document_uri(VALUE self) { void *graph = rdxi_graph_from_handle(self, &data); const char *uri = rdx_document_uri(graph, data->id); - if (uri == NULL) { - return Qnil; - } - - VALUE str = rb_utf8_str_new_cstr(uri); - free_c_string(uri); - - return str; + return rdxi_owned_c_string_to_ruby(uri); } // Body function for rb_ensure in Document#definitions diff --git a/ext/rubydex/graph.c b/ext/rubydex/graph.c index 4eb79eae8..96174f5bf 100644 --- a/ext/rubydex/graph.c +++ b/ext/rubydex/graph.c @@ -843,8 +843,7 @@ static VALUE rdxr_graph_workspace_path(VALUE self) { rb_raise(rb_eRuntimeError, "Converting workspace path to Ruby string failed"); } - VALUE path = rb_utf8_str_new_cstr(result); - free_c_string(result); + VALUE path = rdxi_owned_c_string_to_ruby(result); return path; } diff --git a/ext/rubydex/reference.c b/ext/rubydex/reference.c index 825f12697..8d7e6c67c 100644 --- a/ext/rubydex/reference.c +++ b/ext/rubydex/reference.c @@ -4,6 +4,7 @@ #include "handle.h" #include "location.h" #include "rustbindings.h" +#include "utils.h" /* * RDoc parser workaround for https://github.com/ruby/rdoc/issues/1744: @@ -27,13 +28,7 @@ static VALUE rdxr_constant_reference_name(VALUE self) { void *graph = rdxi_graph_from_handle(self, &data); const char *name = rdx_constant_reference_name(graph, data->id); - if (name == NULL) { - return Qnil; - } - - VALUE str = rb_utf8_str_new_cstr(name); - free_c_string(name); - return str; + return rdxi_owned_c_string_to_ruby(name); } /* @@ -63,13 +58,7 @@ static VALUE rdxr_method_reference_name(VALUE self) { void *graph = rdxi_graph_from_handle(self, &data); const char *name = rdx_method_reference_name(graph, data->id); - if (name == NULL) { - return Qnil; - } - - VALUE str = rb_utf8_str_new_cstr(name); - free_c_string(name); - return str; + return rdxi_owned_c_string_to_ruby(name); } /* diff --git a/ext/rubydex/utils.c b/ext/rubydex/utils.c index 5860a8dd4..bf046e865 100644 --- a/ext/rubydex/utils.c +++ b/ext/rubydex/utils.c @@ -39,6 +39,19 @@ void rdxi_check_array_of_strings(VALUE array) { } } +// Convert a Rust-owned C string to a Ruby string and release it with free_c_string. +// Returns nil when the Rust side returned NULL. +VALUE rdxi_owned_c_string_to_ruby(const char *string) { + if (string == NULL) { + return Qnil; + } + + VALUE value = rb_utf8_str_new_cstr(string); + free_c_string(string); + + return value; +} + // Yield body for iterating over declarations VALUE rdxi_declarations_yield(VALUE args) { VALUE self = rb_ary_entry(args, 0); diff --git a/ext/rubydex/utils.h b/ext/rubydex/utils.h index 627ce4778..9a72646ce 100644 --- a/ext/rubydex/utils.h +++ b/ext/rubydex/utils.h @@ -13,6 +13,10 @@ void rdxi_free_str_array(char **array, size_t length); // Verify that the Ruby object is an array of strings or raise `TypeError` void rdxi_check_array_of_strings(VALUE array); +// Convert a Rust-owned C string to a Ruby string and release it with free_c_string. +// Returns nil when the Rust side returned NULL. +VALUE rdxi_owned_c_string_to_ruby(const char *string); + // Yield body for iterating over declarations VALUE rdxi_declarations_yield(VALUE args);