@@ -31,7 +31,7 @@ def initialize(top_level, content, options, stats)
3131 @track_visibility = :nodoc != @options . visibility
3232 @encoding = @options . encoding
3333
34- @module_nesting = [ top_level ]
34+ @module_nesting = [ [ top_level , false ] ]
3535 @container = top_level
3636 @visibility = :public
3737 @singleton = false
@@ -60,19 +60,18 @@ def with_container(container, singleton: false)
6060 @singleton = singleton
6161 @include_extend_suppressed = false
6262 unless singleton
63- @module_nesting . push container
64-
6563 # Need to update module parent chain to emulate Module.nesting.
6664 # This mechanism is inaccurate and needs to be fixed.
6765 container . parent = old_container
6866 end
67+ @module_nesting . push ( [ container , singleton ] )
6968 yield container
7069 ensure
7170 @container = old_container
7271 @visibility = old_visibility
7372 @singleton = old_singleton
7473 @include_extend_suppressed = old_include_extend_suppressed
75- @module_nesting . pop unless singleton
74+ @module_nesting . pop
7675 end
7776
7877 # Records the location of this +container+ in the file for this parser and
@@ -584,15 +583,17 @@ def find_or_create_module_path(module_name, create_mode)
584583 if root_name . empty?
585584 mod = @top_level
586585 else
587- @module_nesting . reverse_each do |nesting |
586+ @module_nesting . reverse_each do |nesting , singleton |
587+ next if singleton
588588 mod = nesting . find_module_named ( root_name )
589589 break if mod
590590 # If a constant is found and it is not a module or class, RDoc can't document about it.
591591 # Return an anonymous module to avoid wrong document creation.
592592 return RDoc ::NormalModule . new ( nil ) if nesting . find_constant_named ( root_name )
593593 end
594- return mod || add_module . call ( @module_nesting . last , root_name , create_mode ) unless name
595- mod ||= add_module . call ( @module_nesting . last , root_name , :module )
594+ last_nesting , = @module_nesting . reverse_each . find { |_ , singleton | !singleton }
595+ return mod || add_module . call ( last_nesting , root_name , create_mode ) unless name
596+ mod ||= add_module . call ( last_nesting , root_name , :module )
596597 end
597598 path . each do |name |
598599 mod = mod . find_module_named ( name ) || add_module . call ( mod , name , :module )
@@ -606,7 +607,8 @@ def resolve_constant_path(constant_path)
606607 owner_name , path = constant_path . split ( '::' , 2 )
607608 return constant_path if owner_name . empty? # ::Foo, ::Foo::Bar
608609 mod = nil
609- @module_nesting . reverse_each do |nesting |
610+ @module_nesting . reverse_each do |nesting , singleton |
611+ next if singleton
610612 mod = nesting . find_module_named ( owner_name )
611613 break if mod
612614 end
@@ -620,7 +622,10 @@ def resolve_constant_path(constant_path)
620622 def find_or_create_constant_owner_name ( constant_path )
621623 const_path , colon , name = constant_path . rpartition ( '::' )
622624 if colon . empty? # class Foo
623- [ @container , name ]
625+ # Within `class C` or `module C`, owner is C(== current container)
626+ # Within `class <<C`, owner is C.singleton_class
627+ # but RDoc don't track constants of a singleton class of module
628+ [ ( @singleton ? nil : @container ) , name ]
624629 elsif const_path . empty? # class ::Foo
625630 [ @top_level , name ]
626631 else # `class Foo::Bar` or `class ::Foo::Bar`
@@ -634,6 +639,8 @@ def add_constant(constant_name, rhs_name, start_line, end_line)
634639 comment = consecutive_comment ( start_line )
635640 handle_consecutive_comment_directive ( @container , comment )
636641 owner , name = find_or_create_constant_owner_name ( constant_name )
642+ return unless owner
643+
637644 constant = RDoc ::Constant . new ( name , rhs_name , comment )
638645 constant . store = @store
639646 constant . line = start_line
@@ -663,6 +670,8 @@ def add_module_or_class(module_name, start_line, end_line, is_class: false, supe
663670 return unless @container . document_children
664671
665672 owner , name = find_or_create_constant_owner_name ( module_name )
673+ return unless owner
674+
666675 if is_class
667676 # RDoc::NormalClass resolves superclass name despite of the lack of module nesting information.
668677 # We need to fix it when RDoc::NormalClass resolved to a wrong constant name
@@ -774,12 +783,13 @@ def visit_alias_method_node(node)
774783 end
775784
776785 def visit_module_node ( node )
786+ node . constant_path . accept ( self )
777787 @scanner . process_comments_until ( node . location . start_line - 1 )
778788 module_name = constant_path_string ( node . constant_path )
779789 mod = @scanner . add_module_or_class ( module_name , node . location . start_line , node . location . end_line ) if module_name
780790 if mod
781791 @scanner . with_container ( mod ) do
782- super
792+ node . body &. accept ( self )
783793 @scanner . process_comments_until ( node . location . end_line )
784794 end
785795 else
@@ -788,14 +798,16 @@ def visit_module_node(node)
788798 end
789799
790800 def visit_class_node ( node )
801+ node . constant_path . accept ( self )
802+ node . superclass &.accept ( self )
791803 @scanner . process_comments_until ( node . location . start_line - 1 )
792804 superclass_name = constant_path_string ( node . superclass ) if node . superclass
793805 superclass_expr = node . superclass . slice if node . superclass && !superclass_name
794806 class_name = constant_path_string ( node . constant_path )
795807 klass = @scanner . add_module_or_class ( class_name , node . location . start_line , node . location . end_line , is_class : true , superclass_name : superclass_name , superclass_expr : superclass_expr ) if class_name
796808 if klass
797809 @scanner . with_container ( klass ) do
798- super
810+ node . body &. accept ( self )
799811 @scanner . process_comments_until ( node . location . end_line )
800812 end
801813 else
@@ -826,9 +838,10 @@ def visit_singleton_class_node(node)
826838 when Prism ::SelfNode
827839 mod = @scanner . container if @scanner . container != @top_level
828840 end
841+ expression . accept ( self )
829842 if mod
830843 @scanner . with_container ( mod , singleton : true ) do
831- super
844+ node . body &. accept ( self )
832845 @scanner . process_comments_until ( node . location . end_line )
833846 end
834847 else
0 commit comments