rdoc 8.0.0 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +1 -3
- data/RI.md +75 -75
- data/exe/rdoc +2 -2
- data/lib/rdoc/code_object/alias.rb +71 -69
- data/lib/rdoc/code_object/any_method.rb +305 -303
- data/lib/rdoc/code_object/attr.rb +150 -148
- data/lib/rdoc/code_object/class_module.rb +798 -792
- data/lib/rdoc/code_object/constant.rb +175 -173
- data/lib/rdoc/code_object/context/section.rb +142 -138
- data/lib/rdoc/code_object/context.rb +926 -958
- data/lib/rdoc/code_object/extend.rb +7 -5
- data/lib/rdoc/code_object/include.rb +7 -5
- data/lib/rdoc/code_object/method_attr.rb +326 -319
- data/lib/rdoc/code_object/mixin.rb +97 -95
- data/lib/rdoc/code_object/normal_class.rb +77 -78
- data/lib/rdoc/code_object/normal_module.rb +61 -59
- data/lib/rdoc/code_object/require.rb +23 -39
- data/lib/rdoc/code_object/single_class.rb +21 -19
- data/lib/rdoc/code_object/top_level.rb +212 -219
- data/lib/rdoc/code_object.rb +305 -303
- data/lib/rdoc/comment.rb +275 -273
- data/lib/rdoc/cross_reference.rb +192 -190
- data/lib/rdoc/encoding.rb +105 -103
- data/lib/rdoc/erb_partial.rb +13 -11
- data/lib/rdoc/erbio.rb +29 -27
- data/lib/rdoc/generator/aliki.rb +161 -153
- data/lib/rdoc/generator/darkfish.rb +645 -635
- data/lib/rdoc/generator/json_index.rb +233 -229
- data/lib/rdoc/generator/markup.rb +164 -146
- data/lib/rdoc/generator/pot/message_extractor.rb +57 -51
- data/lib/rdoc/generator/pot/po.rb +52 -51
- data/lib/rdoc/generator/pot/po_entry.rb +138 -132
- data/lib/rdoc/generator/pot.rb +85 -81
- data/lib/rdoc/generator/ri.rb +23 -19
- data/lib/rdoc/generator/template/aliki/DESIGN.md +6 -4
- data/lib/rdoc/generator/template/aliki/_footer.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/_head.rhtml +10 -10
- data/lib/rdoc/generator/template/aliki/_header.rhtml +29 -44
- data/lib/rdoc/generator/template/aliki/_sidebar_search.rhtml +4 -4
- data/lib/rdoc/generator/template/aliki/css/rdoc.css +207 -178
- data/lib/rdoc/generator/template/aliki/js/aliki.js +60 -84
- data/lib/rdoc/generator/template/darkfish/_footer.rhtml +1 -1
- data/lib/rdoc/generator.rb +48 -46
- data/lib/rdoc/i18n/locale.rb +99 -95
- data/lib/rdoc/i18n/text.rb +109 -105
- data/lib/rdoc/i18n.rb +7 -5
- data/lib/rdoc/markdown/byte_runtime.rb +80 -0
- data/lib/rdoc/markdown.kpeg +15 -11
- data/lib/rdoc/markdown.rb +40 -47
- data/lib/rdoc/markup/block_quote.rb +12 -8
- data/lib/rdoc/markup/document.rb +127 -123
- data/lib/rdoc/markup/formatter.rb +219 -215
- data/lib/rdoc/markup/include.rb +33 -29
- data/lib/rdoc/markup/indented_paragraph.rb +37 -33
- data/lib/rdoc/markup/inline_parser.rb +281 -277
- data/lib/rdoc/markup/list.rb +80 -88
- data/lib/rdoc/markup/list_item.rb +73 -85
- data/lib/rdoc/markup/paragraph.rb +23 -19
- data/lib/rdoc/markup/parser.rb +501 -497
- data/lib/rdoc/markup/pre_process.rb +283 -279
- data/lib/rdoc/markup/raw.rb +2 -2
- data/lib/rdoc/markup/rule.rb +16 -12
- data/lib/rdoc/markup/to_ansi.rb +143 -139
- data/lib/rdoc/markup/to_bs.rb +72 -68
- data/lib/rdoc/markup/to_html.rb +594 -565
- data/lib/rdoc/markup/to_html_crossref.rb +234 -230
- data/lib/rdoc/markup/to_html_snippet.rb +232 -227
- data/lib/rdoc/markup/to_joined_paragraph.rb +36 -32
- data/lib/rdoc/markup/to_label.rb +63 -59
- data/lib/rdoc/markup/to_markdown.rb +212 -208
- data/lib/rdoc/markup/to_rdoc.rb +336 -332
- data/lib/rdoc/markup/to_table_of_contents.rb +66 -62
- data/lib/rdoc/markup/to_test.rb +60 -56
- data/lib/rdoc/markup/to_tt_only.rb +84 -80
- data/lib/rdoc/markup/verbatim.rb +62 -58
- data/lib/rdoc/markup.rb +198 -196
- data/lib/rdoc/options.rb +1063 -1061
- data/lib/rdoc/parser/c.rb +1039 -1037
- data/lib/rdoc/parser/changelog.rb +319 -315
- data/lib/rdoc/parser/markdown.rb +17 -13
- data/lib/rdoc/parser/rbs.rb +239 -235
- data/lib/rdoc/parser/rd.rb +17 -13
- data/lib/rdoc/parser/ruby.rb +1245 -1124
- data/lib/rdoc/parser/ruby_colorizer.rb +263 -213
- data/lib/rdoc/parser/simple.rb +31 -27
- data/lib/rdoc/parser/text.rb +12 -8
- data/lib/rdoc/parser.rb +228 -220
- data/lib/rdoc/rbs_helper.rb +1 -1
- data/lib/rdoc/rd/inline.rb +57 -53
- data/lib/rdoc/rd.rb +90 -88
- data/lib/rdoc/rdoc.rb +500 -491
- data/lib/rdoc/ri/driver.rb +1140 -1135
- data/lib/rdoc/ri/formatter.rb +7 -3
- data/lib/rdoc/ri/paths.rb +140 -136
- data/lib/rdoc/ri/servlet.rb +354 -350
- data/lib/rdoc/ri/store.rb +4 -2
- data/lib/rdoc/ri/task.rb +55 -51
- data/lib/rdoc/ri.rb +14 -12
- data/lib/rdoc/rubygems_hook.rb +183 -181
- data/lib/rdoc/server.rb +349 -347
- data/lib/rdoc/stats/normal.rb +46 -42
- data/lib/rdoc/stats/quiet.rb +39 -35
- data/lib/rdoc/stats/verbose.rb +35 -31
- data/lib/rdoc/stats.rb +365 -363
- data/lib/rdoc/store.rb +888 -902
- data/lib/rdoc/task.rb +260 -256
- data/lib/rdoc/text.rb +135 -133
- data/lib/rdoc/token_stream.rb +101 -93
- data/lib/rdoc/tom_doc.rb +203 -201
- data/lib/rdoc/version.rb +1 -1
- metadata +4 -5
- data/lib/rdoc/markdown/literals.kpeg +0 -21
- data/lib/rdoc/markdown/literals.rb +0 -454
data/lib/rdoc/rdoc.rb
CHANGED
|
@@ -7,191 +7,192 @@ require 'pathname'
|
|
|
7
7
|
require 'time'
|
|
8
8
|
require_relative 'rbs_helper'
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
# This is the driver for generating RDoc output. It handles file parsing and
|
|
12
|
-
# generation of output.
|
|
13
|
-
#
|
|
14
|
-
# To use this class to generate RDoc output via the API, the recommended way
|
|
15
|
-
# is:
|
|
16
|
-
#
|
|
17
|
-
# rdoc = RDoc::RDoc.new
|
|
18
|
-
# options = RDoc::Options.load_options # returns an RDoc::Options instance
|
|
19
|
-
# # set extra options
|
|
20
|
-
# rdoc.document options
|
|
21
|
-
#
|
|
22
|
-
# You can also generate output like the +rdoc+ executable:
|
|
23
|
-
#
|
|
24
|
-
# rdoc = RDoc::RDoc.new
|
|
25
|
-
# rdoc.document argv
|
|
26
|
-
#
|
|
27
|
-
# Where +argv+ is an array of strings, each corresponding to an argument you'd
|
|
28
|
-
# give rdoc on the command line. See <tt>rdoc --help</tt> for details.
|
|
29
|
-
|
|
30
|
-
class RDoc::RDoc
|
|
31
|
-
|
|
32
|
-
@current = nil
|
|
33
|
-
|
|
10
|
+
module RDoc
|
|
34
11
|
##
|
|
35
|
-
# This is the
|
|
12
|
+
# This is the driver for generating RDoc output. It handles file parsing and
|
|
13
|
+
# generation of output.
|
|
14
|
+
#
|
|
15
|
+
# To use this class to generate RDoc output via the API, the recommended way
|
|
16
|
+
# is:
|
|
17
|
+
#
|
|
18
|
+
# rdoc = RDoc::RDoc.new
|
|
19
|
+
# options = RDoc::Options.load_options # returns an RDoc::Options instance
|
|
20
|
+
# # set extra options
|
|
21
|
+
# rdoc.document options
|
|
22
|
+
#
|
|
23
|
+
# You can also generate output like the +rdoc+ executable:
|
|
24
|
+
#
|
|
25
|
+
# rdoc = RDoc::RDoc.new
|
|
26
|
+
# rdoc.document argv
|
|
27
|
+
#
|
|
28
|
+
# Where +argv+ is an array of strings, each corresponding to an argument you'd
|
|
29
|
+
# give rdoc on the command line. See <tt>rdoc --help</tt> for details.
|
|
36
30
|
|
|
37
|
-
|
|
31
|
+
class RDoc
|
|
38
32
|
|
|
39
|
-
|
|
40
|
-
# List of directory names always skipped
|
|
33
|
+
@current = nil
|
|
41
34
|
|
|
42
|
-
|
|
35
|
+
##
|
|
36
|
+
# This is the list of supported output generators
|
|
43
37
|
|
|
44
|
-
|
|
45
|
-
# List of directory names skipped if test suites should be skipped
|
|
38
|
+
GENERATORS = {}
|
|
46
39
|
|
|
47
|
-
|
|
40
|
+
##
|
|
41
|
+
# List of directory names always skipped
|
|
48
42
|
|
|
43
|
+
UNCONDITIONALLY_SKIPPED_DIRECTORIES = %w[CVS .svn .git].freeze
|
|
49
44
|
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
##
|
|
46
|
+
# List of directory names skipped if test suites should be skipped
|
|
52
47
|
|
|
53
|
-
|
|
48
|
+
TEST_SUITE_DIRECTORY_NAMES = %w[spec test].freeze
|
|
54
49
|
|
|
55
|
-
##
|
|
56
|
-
# Hash of files and their last modified times.
|
|
57
50
|
|
|
58
|
-
|
|
51
|
+
##
|
|
52
|
+
# Generator instance used for creating output
|
|
59
53
|
|
|
60
|
-
|
|
61
|
-
# RDoc options
|
|
54
|
+
attr_accessor :generator
|
|
62
55
|
|
|
63
|
-
|
|
56
|
+
##
|
|
57
|
+
# Hash of files and their last modified times.
|
|
64
58
|
|
|
65
|
-
|
|
66
|
-
# Accessor for statistics. Available after each call to parse_files
|
|
59
|
+
attr_reader :last_modified
|
|
67
60
|
|
|
68
|
-
|
|
61
|
+
##
|
|
62
|
+
# RDoc options
|
|
69
63
|
|
|
70
|
-
|
|
71
|
-
# The current documentation store
|
|
64
|
+
attr_accessor :options
|
|
72
65
|
|
|
73
|
-
|
|
66
|
+
##
|
|
67
|
+
# Accessor for statistics. Available after each call to parse_files
|
|
74
68
|
|
|
75
|
-
|
|
76
|
-
# Add +klass+ that can generate output after parsing
|
|
69
|
+
attr_reader :stats
|
|
77
70
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
GENERATORS[name] = klass
|
|
81
|
-
end
|
|
71
|
+
##
|
|
72
|
+
# The current documentation store
|
|
82
73
|
|
|
83
|
-
|
|
84
|
-
# Active RDoc::RDoc instance
|
|
74
|
+
attr_accessor :store
|
|
85
75
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
end
|
|
76
|
+
##
|
|
77
|
+
# Add +klass+ that can generate output after parsing
|
|
89
78
|
|
|
90
|
-
|
|
91
|
-
|
|
79
|
+
def self.add_generator(klass)
|
|
80
|
+
name = klass.name.sub(/^RDoc::Generator::/, '').downcase
|
|
81
|
+
GENERATORS[name] = klass
|
|
82
|
+
end
|
|
92
83
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
end
|
|
84
|
+
##
|
|
85
|
+
# Active RDoc::RDoc instance
|
|
96
86
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
def initialize
|
|
102
|
-
@current = nil
|
|
103
|
-
@generator = nil
|
|
104
|
-
@last_modified = {}
|
|
105
|
-
@old_siginfo = nil
|
|
106
|
-
@options = nil
|
|
107
|
-
@stats = nil
|
|
108
|
-
@store = nil
|
|
109
|
-
end
|
|
87
|
+
def self.current
|
|
88
|
+
@current
|
|
89
|
+
end
|
|
110
90
|
|
|
111
|
-
|
|
112
|
-
|
|
91
|
+
##
|
|
92
|
+
# Sets the active RDoc::RDoc instance
|
|
113
93
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
94
|
+
def self.current=(rdoc)
|
|
95
|
+
@current = rdoc
|
|
96
|
+
end
|
|
117
97
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
98
|
+
##
|
|
99
|
+
# Creates a new RDoc::RDoc instance. Call #document to parse files and
|
|
100
|
+
# generate documentation.
|
|
101
|
+
|
|
102
|
+
def initialize
|
|
103
|
+
@current = nil
|
|
104
|
+
@generator = nil
|
|
105
|
+
@last_modified = {}
|
|
106
|
+
@old_siginfo = nil
|
|
107
|
+
@options = nil
|
|
108
|
+
@stats = nil
|
|
109
|
+
@store = nil
|
|
110
|
+
end
|
|
121
111
|
|
|
122
|
-
|
|
123
|
-
|
|
112
|
+
##
|
|
113
|
+
# Report an error message and exit
|
|
124
114
|
|
|
125
|
-
|
|
115
|
+
def error(msg)
|
|
116
|
+
raise Error, msg
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
##
|
|
120
|
+
# Gathers a set of parseable files from the files and directories listed in
|
|
121
|
+
# +files+.
|
|
122
|
+
|
|
123
|
+
def gather_files(files)
|
|
124
|
+
files = [@options.root.to_s] if files.empty?
|
|
126
125
|
|
|
127
|
-
|
|
126
|
+
file_list = normalized_file_list files, true, @options.exclude
|
|
128
127
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
128
|
+
file_list = remove_duplicate_files(remove_unparseable(file_list))
|
|
129
|
+
|
|
130
|
+
if file_list.count {|name, mtime|
|
|
131
|
+
file_list[name] = @last_modified[name] unless mtime
|
|
132
|
+
mtime
|
|
133
|
+
} > 0
|
|
134
|
+
@last_modified.replace file_list
|
|
135
|
+
file_list.keys.sort
|
|
136
|
+
else
|
|
137
|
+
[]
|
|
138
|
+
end
|
|
137
139
|
end
|
|
138
|
-
end
|
|
139
140
|
|
|
140
|
-
|
|
141
|
-
|
|
141
|
+
##
|
|
142
|
+
# Turns RDoc from stdin into HTML
|
|
142
143
|
|
|
143
|
-
|
|
144
|
-
|
|
144
|
+
def handle_pipe
|
|
145
|
+
@html = Markup::ToHtml.new(pipe: @options.pipe, output_decoration: @options.output_decoration)
|
|
145
146
|
|
|
146
|
-
|
|
147
|
+
parser = Text::MARKUP_FORMAT[@options.markup]
|
|
147
148
|
|
|
148
|
-
|
|
149
|
+
document = parser.parse $stdin.read
|
|
149
150
|
|
|
150
|
-
|
|
151
|
+
out = @html.convert document
|
|
151
152
|
|
|
152
|
-
|
|
153
|
-
|
|
153
|
+
$stdout.write out
|
|
154
|
+
end
|
|
154
155
|
|
|
155
|
-
|
|
156
|
-
|
|
156
|
+
##
|
|
157
|
+
# Installs a siginfo handler that prints the current filename.
|
|
157
158
|
|
|
158
|
-
|
|
159
|
-
|
|
159
|
+
def install_siginfo_handler
|
|
160
|
+
return unless Signal.list.include? 'INFO'
|
|
160
161
|
|
|
161
|
-
|
|
162
|
-
|
|
162
|
+
@old_siginfo = trap 'INFO' do
|
|
163
|
+
puts @current if @current
|
|
164
|
+
end
|
|
163
165
|
end
|
|
164
|
-
end
|
|
165
166
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
167
|
+
##
|
|
168
|
+
# Create an output dir if it doesn't exist. If it does exist, but doesn't
|
|
169
|
+
# contain the flag file <tt>created.rid</tt> then we refuse to use it, as
|
|
170
|
+
# we may clobber some manually generated documentation
|
|
170
171
|
|
|
171
|
-
|
|
172
|
-
|
|
172
|
+
def setup_output_dir(dir, force)
|
|
173
|
+
flag_file = output_flag_file dir
|
|
173
174
|
|
|
174
|
-
|
|
175
|
+
last = {}
|
|
175
176
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
177
|
+
if @options.dry_run
|
|
178
|
+
# do nothing
|
|
179
|
+
elsif File.exist? dir
|
|
180
|
+
error "#{dir} exists and is not a directory" unless File.directory? dir
|
|
180
181
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
182
|
+
begin
|
|
183
|
+
File.open flag_file do |io|
|
|
184
|
+
unless force
|
|
185
|
+
Time.parse io.gets
|
|
186
|
+
|
|
187
|
+
io.each do |line|
|
|
188
|
+
file, time = line.split "\t", 2
|
|
189
|
+
time = Time.parse(time) rescue next
|
|
190
|
+
last[file] = time
|
|
191
|
+
end
|
|
190
192
|
end
|
|
191
193
|
end
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
error <<-ERROR
|
|
194
|
+
rescue SystemCallError, TypeError
|
|
195
|
+
error <<-ERROR
|
|
195
196
|
|
|
196
197
|
Directory #{dir} already exists, but it looks like it isn't an RDoc directory.
|
|
197
198
|
|
|
@@ -200,179 +201,179 @@ you'll need to specify a different output directory name (using the --op <dir>
|
|
|
200
201
|
option)
|
|
201
202
|
|
|
202
203
|
ERROR
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
204
|
+
end unless @options.force_output
|
|
205
|
+
else
|
|
206
|
+
FileUtils.mkdir_p dir
|
|
207
|
+
FileUtils.touch flag_file
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
last
|
|
207
211
|
end
|
|
208
212
|
|
|
209
|
-
|
|
210
|
-
|
|
213
|
+
##
|
|
214
|
+
# Update the flag file in an output directory.
|
|
211
215
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
unless ENV['SOURCE_DATE_EPOCH'].nil?
|
|
218
|
-
time = Time.at(ENV['SOURCE_DATE_EPOCH'].to_i).gmtime
|
|
219
|
-
end
|
|
216
|
+
def update_output_dir(op_dir, time, last = {})
|
|
217
|
+
return if @options.dry_run or not @options.update_output_dir
|
|
218
|
+
unless ENV['SOURCE_DATE_EPOCH'].nil?
|
|
219
|
+
time = Time.at(ENV['SOURCE_DATE_EPOCH'].to_i).gmtime
|
|
220
|
+
end
|
|
220
221
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
222
|
+
File.open output_flag_file(op_dir), "w" do |f|
|
|
223
|
+
f.puts time.rfc2822
|
|
224
|
+
last.each do |n, t|
|
|
225
|
+
f.puts "#{n}\t#{t.rfc2822}"
|
|
226
|
+
end
|
|
225
227
|
end
|
|
226
228
|
end
|
|
227
|
-
end
|
|
228
229
|
|
|
229
|
-
|
|
230
|
-
|
|
230
|
+
##
|
|
231
|
+
# Return the path name of the flag file in an output directory.
|
|
231
232
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
def output_flag_file(op_dir)
|
|
234
|
+
File.join op_dir, "created.rid"
|
|
235
|
+
end
|
|
235
236
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
237
|
+
##
|
|
238
|
+
# The .document file contains a list of file and directory name patterns,
|
|
239
|
+
# representing candidates for documentation. It may also contain comments
|
|
240
|
+
# (starting with '#')
|
|
240
241
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
242
|
+
def parse_dot_doc_file(in_dir, filename)
|
|
243
|
+
# read and strip comments
|
|
244
|
+
patterns = File.read(filename).gsub(/#.*/, '')
|
|
244
245
|
|
|
245
|
-
|
|
246
|
+
result = {}
|
|
246
247
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
248
|
+
patterns.split(' ').each do |patt|
|
|
249
|
+
candidates = Dir.glob(File.join(in_dir, patt))
|
|
250
|
+
result.update normalized_file_list(candidates, false, @options.exclude)
|
|
251
|
+
end
|
|
251
252
|
|
|
252
|
-
|
|
253
|
-
|
|
253
|
+
result
|
|
254
|
+
end
|
|
254
255
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
256
|
+
##
|
|
257
|
+
# Given a list of files and directories, create a list of all the Ruby
|
|
258
|
+
# files they contain.
|
|
259
|
+
#
|
|
260
|
+
# If +force_doc+ is true we always add the given files, if false, only
|
|
261
|
+
# add files that we guarantee we can parse. It is true when looking at
|
|
262
|
+
# files given on the command line, false when recursing through
|
|
263
|
+
# subdirectories.
|
|
264
|
+
#
|
|
265
|
+
# The effect of this is that if you want a file with a non-standard
|
|
266
|
+
# extension parsed, you must name it explicitly.
|
|
267
|
+
|
|
268
|
+
def normalized_file_list(relative_files, force_doc = false,
|
|
269
|
+
exclude_pattern = nil)
|
|
270
|
+
file_list = {}
|
|
271
|
+
|
|
272
|
+
relative_files.each do |rel_file_name|
|
|
273
|
+
rel_file_name = rel_file_name.sub(/^\.\//, '')
|
|
274
|
+
next if rel_file_name.end_with? 'created.rid'
|
|
275
|
+
next if exclude_pattern && exclude_pattern =~ rel_file_name
|
|
276
|
+
stat = File.stat rel_file_name rescue next
|
|
277
|
+
|
|
278
|
+
case type = stat.ftype
|
|
279
|
+
when "file"
|
|
280
|
+
mtime = (stat.mtime unless (last_modified = @last_modified[rel_file_name] and
|
|
281
|
+
stat.mtime.to_i <= last_modified.to_i))
|
|
282
|
+
|
|
283
|
+
if force_doc or Parser.can_parse(rel_file_name)
|
|
284
|
+
file_list[rel_file_name] = mtime
|
|
285
|
+
end
|
|
286
|
+
when "directory"
|
|
287
|
+
next if UNCONDITIONALLY_SKIPPED_DIRECTORIES.include?(rel_file_name)
|
|
287
288
|
|
|
288
|
-
|
|
289
|
-
|
|
289
|
+
basename = File.basename(rel_file_name)
|
|
290
|
+
next if options.skip_tests && TEST_SUITE_DIRECTORY_NAMES.include?(basename)
|
|
290
291
|
|
|
291
|
-
|
|
292
|
-
|
|
292
|
+
created_rid = File.join rel_file_name, "created.rid"
|
|
293
|
+
next if File.file? created_rid
|
|
293
294
|
|
|
294
|
-
|
|
295
|
+
dot_doc = File.join rel_file_name, DOT_DOC_FILENAME
|
|
295
296
|
|
|
296
|
-
|
|
297
|
-
|
|
297
|
+
if File.file? dot_doc
|
|
298
|
+
file_list.update(parse_dot_doc_file(rel_file_name, dot_doc))
|
|
299
|
+
else
|
|
300
|
+
file_list.update(list_files_in_directory(rel_file_name))
|
|
301
|
+
end
|
|
298
302
|
else
|
|
299
|
-
|
|
303
|
+
warn "rdoc can't parse the #{type} #{rel_file_name}"
|
|
300
304
|
end
|
|
301
|
-
else
|
|
302
|
-
warn "rdoc can't parse the #{type} #{rel_file_name}"
|
|
303
305
|
end
|
|
304
|
-
end
|
|
305
306
|
|
|
306
|
-
|
|
307
|
-
|
|
307
|
+
file_list
|
|
308
|
+
end
|
|
308
309
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
310
|
+
##
|
|
311
|
+
# Return a list of the files to be processed in a directory. We know that
|
|
312
|
+
# this directory doesn't have a .document file, so we're looking for real
|
|
313
|
+
# files. However we may well contain subdirectories which must be tested
|
|
314
|
+
# for .document files.
|
|
314
315
|
|
|
315
|
-
|
|
316
|
-
|
|
316
|
+
def list_files_in_directory(dir)
|
|
317
|
+
files = Dir.glob File.join(dir, "*")
|
|
317
318
|
|
|
318
|
-
|
|
319
|
-
|
|
319
|
+
normalized_file_list files, false, @options.exclude
|
|
320
|
+
end
|
|
320
321
|
|
|
321
|
-
|
|
322
|
-
|
|
322
|
+
##
|
|
323
|
+
# Parses +filename+ and returns an RDoc::TopLevel
|
|
323
324
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
325
|
+
def parse_file(filename)
|
|
326
|
+
encoding = @options.encoding
|
|
327
|
+
filename = filename.encode encoding
|
|
327
328
|
|
|
328
|
-
|
|
329
|
+
@stats.add_file filename
|
|
329
330
|
|
|
330
|
-
|
|
331
|
+
return if Parser.binary? filename
|
|
331
332
|
|
|
332
|
-
|
|
333
|
+
content = Encoding.read_file filename, encoding
|
|
333
334
|
|
|
334
|
-
|
|
335
|
+
return unless content
|
|
335
336
|
|
|
336
|
-
|
|
337
|
+
top_level = @store.add_file filename, relative_name: relative_path_for(filename)
|
|
337
338
|
|
|
338
|
-
|
|
339
|
+
parser = Parser.for top_level, content, @options, @stats
|
|
339
340
|
|
|
340
|
-
|
|
341
|
+
return unless parser
|
|
341
342
|
|
|
342
|
-
|
|
343
|
+
parser.scan
|
|
343
344
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
345
|
+
# restart documentation for the classes & modules found
|
|
346
|
+
top_level.classes_or_modules.each do |cm|
|
|
347
|
+
cm.done_documenting = false
|
|
348
|
+
end
|
|
348
349
|
|
|
349
|
-
|
|
350
|
+
top_level
|
|
350
351
|
|
|
351
|
-
|
|
352
|
-
|
|
352
|
+
rescue Errno::EACCES => e
|
|
353
|
+
$stderr.puts <<-EOF
|
|
353
354
|
Unable to read #{filename}, #{e.message}
|
|
354
355
|
|
|
355
356
|
Please check the permissions for this file. Perhaps you do not have access to
|
|
356
357
|
it or perhaps the original author's permissions are to restrictive. If the
|
|
357
358
|
this is not your library please report a bug to the author.
|
|
358
359
|
EOF
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
360
|
+
rescue => e
|
|
361
|
+
syntax_check_command = syntax_check_command_for filename, parser&.class
|
|
362
|
+
syntax_check_message = if syntax_check_command
|
|
363
|
+
<<~MESSAGE
|
|
363
364
|
Before reporting this, could you check that the file you're documenting
|
|
364
365
|
has proper syntax:
|
|
365
366
|
|
|
366
367
|
#{syntax_check_command}
|
|
367
368
|
MESSAGE
|
|
368
|
-
|
|
369
|
-
|
|
369
|
+
else
|
|
370
|
+
<<~MESSAGE
|
|
370
371
|
Before reporting this, could you check that the file you're documenting
|
|
371
372
|
has proper syntax for its language?
|
|
372
373
|
MESSAGE
|
|
373
|
-
|
|
374
|
+
end
|
|
374
375
|
|
|
375
|
-
|
|
376
|
+
$stderr.puts <<-EOF
|
|
376
377
|
#{syntax_check_message}
|
|
377
378
|
RDoc's parsers are not full language parsers and may fail when fed invalid
|
|
378
379
|
source files.
|
|
@@ -383,316 +384,324 @@ The internal error was:
|
|
|
383
384
|
|
|
384
385
|
EOF
|
|
385
386
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
raise e
|
|
389
|
-
end
|
|
387
|
+
$stderr.puts e.backtrace.join("\n\t") if $DEBUG_RDOC
|
|
390
388
|
|
|
391
|
-
|
|
392
|
-
if parser_class == RDoc::Parser::Ruby
|
|
393
|
-
"#{Gem.ruby} -c #{filename}"
|
|
394
|
-
elsif parser_class == RDoc::Parser::C
|
|
395
|
-
cc = ENV['CC']
|
|
396
|
-
cc = 'cc' if cc.nil? || cc.empty?
|
|
397
|
-
"#{cc} -fsyntax-only #{filename}"
|
|
389
|
+
raise e
|
|
398
390
|
end
|
|
399
|
-
end
|
|
400
|
-
|
|
401
|
-
##
|
|
402
|
-
# Returns the relative path for +filename+ against +options.root+ (and
|
|
403
|
-
# +options.page_dir+ when set). This is the key used by RDoc::Store to
|
|
404
|
-
# identify files.
|
|
405
391
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
392
|
+
def syntax_check_command_for(filename, parser_class = Parser.can_parse_by_name(filename))
|
|
393
|
+
if parser_class == Parser::Ruby
|
|
394
|
+
"#{Gem.ruby} -c #{filename}"
|
|
395
|
+
elsif parser_class == Parser::C
|
|
396
|
+
cc = ENV['CC']
|
|
397
|
+
cc = 'cc' if cc.nil? || cc.empty?
|
|
398
|
+
"#{cc} -fsyntax-only #{filename}"
|
|
399
|
+
end
|
|
412
400
|
end
|
|
413
401
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
end
|
|
402
|
+
##
|
|
403
|
+
# Returns the relative path for +filename+ against +options.root+ (and
|
|
404
|
+
# +options.page_dir+ when set). This is the key used by RDoc::Store to
|
|
405
|
+
# identify files.
|
|
419
406
|
|
|
420
|
-
|
|
421
|
-
|
|
407
|
+
def relative_path_for(filename)
|
|
408
|
+
filename_path = Pathname(filename).expand_path
|
|
409
|
+
begin
|
|
410
|
+
relative_path = filename_path.relative_path_from @options.root
|
|
411
|
+
rescue ArgumentError
|
|
412
|
+
relative_path = filename_path
|
|
413
|
+
end
|
|
422
414
|
|
|
423
|
-
|
|
424
|
-
|
|
415
|
+
if @options.page_dir &&
|
|
416
|
+
relative_path.to_s.start_with?(@options.page_dir.to_s)
|
|
417
|
+
relative_path =
|
|
418
|
+
relative_path.relative_path_from @options.page_dir
|
|
419
|
+
end
|
|
425
420
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
@stats = RDoc::Stats.new @store, file_list.length, @options.verbosity
|
|
421
|
+
relative_path.to_s
|
|
422
|
+
end
|
|
429
423
|
|
|
430
|
-
|
|
424
|
+
##
|
|
425
|
+
# Parse each file on the command line, recursively entering directories.
|
|
431
426
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
427
|
+
def parse_files(files)
|
|
428
|
+
file_list = gather_files files
|
|
429
|
+
@stats = Stats.new @store, file_list.length, @options.verbosity
|
|
435
430
|
|
|
436
|
-
|
|
437
|
-
@current = filename
|
|
438
|
-
parse_file filename
|
|
439
|
-
end.compact
|
|
431
|
+
return [] if file_list.empty?
|
|
440
432
|
|
|
441
|
-
|
|
433
|
+
# This workaround can be removed after the :main: directive is removed
|
|
434
|
+
original_options = @options.dup
|
|
435
|
+
@stats.begin_adding
|
|
442
436
|
|
|
443
|
-
|
|
444
|
-
|
|
437
|
+
file_info = file_list.map do |filename|
|
|
438
|
+
@current = filename
|
|
439
|
+
parse_file filename
|
|
440
|
+
end.compact
|
|
445
441
|
|
|
446
|
-
|
|
447
|
-
end
|
|
442
|
+
@store.resolve_c_superclasses
|
|
448
443
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
# files for emacs and vim.
|
|
444
|
+
@stats.done_adding
|
|
445
|
+
@options = original_options
|
|
452
446
|
|
|
453
|
-
|
|
454
|
-
files.reject do |file, *|
|
|
455
|
-
file =~ /\.(?:class|eps|erb|scpt\.txt|svg|ttf|yml)\z/i or
|
|
456
|
-
(file =~ /tags\z/i and
|
|
457
|
-
/\A(\f\n[^,]+,\d+$|!_TAG_)/.match?(File.binread(file, 100)))
|
|
447
|
+
file_info
|
|
458
448
|
end
|
|
459
|
-
end
|
|
460
449
|
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
#
|
|
465
|
-
# +options+ can be either an RDoc::Options instance or an array of strings
|
|
466
|
-
# equivalent to the strings that would be passed on the command line like
|
|
467
|
-
# <tt>%w[-q -o doc -t My\ Doc\ Title]</tt>. #document will automatically
|
|
468
|
-
# call RDoc::Options#finish if an options instance was given.
|
|
469
|
-
#
|
|
470
|
-
# For a list of options, see either RDoc::Options or <tt>rdoc --help</tt>.
|
|
471
|
-
#
|
|
472
|
-
# By default, output will be stored in a directory called "doc" below the
|
|
473
|
-
# current directory, so make sure you're somewhere writable before invoking.
|
|
450
|
+
##
|
|
451
|
+
# Removes file extensions known to be unparseable from +files+ and TAGS
|
|
452
|
+
# files for emacs and vim.
|
|
474
453
|
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
454
|
+
def remove_unparseable(files)
|
|
455
|
+
files.reject do |file, *|
|
|
456
|
+
file =~ /\.(?:class|eps|erb|scpt\.txt|svg|ttf|yml)\z/i or
|
|
457
|
+
(file =~ /tags\z/i and
|
|
458
|
+
/\A(\f\n[^,]+,\d+$|!_TAG_)/.match?(File.binread(file, 100)))
|
|
459
|
+
end
|
|
481
460
|
end
|
|
482
|
-
@options.finish
|
|
483
461
|
|
|
484
|
-
|
|
462
|
+
##
|
|
463
|
+
# Removes duplicate canonical paths while preserving the first path found.
|
|
485
464
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
exit
|
|
465
|
+
def remove_duplicate_files(files)
|
|
466
|
+
files.uniq { |file,| File.realpath(file) }.to_h
|
|
489
467
|
end
|
|
490
468
|
|
|
491
|
-
|
|
492
|
-
|
|
469
|
+
##
|
|
470
|
+
# Generates documentation or a coverage report depending upon the settings
|
|
471
|
+
# in +options+.
|
|
472
|
+
#
|
|
473
|
+
# +options+ can be either an RDoc::Options instance or an array of strings
|
|
474
|
+
# equivalent to the strings that would be passed on the command line like
|
|
475
|
+
# <tt>%w[-q -o doc -t My\ Doc\ Title]</tt>. #document will automatically
|
|
476
|
+
# call RDoc::Options#finish if an options instance was given.
|
|
477
|
+
#
|
|
478
|
+
# For a list of options, see either RDoc::Options or <tt>rdoc --help</tt>.
|
|
479
|
+
#
|
|
480
|
+
# By default, output will be stored in a directory called "doc" below the
|
|
481
|
+
# current directory, so make sure you're somewhere writable before invoking.
|
|
482
|
+
|
|
483
|
+
def document(options)
|
|
484
|
+
if Options === options
|
|
485
|
+
@options = options
|
|
486
|
+
else
|
|
487
|
+
@options = Options.load_options
|
|
488
|
+
@options.parse options
|
|
489
|
+
end
|
|
490
|
+
@options.finish
|
|
493
491
|
|
|
494
|
-
|
|
495
|
-
record_auto_discovered_rbs_signature_mtimes
|
|
492
|
+
@store = Store.new(@options)
|
|
496
493
|
|
|
497
|
-
@options.
|
|
494
|
+
if @options.pipe
|
|
495
|
+
handle_pipe
|
|
496
|
+
exit
|
|
497
|
+
end
|
|
498
498
|
|
|
499
|
-
|
|
500
|
-
|
|
499
|
+
if @options.server_port
|
|
500
|
+
@store.load_cache
|
|
501
501
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
end
|
|
502
|
+
parse_files @options.files
|
|
503
|
+
record_auto_discovered_rbs_signature_mtimes
|
|
505
504
|
|
|
506
|
-
|
|
507
|
-
@last_modified = setup_output_dir @options.op_dir, @options.force_update
|
|
508
|
-
end
|
|
505
|
+
@options.default_title = "RDoc Documentation"
|
|
509
506
|
|
|
510
|
-
|
|
507
|
+
load_auto_discovered_rbs_signatures
|
|
508
|
+
@store.complete @options.visibility
|
|
511
509
|
|
|
512
|
-
|
|
510
|
+
start_server
|
|
511
|
+
exit
|
|
512
|
+
end
|
|
513
513
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
# but not live RDoc::Context objects, so the generator would have nothing
|
|
518
|
-
# to iterate. Force a full reparse so updated signatures show up in the
|
|
519
|
-
# rendered output.
|
|
520
|
-
@last_modified.clear if auto_discovered_rbs_signatures_changed
|
|
514
|
+
unless @options.coverage_report
|
|
515
|
+
@last_modified = setup_output_dir @options.op_dir, @options.force_update
|
|
516
|
+
end
|
|
521
517
|
|
|
522
|
-
|
|
523
|
-
record_auto_discovered_rbs_signature_mtimes
|
|
518
|
+
@start_time = Time.now
|
|
524
519
|
|
|
525
|
-
|
|
520
|
+
@store.load_cache
|
|
526
521
|
|
|
527
|
-
|
|
522
|
+
auto_discovered_rbs_signatures_changed = auto_discovered_rbs_signatures_changed?
|
|
523
|
+
# When only auto-discovered RBS signatures changed, no Ruby file would be
|
|
524
|
+
# reparsed under normal mtime checks. The store cache holds class metadata
|
|
525
|
+
# but not live RDoc::Context objects, so the generator would have nothing
|
|
526
|
+
# to iterate. Force a full reparse so updated signatures show up in the
|
|
527
|
+
# rendered output.
|
|
528
|
+
@last_modified.clear if auto_discovered_rbs_signatures_changed
|
|
528
529
|
|
|
529
|
-
|
|
530
|
+
file_info = parse_files @options.files
|
|
531
|
+
record_auto_discovered_rbs_signature_mtimes
|
|
530
532
|
|
|
531
|
-
|
|
533
|
+
@options.default_title = "RDoc Documentation"
|
|
532
534
|
|
|
533
|
-
|
|
534
|
-
puts
|
|
535
|
+
load_auto_discovered_rbs_signatures
|
|
535
536
|
|
|
536
|
-
|
|
537
|
-
elsif file_info.empty? && !auto_discovered_rbs_signatures_changed then
|
|
538
|
-
$stderr.puts "\nNo newer files." unless @options.quiet
|
|
539
|
-
else
|
|
540
|
-
gen_klass = @options.generator
|
|
537
|
+
@store.complete @options.visibility
|
|
541
538
|
|
|
542
|
-
@
|
|
539
|
+
@stats.coverage_level = @options.coverage_report
|
|
543
540
|
|
|
544
|
-
|
|
545
|
-
|
|
541
|
+
if @options.coverage_report
|
|
542
|
+
puts
|
|
546
543
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
544
|
+
puts @stats.report
|
|
545
|
+
elsif file_info.empty? && !auto_discovered_rbs_signatures_changed
|
|
546
|
+
$stderr.puts "\nNo newer files." unless @options.quiet
|
|
547
|
+
else
|
|
548
|
+
gen_klass = @options.generator
|
|
551
549
|
|
|
552
|
-
|
|
553
|
-
end
|
|
550
|
+
@generator = gen_klass.new @store, @options
|
|
554
551
|
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
# output dir using the generator selected
|
|
558
|
-
# by the RDoc options
|
|
559
|
-
|
|
560
|
-
def generate
|
|
561
|
-
if @options.dry_run then
|
|
562
|
-
# do nothing
|
|
563
|
-
@generator.generate
|
|
564
|
-
else
|
|
565
|
-
Dir.chdir @options.op_dir do
|
|
566
|
-
unless @options.quiet then
|
|
567
|
-
$stderr.puts "\nGenerating #{@generator.class.name.sub(/^.*::/, '')} format into #{Dir.pwd}..."
|
|
568
|
-
uri = "file://#{Dir.pwd}/index.html"
|
|
569
|
-
ref = $stderr.tty? ? "\e]8;;#{uri}\e\\#{uri}\e]8;;\e\\" : uri
|
|
570
|
-
$stderr.puts "\nYou can visit the home page at: #{ref}"
|
|
571
|
-
end
|
|
552
|
+
generate
|
|
553
|
+
end
|
|
572
554
|
|
|
555
|
+
if @stats and (@options.coverage_report or not @options.quiet)
|
|
556
|
+
puts
|
|
557
|
+
puts @stats.summary
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
exit @stats.fully_documented? if @options.coverage_report
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
##
|
|
564
|
+
# Generates documentation for +file_info+ (from #parse_files) into the
|
|
565
|
+
# output dir using the generator selected
|
|
566
|
+
# by the RDoc options
|
|
567
|
+
|
|
568
|
+
def generate
|
|
569
|
+
if @options.dry_run
|
|
570
|
+
# do nothing
|
|
573
571
|
@generator.generate
|
|
574
|
-
|
|
572
|
+
else
|
|
573
|
+
Dir.chdir @options.op_dir do
|
|
574
|
+
unless @options.quiet
|
|
575
|
+
$stderr.puts "\nGenerating #{@generator.class.name.sub(/^.*::/, '')} format into #{Dir.pwd}..."
|
|
576
|
+
uri = "file://#{Dir.pwd}/index.html"
|
|
577
|
+
ref = $stderr.tty? ? "\e]8;;#{uri}\e\\#{uri}\e]8;;\e\\" : uri
|
|
578
|
+
$stderr.puts "\nYou can visit the home page at: #{ref}"
|
|
579
|
+
end
|
|
580
|
+
|
|
581
|
+
@generator.generate
|
|
582
|
+
update_output_dir '.', @start_time, @last_modified
|
|
583
|
+
end
|
|
575
584
|
end
|
|
576
585
|
end
|
|
577
|
-
end
|
|
578
586
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
587
|
+
##
|
|
588
|
+
# Loads RBS type signatures from the project's +sig+ directory and RBS
|
|
589
|
+
# stdlib, then merges them into the store's code objects.
|
|
590
|
+
|
|
591
|
+
def load_auto_discovered_rbs_signatures
|
|
592
|
+
sig_dirs = []
|
|
593
|
+
sig_dir = File.join(@options.root.to_s, 'sig')
|
|
594
|
+
sig_dirs << sig_dir if File.directory?(sig_dir)
|
|
595
|
+
signatures = RbsHelper.load_signatures(*sig_dirs)
|
|
596
|
+
@store.merge_rbs_signatures(signatures)
|
|
597
|
+
rescue RBS::BaseError, Errno::ENOENT, LoadError => e
|
|
598
|
+
# In server mode, a previous successful load may have populated the store;
|
|
599
|
+
# drop those signatures so a now-broken sig file doesn't keep showing
|
|
600
|
+
# stale types alongside the warning.
|
|
601
|
+
@store.clear_rbs_signatures
|
|
602
|
+
@options.warn "Failed to load RBS type signatures: #{e.message}"
|
|
603
|
+
end
|
|
596
604
|
|
|
597
|
-
|
|
598
|
-
|
|
605
|
+
##
|
|
606
|
+
# Returns RBS files that RDoc auto-discovers for signature loading.
|
|
599
607
|
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
608
|
+
def auto_discovered_rbs_signature_files
|
|
609
|
+
Dir[File.join(@options.root.to_s, 'sig', '**', '*.rbs')].sort
|
|
610
|
+
end
|
|
603
611
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
612
|
+
##
|
|
613
|
+
# Returns true if any auto-discovered RBS signature file has changed since
|
|
614
|
+
# the last run.
|
|
607
615
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
616
|
+
def auto_discovered_rbs_signatures_changed?
|
|
617
|
+
current = auto_discovered_rbs_signature_mtimes
|
|
618
|
+
previous = @last_modified.select { |file, _| auto_discovered_rbs_signature_file?(file) }
|
|
611
619
|
|
|
612
|
-
|
|
620
|
+
return true unless (previous.keys - current.keys).empty?
|
|
613
621
|
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
622
|
+
current.any? do |file, mtime|
|
|
623
|
+
last_modified = @last_modified[file]
|
|
624
|
+
last_modified.nil? || mtime.to_i > last_modified.to_i
|
|
625
|
+
end
|
|
617
626
|
end
|
|
618
|
-
end
|
|
619
627
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
628
|
+
##
|
|
629
|
+
# Records auto-discovered RBS signature file mtimes so normal generation
|
|
630
|
+
# freshness checks and the live server watcher can see signature-only edits.
|
|
623
631
|
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
632
|
+
def record_auto_discovered_rbs_signature_mtimes
|
|
633
|
+
@last_modified.reject! { |file, _| auto_discovered_rbs_signature_file?(file) }
|
|
634
|
+
@last_modified.merge! auto_discovered_rbs_signature_mtimes
|
|
635
|
+
end
|
|
628
636
|
|
|
629
|
-
|
|
630
|
-
|
|
637
|
+
##
|
|
638
|
+
# Files watched by the live preview server.
|
|
631
639
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
640
|
+
def watch_files
|
|
641
|
+
(@last_modified.keys + auto_discovered_rbs_signature_files).uniq
|
|
642
|
+
end
|
|
635
643
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
def auto_discovered_rbs_signature_file?(file) # :nodoc:
|
|
643
|
-
return false unless File.extname(file) == '.rbs'
|
|
644
|
-
|
|
645
|
-
root = Pathname(@options.root.to_s).expand_path
|
|
646
|
-
relative_path = Pathname(file).expand_path.relative_path_from root
|
|
647
|
-
relative_path.each_filename.first == 'sig'
|
|
648
|
-
rescue ArgumentError
|
|
649
|
-
# file and root may be on different drives on Windows
|
|
650
|
-
false
|
|
651
|
-
end
|
|
644
|
+
##
|
|
645
|
+
# Returns true for project RBS files that are auto-discovered for signature
|
|
646
|
+
# loading. RDoc parses any selected .rbs file as documentation input, but
|
|
647
|
+
# only +sig/**/*.rbs+ files are loaded through RBS::EnvironmentLoader for
|
|
648
|
+
# type signature merging and live-reload bookkeeping.
|
|
652
649
|
|
|
653
|
-
|
|
654
|
-
|
|
650
|
+
def auto_discovered_rbs_signature_file?(file) # :nodoc:
|
|
651
|
+
return false unless File.extname(file) == '.rbs'
|
|
655
652
|
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
653
|
+
root = Pathname(@options.root.to_s).expand_path
|
|
654
|
+
relative_path = Pathname(file).expand_path.relative_path_from root
|
|
655
|
+
relative_path.each_filename.first == 'sig'
|
|
656
|
+
rescue ArgumentError
|
|
657
|
+
# file and root may be on different drives on Windows
|
|
658
|
+
false
|
|
660
659
|
end
|
|
661
|
-
end
|
|
662
660
|
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
# Called from #document when <tt>--server</tt> is given.
|
|
661
|
+
##
|
|
662
|
+
# Returns mtimes for auto-discovered RBS signature files.
|
|
666
663
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
664
|
+
def auto_discovered_rbs_signature_mtimes # :nodoc:
|
|
665
|
+
auto_discovered_rbs_signature_files.each_with_object({}) do |file, mtimes|
|
|
666
|
+
mtime = ::RDoc.safe_mtime(file)
|
|
667
|
+
mtimes[file] = mtime if mtime
|
|
668
|
+
end
|
|
669
|
+
end
|
|
671
670
|
|
|
672
|
-
|
|
673
|
-
|
|
671
|
+
##
|
|
672
|
+
# Starts a live-reloading HTTP server for previewing documentation.
|
|
673
|
+
# Called from #document when <tt>--server</tt> is given.
|
|
674
674
|
|
|
675
|
-
|
|
676
|
-
|
|
675
|
+
def start_server
|
|
676
|
+
server = Server.new(self, @options.server_port)
|
|
677
|
+
server.start
|
|
678
|
+
end
|
|
677
679
|
|
|
678
|
-
|
|
680
|
+
##
|
|
681
|
+
# Removes a siginfo handler and replaces the previous
|
|
679
682
|
|
|
680
|
-
|
|
681
|
-
|
|
683
|
+
def remove_siginfo_handler
|
|
684
|
+
return unless Signal.list.key? 'INFO'
|
|
682
685
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
686
|
+
handler = @old_siginfo || 'DEFAULT'
|
|
687
|
+
|
|
688
|
+
trap 'INFO', handler
|
|
689
|
+
end
|
|
690
|
+
|
|
691
|
+
##
|
|
692
|
+
# Returns true when +extension+ is the RBS gem's RDoc discovery hook.
|
|
693
|
+
# Released RBS gems install their plugin through this hook, so skip it to
|
|
694
|
+
# avoid replacing the built-in parser during discovery.
|
|
687
695
|
|
|
688
|
-
|
|
689
|
-
|
|
696
|
+
def self.rbs_discovery_extension?(extension) # :nodoc:
|
|
697
|
+
extension = File.expand_path(extension)
|
|
690
698
|
|
|
691
|
-
|
|
692
|
-
|
|
699
|
+
Gem::Specification.find_all_by_name('rbs').any? do |spec|
|
|
700
|
+
File.expand_path('lib/rdoc/discover.rb', spec.full_gem_path) == extension
|
|
701
|
+
end
|
|
693
702
|
end
|
|
694
|
-
end
|
|
695
703
|
|
|
704
|
+
end
|
|
696
705
|
end
|
|
697
706
|
|
|
698
707
|
# Load built-in parser registrations before RubyGems discovery, then skip the
|