From fa0ecc80348aed4173e6eb8806ec82460f3ea3ce Mon Sep 17 00:00:00 2001 From: sjh9714 <163989462+sjh9714@users.noreply.github.com> Date: Tue, 11 Aug 2026 10:12:23 +0900 Subject: [PATCH] Do not select the Ruby parser for non-Ruby files with markup: markdown RDoc::Parser.for consulted use_markup before any file-name-based selection, and use_markup unconditionally mapped the markdown and tomdoc markup formats to the Ruby parser. A C file with /* :markup: markdown */ in its first three lines was therefore parsed as Ruby source. Pass the file name into use_markup and return the Ruby parser for these formats only when the file name selects the Ruby parser (or when no file name is given, preserving the documented behavior for direct callers). Other files fall through to the regular shebang and extension logic, so the C file above is parsed as C while the :markup: directive still sets the comment format. --- lib/rdoc/parser.rb | 18 +++++++++++---- test/rdoc/parser/parser_test.rb | 40 +++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/lib/rdoc/parser.rb b/lib/rdoc/parser.rb index 8e01ef9379..f5f1ddf541 100644 --- a/lib/rdoc/parser.rb +++ b/lib/rdoc/parser.rb @@ -170,7 +170,7 @@ def self.for(top_level, content, options, stats) file_name = top_level.absolute_name return if binary? file_name - parser = use_markup content + parser = use_markup content, file_name unless parser then parse_name = file_name @@ -228,14 +228,24 @@ def self.remove_modeline(content) # appear on the second or third line. # # Any comment style may be used to hide the markup comment. + # + # The +tomdoc+ and +markdown+ markups name comment formats rather than + # parsers, so they select the Ruby parser only when the given +file_name+ + # is a Ruby file (or when no +file_name+ is given). - def self.use_markup(content) + def self.use_markup(content, file_name = nil) markup = content.lines.first(3).grep(/markup:\s+(\w+)/) { $1 }.first return unless markup - # TODO Ruby should be returned only when the filename is correct - return RDoc::Parser::Ruby if %w[tomdoc markdown].include? markup + # tomdoc and markdown are comment formats, not parsers, so they imply + # the Ruby parser only when the file name does not select another parser + if %w[tomdoc markdown].include? markup then + return RDoc::Parser::Ruby if file_name.nil? or + can_parse_by_name(file_name) == RDoc::Parser::Ruby + + return + end markup = Regexp.escape markup diff --git a/test/rdoc/parser/parser_test.rb b/test/rdoc/parser/parser_test.rb index 590aeeef91..f68fde71dd 100644 --- a/test/rdoc/parser/parser_test.rb +++ b/test/rdoc/parser/parser_test.rb @@ -227,6 +227,28 @@ def test_class_for_markup end end + def test_class_for_markup_markdown_c_file + content = <<-CONTENT +/* file.c */ +/* :markup: markdown */ + +/* method comment */ +VALUE rb_a_foo(VALUE self) { +} + CONTENT + + file_name = File.join Dir.tmpdir, "file.c" + File.write file_name, content + + top_level = @store.add_file file_name + + parser = @RP.for top_level, content, @options, :stats + + assert_kind_of @RP::C, parser + ensure + File.unlink file_name + end + def test_class_use_markup content = <<-CONTENT # coding: utf-8 markup: rd @@ -247,6 +269,15 @@ def test_class_use_markup_markdown assert_equal @RP::Ruby, parser end + def test_class_use_markup_markdown_file_name + content = <<-CONTENT +# coding: utf-8 markup: markdown + CONTENT + + assert_equal @RP::Ruby, @RP.use_markup(content, 'file.rb') + assert_nil @RP.use_markup(content, 'file.c') + end + def test_class_use_markup_modeline content = <<-CONTENT # -*- coding: utf-8 -*- @@ -292,6 +323,15 @@ def test_class_use_markup_tomdoc assert_equal @RP::Ruby, parser end + def test_class_use_markup_tomdoc_file_name + content = <<-CONTENT +# coding: utf-8 markup: tomdoc + CONTENT + + assert_equal @RP::Ruby, @RP.use_markup(content, 'file.rb') + assert_nil @RP.use_markup(content, 'file.c') + end + def test_class_use_markup_none parser = @RP.use_markup ''