docscribe 1.4.1 → 1.4.2
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/README.md +149 -0
- data/lib/docscribe/cli/config_builder.rb +125 -35
- data/lib/docscribe/cli/generate.rb +288 -117
- data/lib/docscribe/cli/init.rb +49 -13
- data/lib/docscribe/cli/options.rb +302 -127
- data/lib/docscribe/cli/run.rb +391 -135
- data/lib/docscribe/cli.rb +23 -5
- data/lib/docscribe/config/defaults.rb +11 -11
- data/lib/docscribe/config/emit.rb +1 -0
- data/lib/docscribe/config/filtering.rb +24 -11
- data/lib/docscribe/config/loader.rb +7 -4
- data/lib/docscribe/config/plugin.rb +1 -0
- data/lib/docscribe/config/rbs.rb +31 -22
- data/lib/docscribe/config/sorbet.rb +41 -15
- data/lib/docscribe/config/sorting.rb +1 -0
- data/lib/docscribe/config/template.rb +1 -0
- data/lib/docscribe/config/utils.rb +1 -0
- data/lib/docscribe/config.rb +1 -0
- data/lib/docscribe/infer/constants.rb +15 -0
- data/lib/docscribe/infer/literals.rb +43 -25
- data/lib/docscribe/infer/names.rb +24 -15
- data/lib/docscribe/infer/params.rb +52 -6
- data/lib/docscribe/infer/raises.rb +24 -14
- data/lib/docscribe/infer/returns.rb +365 -182
- data/lib/docscribe/infer.rb +10 -9
- data/lib/docscribe/inline_rewriter/collector.rb +766 -375
- data/lib/docscribe/inline_rewriter/doc_block.rb +217 -74
- data/lib/docscribe/inline_rewriter/doc_builder.rb +1488 -602
- data/lib/docscribe/inline_rewriter/source_helpers.rb +100 -52
- data/lib/docscribe/inline_rewriter/tag_sorter.rb +109 -48
- data/lib/docscribe/inline_rewriter.rb +1009 -595
- data/lib/docscribe/plugin/base/collector_plugin.rb +2 -3
- data/lib/docscribe/plugin/base/tag_plugin.rb +1 -1
- data/lib/docscribe/plugin/registry.rb +34 -7
- data/lib/docscribe/plugin.rb +48 -17
- data/lib/docscribe/types/rbs/collection_loader.rb +0 -1
- data/lib/docscribe/types/rbs/provider.rb +75 -26
- data/lib/docscribe/types/rbs/type_formatter.rb +127 -59
- data/lib/docscribe/types/sorbet/base_provider.rb +31 -12
- data/lib/docscribe/version.rb +1 -1
- metadata +2 -2
|
@@ -4,6 +4,7 @@ require 'optparse'
|
|
|
4
4
|
|
|
5
5
|
module Docscribe
|
|
6
6
|
module CLI
|
|
7
|
+
# CLI option parsing and defaults.
|
|
7
8
|
module Options
|
|
8
9
|
DEFAULT = {
|
|
9
10
|
stdin: false,
|
|
@@ -12,19 +13,58 @@ module Docscribe
|
|
|
12
13
|
verbose: false,
|
|
13
14
|
explain: false,
|
|
14
15
|
config: nil,
|
|
15
|
-
include: [],
|
|
16
|
-
exclude: [],
|
|
17
|
-
include_file: [],
|
|
18
|
-
exclude_file: [],
|
|
16
|
+
include: [], #: Array[String]
|
|
17
|
+
exclude: [], #: Array[String]
|
|
18
|
+
include_file: [], #: Array[String]
|
|
19
|
+
exclude_file: [], #: Array[String]
|
|
19
20
|
rbs: false,
|
|
20
|
-
sig_dirs: [],
|
|
21
|
+
sig_dirs: [], #: Array[String]
|
|
21
22
|
sorbet: false,
|
|
22
|
-
rbi_dirs: [],
|
|
23
|
+
rbi_dirs: [], #: Array[String]
|
|
23
24
|
rbs_collection: false
|
|
24
25
|
}.freeze
|
|
25
26
|
|
|
26
27
|
module_function
|
|
27
28
|
|
|
29
|
+
BANNER = <<~TEXT
|
|
30
|
+
Usage: docscribe [options] [files...]
|
|
31
|
+
|
|
32
|
+
Default behavior:
|
|
33
|
+
Inspect files and report what safe doc updates would be applied.
|
|
34
|
+
|
|
35
|
+
Autocorrect:
|
|
36
|
+
-a, --autocorrect Apply safe doc updates in place
|
|
37
|
+
(insert missing docs, merge existing doc-like blocks,
|
|
38
|
+
normalize tag order)
|
|
39
|
+
-A, --autocorrect-all Apply aggressive doc updates in place
|
|
40
|
+
(rebuild existing doc blocks)
|
|
41
|
+
|
|
42
|
+
Input / config:
|
|
43
|
+
--stdin Read code from STDIN and print rewritten output
|
|
44
|
+
-C, --config PATH Path to config YAML (default: docscribe.yml)
|
|
45
|
+
|
|
46
|
+
Type information:
|
|
47
|
+
--rbs Use RBS signatures for @param/@return when available
|
|
48
|
+
--sig-dir DIR Add an RBS signature directory (repeatable). Implies `--rbs`.
|
|
49
|
+
--sorbet Use Sorbet signatures from inline sigs / RBI files when available
|
|
50
|
+
--rbi-dir DIR Add a Sorbet RBI directory (repeatable). Implies --sorbet.
|
|
51
|
+
--rbs-collection Auto-discover RBS collection from rbs_collection.lock.yaml. Implies --rbs.
|
|
52
|
+
|
|
53
|
+
Filtering:
|
|
54
|
+
--include PATTERN Include PATTERN (method id or file path; glob or /regex/)
|
|
55
|
+
--exclude PATTERN Exclude PATTERN (method id or file path; glob or /regex/)
|
|
56
|
+
--include-file PATTERN Only process files matching PATTERN (glob or /regex/)
|
|
57
|
+
--exclude-file PATTERN Skip files matching PATTERN (glob or /regex/)
|
|
58
|
+
|
|
59
|
+
Output:
|
|
60
|
+
--verbose Print per-file actions
|
|
61
|
+
-e, --explain Show detailed reasons for changes
|
|
62
|
+
|
|
63
|
+
Other:
|
|
64
|
+
-v, --version Print version and exit
|
|
65
|
+
-h, --help Show this help
|
|
66
|
+
TEXT
|
|
67
|
+
|
|
28
68
|
# Parse CLI arguments into normalized Docscribe runtime options.
|
|
29
69
|
#
|
|
30
70
|
# CLI behavior model:
|
|
@@ -41,126 +81,263 @@ module Docscribe
|
|
|
41
81
|
# @return [Hash] normalized runtime options
|
|
42
82
|
def parse!(argv)
|
|
43
83
|
options = Marshal.load(Marshal.dump(DEFAULT))
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
end
|
|
161
|
-
|
|
162
|
-
|
|
84
|
+
autocorrect = { mode: nil }
|
|
85
|
+
|
|
86
|
+
build_option_parser(options, autocorrect).parse!(argv)
|
|
87
|
+
resolve_mode_and_strategy!(options, autocorrect[:mode])
|
|
88
|
+
options
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Build the OptionParser instance and register all CLI option groups.
|
|
92
|
+
#
|
|
93
|
+
# @note module_function: when included, also defines #build_option_parser (instance visibility: private)
|
|
94
|
+
# @param [Hash] options mutable parsed options hash
|
|
95
|
+
# @param [Hash{Symbol => Symbol,nil}] autocorrect mutable container for autocorrect mode
|
|
96
|
+
# @return [OptionParser]
|
|
97
|
+
def build_option_parser(options, autocorrect)
|
|
98
|
+
OptionParser.new do |opts|
|
|
99
|
+
opts.banner = BANNER
|
|
100
|
+
define_autocorrect_options(opts, autocorrect)
|
|
101
|
+
define_input_options(opts, options)
|
|
102
|
+
define_type_options(opts, options)
|
|
103
|
+
define_filter_options(opts, options)
|
|
104
|
+
define_output_options(opts, options)
|
|
105
|
+
define_misc_options(opts)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
110
|
+
# @private
|
|
111
|
+
# @param [OptionParser] opts
|
|
112
|
+
# @param [Hash{Symbol => Symbol,nil}] autocorrect mutable container for autocorrect mode (:safe, :aggressive, nil)
|
|
113
|
+
# @return [void]
|
|
114
|
+
def define_autocorrect_options(opts, autocorrect)
|
|
115
|
+
opts.on('-a', '--autocorrect', 'Apply safe doc updates in place') do
|
|
116
|
+
autocorrect[:mode] = :safe
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
opts.on('-A', '--autocorrect-all', 'Apply aggressive doc updates in place') do
|
|
120
|
+
autocorrect[:mode] = :aggressive
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
125
|
+
# @private
|
|
126
|
+
# @param [OptionParser] opts
|
|
127
|
+
# @param [Hash] options mutable parsed options hash
|
|
128
|
+
# @return [void]
|
|
129
|
+
def define_input_options(opts, options)
|
|
130
|
+
define_stdin_option(opts, options)
|
|
131
|
+
define_config_option(opts, options)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
135
|
+
# @private
|
|
136
|
+
# @param [OptionParser] opts
|
|
137
|
+
# @param [Hash] options mutable parsed options hash
|
|
138
|
+
# @return [void]
|
|
139
|
+
def define_stdin_option(opts, options)
|
|
140
|
+
opts.on('--stdin', 'Read code from STDIN and print rewritten output') do
|
|
141
|
+
options[:stdin] = true
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
146
|
+
# @private
|
|
147
|
+
# @param [OptionParser] opts
|
|
148
|
+
# @param [Hash] options mutable parsed options hash
|
|
149
|
+
# @return [void]
|
|
150
|
+
def define_config_option(opts, options)
|
|
151
|
+
opts.on('-C', '--config PATH', 'Path to config YAML (default: docscribe.yml)') do |v|
|
|
152
|
+
options[:config] = v
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
157
|
+
# @private
|
|
158
|
+
# @param [OptionParser] opts
|
|
159
|
+
# @param [Hash] options mutable parsed options hash
|
|
160
|
+
# @return [void]
|
|
161
|
+
def define_type_options(opts, options)
|
|
162
|
+
define_rbs_option(opts, options)
|
|
163
|
+
define_sig_dir_option(opts, options)
|
|
164
|
+
define_sorbet_option(opts, options)
|
|
165
|
+
define_rbi_dir_option(opts, options)
|
|
166
|
+
define_rbs_collection_option(opts, options)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
170
|
+
# @private
|
|
171
|
+
# @param [OptionParser] opts
|
|
172
|
+
# @param [Hash] options
|
|
173
|
+
# @return [void]
|
|
174
|
+
def define_rbs_option(opts, options)
|
|
175
|
+
opts.on('--rbs', 'Use RBS signatures for @param/@return when available (falls back to inference)') do
|
|
176
|
+
options[:rbs] = true
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
181
|
+
# @private
|
|
182
|
+
# @param [OptionParser] opts
|
|
183
|
+
# @param [Hash] options
|
|
184
|
+
# @return [void]
|
|
185
|
+
def define_sig_dir_option(opts, options)
|
|
186
|
+
opts.on('--sig-dir DIR', 'Add an RBS signature directory (repeatable). Implies --rbs.') do |v|
|
|
187
|
+
options[:rbs] = true
|
|
188
|
+
options[:sig_dirs] << v
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
193
|
+
# @private
|
|
194
|
+
# @param [OptionParser] opts
|
|
195
|
+
# @param [Hash] options
|
|
196
|
+
# @return [void]
|
|
197
|
+
def define_sorbet_option(opts, options)
|
|
198
|
+
opts.on('--sorbet', 'Use Sorbet signatures from inline sigs / RBI files when available') do
|
|
199
|
+
options[:sorbet] = true
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
204
|
+
# @private
|
|
205
|
+
# @param [OptionParser] opts
|
|
206
|
+
# @param [Hash] options
|
|
207
|
+
# @return [void]
|
|
208
|
+
def define_rbi_dir_option(opts, options)
|
|
209
|
+
opts.on('--rbi-dir DIR', 'Add a Sorbet RBI directory (repeatable). Implies --sorbet.') do |v|
|
|
210
|
+
options[:sorbet] = true
|
|
211
|
+
options[:rbi_dirs] << v
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
216
|
+
# @private
|
|
217
|
+
# @param [OptionParser] opts
|
|
218
|
+
# @param [Hash] options
|
|
219
|
+
# @return [void]
|
|
220
|
+
def define_rbs_collection_option(opts, options)
|
|
221
|
+
opts.on('--rbs-collection', 'Auto-discover RBS collection from rbs_collection.lock.yaml. Implies --rbs.') do
|
|
222
|
+
options[:rbs] = true
|
|
223
|
+
options[:rbs_collection] = true
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
228
|
+
# @private
|
|
229
|
+
# @param [OptionParser] opts
|
|
230
|
+
# @param [Hash] options mutable parsed options hash
|
|
231
|
+
# @return [void]
|
|
232
|
+
def define_filter_options(opts, options)
|
|
233
|
+
define_include_option(opts, options)
|
|
234
|
+
define_exclude_option(opts, options)
|
|
235
|
+
define_include_file_option(opts, options)
|
|
236
|
+
define_exclude_file_option(opts, options)
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
240
|
+
# @private
|
|
241
|
+
# @param [OptionParser] opts
|
|
242
|
+
# @param [Hash] options mutable parsed options hash
|
|
243
|
+
# @return [void]
|
|
244
|
+
def define_include_option(opts, options)
|
|
245
|
+
opts.on('--include PATTERN', 'Include PATTERN (method id or file path; glob or /regex/)') do |v|
|
|
246
|
+
route_include_exclude(options, :include, v)
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
251
|
+
# @private
|
|
252
|
+
# @param [OptionParser] opts
|
|
253
|
+
# @param [Hash] options mutable parsed options hash
|
|
254
|
+
# @return [void]
|
|
255
|
+
def define_exclude_option(opts, options)
|
|
256
|
+
opts.on('--exclude PATTERN',
|
|
257
|
+
'Exclude PATTERN (method id or file path; glob or /regex/). Exclude wins.') do |v|
|
|
258
|
+
route_include_exclude(options, :exclude, v)
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
263
|
+
# @private
|
|
264
|
+
# @param [OptionParser] opts
|
|
265
|
+
# @param [Hash] options mutable parsed options hash
|
|
266
|
+
# @return [void]
|
|
267
|
+
def define_include_file_option(opts, options)
|
|
268
|
+
opts.on('--include-file PATTERN', 'Only process files matching PATTERN (glob or /regex/)') do |v|
|
|
269
|
+
options[:include_file] << v
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
274
|
+
# @private
|
|
275
|
+
# @param [OptionParser] opts
|
|
276
|
+
# @param [Hash] options mutable parsed options hash
|
|
277
|
+
# @return [void]
|
|
278
|
+
def define_exclude_file_option(opts, options)
|
|
279
|
+
opts.on('--exclude-file PATTERN', 'Skip files matching PATTERN (glob or /regex/). Exclude wins.') do |v|
|
|
280
|
+
options[:exclude_file] << v
|
|
281
|
+
end
|
|
282
|
+
end
|
|
163
283
|
|
|
284
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
285
|
+
# @private
|
|
286
|
+
# @param [OptionParser] opts
|
|
287
|
+
# @param [Hash] options mutable parsed options hash
|
|
288
|
+
# @return [void]
|
|
289
|
+
def define_output_options(opts, options)
|
|
290
|
+
define_verbose_option(opts, options)
|
|
291
|
+
define_explain_option(opts, options)
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
295
|
+
# @private
|
|
296
|
+
# @param [OptionParser] opts
|
|
297
|
+
# @param [Hash] options mutable parsed options hash
|
|
298
|
+
# @return [void]
|
|
299
|
+
def define_verbose_option(opts, options)
|
|
300
|
+
opts.on('--verbose', 'Print per-file actions') do
|
|
301
|
+
options[:verbose] = true
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
306
|
+
# @private
|
|
307
|
+
# @param [OptionParser] opts
|
|
308
|
+
# @param [Hash] options mutable parsed options hash
|
|
309
|
+
# @return [void]
|
|
310
|
+
def define_explain_option(opts, options)
|
|
311
|
+
opts.on('-e', '--explain', 'Show detailed reasons for changes') do
|
|
312
|
+
options[:explain] = true
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
317
|
+
# @private
|
|
318
|
+
# @param [OptionParser] opts
|
|
319
|
+
# @return [void]
|
|
320
|
+
def define_misc_options(opts)
|
|
321
|
+
opts.on('-v', '--version', 'Print version and exit') do
|
|
322
|
+
require 'docscribe/version'
|
|
323
|
+
puts Docscribe::VERSION
|
|
324
|
+
exit 0
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
opts.on('-h', '--help', 'Show this help') do
|
|
328
|
+
puts opts
|
|
329
|
+
exit 0
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
# Set the runtime mode and strategy after all options have been parsed.
|
|
334
|
+
#
|
|
335
|
+
# @note module_function: when included, also defines # (instance visibility: private)
|
|
336
|
+
# @private
|
|
337
|
+
# @param [Hash] options mutable parsed options hash
|
|
338
|
+
# @param [Symbol, nil] autocorrect_mode autocorrect mode selected (:safe, :aggressive, or nil)
|
|
339
|
+
# @return [void]
|
|
340
|
+
def resolve_mode_and_strategy!(options, autocorrect_mode)
|
|
164
341
|
if options[:stdin]
|
|
165
342
|
options[:mode] = :stdin
|
|
166
343
|
options[:strategy] = autocorrect_mode || :safe
|
|
@@ -171,8 +348,6 @@ module Docscribe
|
|
|
171
348
|
options[:mode] = :check
|
|
172
349
|
options[:strategy] = :safe
|
|
173
350
|
end
|
|
174
|
-
|
|
175
|
-
options
|
|
176
351
|
end
|
|
177
352
|
|
|
178
353
|
# Route an include/exclude pattern into method filters or file filters.
|