diff --git a/History.rdoc b/History.rdoc
index deb8c77787..6a76722696 100644
--- a/History.rdoc
+++ b/History.rdoc
@@ -163,7 +163,7 @@
* Moved old DEVELOPERS file to CONTRIBUTING to match github conventions.
* TomDoc output now has a "Returns" heading. Issue #234 by Brian Henderson
* Metaprogrammed methods can now use the :args: directive in addition to the
- :call-seq: directive. Issue #236 by Mike Moore.
+ \:call-seq: directive. Issue #236 by Mike Moore.
* Sections can be linked to using "@" like labels. If a section and a label
have the same name the section will be preferred. Issue #233 by Brian
Henderson.
diff --git a/doc/rdoc/markup_reference.rb b/doc/rdoc/markup_reference.rb
index ee585b2497..6224e534bc 100644
--- a/doc/rdoc/markup_reference.rb
+++ b/doc/rdoc/markup_reference.rb
@@ -1245,7 +1245,7 @@ def dummy_instance_method(foo, bar); end;
#
# Here is the :call-seq: directive given for the method:
#
- # :call-seq:
+ # \:call-seq:
# call_seq_directive(foo, bar)
# Can be anything -> bar
# Also anything more -> baz or bat
diff --git a/lib/rdoc/comment.rb b/lib/rdoc/comment.rb
index aa916071a2..8f69616a86 100644
--- a/lib/rdoc/comment.rb
+++ b/lib/rdoc/comment.rb
@@ -162,6 +162,12 @@ def normalize
self
end
+ # Change normalized, when creating already normalized comment.
+
+ def normalized=(value)
+ @normalized = value
+ end
+
##
# Was this text normalized?
@@ -223,14 +229,190 @@ def tomdoc?
@format == 'tomdoc'
end
- ##
- # Create a new parsed comment from a document
+ MULTILINE_DIRECTIVES = %w[call-seq].freeze # :nodoc:
- def self.from_document(document) # :nodoc:
- comment = RDoc::Comment.new('')
- comment.document = document
- comment.location = RDoc::TopLevel.new(document.file) if document.file
- comment
- end
+ # There are more, but already handled by RDoc::Parser::C
+ COLON_LESS_DIRECTIVES = %w[call-seq Document-method].freeze # :nodoc:
+
+ DIRECTIVE_OR_ESCAPED_DIRECTIV_REGEXP = /\A(?\\?:|:?)(?[\w-]+):(?.*)/
+
+ private_constant :MULTILINE_DIRECTIVES, :COLON_LESS_DIRECTIVES, :DIRECTIVE_OR_ESCAPED_DIRECTIV_REGEXP
+
+ class << self
+
+ ##
+ # Create a new parsed comment from a document
+ def from_document(document) # :nodoc:
+ comment = RDoc::Comment.new('')
+ comment.document = document
+ comment.location = RDoc::TopLevel.new(document.file) if document.file
+ comment
+ end
+
+ # Parse comment, collect directives as an attribute and return [normalized_comment_text, directives_hash]
+ # This method expands include and removes everything not needed in the document text, such as
+ # private section, directive line, comment characters `# /* * */` and indent spaces.
+ #
+ # RDoc comment consists of include, directive, multiline directive, private section and comment text.
+ #
+ # Include
+ # # :include: filename
+ #
+ # Directive
+ # # :directive-without-value:
+ # # :directive-with-value: value
+ #
+ # Multiline directive (only :call-seq:)
+ # # :multiline-directive:
+ # # value1
+ # # value2
+ #
+ # Private section
+ # #--
+ # # private comment
+ # #++
+
+ def parse(text, filename, line_no, type, &include_callback)
+ case type
+ when :ruby
+ text = text.gsub(/^#+/, '') if text.start_with?('#')
+ private_start_regexp = /^-{2,}$/
+ private_end_regexp = /^\+{2}$/
+ indent_regexp = /^\s*/
+ when :c
+ private_start_regexp = /^(\s*\*)?-{2,}$/
+ private_end_regexp = /^(\s*\*)?\+{2}$/
+ indent_regexp = /^\s*(\/\*+|\*)?\s*/
+ text = text.gsub(/\s*\*+\/\s*\z/, '')
+ when :simple
+ # Unlike other types, this implementation only looks for two dashes at
+ # the beginning of the line. Three or more dashes are considered to be
+ # a rule and ignored.
+ private_start_regexp = /^-{2}$/
+ private_end_regexp = /^\+{2}$/
+ indent_regexp = /^\s*/
+ end
+
+ directives = {}
+ lines = text.split("\n")
+ in_private = false
+ comment_lines = []
+ until lines.empty?
+ line = lines.shift
+ read_lines = 1
+ if in_private
+ # If `++` appears in a private section that starts with `--`, private section ends.
+ in_private = false if line.match?(private_end_regexp)
+ line_no += read_lines
+ next
+ elsif line.match?(private_start_regexp)
+ # If `--` appears in a line, private section starts.
+ in_private = true
+ line_no += read_lines
+ next
+ end
+
+ prefix = line[indent_regexp]
+ prefix_indent = ' ' * prefix.size
+ line = line.byteslice(prefix.bytesize..)
+
+ if (directive_match = DIRECTIVE_OR_ESCAPED_DIRECTIV_REGEXP.match(line))
+ colon = directive_match[:colon]
+ directive = directive_match[:directive]
+ raw_param = directive_match[:param]
+ param = raw_param.strip
+ else
+ colon = directive = raw_param = param = nil
+ end
+
+ if !directive
+ comment_lines << prefix_indent + line
+ elsif colon == '\\:'
+ # If directive is escaped, unescape it
+ comment_lines << prefix_indent + line.sub('\\:', ':')
+ elsif raw_param.start_with?(':') || (colon.empty? && !COLON_LESS_DIRECTIVES.include?(directive))
+ # Something like `:toto::` is not a directive
+ # Only few directives allows to start without a colon
+ comment_lines << prefix_indent + line
+ elsif directive == 'include'
+ filename_to_include = param
+ include_callback.call(filename_to_include, prefix_indent).lines.each { |l| comment_lines << l.chomp }
+ elsif MULTILINE_DIRECTIVES.include?(directive)
+ value_lines = take_multiline_directive_value_lines(directive, filename, line_no, lines, prefix_indent.size, indent_regexp, !param.empty?)
+ read_lines += value_lines.size
+ lines.shift(value_lines.size)
+ unless param.empty?
+ # Accept `:call-seq: first-line\n second-line` for now
+ value_lines.unshift(param)
+ end
+ value = value_lines.join("\n")
+ directives[directive] = [value.empty? ? nil : value, line_no]
+ else
+ directives[directive] = [param.empty? ? nil : param, line_no]
+ end
+ line_no += read_lines
+ end
+
+ normalized_comment = String.new(encoding: text.encoding) << normalize_comment_lines(comment_lines).join("\n")
+ [normalized_comment, directives]
+ end
+
+ # Remove preceding indent spaces and blank lines from the comment lines
+
+ private def normalize_comment_lines(lines)
+ blank_line_regexp = /\A\s*\z/
+ lines = lines.dup
+ lines.shift while lines.first&.match?(blank_line_regexp)
+ lines.pop while lines.last&.match?(blank_line_regexp)
+
+ min_spaces = lines.map do |l|
+ l.match(/\A *(?=\S)/)&.end(0)
+ end.compact.min
+ if min_spaces && min_spaces > 0
+ lines.map { |l| l[min_spaces..] || '' }
+ else
+ lines
+ end
+ end
+
+ # Take value lines of multiline directive
+
+ private def take_multiline_directive_value_lines(directive, filename, line_no, lines, base_indent_size, indent_regexp, has_param)
+ return [] if lines.empty?
+
+ first_indent_size = lines.first.match(indent_regexp).end(0)
+
+ # Blank line or unindented line is not part of multiline-directive value
+ return [] if first_indent_size <= base_indent_size
+
+ if has_param
+ # :multiline-directive: line1
+ # line2
+ # line3
+ #
+ value_lines = lines.take_while do |l|
+ l.rstrip.match(indent_regexp).end(0) > base_indent_size
+ end
+ min_indent = value_lines.map { |l| l.match(indent_regexp).end(0) }.min
+ value_lines.map { |l| l[min_indent..] }
+ else
+ # Take indented lines accepting blank lines between them
+ value_lines = lines.take_while do |l|
+ l = l.rstrip
+ indent = l[indent_regexp]
+ if indent == l || indent.size >= first_indent_size
+ true
+ end
+ end
+ value_lines.map! { |l| (l[first_indent_size..] || '').chomp }
+
+ if value_lines.size != lines.size && !value_lines.last.empty?
+ warn "#{filename}:#{line_no} Multiline directive :#{directive}: should end with a blank line."
+ end
+ value_lines.pop while value_lines.last&.empty?
+ value_lines
+ end
+ end
+ end
end
diff --git a/lib/rdoc/markup/pre_process.rb b/lib/rdoc/markup/pre_process.rb
index 3270f8ada2..e7edaebcf4 100644
--- a/lib/rdoc/markup/pre_process.rb
+++ b/lib/rdoc/markup/pre_process.rb
@@ -97,18 +97,15 @@ def initialize(input_file_name, include_path)
# RDoc::CodeObject#metadata for details.
def handle text, code_object = nil, &block
- first_line = 1
if RDoc::Comment === text then
comment = text
text = text.text
- first_line = comment.line || 1
end
# regexp helper (square brackets for optional)
# $1 $2 $3 $4 $5
# [prefix][\]:directive:[spaces][param]newline
- text = text.lines.map.with_index(first_line) do |line, num|
- next line unless line =~ /\A([ \t]*(?:#|\/?\*)?[ \t]*)(\\?):([\w-]+):([ \t]*)(.+)?(\r?\n|$)/
+ text = text.gsub(/^([ \t]*(?:#|\/?\*)?[ \t]*)(\\?):([\w-]+):([ \t]*)(.+)?(\r?\n|$)/) do
# skip something like ':toto::'
next $& if $4.empty? and $5 and $5[0, 1] == ':'
@@ -122,9 +119,8 @@ def handle text, code_object = nil, &block
comment.format = $5.downcase
next "#{$1.strip}\n"
end
-
- handle_directive $1, $3, $5, code_object, text.encoding, num, &block
- end.join
+ handle_directive $1, $3, $5, code_object, text.encoding, &block
+ end
if comment then
comment.text = text
@@ -132,11 +128,40 @@ def handle text, code_object = nil, &block
comment = text
end
+ run_post_processes(comment, code_object)
+
+ text
+ end
+
+ # Apply directives to a code object
+
+ def run_pre_processes(comment_text, code_object, start_line_no, type)
+ comment_text, directives = parse_comment(comment_text, start_line_no, type)
+ directives.each do |directive, (param, line_no)|
+ handle_directive('', directive, param, code_object)
+ end
+ if code_object.is_a?(RDoc::AnyMethod) && (call_seq, = directives['call-seq']) && call_seq
+ code_object.call_seq = call_seq.lines.map(&:chomp).reject(&:empty?).join("\n") if call_seq
+ end
+ format, = directives['markup']
+ [comment_text, format]
+ end
+
+
+ # Perform post preocesses to a code object
+
+ def run_post_processes(comment, code_object)
self.class.post_processors.each do |handler|
handler.call comment, code_object
end
+ end
- text
+ # Parse comment and return [normalized_comment_text, directives_hash]
+
+ def parse_comment(text, line_no, type)
+ RDoc::Comment.parse(text, @input_file_name, line_no, type) do |filename, prefix_indent|
+ include_file(filename, prefix_indent, text.encoding)
+ end
end
##
@@ -151,7 +176,7 @@ def handle text, code_object = nil, &block
# When 1.8.7 support is ditched prefix can be defaulted to ''
def handle_directive prefix, directive, param, code_object = nil,
- encoding = nil, line = nil
+ encoding = nil
blankline = "#{prefix.strip}\n"
directive = directive.downcase
@@ -244,7 +269,7 @@ def handle_directive prefix, directive, param, code_object = nil,
blankline
else
- result = yield directive, param, line if block_given?
+ result = yield directive, param if block_given?
case result
when nil then
diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb
index bc4ab6b8a0..49de49c7a1 100644
--- a/lib/rdoc/parser/c.rb
+++ b/lib/rdoc/parser/c.rb
@@ -607,8 +607,6 @@ def find_body class_name, meth_name, meth_obj, file_content, quiet = false
body = args[1]
offset, = args[2]
- comment.remove_private if comment
-
# try to find the whole body
body = $& if /#{Regexp.escape body}[^(]*?\{.*?^\}/m =~ file_content
@@ -621,7 +619,6 @@ def find_body class_name, meth_name, meth_obj, file_content, quiet = false
override_comment = find_override_comment class_name, meth_obj
comment = override_comment if override_comment
- comment.normalize
find_modifiers comment, meth_obj if comment
#meth_obj.params = params
@@ -639,7 +636,6 @@ def find_body class_name, meth_name, meth_obj, file_content, quiet = false
find_body class_name, args[3], meth_obj, file_content, true
- comment.normalize
find_modifiers comment, meth_obj
meth_obj.start_collecting_tokens
@@ -663,7 +659,6 @@ def find_body class_name, meth_name, meth_obj, file_content, quiet = false
comment = find_override_comment class_name, meth_obj
if comment then
- comment.normalize
find_modifiers comment, meth_obj
meth_obj.comment = comment
@@ -742,7 +737,6 @@ def find_class_comment class_name, class_mod
end
comment = new_comment comment, @top_level, :c
- comment.normalize
look_for_directives_in class_mod, comment
@@ -807,9 +801,6 @@ def find_const_comment(type, const_name, class_name = nil)
# Handles modifiers in +comment+ and updates +meth_obj+ as appropriate.
def find_modifiers comment, meth_obj
- comment.normalize
- meth_obj.call_seq = comment.extract_call_seq
-
look_for_directives_in meth_obj, comment
end
@@ -823,10 +814,10 @@ def find_override_comment class_name, meth_obj
comment = if @content =~ %r%Document-method:
\s+#{class_name}#{prefix}#{name}
\s*?\n((?>.*?\*/))%xm then
- "/*#{$1}"
+ "/*\n#{$1}"
elsif @content =~ %r%Document-method:
\s#{name}\s*?\n((?>.*?\*/))%xm then
- "/*#{$1}"
+ "/*\n#{$1}"
end
return unless comment
@@ -1102,35 +1093,10 @@ def load_variable_map map_name
# Both :main: and :title: directives are deprecated and will be removed in RDoc 7.
def look_for_directives_in context, comment
- @preprocess.handle comment, context do |directive, param|
- case directive
- when 'main' then
- @options.main_page = param
-
- warn <<~MSG
- The :main: directive is deprecated and will be removed in RDoc 7.
-
- You can use these options to specify the initial page displayed instead:
- - `--main=#{param}` via the command line
- - `rdoc.main = "#{param}"` if you use `RDoc::Task`
- - `main_page: #{param}` in your `.rdoc_options` file
- MSG
- ''
- when 'title' then
- @options.default_title = param if @options.respond_to? :default_title=
-
- warn <<~MSG
- The :title: directive is deprecated and will be removed in RDoc 7.
-
- You can use these options to specify the title displayed instead:
- - `--title=#{param}` via the command line
- - `rdoc.title = "#{param}"` if you use `RDoc::Task`
- - `title: #{param}` in your `.rdoc_options` file
- MSG
- ''
- end
- end
-
+ comment.text, format = @preprocess.run_pre_processes(comment.text, context, comment.line || 1, :c)
+ comment.format = format if format
+ @preprocess.run_post_processes(comment, context)
+ comment.normalized = true
comment
end
diff --git a/lib/rdoc/parser/prism_ruby.rb b/lib/rdoc/parser/prism_ruby.rb
index babd02f18f..aa5c01e995 100644
--- a/lib/rdoc/parser/prism_ruby.rb
+++ b/lib/rdoc/parser/prism_ruby.rb
@@ -98,9 +98,9 @@ def scan
prepare_comments(result.comments)
return if @top_level.done_documenting
- @first_non_meta_comment = nil
- if (_line_no, start_line, rdoc_comment = @unprocessed_comments.first)
- @first_non_meta_comment = rdoc_comment if start_line < @program_node.location.start_line
+ @first_non_meta_comment_start_line = nil
+ if (_line_no, start_line = @unprocessed_comments.first)
+ @first_non_meta_comment_start_line = start_line if start_line < @program_node.location.start_line
end
@program_node.accept(RDocVisitor.new(self, @top_level, @store))
@@ -150,7 +150,9 @@ def prepare_comments(comments)
if comment.is_a? Prism::EmbDocComment
consecutive_comments << [comment] << (current = [])
elsif comment.location.start_line_slice.match?(/\S/)
- @modifier_comments[comment.location.start_line] = RDoc::Comment.new(comment.slice, @top_level, :ruby)
+ text = comment.slice
+ text = RDoc::Encoding.change_encoding(text, @encoding) if @encoding
+ @modifier_comments[comment.location.start_line] = text
elsif current.empty? || current.last.location.end_line + 1 == comment.location.start_line
current << comment
else
@@ -172,22 +174,18 @@ def prepare_comments(comments)
texts = comments.map do |c|
c.is_a?(Prism::EmbDocComment) ? c.slice.lines[1...-1].join : c.slice
end
- text = RDoc::Encoding.change_encoding(texts.join("\n"), @encoding) if @encoding
+ text = texts.join("\n")
+ text = RDoc::Encoding.change_encoding(text, @encoding) if @encoding
line_no += 1 while @lines[line_no - 1]&.match?(/\A\s*$/)
- comment = RDoc::Comment.new(text, @top_level, :ruby)
- comment.line = start_line
- [line_no, start_line, comment]
+ [line_no, start_line, text]
end
# The first comment is special. It defines markup for the rest of the comments.
_, first_comment_start_line, first_comment_text = @unprocessed_comments.first
if first_comment_text && @lines[0...first_comment_start_line - 1].all? { |l| l.match?(/\A\s*$/) }
- comment = RDoc::Comment.new(first_comment_text.text, @top_level, :ruby)
- handle_consecutive_comment_directive(@container, comment)
- @markup = comment.format
- end
- @unprocessed_comments.each do |_, _, comment|
- comment.format = @markup
+ _text, directives = @preprocess.parse_comment(first_comment_text, first_comment_start_line, :ruby)
+ markup, = directives['markup']
+ @markup = markup.downcase if markup
end
end
@@ -211,36 +209,19 @@ def parse_comment_tomdoc(container, comment, line_no, start_line)
tokens.each { |token| meth.token_stream << token }
container.add_method meth
- comment.remove_private
- comment.normalize
meth.comment = comment
@stats.add_method meth
end
def has_modifier_nodoc?(line_no) # :nodoc:
- @modifier_comments[line_no]&.text&.match?(/\A#\s*:nodoc:/)
+ @modifier_comments[line_no]&.match?(/\A#\s*:nodoc:/)
end
def handle_modifier_directive(code_object, line_no) # :nodoc:
- comment = @modifier_comments[line_no]
- @preprocess.handle(comment.text, code_object) if comment
- end
-
- def handle_consecutive_comment_directive(code_object, comment) # :nodoc:
- return unless comment
- @preprocess.handle(comment, code_object) do |directive, param|
- case directive
- when 'method', 'singleton-method',
- 'attr', 'attr_accessor', 'attr_reader', 'attr_writer' then
- # handled elsewhere
- ''
- when 'section' then
- @container.set_current_section(param, comment.dup)
- comment.text = ''
- break
- end
+ if (comment_text = @modifier_comments[line_no])
+ _text, directives = @preprocess.parse_comment(comment_text, line_no, :ruby)
+ handle_code_object_directives(code_object, directives)
end
- comment.remove_private
end
def call_node_name_arguments(call_node) # :nodoc:
@@ -257,39 +238,32 @@ def call_node_name_arguments(call_node) # :nodoc:
# Handles meta method comments
- def handle_meta_method_comment(comment, node)
+ def handle_meta_method_comment(comment, directives, node)
+ handle_code_object_directives(@container, directives)
is_call_node = node.is_a?(Prism::CallNode)
singleton_method = false
visibility = @visibility
attributes = rw = line_no = method_name = nil
-
- processed_comment = comment.dup
- @preprocess.handle(processed_comment, @container) do |directive, param, line|
+ directives.each do |directive, (param, line)|
case directive
when 'attr', 'attr_reader', 'attr_writer', 'attr_accessor'
attributes = [param] if param
attributes ||= call_node_name_arguments(node) if is_call_node
rw = directive == 'attr_writer' ? 'W' : directive == 'attr_accessor' ? 'RW' : 'R'
- ''
when 'method'
- method_name = param
+ method_name = param if param
line_no = line
- ''
when 'singleton-method'
- method_name = param
+ method_name = param if param
line_no = line
singleton_method = true
visibility = :public
- ''
- when 'section' then
- @container.set_current_section(param, comment.dup)
- return # If the comment contains :section:, it is not a meta method comment
end
end
if attributes
attributes.each do |attr|
- a = RDoc::Attr.new(@container, attr, rw, processed_comment, singleton: @singleton)
+ a = RDoc::Attr.new(@container, attr, rw, comment, singleton: @singleton)
a.store = @store
a.line = line_no
record_location(a)
@@ -298,11 +272,6 @@ def handle_meta_method_comment(comment, node)
end
elsif line_no || node
method_name ||= call_node_name_arguments(node).first if is_call_node
- meth = RDoc::AnyMethod.new(@container, method_name, singleton: @singleton || singleton_method)
- handle_consecutive_comment_directive(meth, comment)
- comment.normalize
- meth.call_seq = comment.extract_call_seq
- meth.comment = comment
if node
tokens = visible_tokens_from_location(node.location)
line_no = node.location.start_line
@@ -310,37 +279,41 @@ def handle_meta_method_comment(comment, node)
tokens = [file_line_comment_token(line_no)]
end
internal_add_method(
+ method_name,
@container,
- meth,
+ comment: comment,
+ directives: directives,
+ dont_rename_initialize: false,
line_no: line_no,
visibility: visibility,
- params: '()',
+ singleton: @singleton || singleton_method,
+ params: nil,
calls_super: false,
block_params: nil,
- tokens: tokens
+ tokens: tokens,
)
end
end
- def normal_comment_treat_as_ghost_method_for_now?(comment_text, line_no) # :nodoc:
+ INVALID_GHOST_METHOD_ACCEPT_DIRECTIVE_LIST = %w[
+ method singleton-method attr attr_reader attr_writer attr_accessor
+ ].freeze
+ private_constant :INVALID_GHOST_METHOD_ACCEPT_DIRECTIVE_LIST
+
+ def normal_comment_treat_as_ghost_method_for_now?(directives, line_no) # :nodoc:
# Meta method comment should start with `##` but some comments does not follow this rule.
# For now, RDoc accepts them as a meta method comment if there is no node linked to it.
- !@line_nodes[line_no] && comment_text.match?(/^#\s+:(method|singleton-method|attr|attr_reader|attr_writer|attr_accessor):/)
+ !@line_nodes[line_no] && INVALID_GHOST_METHOD_ACCEPT_DIRECTIVE_LIST.any? { |directive| directives.has_key?(directive) }
end
- def handle_standalone_consecutive_comment_directive(comment, line_no, start_line) # :nodoc:
- if @markup == 'tomdoc'
- parse_comment_tomdoc(@container, comment, line_no, start_line)
- return
- end
-
- if comment.text =~ /\A#\#$/ && comment != @first_non_meta_comment
+ def handle_standalone_consecutive_comment_directive(comment, directives, start_with_sharp_sharp, line_no, start_line) # :nodoc:
+ if start_with_sharp_sharp && start_line != @first_non_meta_comment_start_line
node = @line_nodes[line_no]
- handle_meta_method_comment(comment, node)
- elsif normal_comment_treat_as_ghost_method_for_now?(comment.text, line_no) && comment != @first_non_meta_comment
- handle_meta_method_comment(comment, nil)
+ handle_meta_method_comment(comment, directives, node)
+ elsif normal_comment_treat_as_ghost_method_for_now?(directives, line_no) && start_line != @first_non_meta_comment_start_line
+ handle_meta_method_comment(comment, directives, nil)
else
- handle_consecutive_comment_directive(@container, comment)
+ handle_code_object_directives(@container, directives)
end
end
@@ -348,8 +321,15 @@ def handle_standalone_consecutive_comment_directive(comment, line_no, start_line
def process_comments_until(line_no_until)
while !@unprocessed_comments.empty? && @unprocessed_comments.first[0] <= line_no_until
- line_no, start_line, rdoc_comment = @unprocessed_comments.shift
- handle_standalone_consecutive_comment_directive(rdoc_comment, line_no, start_line)
+ line_no, start_line, text = @unprocessed_comments.shift
+ if @markup == 'tomdoc'
+ comment = RDoc::Comment.new(text, @top_level, :ruby)
+ comment.format = 'tomdoc'
+ parse_comment_tomdoc(@container, comment, line_no, start_line)
+ @preprocess.run_post_processes(comment, @container)
+ elsif (comment_text, directives = parse_comment_text_to_directives(text, start_line))
+ handle_standalone_consecutive_comment_directive(comment_text, directives, text.start_with?(/#\#$/), line_no, start_line)
+ end
end
end
@@ -365,9 +345,27 @@ def skip_comments_until(line_no_until)
# Returns consecutive comment linked to the given line number
def consecutive_comment(line_no)
- if @unprocessed_comments.first&.first == line_no
- @unprocessed_comments.shift.last
+ return unless @unprocessed_comments.first&.first == line_no
+ _line_no, start_line, text = @unprocessed_comments.shift
+ parse_comment_text_to_directives(text, start_line)
+ end
+
+ # Parses comment text and retuns a pair of RDoc::Comment and directives
+
+ def parse_comment_text_to_directives(comment_text, start_line) # :nodoc:
+ comment_text, directives = @preprocess.parse_comment(comment_text, start_line, :ruby)
+ comment = RDoc::Comment.new(comment_text, @top_level, :ruby)
+ comment.normalized = true
+ comment.line = start_line
+ markup, = directives['markup']
+ comment.format = markup&.downcase || @markup
+ if (section, = directives['section'])
+ # If comment has :section:, it is not a documentable comment for a code object
+ @container.set_current_section(section, comment.dup)
+ return
end
+ @preprocess.run_post_processes(comment, @container)
+ [comment, directives]
end
def slice_tokens(start_pos, end_pos) # :nodoc:
@@ -443,11 +441,17 @@ def change_method_to_module_function(names)
end
end
+ def handle_code_object_directives(code_object, directives) # :nodoc:
+ directives.each do |directive, (param)|
+ @preprocess.handle_directive('', directive, param, code_object)
+ end
+ end
+
# Handles `alias foo bar` and `alias_method :foo, :bar`
def add_alias_method(old_name, new_name, line_no)
- comment = consecutive_comment(line_no)
- handle_consecutive_comment_directive(@container, comment)
+ comment, directives = consecutive_comment(line_no)
+ handle_code_object_directives(@container, directives) if directives
visibility = @container.find_method(old_name, @singleton)&.visibility || :public
a = RDoc::Alias.new(nil, old_name, new_name, comment, singleton: @singleton)
handle_modifier_directive(a, line_no)
@@ -463,8 +467,8 @@ def add_alias_method(old_name, new_name, line_no)
# Handles `attr :a, :b`, `attr_reader :a, :b`, `attr_writer :a, :b` and `attr_accessor :a, :b`
def add_attributes(names, rw, line_no)
- comment = consecutive_comment(line_no)
- handle_consecutive_comment_directive(@container, comment)
+ comment, directives = consecutive_comment(line_no)
+ handle_code_object_directives(@container, directives) if directives
return unless @container.document_children
names.each do |symbol|
@@ -480,8 +484,8 @@ def add_attributes(names, rw, line_no)
def add_includes_extends(names, rdoc_class, line_no) # :nodoc:
return if @in_proc_block
- comment = consecutive_comment(line_no)
- handle_consecutive_comment_directive(@container, comment)
+ comment, directives = consecutive_comment(line_no)
+ handle_code_object_directives(@container, directives) if directives
names.each do |name|
ie = @container.add(rdoc_class, name, '')
ie.store = @store
@@ -505,56 +509,48 @@ def add_extends(names, line_no) # :nodoc:
# Adds a method defined by `def` syntax
- def add_method(name, receiver_name:, receiver_fallback_type:, visibility:, singleton:, params:, calls_super:, block_params:, tokens:, start_line:, args_end_line:, end_line:)
+ 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:)
return if @in_proc_block
receiver = receiver_name ? find_or_create_module_path(receiver_name, receiver_fallback_type) : @container
- meth = RDoc::AnyMethod.new(nil, name, singleton: singleton)
- if (comment = consecutive_comment(start_line))
- handle_consecutive_comment_directive(@container, comment)
- handle_consecutive_comment_directive(meth, comment)
-
- comment.normalize
- meth.call_seq = comment.extract_call_seq
- meth.comment = comment
- end
- handle_modifier_directive(meth, start_line)
- handle_modifier_directive(meth, args_end_line)
- handle_modifier_directive(meth, end_line)
- return unless should_document?(meth)
+ comment, directives = consecutive_comment(start_line)
+ handle_code_object_directives(@container, directives) if directives
internal_add_method(
+ method_name,
receiver,
- meth,
+ comment: comment,
+ directives: directives,
+ modifier_comment_lines: [start_line, args_end_line, end_line],
line_no: start_line,
visibility: visibility,
+ singleton: singleton,
params: params,
calls_super: calls_super,
block_params: block_params,
tokens: tokens
)
+ end
- # Rename after add_method to register duplicated 'new' and 'initialize'
- # defined in c and ruby just like the old parser did.
- if meth.name == 'initialize' && !singleton
- if meth.dont_rename_initialize
- meth.visibility = :protected
- else
- meth.name = 'new'
- meth.singleton = true
- meth.visibility = :public
- end
+ 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:
+ meth = RDoc::AnyMethod.new(nil, method_name, singleton: singleton)
+ meth.comment = comment
+ handle_code_object_directives(meth, directives) if directives
+ modifier_comment_lines&.each do |line|
+ handle_modifier_directive(meth, line)
end
- end
+ return unless should_document?(meth)
- private def internal_add_method(container, meth, line_no:, visibility:, params:, calls_super:, block_params:, tokens:) # :nodoc:
+ if directives && (call_seq, = directives['call-seq'])
+ meth.call_seq = call_seq.lines.map(&:chomp).reject(&:empty?).join("\n") if call_seq
+ end
meth.name ||= meth.call_seq[/\A[^()\s]+/] if meth.call_seq
meth.name ||= 'unknown'
meth.store = @store
meth.line = line_no
container.add_method(meth) # should add after setting singleton and before setting visibility
meth.visibility = visibility
- meth.params ||= params
+ meth.params ||= params || '()'
meth.calls_super = calls_super
meth.block_params ||= block_params if block_params
record_location(meth)
@@ -562,6 +558,18 @@ def add_method(name, receiver_name:, receiver_fallback_type:, visibility:, singl
tokens.each do |token|
meth.token_stream << token
end
+
+ # Rename after add_method to register duplicated 'new' and 'initialize'
+ # defined in c and ruby just like the old parser did.
+ if !dont_rename_initialize && method_name == 'initialize' && !singleton
+ if meth.dont_rename_initialize
+ meth.visibility = :protected
+ else
+ meth.name = 'new'
+ meth.singleton = true
+ meth.visibility = :public
+ end
+ end
end
# Find or create module or class from a given module name.
@@ -633,8 +641,8 @@ def find_or_create_constant_owner_name(constant_path)
# Adds a constant
def add_constant(constant_name, rhs_name, start_line, end_line)
- comment = consecutive_comment(start_line)
- handle_consecutive_comment_directive(@container, comment)
+ comment, directives = consecutive_comment(start_line)
+ handle_code_object_directives(@container, directives) if directives
owner, name = find_or_create_constant_owner_name(constant_name)
return unless owner
@@ -662,8 +670,8 @@ def add_constant(constant_name, rhs_name, start_line, end_line)
# Adds module or class
def add_module_or_class(module_name, start_line, end_line, is_class: false, superclass_name: nil, superclass_expr: nil)
- comment = consecutive_comment(start_line)
- handle_consecutive_comment_directive(@container, comment)
+ comment, directives = consecutive_comment(start_line)
+ handle_code_object_directives(@container, directives) if directives
return unless @container.document_children
owner, name = find_or_create_constant_owner_name(module_name)
diff --git a/lib/rdoc/parser/ruby.rb b/lib/rdoc/parser/ruby.rb
index d11497be22..b121793061 100644
--- a/lib/rdoc/parser/ruby.rb
+++ b/lib/rdoc/parser/ruby.rb
@@ -120,7 +120,7 @@
# # :singleton-method: some_method!
#
# You can define arguments for metaprogrammed methods via either the
-# :call-seq:, :arg: or :args: directives.
+# \:call-seq:, :arg: or :args: directives.
#
# Additionally you can mark a method as an attribute by
# using :attr:, :attr_reader:, :attr_writer: or :attr_accessor:. Just like
@@ -1088,7 +1088,7 @@ def parse_constant_body container, constant, is_array_or_hash # :nodoc:
##
# Generates an RDoc::Method or RDoc::Attr from +comment+ by looking for
- # :method: or :attr: directives in +comment+.
+ # \:method: or :attr: directives in +comment+.
def parse_comment container, tk, comment
return parse_comment_tomdoc container, tk, comment if @markup == 'tomdoc'
diff --git a/lib/rdoc/parser/simple.rb b/lib/rdoc/parser/simple.rb
index 931fa28913..0f5baabbe7 100644
--- a/lib/rdoc/parser/simple.rb
+++ b/lib/rdoc/parser/simple.rb
@@ -19,17 +19,17 @@ def initialize(top_level, content, options, stats)
preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include
- @content = preprocess.handle @content, @top_level
+ content = RDoc::Text.expand_tabs(@content)
+ @content, = preprocess.run_pre_processes(content, @top_level, 1, :simple)
end
##
# Extract the file contents and attach them to the TopLevel as a comment
def scan
- comment = remove_coding_comment @content
- comment = remove_private_comment comment
+ content = remove_coding_comment @content
- comment = RDoc::Comment.new comment, @top_level
+ comment = RDoc::Comment.new content, @top_level
@top_level.comment = comment
@top_level
@@ -41,21 +41,4 @@ def scan
def remove_coding_comment text
text.sub(/\A# .*coding[=:].*$/, '')
end
-
- ##
- # Removes private comments.
- #
- # Unlike RDoc::Comment#remove_private this implementation only looks for two
- # dashes at the beginning of the line. Three or more dashes are considered
- # to be a rule and ignored.
-
- def remove_private_comment comment
- # Workaround for gsub encoding for Ruby 1.9.2 and earlier
- empty = ''
- empty = RDoc::Encoding.change_encoding empty, comment.encoding
-
- comment = comment.gsub(%r%^--\n.*?^\+\+\n?%m, empty)
- comment.sub(%r%^--\n.*%m, empty)
- end
-
end
diff --git a/lib/rdoc/text.rb b/lib/rdoc/text.rb
index 2350ba4b65..b853c76860 100644
--- a/lib/rdoc/text.rb
+++ b/lib/rdoc/text.rb
@@ -60,7 +60,7 @@ def self.encode_fallback character, encoding, fallback
##
# Expands tab characters in +text+ to eight spaces
- def expand_tabs text
+ module_function def expand_tabs text
expanded = []
text.each_line do |line|
diff --git a/lib/rdoc/tom_doc.rb b/lib/rdoc/tom_doc.rb
index d10f024f70..52b2d3556a 100644
--- a/lib/rdoc/tom_doc.rb
+++ b/lib/rdoc/tom_doc.rb
@@ -49,7 +49,7 @@ def self.add_post_processor # :nodoc:
next unless code_object and
RDoc::Comment === comment and comment.format == 'tomdoc'
- comment.text.gsub!(/(\A\s*# )(Public|Internal|Deprecated):\s+/) do
+ comment.text.gsub!(/\A(\s*# |)(Public|Internal|Deprecated):\s+/) do
section = code_object.add_section $2
code_object.temporary_section = section
diff --git a/test/rdoc/test_rdoc_comment.rb b/test/rdoc/test_rdoc_comment.rb
index 1699575b9d..66a2c658db 100644
--- a/test/rdoc/test_rdoc_comment.rb
+++ b/test/rdoc/test_rdoc_comment.rb
@@ -477,4 +477,231 @@ def test_remove_private_toggle_encoding_ruby_bug?
assert_equal Encoding::IBM437, comment.text.encoding
end
+ def test_parse_directives
+ comment = <<~COMMENT
+ comment1
+ :foo:
+ comment2
+ :bar: baz
+ comment3
+ COMMENT
+ text, directives = RDoc::Comment.parse(comment.chomp, 'file', 1, :simple)
+ assert_equal({ 'foo' => [nil, 2], 'bar' => ['baz', 4] }, directives)
+
+ comment = <<~COMMENT
+ # comment1
+ # :foo:
+ # comment2
+ # :bar: baz
+ # comment3
+ COMMENT
+ text, directives = RDoc::Comment.parse(comment.chomp, 'file', 10, :ruby)
+ assert_equal "comment1\ncomment2\ncomment3", text
+ assert_equal({ 'foo' => [nil, 11], 'bar' => ['baz', 13] }, directives)
+
+ comment = <<~COMMENT
+ /* comment1
+ * :foo:
+ * comment2
+ * :bar: baz
+ * comment3
+ */
+ COMMENT
+ text, directives = RDoc::Comment.parse(comment.chomp, 'file', 100, :c)
+ assert_equal "comment1\ncomment2\ncomment3", text
+ assert_equal({ 'foo' => [nil, 101], 'bar' => ['baz', 103] }, directives)
+ end
+
+ def test_parse_escaped_directives
+ comment = <<~'COMMENT'
+ :foo: a\a
+ \:bar: b\b
+ \:baz\: c\c
+ COMMENT
+ text, directives = RDoc::Comment.parse(comment.chomp, 'file', 1, :simple)
+ assert_equal ":bar: b\\b\n\\:baz\\: c\\c", text
+ assert_equal({ 'foo' => ['a\\a', 1] }, directives)
+ end
+
+ def test_parse_multiline_directive
+ comment = <<~COMMENT
+ # comment1
+ # :call-seq:
+ # a
+ # b
+ # c
+ #
+ # d
+ #
+ # comment2
+ COMMENT
+ text, directives = RDoc::Comment.parse(comment.chomp, 'file', 1, :ruby)
+ assert_equal "comment1\n\ncomment2", text.chomp
+ assert_equal({ 'call-seq' => ["a\n b\nc\n\n d", 2] }, directives)
+
+ # Some c code contains this kind of call-seq
+ comment = <<~COMMENT
+ * comment1
+ * call-seq: new(ptr,
+ * args)
+ *
+ * comment2
+ COMMENT
+ text, directives = RDoc::Comment.parse(comment.chomp, 'file', 1, :c)
+ assert_equal "comment1\n\ncomment2", text
+ assert_equal({ 'call-seq' => ["new(ptr,\nargs)", 2] }, directives)
+
+ comment = <<~COMMENT
+ # comment1
+ # :call-seq: a
+ #
+ # comment2
+ COMMENT
+ text, directives = RDoc::Comment.parse(comment.chomp, 'file', 1, :ruby)
+ assert_equal "comment1\n\ncomment2", text
+ assert_equal({ 'call-seq' => ['a', 2] }, directives)
+
+ comment = <<~COMMENT
+ # comment1
+ # :call-seq:
+ #
+ # comment2
+ COMMENT
+ text, directives = RDoc::Comment.parse(comment.chomp, 'file', 1, :ruby)
+ assert_equal "comment1\n\ncomment2", text
+ assert_equal({ 'call-seq' => [nil, 2] }, directives)
+ end
+
+ def test_parse_directives_with_include
+ comment = <<~COMMENT
+ # comment1
+ # :include: file.txt
+ # comment2
+ # :include: file.txt
+ # :foo: bar
+ # comment3
+ COMMENT
+ text, directives = RDoc::Comment.parse(comment.chomp, 'file', 1, :ruby) do |file, prefix_indent|
+ 2.times.map { |i| "#{prefix_indent}#{file}:#{i}\n" }.join
+ end
+ assert_equal "comment1\nfile.txt:0\nfile.txt:1\ncomment2\n file.txt:0\n file.txt:1\ncomment3", text
+ assert_equal({ 'foo' => ['bar', 5] }, directives)
+ end
+
+ def test_parse_c_comment_with_double_asterisk
+ # Used in ruby/ruby c files
+ comment = <<~COMMENT
+ /**
+ * :foo: bar
+ * comment
+ */
+ COMMENT
+ text, directives = RDoc::Comment.parse(comment.chomp, 'file', 1, :c)
+ assert_equal "comment", text
+ assert_equal({ 'foo' => ['bar', 2] }, directives)
+ end
+
+ def test_parse_confusing_comment
+ verbose, $VERBOSE = $VERBOSE, nil
+ comment = <<~COMMENT
+ /* :foo: value1
+ * :call-seq:
+ * :include: file.txt
+ * :bar: value2 */
+ COMMENT
+ text, directives = RDoc::Comment.parse(comment.chomp, 'file', 1, :c) do |file, prefix_indent|
+ # callseq-content, comment end and directive inside included file with no newline at the end
+ "#{prefix_indent} f(x,y)\n#{prefix_indent}*/\n#{prefix_indent}:baz: blah\n#{prefix_indent}blah"
+ end
+ assert_equal " f(x,y)\n*/\n:baz: blah\nblah", text
+ assert_equal({ 'call-seq' => [nil, 2], 'foo' => ['value1', 1], 'bar' => ['value2', 4] }, directives)
+ ensure
+ $VERBOSE = verbose
+ end
+
+ def test_parse_directives_with_skipping_private_section_ruby
+ verbose, $VERBOSE = $VERBOSE, nil
+ comment = <<~COMMENT
+ # :foo: foo-value
+ #--
+ # private1
+ #++
+ #-
+ # comment1
+ #+
+ # :call-seq:
+ # a(x)
+ #---
+ # private2
+ # :bar: bar-value
+ #++
+ # a(x, y)
+ #
+ #----
+ # private3
+ COMMENT
+ text, directives = RDoc::Comment.parse(comment.chomp, 'file', 1, :ruby)
+ assert_equal "-\n comment1\n+\n a(x, y)", text.chomp
+ assert_equal({ 'foo' => ['foo-value', 1], 'call-seq' => ["a(x)", 8] }, directives)
+
+ # block comment `=begin\n=end` does not start with `#`
+ comment = <<~COMMENT
+ comment1
+ --
+ private1
+ :foo: foo-value
+ ++
+ :bar: bar-value
+ comment2
+ --
+ COMMENT
+ text, directives = RDoc::Comment.parse(comment.chomp, 'file', 1, :ruby)
+ assert_equal "comment1\ncomment2", text.chomp
+ assert_equal({ 'bar' => ['bar-value', 6] }, directives)
+ ensure
+ $VERBOSE = verbose
+ end
+
+ def test_parse_directives_with_skipping_private_section_c
+ comment = <<~COMMENT
+ /*
+ * comment1
+ *--
+ * private1
+ * :foo: foo-value
+ *++
+ * :bar: bar-value
+ * comment2
+ *---
+ * private2
+ */
+ COMMENT
+ text, directives = RDoc::Comment.parse(comment.chomp, 'file', 1, :c)
+ assert_equal "comment1\ncomment2", text.chomp
+ assert_equal({ 'bar' => ['bar-value', 7] }, directives)
+ end
+
+ def test_parse_directives_with_skipping_private_section_simple
+ comment = <<~COMMENT
+ comment1
+ --
+ private1
+ :foo: foo-value
+ ++
+ -
+ comment2
+ +
+ --
+ comment3
+ ++
+ ---
+ comment4
+ :bar: bar-value
+ --
+ private2
+ COMMENT
+ text, directives = RDoc::Comment.parse(comment.chomp, 'file', 1, :simple)
+ assert_equal "comment1\n-\ncomment2\n+\n --\n comment3\n ++\n---\ncomment4", text.chomp
+ assert_equal({ 'bar' => ['bar-value', 14] }, directives)
+ end
end
diff --git a/test/rdoc/test_rdoc_parser.rb b/test/rdoc/test_rdoc_parser.rb
index 7b890f703d..86df920378 100644
--- a/test/rdoc/test_rdoc_parser.rb
+++ b/test/rdoc/test_rdoc_parser.rb
@@ -120,7 +120,7 @@ def test_class_for_modeline
assert_kind_of RDoc::Parser::Simple, parser
- assert_equal "= NEWS\n", parser.content
+ assert_equal "= NEWS", parser.content.chomp
end
end
diff --git a/test/rdoc/test_rdoc_parser_c.rb b/test/rdoc/test_rdoc_parser_c.rb
index ac9b90c6b9..67e6465a65 100644
--- a/test/rdoc/test_rdoc_parser_c.rb
+++ b/test/rdoc/test_rdoc_parser_c.rb
@@ -1467,12 +1467,7 @@ def test_find_modifiers_call_seq
parser.find_modifiers comment, method_obj
- expected = <<-CALL_SEQ.chomp
-commercial() -> Date
-
- CALL_SEQ
-
- assert_equal expected, method_obj.call_seq
+ assert_equal "commercial() -> Date
", method_obj.call_seq.chomp
end
def test_find_modifiers_nodoc
@@ -1508,7 +1503,7 @@ def test_find_modifiers_yields
assert_equal 'a, b', method_obj.block_params
- assert_equal "\n\nBlah", comment.text
+ assert_equal "Blah", comment.text
end
def test_handle_method_args_minus_1
@@ -1630,11 +1625,11 @@ def test_handle_singleton
def test_look_for_directives_in
parser = util_parser
- comment = RDoc::Comment.new "# :other: not_handled\n"
+ comment = RDoc::Comment.new "* :other: not_handled\n"
parser.look_for_directives_in @top_level, comment
- assert_equal "# :other: not_handled\n", comment.text
+ assert_equal "", comment.text
assert_equal 'not_handled', @top_level.metadata['other']
end
@@ -1737,7 +1732,7 @@ def test_define_method
klass = util_get_class content, 'rb_cIO'
read_method = klass.method_list.first
assert_equal "read", read_method.name
- assert_equal "Method Comment! ", read_method.comment.text
+ assert_equal "Method Comment!", read_method.comment.text
assert_equal "rb_io_s_read", read_method.c_function
assert read_method.singleton
assert_nil read_method.section.title
@@ -1814,7 +1809,7 @@ def test_define_method_with_prototype
klass = util_get_class content, 'rb_cIO'
read_method = klass.method_list.first
assert_equal "read", read_method.name
- assert_equal "Method Comment! ", read_method.comment.text
+ assert_equal "Method Comment!", read_method.comment.text
assert_equal "rb_io_s_read", read_method.c_function
assert read_method.singleton
end
@@ -1844,7 +1839,7 @@ def test_define_method_private
read_method = klass.method_list.first
assert_equal 'IO#read', read_method.full_name
assert_equal :private, read_method.visibility
- assert_equal "Method Comment! ", read_method.comment.text
+ assert_equal "Method Comment!", read_method.comment.text
end
def test_define_method_private_singleton
@@ -1872,7 +1867,7 @@ def test_define_method_private_singleton
klass = util_get_class content, 'rb_cIO'
read_method = klass.method_list.first
assert_equal "read", read_method.name
- assert_equal "Method Comment! ", read_method.comment.text
+ assert_equal "Method Comment!", read_method.comment.text
assert_equal :private, read_method.visibility
assert read_method.singleton
end
@@ -1902,7 +1897,7 @@ def test_define_method_singleton
klass = util_get_class content, 'rb_cIO'
read_method = klass.method_list.first
assert_equal "read", read_method.name
- assert_equal "Method Comment! ", read_method.comment.text
+ assert_equal "Method Comment!", read_method.comment.text
assert read_method.singleton
end
diff --git a/test/rdoc/test_rdoc_parser_prism_ruby.rb b/test/rdoc/test_rdoc_parser_prism_ruby.rb
index 627ffd90ad..f3e264eda3 100644
--- a/test/rdoc/test_rdoc_parser_prism_ruby.rb
+++ b/test/rdoc/test_rdoc_parser_prism_ruby.rb
@@ -2135,6 +2135,58 @@ class C
assert_equal expected, m.comment.parse
end
+
+ def test_tomdoc_postprocess
+ RDoc::TomDoc.add_post_processor
+ util_parser <<~RUBY
+ # :markup: tomdoc
+
+ class C
+ # Public: foo
+ # bar
+ def m1; end
+
+ # Internal: baz
+ # blah
+ def m2; end
+ end
+ RUBY
+ klass = @top_level.classes.first
+ m1, m2 = klass.method_list
+ assert_equal 'Public', m1.section.title
+ assert_equal 'Internal', m2.section.title
+ assert_equal "foo\nbar", m1.comment.text.chomp
+ assert_equal "baz\nblah", m2.comment.text.chomp
+ end
+
+ def test_various_callseq
+ util_parser <<~RUBY
+ class Foo
+ # Undocumented form, maybe we should treat it as a single line call-seq
+ # :call-seq: foo1
+ # bar1
+ #
+ # comment
+ def m1; end
+
+ # Blank line between
+ # :call-seq:
+ # ARGF.readlines(a)
+ # ARGF.readlines(b)
+ #
+ # ARGF.readlines(c)
+ #
+ # ARGF.readlines(d)
+ #
+ # comment
+ def m2; end
+ end
+ RUBY
+
+ m1, m2 = @top_level.classes.first.method_list
+ assert_equal "foo1\nbar1", m1.call_seq.chomp
+ assert_equal "ARGF.readlines(a)\nARGF.readlines(b)\nARGF.readlines(c)\nARGF.readlines(d)", m2.call_seq.chomp
+ end
end
class TestRDocParserPrismRuby < RDoc::TestCase
diff --git a/test/rdoc/test_rdoc_parser_simple.rb b/test/rdoc/test_rdoc_parser_simple.rb
index 5c701d0a08..cdb8d2724f 100644
--- a/test/rdoc/test_rdoc_parser_simple.rb
+++ b/test/rdoc/test_rdoc_parser_simple.rb
@@ -26,7 +26,7 @@ def test_initialize_metadata
assert_includes @top_level.metadata, 'unhandled'
- assert_equal ":unhandled: \n", parser.content
+ assert_equal "", parser.content
end
def test_remove_coding_comment
@@ -68,7 +68,7 @@ def test_remove_coding_comment
# # this is a comment
# #---
# # private text
- # #+++
+ # #++
# # this is a rule:
# # ---