Skip to content

Commit 2ed7fac

Browse files
committed
Change PrismRuby not to depend on hack that stores module nesting information to context.parent
All constant/module/class paths are resolved by PrismRuby parser itself. Resolves include/extend module name before adding it because `Context#parent` will not have an information for delayed full-path name resolve.
1 parent c2c0a01 commit 2ed7fac

File tree

5 files changed

+37
-22
lines changed

5 files changed

+37
-22
lines changed

lib/rdoc/code_object/context.rb

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,8 @@ def find_constant_named(name)
785785
end
786786

787787
##
788-
# Find a module at a higher scope
788+
# Tries to find a module at a higher scope.
789+
# But parent is not always a higher module nesting scope, so the result is not correct.
789790

790791
def find_enclosing_module_named(name)
791792
parent && parent.find_module_named(name)
@@ -860,15 +861,23 @@ def find_method_named(name)
860861
end
861862

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

865867
def find_module_named(name)
866-
res = @modules[name] || @classes[name]
868+
res = get_module_named(name)
867869
return res if res
868870
return self if self.name == name
869871
find_enclosing_module_named name
870872
end
871873

874+
# Get a module named +name+ in this context
875+
# Don't look up for higher module nesting scopes. RDoc::Context doesn't have that information.
876+
877+
def get_module_named(name)
878+
@modules[name] || @classes[name]
879+
end
880+
872881
##
873882
# Look up +symbol+, first as a module, then as a local symbol.
874883

lib/rdoc/code_object/mixin.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ def inspect # :nodoc:
7171
# lookup behavior.
7272
#
7373
# As of the beginning of October, 2011, no gem includes nonexistent modules.
74+
#
75+
# When mixin is created from RDoc::Parser::PrismRuby, module name is already a resolved full-path name.
76+
#
7477

7578
def module
7679
return @module if @module

lib/rdoc/code_object/top_level.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ def find_module_named(name)
149149
find_class_or_module(name)
150150
end
151151

152+
alias get_module_named find_module_named
153+
152154
##
153155
# Returns the relative name of this file
154156

lib/rdoc/parser/prism_ruby.rb

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,6 @@ def with_container(container, singleton: false)
5959
@container = container
6060
@singleton = singleton
6161
@in_proc_block = false
62-
unless singleton
63-
# Need to update module parent chain to emulate Module.nesting.
64-
# This mechanism is inaccurate and needs to be fixed.
65-
container.parent = old_container
66-
end
6762
@module_nesting.push([container, singleton])
6863
yield container
6964
ensure
@@ -482,12 +477,15 @@ def add_attributes(names, rw, line_no)
482477
end
483478
end
484479

480+
# Adds includes/extends. Module name is resolved to full before adding.
481+
485482
def add_includes_extends(names, rdoc_class, line_no) # :nodoc:
486483
return if @in_proc_block
487484
comment, directives = consecutive_comment(line_no)
488485
handle_code_object_directives(@container, directives) if directives
489486
names.each do |name|
490-
ie = @container.add(rdoc_class, name, '')
487+
resolved_name = resolve_constant_path(name)
488+
ie = @container.add(rdoc_class, resolved_name || name, '')
491489
ie.store = @store
492490
ie.line = line_no
493491
ie.comment = comment
@@ -590,7 +588,7 @@ def find_or_create_module_path(module_name, create_mode)
590588
else
591589
@module_nesting.reverse_each do |nesting, singleton|
592590
next if singleton
593-
mod = nesting.find_module_named(root_name)
591+
mod = nesting.get_module_named(root_name)
594592
break if mod
595593
# If a constant is found and it is not a module or class, RDoc can't document about it.
596594
# Return an anonymous module to avoid wrong document creation.
@@ -601,9 +599,9 @@ def find_or_create_module_path(module_name, create_mode)
601599
mod ||= add_module.call(last_nesting, root_name, :module)
602600
end
603601
path.each do |name|
604-
mod = mod.find_module_named(name) || add_module.call(mod, name, :module)
602+
mod = mod.get_module_named(name) || add_module.call(mod, name, :module)
605603
end
606-
mod.find_module_named(name) || add_module.call(mod, name, create_mode)
604+
mod.get_module_named(name) || add_module.call(mod, name, create_mode)
607605
end
608606

609607
# Resolves constant path to a full path by searching module nesting
@@ -614,10 +612,10 @@ def resolve_constant_path(constant_path)
614612
mod = nil
615613
@module_nesting.reverse_each do |nesting, singleton|
616614
next if singleton
617-
mod = nesting.find_module_named(owner_name)
615+
mod = nesting.get_module_named(owner_name)
618616
break if mod
619617
end
620-
mod ||= @top_level.find_module_named(owner_name)
618+
mod ||= @top_level.get_module_named(owner_name)
621619
[mod.full_name, path].compact.join('::') if mod
622620
end
623621

@@ -657,7 +655,8 @@ def add_constant(constant_name, rhs_name, start_line, end_line)
657655
if rhs_name =~ /^::/
658656
@store.find_class_or_module(rhs_name)
659657
else
660-
@container.find_module_named(rhs_name)
658+
full_name = resolve_constant_path(rhs_name)
659+
@store.find_class_or_module(full_name)
661660
end
662661
if mod && constant.document_self
663662
a = @container.add_module_alias(mod, rhs_name, constant, @top_level)

test/rdoc/parser/prism_ruby_test.rb

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,6 +1746,7 @@ class << self
17461746
end
17471747

17481748
def test_include_with_module_nesting
1749+
omit 'not implemented' if accept_legacy_bug?
17491750
util_parser <<~RUBY
17501751
module A
17511752
module M; end
@@ -1765,15 +1766,16 @@ class C::D::Foo
17651766
include M
17661767
end
17671768
end
1768-
# TODO: make test pass with the following code appended
1769-
# module A::B::C
1770-
# class D::Foo
1771-
# include M
1772-
# end
1773-
# end
1769+
1770+
module A::B::C
1771+
class D::Foo
1772+
include M
1773+
end
1774+
end
17741775
RUBY
17751776
klass = @store.find_class_named 'A::B::C::D::Foo'
1776-
assert_equal 'A::B::M', klass.includes.first.module.full_name
1777+
assert_equal 'A::B::M', klass.includes[0].module.full_name
1778+
assert_equal 'A::B::C::M', klass.includes[1].module.full_name
17771779
end
17781780

17791781
def test_various_argument_include

0 commit comments

Comments
 (0)