From 83b528abc3d0bf927cfa1041839f04cfe334d099 Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@ruby-lang.org>
Date: Sat, 16 Apr 2022 21:16:51 +0900
Subject: [PATCH] New line-oriented `.document` file format
Introduce the new format similar to the `.gitignore` file by starting
with the comment `rdoc.document: 1`.
- one pattern per line
- negative pattern starting with `!`
- escaping space and `#` by a backslash
---
lib/rdoc/rdoc.rb | 62 ++++++++++++++++++++++++++++++++++---
test/rdoc/test_rdoc_rdoc.rb | 43 +++++++++++++++++++++++++
2 files changed, 100 insertions(+), 5 deletions(-)
diff --git a/lib/rdoc/rdoc.rb b/lib/rdoc/rdoc.rb
index a7f9239b62..04a00cd347 100644
--- a/lib/rdoc/rdoc.rb
+++ b/lib/rdoc/rdoc.rb
@@ -245,15 +245,67 @@ def output_flag_file(op_dir)
# The .document file contains a list of file and directory name patterns,
# representing candidates for documentation. It may also contain comments
# (starting with '#')
+ #
+ # If the first line is the comment starts with +rdoc.document:+
+ # (case-insensitive) followed by a version string, the file is
+ # parsed as per the version. If a version is not written, it is
+ # defaulted to 0.
+ #
+ # version 0::
+ #
+ # The file will be parsed as white-space separated glob patterns.
+ #
+ # - A <tt>#</tt> in middle starts a comment.
+ #
+ # - Multiple patterns can be in a single line.
+ #
+ # - That means patterns cannot contain white-spaces and <tt>#</tt>
+ # marks.
+ #
+ # version 1::
+ #
+ # The file will be parsed as single glob pattern per each line.
+ #
+ # - Only lines starting with <tt>#</tt> at the first colmun are
+ # comments. A <tt>#</tt> in middle is a part of the pattern.
+ #
+ # - Patterns starting with <tt>#</tt> need to be prefixed with a
+ # backslash (<tt>\\</tt>).
+ #
+ # - Leading spaces are not stripped while trailing spaces which
+ # are not escaped with a backslash are stripped.
+ #
+ # - The pattern starting with <tt>!</tt> is a negative pattern,
+ # which rejects matching files.
def parse_dot_doc_file in_dir, filename
- # read and strip comments
- patterns = File.read(filename).gsub(/#.*/, '')
-
result = {}
+ patterns = rejects = nil
+
+ content = File.read(filename)
+ version = content[/\A#+\s*rdoc\.document:\s*\K\S+/i]&.to_i || 0
+ if version >= 1
+ content.each_line(chomp: true) do |line|
+ next if line.start_with?("#") # skip comments
+ line.sub!(/(?<!\\)\s*$/, "") # rstrip unescaped trailing spaces
+ (line.sub!(/\A!/, "") ? (rejects ||= []) : (patterns ||= [])) << line
+ end
+ else
+ # read and strip comments
+ patterns = content.gsub(/#.*/, '').split(' ')
+ end
- patterns.split(' ').each do |patt|
- candidates = Dir.glob(File.join(in_dir, patt))
+ if patterns
+ patterns.each {|patt| patt.sub!(/\A\/+/, "")}
+ candidates = Dir.glob(patterns, base: in_dir)
+ if rejects
+ rejects.each {|patt| patt.sub!(/\A\/+/, "")}
+ flag = File::FNM_PATHNAME
+ candidates.delete_if do |name|
+ rejects.any? {|patt| File.fnmatch?(patt, name, flag)}
+ end
+ end
+ candidates.map! {|name| File.join(in_dir, name)}
result.update normalized_file_list(candidates, false, @options.exclude)
end
diff --git a/test/rdoc/test_rdoc_rdoc.rb b/test/rdoc/test_rdoc_rdoc.rb
index 9c94988ffd..ae7925a6ec 100644
--- a/test/rdoc/test_rdoc_rdoc.rb
+++ b/test/rdoc/test_rdoc_rdoc.rb
@@ -177,6 +177,49 @@ def test_normalized_file_list_with_dot_doc
assert_equal expected_files, files
end
+ def test_normalized_file_list_with_dot_doc_version_1
+ expected_files = []
+ files = temp_dir do |dir|
+ a = 'a.rb'
+ b = 'b.rb'
+ a_b = 'a.rb b.rb'
+ FileUtils.touch a
+ FileUtils.touch b
+ FileUtils.touch a_b
+
+ File.open('.document', 'w') do |f|
+ f.puts '# rdoc.document: 1'
+ f.puts a_b
+ end
+ expected_files << File.expand_path(a_b, dir)
+
+ @rdoc.normalized_file_list [dir]
+ end
+
+ assert_equal expected_files, files.keys
+ end
+
+ def test_normalized_file_list_with_dot_doc_negative_pattern
+ expected_files = []
+ files = temp_dir do |dir|
+ a = 'a.rb'
+ b = 'b.rb'
+ FileUtils.touch a
+ FileUtils.touch b
+
+ File.open('.document', 'w') do |f|
+ f.puts '# rdoc.document: 1'
+ f.puts '*.rb'
+ f.puts '!b.rb'
+ end
+ expected_files << File.expand_path(a, dir)
+
+ @rdoc.normalized_file_list [dir]
+ end
+
+ assert_equal expected_files, files.keys
+ end
+
def test_normalized_file_list_with_dot_doc_overridden_by_exclude_option
expected_files = []
files = temp_dir do |dir|