@@ -204,6 +204,10 @@ def parse_comment_tomdoc(container, comment, line_no, start_line)
204204 @stats . add_method meth
205205 end
206206
207+ def has_modifier_nodoc? ( line_no ) # :nodoc:
208+ @modifier_comments [ line_no ] &.text &.match? ( /\A #\s *:nodoc:/ )
209+ end
210+
207211 def handle_modifier_directive ( code_object , line_no ) # :nodoc:
208212 comment = @modifier_comments [ line_no ]
209213 @preprocess . handle ( comment . text , code_object ) if comment
@@ -568,9 +572,12 @@ def find_or_create_module_path(module_name, create_mode)
568572 @module_nesting . reverse_each do |nesting |
569573 mod = nesting . find_module_named ( root_name )
570574 break if mod
575+ # If a constant is found and it is not a module or class, RDoc can't document about it.
576+ # Return an anonymous module to avoid wrong document creation.
577+ return RDoc ::NormalModule . new ( nil ) if nesting . find_constant_named ( root_name )
571578 end
572- return mod || add_module . call ( @top_level , root_name , create_mode ) unless name
573- mod ||= add_module . call ( @top_level , root_name , :module )
579+ return mod || add_module . call ( @module_nesting . last , root_name , create_mode ) unless name
580+ mod ||= add_module . call ( @module_nesting . last , root_name , :module )
574581 end
575582 path . each do |name |
576583 mod = mod . find_module_named ( name ) || add_module . call ( mod , name , :module )
@@ -635,7 +642,7 @@ def add_constant(constant_name, rhs_name, start_line, end_line)
635642
636643 # Adds module or class
637644
638- def add_module_or_class ( module_name , start_line , end_line , is_class : false , superclass_name : nil )
645+ def add_module_or_class ( module_name , start_line , end_line , is_class : false , superclass_name : nil , superclass_expr : nil )
639646 comment = consecutive_comment ( start_line )
640647 handle_consecutive_comment_directive ( @container , comment )
641648 return unless @container . document_children
@@ -650,7 +657,7 @@ def add_module_or_class(module_name, start_line, end_line, is_class: false, supe
650657 superclass_full_path ||= superclass_name
651658 end
652659 # add_class should be done after resolving superclass
653- mod = owner . classes_hash [ name ] || owner . add_class ( RDoc ::NormalClass , name , superclass_name || '::Object' )
660+ mod = owner . classes_hash [ name ] || owner . add_class ( RDoc ::NormalClass , name , superclass_name || superclass_expr || '::Object' )
654661 if superclass_name
655662 if superclass
656663 mod . superclass = superclass
@@ -678,6 +685,20 @@ def initialize(scanner, top_level, store)
678685 @store = store
679686 end
680687
688+ def visit_if_node ( node )
689+ if node . end_keyword
690+ super
691+ else
692+ # Visit with the order in text representation to handle this method comment
693+ # # comment
694+ # def f
695+ # end if call_node
696+ node . statements . accept ( self )
697+ node . predicate . accept ( self )
698+ end
699+ end
700+ alias visit_unless_node visit_if_node
701+
681702 def visit_call_node ( node )
682703 @scanner . process_comments_until ( node . location . start_line - 1 )
683704 if node . receiver . nil?
@@ -745,8 +766,9 @@ def visit_module_node(node)
745766 def visit_class_node ( node )
746767 @scanner . process_comments_until ( node . location . start_line - 1 )
747768 superclass_name = constant_path_string ( node . superclass ) if node . superclass
769+ superclass_expr = node . superclass . slice if node . superclass && !superclass_name
748770 class_name = constant_path_string ( node . constant_path )
749- klass = @scanner . add_module_or_class ( class_name , node . location . start_line , node . location . end_line , is_class : true , superclass_name : superclass_name ) if class_name
771+ 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
750772 if klass
751773 @scanner . with_container ( klass ) do
752774 super
@@ -760,6 +782,12 @@ def visit_class_node(node)
760782 def visit_singleton_class_node ( node )
761783 @scanner . process_comments_until ( node . location . start_line - 1 )
762784
785+ if @scanner . has_modifier_nodoc? ( node . location . start_line )
786+ # Skip visiting inside the singleton class. Also skips creation of node.expression as a module
787+ @scanner . skip_comments_until ( node . location . end_line )
788+ return
789+ end
790+
763791 expression = node . expression
764792 expression = expression . body . body . first if expression . is_a? ( Prism ::ParenthesesNode ) && expression . body &.body &.size == 1
765793
@@ -944,7 +972,7 @@ def _visit_call_public_private_protected(call_node, visibility)
944972 @scanner . visibility = visibility
945973 else # `public :foo, :bar`, `private def foo; end`
946974 yield
947- names = visibility_method_arguments ( call_node , singleton : @scanner . singleton )
975+ names = visibility_method_arguments ( call_node , singleton : false )
948976 @scanner . change_method_visibility ( names , visibility ) if names
949977 end
950978 end
0 commit comments