docscribe 1.4.2 → 1.5.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/README.md +465 -130
- data/lib/docscribe/cli/check_for_comments.rb +183 -0
- data/lib/docscribe/cli/config_builder.rb +107 -53
- data/lib/docscribe/cli/formatters/json.rb +294 -0
- data/lib/docscribe/cli/formatters/sarif.rb +235 -0
- data/lib/docscribe/cli/formatters/text.rb +208 -0
- data/lib/docscribe/cli/formatters.rb +26 -0
- data/lib/docscribe/cli/generate.rb +45 -45
- data/lib/docscribe/cli/init.rb +14 -6
- data/lib/docscribe/cli/options.rb +190 -88
- data/lib/docscribe/cli/rbs_gen.rb +529 -0
- data/lib/docscribe/cli/run.rb +210 -152
- data/lib/docscribe/cli/sigs.rb +366 -0
- data/lib/docscribe/cli/update_types.rb +103 -0
- data/lib/docscribe/cli.rb +21 -13
- data/lib/docscribe/config/defaults.rb +5 -1
- data/lib/docscribe/config/emit.rb +17 -0
- data/lib/docscribe/config/filtering.rb +18 -25
- data/lib/docscribe/config/loader.rb +15 -11
- data/lib/docscribe/config/plugin.rb +1 -1
- data/lib/docscribe/config/rbs.rb +41 -9
- data/lib/docscribe/config/sorbet.rb +9 -12
- data/lib/docscribe/config/sorting.rb +1 -1
- data/lib/docscribe/config/template.rb +9 -1
- data/lib/docscribe/config/utils.rb +11 -9
- data/lib/docscribe/config.rb +2 -4
- data/lib/docscribe/infer/ast_walk.rb +1 -1
- data/lib/docscribe/infer/literals.rb +6 -11
- data/lib/docscribe/infer/names.rb +2 -3
- data/lib/docscribe/infer/params.rb +15 -17
- data/lib/docscribe/infer/raises.rb +3 -5
- data/lib/docscribe/infer/returns.rb +542 -140
- data/lib/docscribe/infer.rb +22 -23
- data/lib/docscribe/inline_rewriter/collector.rb +159 -164
- data/lib/docscribe/inline_rewriter/doc_block.rb +145 -115
- data/lib/docscribe/inline_rewriter/doc_builder.rb +1026 -723
- data/lib/docscribe/inline_rewriter/source_helpers.rb +49 -49
- data/lib/docscribe/inline_rewriter/tag_sorter.rb +82 -85
- data/lib/docscribe/inline_rewriter.rb +495 -492
- data/lib/docscribe/parsing.rb +29 -10
- data/lib/docscribe/plugin/base/collector_plugin.rb +2 -1
- data/lib/docscribe/plugin/base/tag_plugin.rb +0 -1
- data/lib/docscribe/plugin/context.rb +28 -18
- data/lib/docscribe/plugin/registry.rb +26 -27
- data/lib/docscribe/plugin/tag.rb +9 -14
- data/lib/docscribe/plugin.rb +17 -16
- data/lib/docscribe/types/provider_chain.rb +4 -2
- data/lib/docscribe/types/rbs/collection_loader.rb +2 -2
- data/lib/docscribe/types/rbs/provider.rb +60 -44
- data/lib/docscribe/types/rbs/type_formatter.rb +224 -83
- data/lib/docscribe/types/signature.rb +22 -42
- data/lib/docscribe/types/sorbet/base_provider.rb +24 -19
- data/lib/docscribe/types/sorbet/rbi_provider.rb +3 -3
- data/lib/docscribe/types/sorbet/source_provider.rb +3 -2
- data/lib/docscribe/types/yard/formatter.rb +100 -0
- data/lib/docscribe/types/yard/parser.rb +240 -0
- data/lib/docscribe/types/yard/types.rb +52 -0
- data/lib/docscribe/version.rb +1 -1
- metadata +33 -1
data/lib/docscribe/cli/run.rb
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require 'pathname'
|
|
4
4
|
|
|
5
5
|
require 'docscribe/cli/config_builder'
|
|
6
|
+
require 'docscribe/cli/formatters'
|
|
6
7
|
require 'docscribe/inline_rewriter'
|
|
7
8
|
|
|
8
9
|
module Docscribe
|
|
@@ -23,12 +24,16 @@ module Docscribe
|
|
|
23
24
|
checked_ok: 0,
|
|
24
25
|
checked_fail: 0,
|
|
25
26
|
corrected: 0,
|
|
27
|
+
corrected_paths: [], #: Array[String]
|
|
28
|
+
corrected_changes: {}, #: Hash[String, untyped]
|
|
26
29
|
fail_paths: [], #: Array[String]
|
|
27
30
|
fail_changes: {}, #: Hash[String, untyped]
|
|
28
31
|
error_paths: [], #: Array[String]
|
|
29
32
|
error_messages: {}, #: Hash[String, String]
|
|
30
33
|
type_mismatch_paths: [], #: Array[String]
|
|
31
|
-
type_mismatch_changes: {} #: Hash[String, untyped]
|
|
34
|
+
type_mismatch_changes: {}, #: Hash[String, untyped]
|
|
35
|
+
total: 0,
|
|
36
|
+
processed: 0
|
|
32
37
|
}.freeze
|
|
33
38
|
# Run Docscribe for files or STDIN using the selected mode and strategy.
|
|
34
39
|
#
|
|
@@ -41,7 +46,7 @@ module Docscribe
|
|
|
41
46
|
# - :safe => merge/add/normalize non-destructively
|
|
42
47
|
# - :aggressive => rebuild existing doc blocks
|
|
43
48
|
#
|
|
44
|
-
# @param [
|
|
49
|
+
# @param [Docscribe::CLI::Formatters::opts] options parsed CLI options
|
|
45
50
|
# @param [Array<String>] argv remaining path arguments
|
|
46
51
|
# @return [Integer] process exit code
|
|
47
52
|
def run(options:, argv:)
|
|
@@ -57,7 +62,7 @@ module Docscribe
|
|
|
57
62
|
|
|
58
63
|
# Load and build the effective config from CLI options.
|
|
59
64
|
#
|
|
60
|
-
# @param [
|
|
65
|
+
# @param [Docscribe::CLI::Formatters::opts] options parsed CLI options
|
|
61
66
|
# @return [Docscribe::Config] effective config with plugins loaded
|
|
62
67
|
def build_config(options)
|
|
63
68
|
conf = Docscribe::Config.load(options[:config])
|
|
@@ -69,10 +74,11 @@ module Docscribe
|
|
|
69
74
|
# Rewrite code from STDIN using the selected strategy and print the
|
|
70
75
|
# result.
|
|
71
76
|
#
|
|
72
|
-
# @param [
|
|
77
|
+
# @param [Docscribe::CLI::Formatters::opts] options parsed CLI options
|
|
73
78
|
# @param [Docscribe::Config] conf effective config
|
|
74
79
|
# @raise [StandardError]
|
|
75
|
-
# @return [Integer]
|
|
80
|
+
# @return [Integer] if StandardError
|
|
81
|
+
# @return [Integer] if StandardError
|
|
76
82
|
def run_stdin(options:, conf:)
|
|
77
83
|
puts stdin_rewrite_result(options, conf)[:output]
|
|
78
84
|
0
|
|
@@ -83,9 +89,9 @@ module Docscribe
|
|
|
83
89
|
|
|
84
90
|
# Rewrite STDIN input and return the result report.
|
|
85
91
|
#
|
|
86
|
-
# @param [
|
|
92
|
+
# @param [Docscribe::CLI::Formatters::opts] options parsed CLI options
|
|
87
93
|
# @param [Docscribe::Config] conf effective config
|
|
88
|
-
# @return [Hash] rewrite result with :output key
|
|
94
|
+
# @return [Hash<Symbol, Object>] rewrite result with :output key
|
|
89
95
|
def stdin_rewrite_result(options, conf)
|
|
90
96
|
Docscribe::InlineRewriter.rewrite_with_report(
|
|
91
97
|
$stdin.read,
|
|
@@ -99,7 +105,7 @@ module Docscribe
|
|
|
99
105
|
# Return the core RBS provider from the config if available.
|
|
100
106
|
#
|
|
101
107
|
# @param [Docscribe::Config] conf effective config
|
|
102
|
-
# @return [
|
|
108
|
+
# @return [Docscribe::Types::RBS::Provider, nil] core RBS provider or nil
|
|
103
109
|
def core_rbs_provider_for(conf)
|
|
104
110
|
conf.respond_to?(:core_rbs_provider) ? conf.core_rbs_provider : nil
|
|
105
111
|
end
|
|
@@ -115,10 +121,10 @@ module Docscribe
|
|
|
115
121
|
|
|
116
122
|
# Warn and return exit code when no matching files were found.
|
|
117
123
|
#
|
|
118
|
-
# @return [Integer] exit code
|
|
124
|
+
# @return [Integer] exit code 2
|
|
119
125
|
def no_files_found
|
|
120
126
|
warn 'No files found. Pass files or directories (e.g. `docscribe lib`).'
|
|
121
|
-
|
|
127
|
+
2
|
|
122
128
|
end
|
|
123
129
|
|
|
124
130
|
# Expand CLI path arguments into a sorted list of Ruby files.
|
|
@@ -164,7 +170,7 @@ module Docscribe
|
|
|
164
170
|
# - rewrites changed files in place
|
|
165
171
|
# - exits non-zero only if errors occurred
|
|
166
172
|
#
|
|
167
|
-
# @param [
|
|
173
|
+
# @param [Docscribe::CLI::Formatters::opts] options parsed CLI options
|
|
168
174
|
# @param [Docscribe::Config] conf effective config
|
|
169
175
|
# @param [Array<String>] paths Ruby file paths to process
|
|
170
176
|
# @return [Integer] process exit code
|
|
@@ -172,6 +178,7 @@ module Docscribe
|
|
|
172
178
|
$stdout.sync = true
|
|
173
179
|
|
|
174
180
|
state = initial_run_state
|
|
181
|
+
state[:total] = paths.size
|
|
175
182
|
pwd = Pathname.pwd
|
|
176
183
|
|
|
177
184
|
paths.each do |path|
|
|
@@ -188,25 +195,27 @@ module Docscribe
|
|
|
188
195
|
# Print the check or write summary at the end of a run.
|
|
189
196
|
#
|
|
190
197
|
# @private
|
|
191
|
-
# @param [
|
|
192
|
-
# @param [
|
|
198
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
199
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
193
200
|
# @return [void]
|
|
194
201
|
def finalize_run(options, state)
|
|
202
|
+
formatter = Formatters.for(options[:format])
|
|
203
|
+
|
|
195
204
|
if options[:mode] == :check
|
|
196
|
-
|
|
205
|
+
formatter.format_check_summary(state: state, options: options)
|
|
197
206
|
elsif options[:mode] == :write
|
|
198
|
-
|
|
207
|
+
formatter.format_write_summary(state: state, options: options)
|
|
199
208
|
end
|
|
200
209
|
end
|
|
201
210
|
|
|
202
211
|
# Determine the process exit code based on run state and mode.
|
|
203
212
|
#
|
|
204
213
|
# @private
|
|
205
|
-
# @param [
|
|
206
|
-
# @param [
|
|
207
|
-
# @return [Integer] exit code 0
|
|
214
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
215
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
216
|
+
# @return [Integer] exit code: 0 = OK, 1 = findings, 2 = error
|
|
208
217
|
def run_exit_code(options, state)
|
|
209
|
-
return
|
|
218
|
+
return 2 if state[:had_errors]
|
|
210
219
|
return 1 if options[:mode] == :check && state[:changed]
|
|
211
220
|
|
|
212
221
|
0
|
|
@@ -215,7 +224,7 @@ module Docscribe
|
|
|
215
224
|
# Initialize the shared state hash used throughout a run.
|
|
216
225
|
#
|
|
217
226
|
# @private
|
|
218
|
-
# @return [
|
|
227
|
+
# @return [Docscribe::CLI::Formatters::state] initial state with counters and tracking arrays
|
|
219
228
|
def initial_run_state
|
|
220
229
|
Marshal.load(Marshal.dump(INITIAL_RUN_STATE))
|
|
221
230
|
end
|
|
@@ -224,13 +233,14 @@ module Docscribe
|
|
|
224
233
|
#
|
|
225
234
|
# @private
|
|
226
235
|
# @param [String] path file path
|
|
227
|
-
# @param [
|
|
236
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
228
237
|
# @param [Docscribe::Config] conf configuration
|
|
229
238
|
# @param [Pathname] pwd current working directory
|
|
230
|
-
# @param [
|
|
239
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
231
240
|
# @return [void]
|
|
232
241
|
def process_one_file(path, options:, conf:, pwd:, state:)
|
|
233
242
|
display_path = display_path_for(path, pwd: pwd)
|
|
243
|
+
report_progress(state, options, display_path)
|
|
234
244
|
|
|
235
245
|
src = read_source_for_path(path, display_path: display_path, options: options, state: state)
|
|
236
246
|
return unless src
|
|
@@ -243,14 +253,28 @@ module Docscribe
|
|
|
243
253
|
display_path: display_path, options: options, state: state)
|
|
244
254
|
end
|
|
245
255
|
|
|
256
|
+
# Print progress indicator to stderr when --progress is active.
|
|
257
|
+
#
|
|
258
|
+
# @private
|
|
259
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
260
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
261
|
+
# @param [String] display_path path to display
|
|
262
|
+
# @return [void]
|
|
263
|
+
def report_progress(state, options, display_path)
|
|
264
|
+
state[:processed] += 1
|
|
265
|
+
return unless options[:progress]
|
|
266
|
+
|
|
267
|
+
warn "[#{state[:processed]}/#{state[:total]}] #{display_path}"
|
|
268
|
+
end
|
|
269
|
+
|
|
246
270
|
# Dispatch the rewrite result to the check or write handler based on mode.
|
|
247
271
|
#
|
|
248
272
|
# @private
|
|
249
273
|
# @param [String] path file path
|
|
250
274
|
# @param [String] src original source code
|
|
251
275
|
# @param [String] out rewritten source code
|
|
252
|
-
# @param [Array<
|
|
253
|
-
# @param [
|
|
276
|
+
# @param [Array<Docscribe::CLI::Formatters::change>] file_changes structured change records
|
|
277
|
+
# @param [Object] ctx context hash with :options, :state, :display_path, :conf
|
|
254
278
|
# @return [void]
|
|
255
279
|
def dispatch_file_result(path, src:, out:, file_changes:, **ctx)
|
|
256
280
|
if ctx[:options][:mode] == :check
|
|
@@ -269,7 +293,8 @@ module Docscribe
|
|
|
269
293
|
# @param [String] path file path to display
|
|
270
294
|
# @param [Pathname] pwd current working directory
|
|
271
295
|
# @raise [StandardError]
|
|
272
|
-
# @return [String]
|
|
296
|
+
# @return [String] if StandardError
|
|
297
|
+
# @return [Object] if StandardError
|
|
273
298
|
def display_path_for(path, pwd:)
|
|
274
299
|
abs = Pathname.new(path).expand_path
|
|
275
300
|
|
|
@@ -287,17 +312,18 @@ module Docscribe
|
|
|
287
312
|
# @private
|
|
288
313
|
# @param [String] path file path to read
|
|
289
314
|
# @param [String] display_path path shown in CLI output
|
|
290
|
-
# @param [
|
|
291
|
-
# @param [
|
|
315
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
316
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
292
317
|
# @raise [StandardError]
|
|
293
|
-
# @return [String, nil]
|
|
318
|
+
# @return [String, nil] if StandardError
|
|
319
|
+
# @return [nil] if StandardError
|
|
294
320
|
def read_source_for_path(path, display_path:, options:, state:)
|
|
295
321
|
File.read(path)
|
|
296
322
|
rescue StandardError => e
|
|
297
323
|
state[:had_errors] = true
|
|
298
324
|
state[:error_paths] << path
|
|
299
325
|
state[:error_messages][path] = "#{e.class}: #{e.message}"
|
|
300
|
-
options[:verbose] ? warn("ERR #{display_path}: #{state[:error_messages][path]}") : print('E')
|
|
326
|
+
options[:verbose] ? warn("ERR #{display_path}: #{state[:error_messages][path]}") : $stderr.print('E')
|
|
301
327
|
nil
|
|
302
328
|
end
|
|
303
329
|
|
|
@@ -306,13 +332,10 @@ module Docscribe
|
|
|
306
332
|
# @private
|
|
307
333
|
# @param [String] path file path
|
|
308
334
|
# @param [String] src source code
|
|
309
|
-
# @param [
|
|
310
|
-
# @param [String] display_path path shown in CLI output
|
|
311
|
-
# @param [Hash] options CLI options
|
|
312
|
-
# @param [Hash] state shared processing state
|
|
313
|
-
# @param [Hash] ctx context hash with :conf, :display_path, :options, :state keys
|
|
335
|
+
# @param [Hash<Symbol, Object>] ctx context hash with :conf, :display_path, :options, :state keys
|
|
314
336
|
# @raise [StandardError]
|
|
315
|
-
# @return [Hash, nil]
|
|
337
|
+
# @return [Hash<Symbol, Object>, nil] if StandardError
|
|
338
|
+
# @return [nil] if StandardError
|
|
316
339
|
def rewrite_result_for_path(path, src:, ctx:)
|
|
317
340
|
conf = ctx[:conf]
|
|
318
341
|
|
|
@@ -332,7 +355,7 @@ module Docscribe
|
|
|
332
355
|
# @private
|
|
333
356
|
# @param [String] path file path that caused the error
|
|
334
357
|
# @param [StandardError] error the exception raised during rewriting
|
|
335
|
-
# @param [Hash] ctx context hash with :state, :options, :display_path
|
|
358
|
+
# @param [Hash<Symbol, Object>] ctx context hash with :state, :options, :display_path
|
|
336
359
|
# @return [void]
|
|
337
360
|
def record_rewrite_error(path, error, ctx)
|
|
338
361
|
state = ctx[:state]
|
|
@@ -344,7 +367,7 @@ module Docscribe
|
|
|
344
367
|
if ctx[:options][:verbose]
|
|
345
368
|
warn "ERR #{ctx[:display_path]}: #{state[:error_messages][path]}"
|
|
346
369
|
else
|
|
347
|
-
print('E')
|
|
370
|
+
$stderr.print('E')
|
|
348
371
|
end
|
|
349
372
|
end
|
|
350
373
|
|
|
@@ -354,11 +377,8 @@ module Docscribe
|
|
|
354
377
|
# @param [String] path file path
|
|
355
378
|
# @param [String] src original source code
|
|
356
379
|
# @param [String] out rewritten source code
|
|
357
|
-
# @param [Array<
|
|
358
|
-
# @param [
|
|
359
|
-
# @param [Hash] options CLI options
|
|
360
|
-
# @param [Hash] state shared processing state
|
|
361
|
-
# @param [Hash] ctx context hash with :display_path, :options, :state keys
|
|
380
|
+
# @param [Array<Docscribe::CLI::Formatters::change>] file_changes structured change records
|
|
381
|
+
# @param [Object] ctx context hash with :display_path, :options, :state keys
|
|
362
382
|
# @return [void]
|
|
363
383
|
def handle_check_result(path, src:, out:, file_changes:, **ctx)
|
|
364
384
|
type_mismatches = type_mismatch_changes(file_changes)
|
|
@@ -377,8 +397,8 @@ module Docscribe
|
|
|
377
397
|
# Extract type mismatch changes from file_changes.
|
|
378
398
|
#
|
|
379
399
|
# @private
|
|
380
|
-
# @param [Array<
|
|
381
|
-
# @return [Array<
|
|
400
|
+
# @param [Array<Docscribe::CLI::Formatters::change>] file_changes structured change records
|
|
401
|
+
# @return [Array<Docscribe::CLI::Formatters::change>]
|
|
382
402
|
def type_mismatch_changes(file_changes)
|
|
383
403
|
file_changes.select { |c| %i[updated_param updated_return].include?(c[:type]) }
|
|
384
404
|
end
|
|
@@ -386,11 +406,11 @@ module Docscribe
|
|
|
386
406
|
# Handle check result when there are no real changes.
|
|
387
407
|
#
|
|
388
408
|
# @private
|
|
389
|
-
# @param [String] path
|
|
390
|
-
# @param [Array<
|
|
391
|
-
# @param [String] display_path
|
|
392
|
-
# @param [
|
|
393
|
-
# @param [
|
|
409
|
+
# @param [String] path file path
|
|
410
|
+
# @param [Array<Docscribe::CLI::Formatters::change>] type_mismatches type mismatch changes to record
|
|
411
|
+
# @param [String] display_path path shown in CLI output
|
|
412
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
413
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
394
414
|
# @return [void]
|
|
395
415
|
def handle_check_no_changes(path, type_mismatches:, display_path:, options:, state:)
|
|
396
416
|
if type_mismatches.any?
|
|
@@ -404,20 +424,21 @@ module Docscribe
|
|
|
404
424
|
end
|
|
405
425
|
|
|
406
426
|
# Handle a failed check (file needs updates).
|
|
427
|
+
# With --verbose, prints the per-file verdict and all change reasons.
|
|
407
428
|
#
|
|
408
429
|
# @private
|
|
409
|
-
# @param [String] path
|
|
410
|
-
# @param [Array<
|
|
411
|
-
# @param [String] display_path
|
|
412
|
-
# @param [
|
|
413
|
-
# @param [
|
|
430
|
+
# @param [String] path file path
|
|
431
|
+
# @param [Array<Docscribe::CLI::Formatters::change>] file_changes structured change records
|
|
432
|
+
# @param [String] display_path path shown in CLI output
|
|
433
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
434
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
414
435
|
# @return [void]
|
|
415
436
|
def handle_check_failed(path, file_changes:, display_path:, options:, state:)
|
|
416
437
|
if options[:verbose]
|
|
417
|
-
|
|
418
|
-
print_check_explanations(file_changes
|
|
438
|
+
warn("FAIL #{display_path}")
|
|
439
|
+
print_check_explanations(file_changes)
|
|
419
440
|
else
|
|
420
|
-
print('F')
|
|
441
|
+
$stderr.print('F')
|
|
421
442
|
end
|
|
422
443
|
|
|
423
444
|
state[:checked_fail] += 1
|
|
@@ -432,66 +453,84 @@ module Docscribe
|
|
|
432
453
|
# @param [String] path file path
|
|
433
454
|
# @param [String] src original source code
|
|
434
455
|
# @param [String] out rewritten source code
|
|
435
|
-
# @param [Array<
|
|
436
|
-
# @param [
|
|
437
|
-
# @param [Hash] options CLI options
|
|
438
|
-
# @param [Hash] state shared processing state
|
|
439
|
-
# @param [Hash] ctx context hash with :display_path, :options, :state keys
|
|
456
|
+
# @param [Array<Docscribe::CLI::Formatters::change>] file_changes structured change records
|
|
457
|
+
# @param [Object] ctx context hash with :display_path, :options, :state keys
|
|
440
458
|
# @raise [StandardError]
|
|
441
|
-
# @return [void]
|
|
459
|
+
# @return [void] if StandardError
|
|
460
|
+
# @return [Object] if StandardError
|
|
442
461
|
def handle_write_result(path, src:, out:, file_changes:, **ctx)
|
|
443
|
-
if out == src
|
|
444
|
-
log_check_verdict('OK', ctx[:display_path], ctx[:options])
|
|
445
|
-
return
|
|
446
|
-
end
|
|
462
|
+
return log_check_verdict('OK', ctx[:display_path], ctx[:options]) if out == src
|
|
447
463
|
|
|
448
|
-
|
|
449
|
-
log_write_verdict('CHANGED', ctx[:display_path], file_changes, ctx[:options])
|
|
450
|
-
ctx[:state][:corrected] += 1
|
|
464
|
+
apply_correction(path, out, file_changes, ctx)
|
|
451
465
|
rescue StandardError => e
|
|
452
466
|
record_write_error(path, e, display_path: ctx[:display_path], options: ctx[:options], state: ctx[:state])
|
|
453
467
|
end
|
|
454
468
|
|
|
469
|
+
# Apply a file correction — write to disk, log, and update state.
|
|
470
|
+
#
|
|
471
|
+
# @private
|
|
472
|
+
# @param [String] path file path
|
|
473
|
+
# @param [String] out rewritten source code
|
|
474
|
+
# @param [Array<Docscribe::CLI::Formatters::change>] file_changes structured change records
|
|
475
|
+
# @param [Hash<Symbol, Object>] ctx context hash with :display_path, :options, :state keys
|
|
476
|
+
# @return [void]
|
|
477
|
+
def apply_correction(path, out, file_changes, ctx)
|
|
478
|
+
File.write(path, out)
|
|
479
|
+
log_write_verdict('CHANGED', ctx[:display_path], file_changes, ctx[:options])
|
|
480
|
+
update_correction_state(ctx[:state], ctx[:display_path], file_changes)
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
# Update the shared state after a successful correction.
|
|
484
|
+
#
|
|
485
|
+
# @private
|
|
486
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
487
|
+
# @param [String] display_path path shown in CLI output
|
|
488
|
+
# @param [Array<Docscribe::CLI::Formatters::change>] file_changes structured change records
|
|
489
|
+
# @return [void]
|
|
490
|
+
def update_correction_state(state, display_path, file_changes)
|
|
491
|
+
state[:corrected] += 1
|
|
492
|
+
state[:corrected_paths] << display_path
|
|
493
|
+
state[:corrected_changes][display_path] = file_changes
|
|
494
|
+
end
|
|
495
|
+
|
|
455
496
|
# Log a write-mode verdict.
|
|
456
497
|
#
|
|
457
498
|
# @private
|
|
458
|
-
# @param [String] verdict
|
|
459
|
-
# @param [String] display_path
|
|
460
|
-
# @param [Array<
|
|
461
|
-
# @param [
|
|
499
|
+
# @param [String] verdict verdict string to display
|
|
500
|
+
# @param [String] display_path path shown in CLI output
|
|
501
|
+
# @param [Array<Docscribe::CLI::Formatters::change>] file_changes structured change records
|
|
502
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
462
503
|
# @return [void]
|
|
463
504
|
def log_write_verdict(verdict, display_path, file_changes, options)
|
|
464
505
|
if options[:verbose]
|
|
465
|
-
|
|
466
|
-
print_check_explanations(file_changes
|
|
506
|
+
warn("#{verdict} #{display_path}")
|
|
507
|
+
print_check_explanations(file_changes)
|
|
467
508
|
else
|
|
468
|
-
print('C')
|
|
509
|
+
$stderr.print('C')
|
|
469
510
|
end
|
|
470
511
|
end
|
|
471
512
|
|
|
472
513
|
# Print explanations for file changes.
|
|
473
514
|
#
|
|
515
|
+
# Callers are responsible for gating on --verbose / --explain.
|
|
516
|
+
#
|
|
474
517
|
# @private
|
|
475
|
-
# @param [Array<
|
|
476
|
-
# @param [Hash] options
|
|
518
|
+
# @param [Array<Docscribe::CLI::Formatters::change>] file_changes structured change records
|
|
477
519
|
# @return [void]
|
|
478
|
-
def print_check_explanations(file_changes
|
|
479
|
-
return unless options[:explain]
|
|
480
|
-
|
|
520
|
+
def print_check_explanations(file_changes)
|
|
481
521
|
file_changes.each do |change|
|
|
482
|
-
|
|
522
|
+
warn(" - #{format_change_reason(change)}")
|
|
483
523
|
end
|
|
484
524
|
end
|
|
485
525
|
|
|
486
526
|
# Record a write error in state.
|
|
487
527
|
#
|
|
488
528
|
# @private
|
|
489
|
-
# @param [String] path
|
|
490
|
-
# @param [StandardError] e
|
|
491
|
-
# @param [String] display_path
|
|
492
|
-
# @param [Hash] options
|
|
493
|
-
# @param [Hash] state
|
|
529
|
+
# @param [String] path file path
|
|
494
530
|
# @param [StandardError] error the exception raised during file write
|
|
531
|
+
# @param [String] display_path path shown in CLI output
|
|
532
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
533
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
495
534
|
# @return [void]
|
|
496
535
|
def record_write_error(path, error, display_path:, options:, state:)
|
|
497
536
|
state[:had_errors] = true
|
|
@@ -503,40 +542,60 @@ module Docscribe
|
|
|
503
542
|
# Log a per-file check verdict.
|
|
504
543
|
#
|
|
505
544
|
# @private
|
|
506
|
-
# @param [String] verdict
|
|
507
|
-
# @param [String] display_path
|
|
508
|
-
# @param [
|
|
545
|
+
# @param [String] verdict verdict string to display
|
|
546
|
+
# @param [String] display_path path shown in CLI output
|
|
547
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
509
548
|
# @return [void]
|
|
510
549
|
def log_check_verdict(verdict, display_path, options)
|
|
511
550
|
if options[:verbose]
|
|
512
|
-
|
|
551
|
+
warn("#{verdict} #{display_path}")
|
|
513
552
|
else
|
|
514
|
-
print(if verdict == 'FAIL'
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
553
|
+
$stderr.print(if verdict == 'FAIL'
|
|
554
|
+
'F'
|
|
555
|
+
else
|
|
556
|
+
verdict == 'MT' ? 'M' : '.'
|
|
557
|
+
end)
|
|
519
558
|
end
|
|
520
559
|
end
|
|
521
560
|
|
|
522
|
-
# Print the check-mode summary (
|
|
561
|
+
# Print the check-mode summary (fail paths, then status line).
|
|
523
562
|
#
|
|
524
563
|
# @private
|
|
525
|
-
# @param [
|
|
526
|
-
# @param [
|
|
564
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
565
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
527
566
|
# @return [void]
|
|
528
567
|
def print_check_summary(state:, options:)
|
|
529
568
|
puts
|
|
530
|
-
print_check_status_line(state)
|
|
531
569
|
print_fail_paths(state, options)
|
|
570
|
+
print_check_status_line(state)
|
|
532
571
|
print_type_mismatch_paths(state, options)
|
|
533
572
|
print_error_paths(state)
|
|
534
573
|
end
|
|
535
574
|
|
|
575
|
+
public
|
|
576
|
+
|
|
577
|
+
# Print fail paths from check summary (stdout).
|
|
578
|
+
#
|
|
579
|
+
# Skips explanations when --verbose showed them inline per-file.
|
|
580
|
+
#
|
|
581
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
582
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
583
|
+
# @return [void]
|
|
584
|
+
def print_fail_paths(state, options)
|
|
585
|
+
state[:fail_paths].each do |p|
|
|
586
|
+
puts "Would update: #{p}"
|
|
587
|
+
|
|
588
|
+
next if options[:verbose] || options[:quiet]
|
|
589
|
+
|
|
590
|
+
Array(state[:fail_changes][p]).each do |change|
|
|
591
|
+
puts " - #{format_change_reason(change)}"
|
|
592
|
+
end
|
|
593
|
+
end
|
|
594
|
+
end
|
|
595
|
+
|
|
536
596
|
# Print the check-mode status line.
|
|
537
597
|
#
|
|
538
|
-
# @
|
|
539
|
-
# @param [Hash] state
|
|
598
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
540
599
|
# @return [void]
|
|
541
600
|
def print_check_status_line(state)
|
|
542
601
|
checked_error = state[:error_paths].size
|
|
@@ -553,8 +612,7 @@ module Docscribe
|
|
|
553
612
|
|
|
554
613
|
# Whether no failures, errors, or type mismatches occurred.
|
|
555
614
|
#
|
|
556
|
-
# @
|
|
557
|
-
# @param [Hash] state shared processing state
|
|
615
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
558
616
|
# @param [Integer] checked_error number of files with errors
|
|
559
617
|
# @param [Integer] type_mismatch_count number of files with type mismatches
|
|
560
618
|
# @return [Boolean]
|
|
@@ -564,8 +622,7 @@ module Docscribe
|
|
|
564
622
|
|
|
565
623
|
# Whether type mismatches exist but no failures or errors.
|
|
566
624
|
#
|
|
567
|
-
# @
|
|
568
|
-
# @param [Hash] state shared processing state
|
|
625
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
569
626
|
# @param [Integer] checked_error number of files with errors
|
|
570
627
|
# @return [Boolean]
|
|
571
628
|
def mismatch_only?(state, checked_error)
|
|
@@ -574,8 +631,7 @@ module Docscribe
|
|
|
574
631
|
|
|
575
632
|
# Build the human-readable failure summary line for check output.
|
|
576
633
|
#
|
|
577
|
-
# @
|
|
578
|
-
# @param [Hash] state shared processing state
|
|
634
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
579
635
|
# @param [Integer] type_mismatch_count number of files with type mismatches
|
|
580
636
|
# @param [Integer] checked_error number of files with errors
|
|
581
637
|
# @return [String]
|
|
@@ -587,46 +643,61 @@ module Docscribe
|
|
|
587
643
|
"Docscribe: FAILED (#{parts.join(', ')})"
|
|
588
644
|
end
|
|
589
645
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
# Print fail paths from check summary.
|
|
646
|
+
# Print type mismatch paths from check summary.
|
|
593
647
|
#
|
|
594
|
-
# @
|
|
595
|
-
# @param [
|
|
596
|
-
# @param [Hash] options
|
|
648
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
649
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
597
650
|
# @return [void]
|
|
598
|
-
def
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
next unless options[:explain] && !options[:verbose]
|
|
651
|
+
def print_type_mismatch_paths(state, options)
|
|
652
|
+
return if options[:quiet]
|
|
653
|
+
return unless options[:verbose] || options[:explain]
|
|
602
654
|
|
|
603
|
-
|
|
655
|
+
state[:type_mismatch_paths].each do |p|
|
|
656
|
+
warn "Type mismatches: #{p}"
|
|
657
|
+
Array(state[:type_mismatch_changes][p]).each do |change|
|
|
604
658
|
warn " - #{format_change_reason(change)}"
|
|
605
659
|
end
|
|
606
660
|
end
|
|
607
661
|
end
|
|
608
662
|
|
|
609
|
-
# Print
|
|
663
|
+
# Print the write-mode summary (files corrected, errors).
|
|
610
664
|
#
|
|
611
|
-
# @
|
|
612
|
-
# @param [
|
|
613
|
-
# @param [Hash] options
|
|
665
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
666
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
614
667
|
# @return [void]
|
|
615
|
-
def
|
|
616
|
-
|
|
668
|
+
def print_write_summary(state:, options:)
|
|
669
|
+
puts
|
|
670
|
+
puts "Docscribe: updated #{state[:corrected]} file(s)" if state[:corrected].positive?
|
|
671
|
+
print_corrected_paths(state, options)
|
|
617
672
|
|
|
618
|
-
state[:
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
673
|
+
return unless state[:had_errors]
|
|
674
|
+
|
|
675
|
+
warn "Docscribe: #{state[:error_paths].size} file(s) had errors"
|
|
676
|
+
print_error_paths(state)
|
|
677
|
+
end
|
|
678
|
+
|
|
679
|
+
# Print corrected paths from write-mode summary (stdout).
|
|
680
|
+
#
|
|
681
|
+
# Skips explanations when --verbose showed them inline per-file.
|
|
682
|
+
#
|
|
683
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
684
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
685
|
+
# @return [void]
|
|
686
|
+
def print_corrected_paths(state, options)
|
|
687
|
+
state[:corrected_paths].each do |p|
|
|
688
|
+
puts "Updated: #{p}"
|
|
689
|
+
|
|
690
|
+
next if options[:verbose] || options[:quiet]
|
|
691
|
+
|
|
692
|
+
Array(state[:corrected_changes][p]).each do |change|
|
|
693
|
+
puts " - #{format_change_reason(change)}"
|
|
622
694
|
end
|
|
623
695
|
end
|
|
624
696
|
end
|
|
625
697
|
|
|
626
698
|
# Format a structured change record into human-readable CLI output.
|
|
627
699
|
#
|
|
628
|
-
# @
|
|
629
|
-
# @param [Hash] change structured change produced by the inline rewriter
|
|
700
|
+
# @param [Docscribe::CLI::Formatters::change] change structured change produced by the inline rewriter
|
|
630
701
|
# @return [String] human-readable explanation line
|
|
631
702
|
def format_change_reason(change)
|
|
632
703
|
line = change_line_suffix(change)
|
|
@@ -640,7 +711,7 @@ module Docscribe
|
|
|
640
711
|
|
|
641
712
|
# Format the line number suffix for a change reason string.
|
|
642
713
|
#
|
|
643
|
-
# @param [
|
|
714
|
+
# @param [Docscribe::CLI::Formatters::change] change structured change record
|
|
644
715
|
# @return [String] " at line N" or empty
|
|
645
716
|
def change_line_suffix(change)
|
|
646
717
|
change[:line] ? " at line #{change[:line]}" : ''
|
|
@@ -648,7 +719,7 @@ module Docscribe
|
|
|
648
719
|
|
|
649
720
|
# Format the method name suffix for a change reason string.
|
|
650
721
|
#
|
|
651
|
-
# @param [
|
|
722
|
+
# @param [Docscribe::CLI::Formatters::change] change structured change record
|
|
652
723
|
# @return [String] " for method_name" or empty
|
|
653
724
|
def change_method_suffix(change)
|
|
654
725
|
change[:method] ? " for #{change[:method]}" : ''
|
|
@@ -656,7 +727,7 @@ module Docscribe
|
|
|
656
727
|
|
|
657
728
|
# Whether a change type uses its own :message field directly as the reason.
|
|
658
729
|
#
|
|
659
|
-
# @param [
|
|
730
|
+
# @param [Docscribe::CLI::Formatters::change] change structured change record
|
|
660
731
|
# @return [Boolean]
|
|
661
732
|
def direct_message_change?(change)
|
|
662
733
|
%i[
|
|
@@ -669,27 +740,14 @@ module Docscribe
|
|
|
669
740
|
].include?(change[:type])
|
|
670
741
|
end
|
|
671
742
|
|
|
672
|
-
# Print the write-mode summary (files corrected, errors).
|
|
673
|
-
#
|
|
674
|
-
# @private
|
|
675
|
-
# @param [Hash] state shared processing state
|
|
676
|
-
# @return [void]
|
|
677
|
-
def print_write_summary(state:)
|
|
678
|
-
puts
|
|
679
|
-
puts "Docscribe: updated #{state[:corrected]} file(s)" if state[:corrected].positive?
|
|
680
|
-
|
|
681
|
-
return unless state[:had_errors]
|
|
682
|
-
|
|
683
|
-
warn "Docscribe: #{state[:error_paths].size} file(s) had errors"
|
|
684
|
-
print_error_paths(state)
|
|
685
|
-
end
|
|
686
|
-
|
|
687
743
|
# Print error paths from check summary.
|
|
688
744
|
#
|
|
689
|
-
# @
|
|
690
|
-
# @param [Hash] state
|
|
745
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
691
746
|
# @return [void]
|
|
692
747
|
def print_error_paths(state)
|
|
748
|
+
return if state[:error_paths].empty?
|
|
749
|
+
|
|
750
|
+
warn ''
|
|
693
751
|
state[:error_paths].each do |p|
|
|
694
752
|
warn "Error processing: #{p}"
|
|
695
753
|
warn " #{state[:error_messages][p]}" if state[:error_messages][p]
|