From b48030b26a6670ef17c205aa9ba2997dd23dc7a4 Mon Sep 17 00:00:00 2001 From: Amauri Bizerra <10775696+extern-c@users.noreply.github.com> Date: Fri, 2 Jan 2026 16:14:31 +0000 Subject: [PATCH 1/4] Fix constant lookup in contexts --- lib/rdoc/code_object/context.rb | 5 ++--- test/rdoc/rdoc_context_test.rb | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/rdoc/code_object/context.rb b/lib/rdoc/code_object/context.rb index 3a4dd0ec68..d7c8bbd91b 100644 --- a/lib/rdoc/code_object/context.rb +++ b/lib/rdoc/code_object/context.rb @@ -779,9 +779,8 @@ def find_class_method_named(name) # Finds a constant with +name+ in this context def find_constant_named(name) - @constants.find do |m| - m.name == name || m.full_name == name - end + name = name[2..-1] if name&.start_with?('::') + @constants.find { |m| m.name == name || m.full_name == name } end ## diff --git a/test/rdoc/rdoc_context_test.rb b/test/rdoc/rdoc_context_test.rb index a6ad176218..4e2ab58081 100644 --- a/test/rdoc/rdoc_context_test.rb +++ b/test/rdoc/rdoc_context_test.rb @@ -524,6 +524,7 @@ def test_find_class_method_named def test_find_constant_named assert_nil @c1.find_constant_named('NONE') assert_equal ':const', @c1.find_constant_named('CONST').value + assert_equal ':const', @c1.find_constant_named('::CONST').value end def test_find_enclosing_module_named From 2e0782112723607096636965a19b3e63bb41c317 Mon Sep 17 00:00:00 2001 From: Amauri Bizerra <10775696+extern-c@users.noreply.github.com> Date: Tue, 6 Jan 2026 12:34:39 +0000 Subject: [PATCH 2/4] Rename resolve_method to resolve_local_symbol --- lib/rdoc/cross_reference.rb | 38 +++++++++++++++----------- test/rdoc/rdoc_cross_reference_test.rb | 8 +++--- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/lib/rdoc/cross_reference.rb b/lib/rdoc/cross_reference.rb index 1f33538b73..6c80dc0371 100644 --- a/lib/rdoc/cross_reference.rb +++ b/lib/rdoc/cross_reference.rb @@ -132,25 +132,31 @@ def initialize(context) end ## - # Returns a method reference to +name+. + # Returns a method, attribute or constant reference to +name+ + # if it exists in the containing context object. It returns + # nil otherwise. + # + # For example, this method would decompose name = 'A::CONSTANT' into a + # container object A and a symbol object ::CONSTANT, and it would try + # to find ::CONSTANT in A. - def resolve_method(name) + def resolve_local_symbol(name) ref = nil if /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then type = $2 if '.' == type # will find either #method or ::method - method = $3 + symbol = $3 else - method = "#{type}#{$3}" + symbol = "#{type}#{$3}" end container = @context.find_symbol_module($1) elsif /^([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then type = $1 if '.' == type - method = $2 + symbol = $2 else - method = "#{type}#{$2}" + symbol = "#{type}#{$2}" end container = @context else @@ -161,18 +167,18 @@ def resolve_method(name) if container then unless RDoc::TopLevel === container then if '.' == type then - if 'new' == method then # AnyClassName.new will be class method - ref = container.find_local_symbol method - ref = container.find_ancestor_local_symbol method unless ref + if 'new' == symbol then # AnyClassName.new will be class method + ref = container.find_local_symbol symbol + ref = container.find_ancestor_local_symbol symbol unless ref else - ref = container.find_local_symbol "::#{method}" - ref = container.find_ancestor_local_symbol "::#{method}" unless ref - ref = container.find_local_symbol "##{method}" unless ref - ref = container.find_ancestor_local_symbol "##{method}" unless ref + ref = container.find_local_symbol "::#{symbol}" + ref = container.find_ancestor_local_symbol "::#{symbol}" unless ref + ref = container.find_local_symbol "##{symbol}" unless ref + ref = container.find_ancestor_local_symbol "##{symbol}" unless ref end else - ref = container.find_local_symbol method - ref = container.find_ancestor_local_symbol method unless ref + ref = container.find_local_symbol symbol + ref = container.find_ancestor_local_symbol symbol unless ref end end end @@ -197,7 +203,7 @@ def resolve(name, text) @context.find_symbol name end - ref = resolve_method name unless ref + ref = resolve_local_symbol name unless ref # Try a page name ref = @store.page name if not ref and name =~ /^[\w.\/]+$/ diff --git a/test/rdoc/rdoc_cross_reference_test.rb b/test/rdoc/rdoc_cross_reference_test.rb index e536a67a89..3a61ad6989 100644 --- a/test/rdoc/rdoc_cross_reference_test.rb +++ b/test/rdoc/rdoc_cross_reference_test.rb @@ -118,7 +118,7 @@ def test_resolve_file assert_ref @top_level, 'xref_data.rb' end - def test_resolve_method + def test_resolve_local_symbol assert_ref @c1__m, 'm' assert_ref @c1__m, '::m' assert_ref @c1_m, '#m' @@ -172,7 +172,7 @@ def test_resolve_page assert_ref page, 'README' end - def assert_resolve_method(x) + def assert_resolve_local_symbol(x) @c1.methods_hash.clear i_op = RDoc::AnyMethod.new nil, x @@ -190,8 +190,8 @@ def assert_resolve_method(x) end EXAMPLE_METHODS.each do |x| - define_method("test_resolve_method:#{x}") do - assert_resolve_method(x) + define_method("test_resolve_local_symbol:#{x}") do + assert_resolve_local_symbol(x) end end From 20b3cd18247333648d4cd2180fc5e368285bd496 Mon Sep 17 00:00:00 2001 From: Amauri Bizerra <10775696+extern-c@users.noreply.github.com> Date: Wed, 7 Jan 2026 12:23:01 +0000 Subject: [PATCH 3/4] Move resolution of fully qualified constants to resolve_local_symbol --- lib/rdoc/code_object/context.rb | 1 - lib/rdoc/cross_reference.rb | 17 ++++++++++------- test/rdoc/rdoc_context_test.rb | 1 - test/rdoc/rdoc_cross_reference_test.rb | 14 ++++++++++---- test/rdoc/rdoc_store_test.rb | 4 ++-- test/rdoc/xref_data.rb | 3 +++ test/rdoc/xref_test_case.rb | 1 + 7 files changed, 26 insertions(+), 15 deletions(-) diff --git a/lib/rdoc/code_object/context.rb b/lib/rdoc/code_object/context.rb index d7c8bbd91b..cdee0486b5 100644 --- a/lib/rdoc/code_object/context.rb +++ b/lib/rdoc/code_object/context.rb @@ -779,7 +779,6 @@ def find_class_method_named(name) # Finds a constant with +name+ in this context def find_constant_named(name) - name = name[2..-1] if name&.start_with?('::') @constants.find { |m| m.name == name || m.full_name == name } end diff --git a/lib/rdoc/cross_reference.rb b/lib/rdoc/cross_reference.rb index 6c80dc0371..3dcf9b0ea7 100644 --- a/lib/rdoc/cross_reference.rb +++ b/lib/rdoc/cross_reference.rb @@ -137,13 +137,19 @@ def initialize(context) # nil otherwise. # # For example, this method would decompose name = 'A::CONSTANT' into a - # container object A and a symbol object ::CONSTANT, and it would try - # to find ::CONSTANT in A. + # container object A and a symbol 'CONSTANT', and it would try to find + # 'CONSTANT' in A. def resolve_local_symbol(name) ref = nil + type = nil + container = nil - if /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then + case name + when /#{CLASS_REGEXP_STR}::([A-Z]\w*)\z/o then + symbol = $2 + container = @context.find_symbol_module($1) + when /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/o then type = $2 if '.' == type # will find either #method or ::method symbol = $3 @@ -151,7 +157,7 @@ def resolve_local_symbol(name) symbol = "#{type}#{$3}" end container = @context.find_symbol_module($1) - elsif /^([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then + when /^([.#]|::)#{METHOD_REGEXP_STR}/o then type = $1 if '.' == type symbol = $2 @@ -159,9 +165,6 @@ def resolve_local_symbol(name) symbol = "#{type}#{$2}" end container = @context - else - type = nil - container = nil end if container then diff --git a/test/rdoc/rdoc_context_test.rb b/test/rdoc/rdoc_context_test.rb index 4e2ab58081..a6ad176218 100644 --- a/test/rdoc/rdoc_context_test.rb +++ b/test/rdoc/rdoc_context_test.rb @@ -524,7 +524,6 @@ def test_find_class_method_named def test_find_constant_named assert_nil @c1.find_constant_named('NONE') assert_equal ':const', @c1.find_constant_named('CONST').value - assert_equal ':const', @c1.find_constant_named('::CONST').value end def test_find_enclosing_module_named diff --git a/test/rdoc/rdoc_cross_reference_test.rb b/test/rdoc/rdoc_cross_reference_test.rb index 3a61ad6989..ebb70bb564 100644 --- a/test/rdoc/rdoc_cross_reference_test.rb +++ b/test/rdoc/rdoc_cross_reference_test.rb @@ -118,7 +118,7 @@ def test_resolve_file assert_ref @top_level, 'xref_data.rb' end - def test_resolve_local_symbol + def test_resolve_method assert_ref @c1__m, 'm' assert_ref @c1__m, '::m' assert_ref @c1_m, '#m' @@ -157,6 +157,12 @@ def test_resolve_local_symbol assert_ref @c2_c3_m, '::C2::C3#m(*)' end + def test_resolve_constant + assert_ref @c1_const, 'CONST' + assert_ref @c1_const, 'C1::CONST' + assert_ref @c1_const, 'C12::CONST' + end + def test_resolve_the_same_name_in_instance_and_class_method assert_ref @c9_a_i_foo, 'C9::A#foo' assert_ref @c9_a_c_bar, 'C9::A::bar' @@ -172,7 +178,7 @@ def test_resolve_page assert_ref page, 'README' end - def assert_resolve_local_symbol(x) + def assert_resolve_method(x) @c1.methods_hash.clear i_op = RDoc::AnyMethod.new nil, x @@ -190,8 +196,8 @@ def assert_resolve_local_symbol(x) end EXAMPLE_METHODS.each do |x| - define_method("test_resolve_local_symbol:#{x}") do - assert_resolve_local_symbol(x) + define_method("test_resolve_method:#{x}") do + assert_resolve_method(x) end end diff --git a/test/rdoc/rdoc_store_test.rb b/test/rdoc/rdoc_store_test.rb index 7bd1d48902..51708c8e9b 100644 --- a/test/rdoc/rdoc_store_test.rb +++ b/test/rdoc/rdoc_store_test.rb @@ -163,7 +163,7 @@ def test_add_file_relative def test_all_classes_and_modules expected = %w[ - C1 C10 C10::C11 C11 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 C6 C7 C8 C9 C9::A C9::B + C1 C10 C10::C11 C11 C12 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 C6 C7 C8 C9 C9::A C9::B Child M1 M1::M2 Object @@ -219,7 +219,7 @@ def test_class_path def test_classes expected = %w[ - C1 C10 C10::C11 C11 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 C6 C7 C8 C9 C9::A C9::B + C1 C10 C10::C11 C11 C12 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 C6 C7 C8 C9 C9::A C9::B Child Object Parent diff --git a/test/rdoc/xref_data.rb b/test/rdoc/xref_data.rb index acfc0ce3ff..616b0eba81 100644 --- a/test/rdoc/xref_data.rb +++ b/test/rdoc/xref_data.rb @@ -145,6 +145,9 @@ class C11 def C11 end +class C12 < C1 +end + module M1 def m end diff --git a/test/rdoc/xref_test_case.rb b/test/rdoc/xref_test_case.rb index 4c3e3166b2..1c7a8804e4 100644 --- a/test/rdoc/xref_test_case.rb +++ b/test/rdoc/xref_test_case.rb @@ -33,6 +33,7 @@ def setup @c1__m = @c1.find_class_method_named 'm' # C1::m @c1_m = @c1.find_instance_method_named 'm' # C1#m @c1_plus = @c1.find_instance_method_named '+' + @c1_const = @c1.find_constant_named 'CONST' @c2 = @xref_data.find_module_named 'C2' @c2_a = @c2.method_list.last From f2bfdddaca444bfddb6718d5cf7d798562865182 Mon Sep 17 00:00:00 2001 From: Amauri Bizerra <10775696+extern-c@users.noreply.github.com> Date: Sat, 10 Jan 2026 03:19:11 +0000 Subject: [PATCH 4/4] Revert unnecessary coding style change in find_constant_named --- lib/rdoc/code_object/context.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/rdoc/code_object/context.rb b/lib/rdoc/code_object/context.rb index cdee0486b5..3a4dd0ec68 100644 --- a/lib/rdoc/code_object/context.rb +++ b/lib/rdoc/code_object/context.rb @@ -779,7 +779,9 @@ def find_class_method_named(name) # Finds a constant with +name+ in this context def find_constant_named(name) - @constants.find { |m| m.name == name || m.full_name == name } + @constants.find do |m| + m.name == name || m.full_name == name + end end ##