From 8013d3d9a730406bebfc0c97d08b08420253d461 Mon Sep 17 00:00:00 2001 From: Mike Dalessio Date: Thu, 28 Nov 2024 11:15:57 -0500 Subject: [PATCH] fix: C variables should never show up in Ancestors tree If a NormalClass's superclass is a C enclosure, then update the superclass to point to the RDoc::NormalClass. This is done in a single pass after all files have been parsed. Fixes #1205. --- lib/rdoc/rdoc.rb | 2 ++ lib/rdoc/store.rb | 12 ++++++++++++ test/rdoc/test_rdoc_store.rb | 20 ++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/lib/rdoc/rdoc.rb b/lib/rdoc/rdoc.rb index 88ae55b409..a910215ff6 100644 --- a/lib/rdoc/rdoc.rb +++ b/lib/rdoc/rdoc.rb @@ -415,6 +415,8 @@ def parse_files files parse_file filename end.compact + @store.resolve_c_superclasses + @stats.done_adding @options = original_options diff --git a/lib/rdoc/store.rb b/lib/rdoc/store.rb index cd27d47dd1..e85bc9d33a 100644 --- a/lib/rdoc/store.rb +++ b/lib/rdoc/store.rb @@ -197,6 +197,18 @@ def add_file absolute_name, relative_name: absolute_name, parser: nil top_level end + ## + # Make sure any references to C variable names are resolved to the corresponding class. + # + + def resolve_c_superclasses + @classes_hash.each_value do |klass| + if klass.superclass.is_a?(String) && (candidate = find_c_enclosure(klass.superclass)) + klass.superclass = candidate + end + end + end + ## # Sets the parser of +absolute_name+, unless it from a source code file. diff --git a/test/rdoc/test_rdoc_store.rb b/test/rdoc/test_rdoc_store.rb index 50e8667d81..2665f163e4 100644 --- a/test/rdoc/test_rdoc_store.rb +++ b/test/rdoc/test_rdoc_store.rb @@ -281,6 +281,26 @@ def test_find_c_enclosure_from_cache_legacy assert_nil @s.find_c_enclosure('cObject') end + def test_resolve_c_superclasses + # first parse a child that references an unknown parent + c_file1 = @s.add_file 'ext1.c' + c_file1.add_class RDoc::NormalClass, 'Child', 'cExternParent' + + # then parse the parent and register the C variable name as a C enclosure + c_file2 = @s.add_file 'ext2.c' + parent = c_file2.add_class RDoc::NormalClass, 'Parent', 'rb_cObject' + + @s.add_c_enclosure('cExternParent', parent) + + # at this point, the child's superclass is still the name of the C variable + assert_equal("cExternParent", @s.classes_hash['Child'].superclass) + + @s.resolve_c_superclasses + + # now the ancestor tree correctly references the NormalClass objects + assert_equal(parent, @s.classes_hash['Child'].superclass) + end + def test_find_class_named assert_equal @c1, @store.find_class_named('C1')