Skip to content

Commit a5df24f

Browse files
committed
Define a debug method Kernel#dump_classext only when RUBY_DEBUG is set
1 parent bb21b61 commit a5df24f

File tree

1 file changed

+139
-0
lines changed

1 file changed

+139
-0
lines changed

namespace.c

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,140 @@ Init_enable_namespace(void)
950950
}
951951
}
952952

953+
#ifdef RUBY_DEBUG
954+
955+
static const char *
956+
classname(VALUE klass)
957+
{
958+
VALUE p = RCLASS_CLASSPATH(klass);
959+
if (RTEST(p))
960+
return RSTRING_PTR(p);
961+
if (RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_MODULE) || RB_TYPE_P(klass, T_ICLASS))
962+
return RSTRING_PTR(rb_inspect(klass));
963+
return "NonClassValue";
964+
}
965+
966+
static enum rb_id_table_iterator_result
967+
dump_classext_methods_i(ID mid, VALUE _val, void *data)
968+
{
969+
VALUE ary = (VALUE)data;
970+
rb_ary_push(ary, rb_id2str(mid));
971+
return ID_TABLE_CONTINUE;
972+
}
973+
974+
static enum rb_id_table_iterator_result
975+
dump_classext_constants_i(ID mid, VALUE _val, void *data)
976+
{
977+
VALUE ary = (VALUE)data;
978+
rb_ary_push(ary, rb_id2str(mid));
979+
return ID_TABLE_CONTINUE;
980+
}
981+
982+
static void
983+
dump_classext_i(rb_classext_t *ext, bool is_prime, VALUE _ns, void *data)
984+
{
985+
char buf[4096];
986+
struct rb_id_table *tbl;
987+
VALUE ary, res = (VALUE)data;
988+
989+
snprintf(buf, 4096, "Namespace %ld:%s classext %p\n",
990+
RCLASSEXT_NS(ext)->ns_id, is_prime ? " prime" : "", (void *)ext);
991+
rb_str_cat_cstr(res, buf);
992+
993+
snprintf(buf, 2048, " Super: %s\n", classname(RCLASSEXT_SUPER(ext)));
994+
rb_str_cat_cstr(res, buf);
995+
996+
tbl = RCLASSEXT_M_TBL(ext);
997+
if (tbl) {
998+
ary = rb_ary_new_capa((long)rb_id_table_size(tbl));
999+
rb_id_table_foreach(RCLASSEXT_M_TBL(ext), dump_classext_methods_i, (void *)ary);
1000+
rb_ary_sort_bang(ary);
1001+
snprintf(buf, 4096, " Methods(%ld): ", RARRAY_LEN(ary));
1002+
rb_str_cat_cstr(res, buf);
1003+
rb_str_concat(res, rb_ary_join(ary, rb_str_new_cstr(",")));
1004+
rb_str_cat_cstr(res, "\n");
1005+
}
1006+
else {
1007+
rb_str_cat_cstr(res, " Methods(0): .\n");
1008+
}
1009+
1010+
tbl = RCLASSEXT_CONST_TBL(ext);
1011+
if (tbl) {
1012+
ary = rb_ary_new_capa((long)rb_id_table_size(tbl));
1013+
rb_id_table_foreach(tbl, dump_classext_constants_i, (void *)ary);
1014+
rb_ary_sort_bang(ary);
1015+
snprintf(buf, 4096, " Constants(%ld): ", RARRAY_LEN(ary));
1016+
rb_str_cat_cstr(res, buf);
1017+
rb_str_concat(res, rb_ary_join(ary, rb_str_new_cstr(",")));
1018+
rb_str_cat_cstr(res, "\n");
1019+
}
1020+
else {
1021+
rb_str_cat_cstr(res, " Constants(0): .\n");
1022+
}
1023+
}
1024+
1025+
static VALUE
1026+
rb_f_dump_classext(VALUE recv, VALUE klass)
1027+
{
1028+
/*
1029+
* The desired output String value is:
1030+
* Class: 0x88800932 (String) [singleton]
1031+
* Prime classext namespace(2,main), readable(t), writable(f)
1032+
* Non-prime classexts: 3
1033+
* Namespace 2: prime classext 0x88800933
1034+
* Super: Object
1035+
* Methods(43): aaaaa, bbbb, cccc, dddd, eeeee, ffff, gggg, hhhhh, ...
1036+
* Constants(12): FOO, Bar, ...
1037+
* Namespace 5: classext 0x88800934
1038+
* Super: Object
1039+
* Methods(43): aaaaa, bbbb, cccc, dddd, eeeee, ffff, gggg, hhhhh, ...
1040+
* Constants(12): FOO, Bar, ...
1041+
*/
1042+
char buf[2048];
1043+
VALUE res;
1044+
const rb_classext_t *ext;
1045+
const rb_namespace_t *ns;
1046+
st_table *classext_tbl;
1047+
1048+
if (!(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_MODULE))) {
1049+
snprintf(buf, 2048, "Non-class/module value: %p (%s)\n", (void *)klass, rb_type_str(BUILTIN_TYPE(klass)));
1050+
return rb_str_new_cstr(buf);
1051+
}
1052+
1053+
if (RB_TYPE_P(klass, T_CLASS)) {
1054+
snprintf(buf, 2048, "Class: %p (%s)%s\n",
1055+
(void *)klass, classname(klass), RCLASS_SINGLETON_P(klass) ? " [singleton]" : "");
1056+
}
1057+
else {
1058+
snprintf(buf, 2048, "Module: %p (%s)\n", (void *)klass, classname(klass));
1059+
}
1060+
res = rb_str_new_cstr(buf);
1061+
1062+
ext = RCLASS_EXT_PRIME(klass);
1063+
ns = RCLASSEXT_NS(ext);
1064+
snprintf(buf, 2048, "Prime classext namespace(%ld,%s), readable(%s), writable(%s)\n",
1065+
ns->ns_id,
1066+
NAMESPACE_ROOT_P(ns) ? "root" : (NAMESPACE_MAIN_P(ns) ? "main" : "optional"),
1067+
RCLASS_PRIME_CLASSEXT_READABLE_P(klass) ? "t" : "f",
1068+
RCLASS_PRIME_CLASSEXT_WRITABLE_P(klass) ? "t" : "f");
1069+
rb_str_cat_cstr(res, buf);
1070+
1071+
classext_tbl = RCLASS_CLASSEXT_TBL(klass);
1072+
if (!classext_tbl) {
1073+
rb_str_cat_cstr(res, "Non-prime classexts: 0\n");
1074+
}
1075+
else {
1076+
snprintf(buf, 2048, "Non-prime classexts: %zu\n", st_table_size(classext_tbl));
1077+
rb_str_cat_cstr(res, buf);
1078+
}
1079+
1080+
rb_class_classext_foreach(klass, dump_classext_i, (void *)res);
1081+
1082+
return res;
1083+
}
1084+
1085+
#endif /* RUBY_DEBUG */
1086+
9531087
/*
9541088
* Document-class: Namespace
9551089
*
@@ -977,8 +1111,13 @@ Init_Namespace(void)
9771111
namespace_define_loader_method("require");
9781112
namespace_define_loader_method("require_relative");
9791113
namespace_define_loader_method("load");
1114+
9801115
if (rb_namespace_available()) {
9811116
rb_include_module(rb_cObject, rb_mNamespaceLoader);
1117+
1118+
#ifdef RUBY_DEBUG
1119+
rb_define_global_function("dump_classext", rb_f_dump_classext, 1);
1120+
#endif
9821121
}
9831122

9841123
rb_define_singleton_method(rb_cNamespace, "enabled?", rb_namespace_s_getenabled, 0);

0 commit comments

Comments
 (0)