Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions lib/rdoc/code_object/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

##
Expand Down
38 changes: 22 additions & 16 deletions lib/rdoc/cross_reference.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about checking for constant after this line?

ref = container.find_constant_named(symbol[2..]) if !ref && type == '::'

Treating ::NAME as local constant is really misleading because normally ::NAME means top level constant in Ruby, and :: is just a separator to be removed.

For background, current codebase of RDoc is hard to maintain. Removing complexity, fixing misleading code and refactoring is in a highest priority for me as a maintainer of RDoc.
So changing find_constant_named to ignore preceding :: is not acceptable.

Adding an explicit constant-name regexp extraction is also a good idea.

if /#{CLASS_REGEXP_STR}::([A-Z]\w*)\z/o =~ name then
  type = 'const'
  container = @context.find_symbol_module($1)
  symbol = $2
elsif ...

end
end
end
Expand All @@ -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.\/]+$/
Expand Down
1 change: 1 addition & 0 deletions test/rdoc/rdoc_context_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions test/rdoc/rdoc_cross_reference_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down Expand Up @@ -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
Expand All @@ -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

Expand Down
Loading