diff --git a/lib/rdoc/parser/changelog.rb b/lib/rdoc/parser/changelog.rb index 167892f543..dcc8464990 100644 --- a/lib/rdoc/parser/changelog.rb +++ b/lib/rdoc/parser/changelog.rb @@ -131,6 +131,13 @@ def group_entries entries def parse_entries @time_cache ||= {} + + if /\A((?:.*\n){,3})commit\s/ =~ @content + class << self; prepend Git; end + parse_info($1) + return parse_entries + end + entries = [] entry_name = nil entry_body = [] @@ -190,6 +197,7 @@ def parse_entries def scan @time_cache = {} + entries = parse_entries grouped_entries = group_entries entries @@ -200,5 +208,120 @@ def scan @top_level end + module Git + def parse_info(info) + /^\s*base-url\s*=\s*(.*\S)/ =~ info + @base_url = $1 + end + + def parse_entries + entries = [] + + @content.scan(/^commit\s+(\h{20})\h*\n((?:.+\n)*)\n((?: {4}.*\n+)*)/) do + entry_name, header, entry_body = $1, $2, $3.gsub(/^ {4}/, '') + # header = header.scan(/^ *(\S+?): +(.*)/).to_h + # date = header["CommitDate"] || header["Date"] + date = header[/^ *(?:Author)?Date: +(.*)/, 1] + author = header[/^ *Author: +(.*)/, 1] + if /(\d+)-(\d+)-(\d+) (\d+):(\d+):(\d+) *([-+]\d\d)(\d\d)/ =~ + (header[/^ *CommitDate: +(.*)/, 1] || date) + time = Time.new($1, $2, $3, $4, $5, $6, "#{$7}:#{$8}") + @time_cache[entry_name] = time + author.sub!(/\s*<(.*)>/, '') + email = $1 + entries << [entry_name, [author, email, date, entry_body]] + end + end + + entries + end + + def create_entries entries + # git log entries have no strictly itemized style like the old + # style, just assume Markdown. + entries.map do |commit, entry| + LogEntry.new(@base_url, commit, *entry) + end + end + + LogEntry = Struct.new(:base, :commit, :author, :email, :date, :contents) do + HEADING_LEVEL = 3 + + def initialize(base, commit, author, email, date, contents) + case contents + when String + contents = RDoc::Markdown.parse(contents).parts.each do |body| + case body + when RDoc::Markup::Heading + body.level += HEADING_LEVEL + 1 + end + end + case first = contents[0] + when RDoc::Markup::Paragraph + contents[0] = RDoc::Markup::Heading.new(HEADING_LEVEL + 1, first.text) + end + end + super + end + + def level + HEADING_LEVEL + end + + def aref + "label-#{commit}" + end + + def label context = nil + aref + end + + def text + case base + when nil + "#{date}" + when /%s/ + "{#{date}}[#{base % commit}]" + else + "{#{date}}[#{base}#{commit}]" + end + " {#{author}}[mailto:#{email}]" + end + + def accept visitor + visitor.accept_heading self + begin + if visitor.respond_to?(:code_object=) + code_object = visitor.code_object + visitor.code_object = self + end + contents.each do |body| + body.accept visitor + end + ensure + if visitor.respond_to?(:code_object) + visitor.code_object = code_object + end + end + end + + def pretty_print q # :nodoc: + q.group(2, '[log_entry: ', ']') do + q.text commit + q.text ',' + q.breakable + q.group(2, '[date: ', ']') { q.text date } + q.text ',' + q.breakable + q.group(2, '[author: ', ']') { q.text author } + q.text ',' + q.breakable + q.group(2, '[email: ', ']') { q.text email } + q.text ',' + q.breakable + q.pp contents + end + end + end + end end diff --git a/test/rdoc/test_rdoc_parser_changelog.rb b/test/rdoc/test_rdoc_parser_changelog.rb index d93cb7deca..6a14b61ca2 100644 --- a/test/rdoc/test_rdoc_parser_changelog.rb +++ b/test/rdoc/test_rdoc_parser_changelog.rb @@ -270,6 +270,24 @@ def test_parse_entries_gnu assert_equal expected, parser.parse_entries end + def test_parse_entries_git + parser = util_parser <<-ChangeLog +commit\ 709bed2afaee50e2ce803f87bf1ee8291bea41e3 + Author: git + Date: 2021-01-21 01:03:52 +0900 + + * 2021-01-21 [ci skip] +ChangeLog + + expected = [ + [ "709bed2afaee50e2ce80", + [ "git", "svn-admin@ruby-lang.org", + "2021-01-21 01:03:52 +0900", + "* 2021-01-21 [ci skip]\n"]]] + + assert_equal expected, parser.parse_entries + end + def test_scan parser = util_parser <<-ChangeLog Tue Dec 4 08:32:10 2012 Eric Hodel @@ -309,10 +327,124 @@ def test_scan assert_equal expected, @top_level.comment end + def test_scan_git + parser = util_parser <<-ChangeLog +commit\ 709bed2afaee50e2ce803f87bf1ee8291bea41e3 + Author: git + Date: 2021-01-21 01:03:52 +0900 + + * 2021-01-21 [ci skip] + +commit\ a8dc5156e183489c5121fb1759bda5d9406d9175 + Author: git + Date: 2021-01-20 01:58:26 +0900 + + * 2021-01-20 [ci skip] + +commit\ de5f8a92d5001799bedb3b1a271a2d9b23c6c8fb + Author: Masataka Pocke Kuwabara + Date: 2021-01-01 14:25:08 +0900 + + Make args info for RubyVM::AST to available on endless method without parens + + Problem + === + + Arguments information is missing for endless method without parens. + For example: + + ```ruby + # ok + ``` + + It causes an error if a program expects `args` node exists. + + Solution + === + + Call `new_args` on this case. +ChangeLog + + parser.scan + + expected = doc( + head(1, File.basename(@tempfile.path)), + blank_line, + head(2, '2021-01-21'), + blank_line, + log_entry(nil, '709bed2afaee50e2ce80', + 'git', 'svn-admin@ruby-lang.org', '2021-01-21 01:03:52 +0900', + [list(:BULLET, item(nil, para('2021-01-21 [ci skip]')))]), + head(2, '2021-01-20'), + blank_line, + log_entry(nil, 'a8dc5156e183489c5121', + 'git', 'svn-admin@ruby-lang.org', '2021-01-20 01:58:26 +0900', + [list(:BULLET, item(nil, para('2021-01-20 [ci skip]')))]), + head(2, '2021-01-01'), + blank_line, + log_entry(nil, 'de5f8a92d5001799bedb', + 'Masataka Pocke Kuwabara', 'kuwabara@pocke.me', '2021-01-01 14:25:08 +0900', + [head(4, 'Make args info for RubyVM::AST to available on endless method without parens'), + head(5, 'Problem'), + para("Arguments information is missing for endless method without parens.\n" + + "For example:"), + verb("# ok\n").tap {|v| v.format = :ruby}, + para('It causes an error if a program expects args node exists.'), + head(5, 'Solution'), + para('Call new_args on this case.')])) + + expected.file = @top_level + + assert_equal expected, @top_level.comment + end + + def test_scan_git_commit_date + parser = util_parser <<-ChangeLog +commit\ ee1e690a2df901adb279d7a63fbd92c64e0a5ae6 + Author: Igor Zubkov + AuthorDate: 2016-10-25 03:56:11 +0900 + Commit: Nobuyoshi Nakada + CommitDate: 2021-01-07 13:40:42 +0900 + + We don't need "require 'uri'" after "require 'net/http'". + +commit\ 4d0985a7bd8f591dff4b430e288bfd83af782e51 + Author: git + AuthorDate: 2021-01-07 10:21:34 +0900 + Commit: git + CommitDate: 2021-01-07 10:21:34 +0900 + + * 2021-01-07 [ci skip] +ChangeLog + + parser.scan + + expected = doc( + head(1, File.basename(@tempfile.path)), + blank_line, + head(2, "2021-01-07"), + blank_line, + log_entry(nil, 'ee1e690a2df901adb279', + 'Igor Zubkov', 'igor.zubkov@gmail.com', + '2016-10-25 03:56:11 +0900', + [head(4, %[We don't need "require 'uri'" after "require 'net/http'".])]), + log_entry(nil, '4d0985a7bd8f591dff4b', + 'git', 'svn-admin@ruby-lang.org', + '2021-01-07 10:21:34 +0900', + [list(:BULLET, item(nil, para("2021-01-07 [ci skip]")))])) + + expected.file = @top_level + + assert_equal expected, @top_level.comment + end + def util_parser content = '' RDoc::Parser::ChangeLog.new \ @top_level, @tempfile.path, content, @options, @stats end + def log_entry(*a) + RDoc::Parser::ChangeLog::Git::LogEntry.new(*a) + end end