Skip to content
Merged
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
17 changes: 14 additions & 3 deletions lib/rdoc/code_object/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,10 @@ def find_constant_named(name)
end

##
# Find a module at a higher scope
# Tries to find a module at a higher scope.
# But parent is not always a higher module nesting scope, so the result is not correct.
# Parent chain can only represent last-opened nesting, and may be broken in some cases.
# PrismRuby parser stopped representing module nesting with parent chain at all.

def find_enclosing_module_named(name)
parent && parent.find_module_named(name)
Expand Down Expand Up @@ -860,15 +863,23 @@ def find_method_named(name)
end

##
# Find a module with +name+ using ruby's scoping rules
# Find a module with +name+ trying to using ruby's scoping rules.
# find_enclosing_module_named cannot use ruby's scoping so the result is not correct.

def find_module_named(name)
res = @modules[name] || @classes[name]
res = get_module_named(name)
return res if res
return self if self.name == name
find_enclosing_module_named name
end

# Get a module named +name+ in this context
# Don't look up for higher module nesting scopes. RDoc::Context doesn't have that information.

def get_module_named(name)
@modules[name] || @classes[name]
end

##
# Look up +symbol+, first as a module, then as a local symbol.

Expand Down
3 changes: 3 additions & 0 deletions lib/rdoc/code_object/mixin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ def inspect # :nodoc:
# lookup behavior.
#
# As of the beginning of October, 2011, no gem includes nonexistent modules.
#
# When mixin is created from RDoc::Parser::PrismRuby, module name is already a resolved full-path name.
#

def module
return @module if @module
Expand Down
2 changes: 2 additions & 0 deletions lib/rdoc/code_object/top_level.rb
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ def find_module_named(name)
find_class_or_module(name)
end

alias get_module_named find_module_named

##
# Returns the relative name of this file

Expand Down
23 changes: 11 additions & 12 deletions lib/rdoc/parser/prism_ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,6 @@ def with_container(container, singleton: false)
@container = container
@singleton = singleton
@in_proc_block = false
unless singleton
# Need to update module parent chain to emulate Module.nesting.
# This mechanism is inaccurate and needs to be fixed.
container.parent = old_container
end
@module_nesting.push([container, singleton])
yield container
ensure
Expand Down Expand Up @@ -482,12 +477,15 @@ def add_attributes(names, rw, line_no)
end
end

# Adds includes/extends. Module name is resolved to full before adding.

def add_includes_extends(names, rdoc_class, line_no) # :nodoc:
return if @in_proc_block
comment, directives = consecutive_comment(line_no)
handle_code_object_directives(@container, directives) if directives
names.each do |name|
ie = @container.add(rdoc_class, name, '')
resolved_name = resolve_constant_path(name)
ie = @container.add(rdoc_class, resolved_name || name, '')
ie.store = @store
ie.line = line_no
ie.comment = comment
Expand Down Expand Up @@ -590,7 +588,7 @@ def find_or_create_module_path(module_name, create_mode)
else
@module_nesting.reverse_each do |nesting, singleton|
next if singleton
mod = nesting.find_module_named(root_name)
mod = nesting.get_module_named(root_name)
break if mod
# If a constant is found and it is not a module or class, RDoc can't document about it.
# Return an anonymous module to avoid wrong document creation.
Expand All @@ -601,9 +599,9 @@ def find_or_create_module_path(module_name, create_mode)
mod ||= add_module.call(last_nesting, root_name, :module)
end
path.each do |name|
mod = mod.find_module_named(name) || add_module.call(mod, name, :module)
mod = mod.get_module_named(name) || add_module.call(mod, name, :module)
end
mod.find_module_named(name) || add_module.call(mod, name, create_mode)
mod.get_module_named(name) || add_module.call(mod, name, create_mode)
end

# Resolves constant path to a full path by searching module nesting
Expand All @@ -614,10 +612,10 @@ def resolve_constant_path(constant_path)
mod = nil
@module_nesting.reverse_each do |nesting, singleton|
next if singleton
mod = nesting.find_module_named(owner_name)
mod = nesting.get_module_named(owner_name)
break if mod
end
mod ||= @top_level.find_module_named(owner_name)
mod ||= @top_level.get_module_named(owner_name)
[mod.full_name, path].compact.join('::') if mod
end

Expand Down Expand Up @@ -657,7 +655,8 @@ def add_constant(constant_name, rhs_name, start_line, end_line)
if rhs_name =~ /^::/
@store.find_class_or_module(rhs_name)
else
@container.find_module_named(rhs_name)
full_name = resolve_constant_path(rhs_name)
@store.find_class_or_module(full_name)
end
if mod && constant.document_self
a = @container.add_module_alias(mod, rhs_name, constant, @top_level)
Expand Down
16 changes: 9 additions & 7 deletions test/rdoc/parser/prism_ruby_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1746,6 +1746,7 @@ class << self
end

def test_include_with_module_nesting
omit 'not implemented' if accept_legacy_bug?
util_parser <<~RUBY
module A
module M; end
Expand All @@ -1765,15 +1766,16 @@ class C::D::Foo
include M
end
end
# TODO: make test pass with the following code appended
# module A::B::C
# class D::Foo
# include M
# end
# end

module A::B::C
class D::Foo
include M
end
end
RUBY
klass = @store.find_class_named 'A::B::C::D::Foo'
assert_equal 'A::B::M', klass.includes.first.module.full_name
assert_equal 'A::B::M', klass.includes[0].module.full_name
assert_equal 'A::B::C::M', klass.includes[1].module.full_name
end

def test_various_argument_include
Expand Down
Loading