@@ -133,6 +133,9 @@ class RDoc::Parser::PrismRuby < RDoc::Parser
133133
134134 parse_files_matching ( /\. rbw?$/ ) unless ENV [ 'RDOC_USE_RIPPER_PARSER' ]
135135
136+ # Matches an RBS inline type annotation line: #: followed by whitespace
137+ RBS_SIG_LINE = /\A #:\s / # :nodoc:
138+
136139 attr_accessor :visibility
137140 attr_reader :container , :singleton , :in_proc_block
138141
@@ -461,10 +464,14 @@ def skip_comments_until(line_no_until)
461464 def consecutive_comment ( line_no )
462465 return unless @unprocessed_comments . first &.first == line_no
463466 _line_no , start_line , text = @unprocessed_comments . shift
464- parse_comment_text_to_directives ( text , start_line )
467+ type_signature = extract_type_signature! ( text , start_line )
468+ result = parse_comment_text_to_directives ( text , start_line )
469+ return unless result
470+ comment , directives = result
471+ [ comment , directives , type_signature ]
465472 end
466473
467- # Parses comment text and retuns a pair of RDoc::Comment and directives
474+ # Parses comment text and returns a pair of RDoc::Comment and directives
468475
469476 def parse_comment_text_to_directives ( comment_text , start_line ) # :nodoc:
470477 comment_text , directives = @preprocess . parse_comment ( comment_text , start_line , :ruby )
@@ -594,14 +601,15 @@ def add_alias_method(old_name, new_name, line_no)
594601 # Handles `attr :a, :b`, `attr_reader :a, :b`, `attr_writer :a, :b` and `attr_accessor :a, :b`
595602
596603 def add_attributes ( names , rw , line_no )
597- comment , directives = consecutive_comment ( line_no )
604+ comment , directives , type_signature = consecutive_comment ( line_no )
598605 handle_code_object_directives ( @container , directives ) if directives
599606 return unless @container . document_children
600607
601608 names . each do |symbol |
602609 a = RDoc ::Attr . new ( nil , symbol . to_s , rw , comment , singleton : @singleton )
603610 a . store = @store
604611 a . line = line_no
612+ a . type_signature = type_signature
605613 record_location ( a )
606614 handle_modifier_directive ( a , line_no )
607615 @container . add_attribute ( a ) if should_document? ( a )
@@ -640,7 +648,7 @@ def add_extends(names, line_no) # :nodoc:
640648
641649 def add_method ( method_name , receiver_name :, receiver_fallback_type :, visibility :, singleton :, params :, calls_super :, block_params :, tokens :, start_line :, args_end_line :, end_line :)
642650 receiver = receiver_name ? find_or_create_module_path ( receiver_name , receiver_fallback_type ) : @container
643- comment , directives = consecutive_comment ( start_line )
651+ comment , directives , type_signature = consecutive_comment ( start_line )
644652 handle_code_object_directives ( @container , directives ) if directives
645653
646654 internal_add_method (
@@ -655,11 +663,12 @@ def add_method(method_name, receiver_name:, receiver_fallback_type:, visibility:
655663 params : params ,
656664 calls_super : calls_super ,
657665 block_params : block_params ,
658- tokens : tokens
666+ tokens : tokens ,
667+ type_signature : type_signature
659668 )
660669 end
661670
662- private def internal_add_method ( method_name , container , comment :, dont_rename_initialize : false , directives :, modifier_comment_lines : nil , line_no :, visibility :, singleton :, params :, calls_super :, block_params :, tokens :) # :nodoc:
671+ private def internal_add_method ( method_name , container , comment :, dont_rename_initialize : false , directives :, modifier_comment_lines : nil , line_no :, visibility :, singleton :, params :, calls_super :, block_params :, tokens :, type_signature : nil ) # :nodoc:
663672 meth = RDoc ::AnyMethod . new ( nil , method_name , singleton : singleton )
664673 meth . comment = comment
665674 handle_code_object_directives ( meth , directives ) if directives
@@ -680,6 +689,7 @@ def add_method(method_name, receiver_name:, receiver_fallback_type:, visibility:
680689 meth . params ||= params || '()'
681690 meth . calls_super = calls_super
682691 meth . block_params ||= block_params if block_params
692+ meth . type_signature = type_signature
683693 record_location ( meth )
684694 meth . start_collecting_tokens ( :ruby )
685695 tokens . each do |token |
@@ -836,6 +846,35 @@ def add_module_or_class(module_name, start_line, end_line, is_class: false, supe
836846 mod
837847 end
838848
849+ private
850+
851+ # Extracts RBS type signature lines (#: ...) from raw comment text.
852+ # Mutates the input text to remove the extracted lines.
853+ # Returns the type signature string, or nil if none found.
854+
855+ def extract_type_signature! ( text , start_line )
856+ return nil unless text . include? ( '#:' )
857+
858+ lines = text . lines
859+ sig_lines , doc_lines = lines . partition { |l | l . match? ( RBS_SIG_LINE ) }
860+ return nil if sig_lines . empty?
861+
862+ text . replace ( doc_lines . join )
863+ type_sig = sig_lines . map { |l | l . sub ( RBS_SIG_LINE , '' ) . chomp } . join ( "\n " )
864+ validate_type_signature ( type_sig , start_line + doc_lines . size )
865+ type_sig
866+ end
867+
868+ def validate_type_signature ( sig , line_no )
869+ sig . split ( "\n " ) . each_with_index do |line , i |
870+ method_error = RDoc ::RbsHelper . validate_method_type ( line )
871+ next unless method_error
872+ type_error = RDoc ::RbsHelper . validate_type ( line )
873+ next unless type_error
874+ @options . warn "#{ @top_level . relative_name } :#{ line_no + i } : invalid RBS type signature: #{ line . inspect } "
875+ end
876+ end
877+
839878 class RDocVisitor < Prism ::Visitor # :nodoc:
840879 def initialize ( scanner , top_level , store )
841880 @scanner = scanner
0 commit comments