Skip to content

Commit fcb515f

Browse files
authored
Fix rb_define_method(singleton_class_of_module, ...) not to change nested module name (#1458)
Fixes #1440 Always track class and singleton class stored to a variable to `@classes`. Otherwise, `find_class var_name, class_name` called from `handle_method` will add a new class. Before: <img width="303" height="167" alt="before" src="https://github.com/user-attachments/assets/fb885b6c-40bf-44c5-8f01-095cfdc75c16" /> After: <img width="303" height="167" alt="after" src="https://github.com/user-attachments/assets/e0aae152-f46e-4954-8b68-23b74dd3bc90" /> Minimal reproduction: ```c VALUE mFoo = rb_define_module("Foo"); VALUE mBar = rb_define_module_under(mFoo, "Bar"); VALUE mBarS = rb_singleton_class(mBar); rb_define_method(mBarS, "baz", baz, 0); ``` `RDoc::Parser::C#handle_method` calls `find_class 'mBarS', 'Foo::Bar'`. `RDoc::Parser::C#find_class` calls `@top_level.add_class RDoc::NormalClass, 'Foo::Bar'`. This will create `::Bar` for some reason and `Foo::Bar` disappears from generated document.
1 parent b0e21ef commit fcb515f

File tree

2 files changed

+43
-5
lines changed

2 files changed

+43
-5
lines changed

lib/rdoc/parser/c.rb

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,10 +1052,13 @@ def handle_method(type, var_name, meth_name, function, param_count,
10521052
# Registers a singleton class +sclass_var+ as a singleton of +class_var+
10531053

10541054
def handle_singleton(sclass_var, class_var)
1055-
class_name = @known_classes[class_var]
1056-
1057-
@known_classes[sclass_var] = class_name
1058-
@singleton_classes[sclass_var] = class_name
1055+
if (klass = @classes[class_var])
1056+
@classes[sclass_var] = klass
1057+
end
1058+
if (class_name = @known_classes[class_var])
1059+
@known_classes[sclass_var] = class_name
1060+
@singleton_classes[sclass_var] = class_name
1061+
end
10591062
end
10601063

10611064
##

test/rdoc/parser/c_test.rb

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,40 @@ def test_do_methods_singleton_class
781781
assert methods.first.singleton
782782
end
783783

784+
def test_do_methods_nested_module_singleton_class
785+
parser = util_parser <<~EOF
786+
VALUE baz(VALUE klass, VALUE year) {
787+
}
788+
void Init_Foo(void) {
789+
VALUE mFoo = rb_define_module("Foo");
790+
VALUE mBar = rb_define_module_under(mFoo, "Bar");
791+
VALUE mBarS = rb_singleton_class(mBar);
792+
rb_define_method(mBarS, "baz", baz, 0);
793+
}
794+
EOF
795+
parser.scan
796+
797+
klass = parser.classes['mBarS']
798+
assert_equal 'Foo::Bar', klass.full_name
799+
assert_equal 'Foo::Bar', parser.singleton_classes['mBarS']
800+
methods = klass.method_list
801+
assert_equal 1, methods.length
802+
assert_equal 'baz', methods.first.name
803+
assert methods.first.singleton
804+
end
805+
806+
def test_do_singleton_class_undocumentable
807+
parser = util_parser <<~EOF
808+
void Func(VALUE v) {
809+
VALUE k = rb_singleton_class(v);
810+
rb_define_method(k, "baz", baz, 0);
811+
}
812+
EOF
813+
parser.scan
814+
assert_empty parser.classes
815+
assert_empty parser.singleton_classes
816+
end
817+
784818
def test_do_missing
785819
parser = util_parser
786820

@@ -1973,7 +2007,8 @@ def test_scan
19732007
expected = {
19742008
@fn => {
19752009
'mM' => 'M',
1976-
'cC' => 'C', }}
2010+
'cC' => 'C',
2011+
'sC' => 'C' }}
19772012
assert_equal expected, @store.c_class_variables
19782013

19792014
expected = {

0 commit comments

Comments
 (0)