docscribe 1.4.1 → 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 +588 -104
- data/lib/docscribe/cli/check_for_comments.rb +183 -0
- data/lib/docscribe/cli/config_builder.rb +180 -36
- 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 +296 -125
- data/lib/docscribe/cli/init.rb +58 -14
- data/lib/docscribe/cli/options.rb +410 -133
- data/lib/docscribe/cli/rbs_gen.rb +529 -0
- data/lib/docscribe/cli/run.rb +503 -189
- data/lib/docscribe/cli/sigs.rb +366 -0
- data/lib/docscribe/cli/update_types.rb +103 -0
- data/lib/docscribe/cli.rb +35 -9
- data/lib/docscribe/config/defaults.rb +16 -12
- data/lib/docscribe/config/emit.rb +18 -0
- data/lib/docscribe/config/filtering.rb +37 -31
- data/lib/docscribe/config/loader.rb +20 -13
- data/lib/docscribe/config/plugin.rb +2 -1
- data/lib/docscribe/config/rbs.rb +68 -27
- data/lib/docscribe/config/sorbet.rb +40 -17
- data/lib/docscribe/config/sorting.rb +2 -1
- data/lib/docscribe/config/template.rb +10 -1
- data/lib/docscribe/config/utils.rb +12 -9
- data/lib/docscribe/config.rb +3 -4
- data/lib/docscribe/infer/ast_walk.rb +1 -1
- data/lib/docscribe/infer/constants.rb +15 -0
- data/lib/docscribe/infer/literals.rb +39 -26
- data/lib/docscribe/infer/names.rb +24 -16
- data/lib/docscribe/infer/params.rb +57 -13
- data/lib/docscribe/infer/raises.rb +23 -15
- data/lib/docscribe/infer/returns.rb +784 -199
- data/lib/docscribe/infer.rb +28 -28
- data/lib/docscribe/inline_rewriter/collector.rb +816 -430
- data/lib/docscribe/inline_rewriter/doc_block.rb +323 -150
- data/lib/docscribe/inline_rewriter/doc_builder.rb +1837 -648
- data/lib/docscribe/inline_rewriter/source_helpers.rb +119 -71
- data/lib/docscribe/inline_rewriter/tag_sorter.rb +165 -107
- data/lib/docscribe/inline_rewriter.rb +1144 -727
- data/lib/docscribe/parsing.rb +29 -10
- data/lib/docscribe/plugin/base/collector_plugin.rb +3 -3
- data/lib/docscribe/plugin/base/tag_plugin.rb +1 -2
- data/lib/docscribe/plugin/context.rb +28 -18
- data/lib/docscribe/plugin/registry.rb +49 -23
- data/lib/docscribe/plugin/tag.rb +9 -14
- data/lib/docscribe/plugin.rb +54 -22
- data/lib/docscribe/types/provider_chain.rb +4 -2
- data/lib/docscribe/types/rbs/collection_loader.rb +2 -3
- data/lib/docscribe/types/rbs/provider.rb +127 -62
- data/lib/docscribe/types/rbs/type_formatter.rb +286 -77
- data/lib/docscribe/types/signature.rb +22 -42
- data/lib/docscribe/types/sorbet/base_provider.rb +51 -27
- 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 +34 -2
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
|
|
@@ -17,6 +18,23 @@ module Docscribe
|
|
|
17
18
|
# - process exit status
|
|
18
19
|
module Run
|
|
19
20
|
class << self
|
|
21
|
+
INITIAL_RUN_STATE = {
|
|
22
|
+
changed: false,
|
|
23
|
+
had_errors: false,
|
|
24
|
+
checked_ok: 0,
|
|
25
|
+
checked_fail: 0,
|
|
26
|
+
corrected: 0,
|
|
27
|
+
corrected_paths: [], #: Array[String]
|
|
28
|
+
corrected_changes: {}, #: Hash[String, untyped]
|
|
29
|
+
fail_paths: [], #: Array[String]
|
|
30
|
+
fail_changes: {}, #: Hash[String, untyped]
|
|
31
|
+
error_paths: [], #: Array[String]
|
|
32
|
+
error_messages: {}, #: Hash[String, String]
|
|
33
|
+
type_mismatch_paths: [], #: Array[String]
|
|
34
|
+
type_mismatch_changes: {}, #: Hash[String, untyped]
|
|
35
|
+
total: 0,
|
|
36
|
+
processed: 0
|
|
37
|
+
}.freeze
|
|
20
38
|
# Run Docscribe for files or STDIN using the selected mode and strategy.
|
|
21
39
|
#
|
|
22
40
|
# Modes:
|
|
@@ -28,50 +46,87 @@ module Docscribe
|
|
|
28
46
|
# - :safe => merge/add/normalize non-destructively
|
|
29
47
|
# - :aggressive => rebuild existing doc blocks
|
|
30
48
|
#
|
|
31
|
-
# @param [
|
|
49
|
+
# @param [Docscribe::CLI::Formatters::opts] options parsed CLI options
|
|
32
50
|
# @param [Array<String>] argv remaining path arguments
|
|
33
51
|
# @return [Integer] process exit code
|
|
34
52
|
def run(options:, argv:)
|
|
35
|
-
conf =
|
|
36
|
-
conf = Docscribe::CLI::ConfigBuilder.build(conf, options)
|
|
37
|
-
conf.load_plugins!
|
|
53
|
+
conf = build_config(options)
|
|
38
54
|
|
|
39
55
|
return run_stdin(options: options, conf: conf) if options[:mode] == :stdin
|
|
40
56
|
|
|
41
|
-
paths =
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if paths.empty?
|
|
45
|
-
warn 'No files found. Pass files or directories (e.g. `docscribe lib`).'
|
|
46
|
-
return 1
|
|
47
|
-
end
|
|
57
|
+
paths = filtered_paths(argv, conf)
|
|
58
|
+
return no_files_found unless paths.any?
|
|
48
59
|
|
|
49
60
|
run_files(options: options, conf: conf, paths: paths)
|
|
50
61
|
end
|
|
51
62
|
|
|
63
|
+
# Load and build the effective config from CLI options.
|
|
64
|
+
#
|
|
65
|
+
# @param [Docscribe::CLI::Formatters::opts] options parsed CLI options
|
|
66
|
+
# @return [Docscribe::Config] effective config with plugins loaded
|
|
67
|
+
def build_config(options)
|
|
68
|
+
conf = Docscribe::Config.load(options[:config])
|
|
69
|
+
conf = Docscribe::CLI::ConfigBuilder.build(conf, options)
|
|
70
|
+
conf.load_plugins!
|
|
71
|
+
conf
|
|
72
|
+
end
|
|
73
|
+
|
|
52
74
|
# Rewrite code from STDIN using the selected strategy and print the
|
|
53
75
|
# result.
|
|
54
76
|
#
|
|
55
|
-
# @param [
|
|
77
|
+
# @param [Docscribe::CLI::Formatters::opts] options parsed CLI options
|
|
56
78
|
# @param [Docscribe::Config] conf effective config
|
|
57
79
|
# @raise [StandardError]
|
|
58
|
-
# @return [Integer]
|
|
80
|
+
# @return [Integer] if StandardError
|
|
81
|
+
# @return [Integer] if StandardError
|
|
59
82
|
def run_stdin(options:, conf:)
|
|
60
|
-
|
|
61
|
-
result = Docscribe::InlineRewriter.rewrite_with_report(
|
|
62
|
-
code,
|
|
63
|
-
strategy: options[:strategy],
|
|
64
|
-
config: conf,
|
|
65
|
-
core_rbs_provider: conf.respond_to?(:core_rbs_provider) ? conf.core_rbs_provider : nil,
|
|
66
|
-
file: '(stdin)'
|
|
67
|
-
)
|
|
68
|
-
puts result[:output]
|
|
83
|
+
puts stdin_rewrite_result(options, conf)[:output]
|
|
69
84
|
0
|
|
70
85
|
rescue StandardError => e
|
|
71
86
|
warn "Docscribe: Error processing stdin: #{e.class}: #{e.message}"
|
|
72
87
|
1
|
|
73
88
|
end
|
|
74
89
|
|
|
90
|
+
# Rewrite STDIN input and return the result report.
|
|
91
|
+
#
|
|
92
|
+
# @param [Docscribe::CLI::Formatters::opts] options parsed CLI options
|
|
93
|
+
# @param [Docscribe::Config] conf effective config
|
|
94
|
+
# @return [Hash<Symbol, Object>] rewrite result with :output key
|
|
95
|
+
def stdin_rewrite_result(options, conf)
|
|
96
|
+
Docscribe::InlineRewriter.rewrite_with_report(
|
|
97
|
+
$stdin.read,
|
|
98
|
+
strategy: options[:strategy],
|
|
99
|
+
config: conf,
|
|
100
|
+
core_rbs_provider: core_rbs_provider_for(conf),
|
|
101
|
+
file: '(stdin)'
|
|
102
|
+
)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Return the core RBS provider from the config if available.
|
|
106
|
+
#
|
|
107
|
+
# @param [Docscribe::Config] conf effective config
|
|
108
|
+
# @return [Docscribe::Types::RBS::Provider, nil] core RBS provider or nil
|
|
109
|
+
def core_rbs_provider_for(conf)
|
|
110
|
+
conf.respond_to?(:core_rbs_provider) ? conf.core_rbs_provider : nil
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Expand CLI path arguments and filter through config file patterns.
|
|
114
|
+
#
|
|
115
|
+
# @param [Array<String>] argv CLI path arguments
|
|
116
|
+
# @param [Docscribe::Config] conf effective config
|
|
117
|
+
# @return [Array<String>] filtered Ruby file paths
|
|
118
|
+
def filtered_paths(argv, conf)
|
|
119
|
+
expand_paths(argv).select { |path| conf.process_file?(path) }
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Warn and return exit code when no matching files were found.
|
|
123
|
+
#
|
|
124
|
+
# @return [Integer] exit code 2
|
|
125
|
+
def no_files_found
|
|
126
|
+
warn 'No files found. Pass files or directories (e.g. `docscribe lib`).'
|
|
127
|
+
2
|
|
128
|
+
end
|
|
129
|
+
|
|
75
130
|
# Expand CLI path arguments into a sorted list of Ruby files.
|
|
76
131
|
#
|
|
77
132
|
# Directories are expanded recursively to `**/*.rb`.
|
|
@@ -80,22 +135,31 @@ module Docscribe
|
|
|
80
135
|
# @param [Array<String>] args file and/or directory arguments
|
|
81
136
|
# @return [Array<String>] unique sorted Ruby file paths
|
|
82
137
|
def expand_paths(args)
|
|
83
|
-
files = []
|
|
138
|
+
files = [] #: Array[String]
|
|
84
139
|
args = ['.'] if args.empty?
|
|
85
140
|
|
|
86
141
|
args.each do |path|
|
|
87
|
-
|
|
88
|
-
files.concat(Dir.glob(File.join(path, '**', '*.rb')))
|
|
89
|
-
elsif File.file?(path)
|
|
90
|
-
files << path
|
|
91
|
-
else
|
|
92
|
-
warn "Skipping missing path: #{path}"
|
|
93
|
-
end
|
|
142
|
+
append_expanded_path(files, path)
|
|
94
143
|
end
|
|
95
144
|
|
|
96
145
|
files.uniq.sort
|
|
97
146
|
end
|
|
98
147
|
|
|
148
|
+
# Append a file or recursively expand a directory into the files array.
|
|
149
|
+
#
|
|
150
|
+
# @param [Array<String>] files mutable file path accumulator
|
|
151
|
+
# @param [String] path file or directory path to expand
|
|
152
|
+
# @return [void]
|
|
153
|
+
def append_expanded_path(files, path)
|
|
154
|
+
if File.directory?(path)
|
|
155
|
+
files.concat(Dir.glob(File.join(path, '**', '*.rb')))
|
|
156
|
+
elsif File.file?(path)
|
|
157
|
+
files << path
|
|
158
|
+
else
|
|
159
|
+
warn "Skipping missing path: #{path}"
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
99
163
|
# Process file paths in inspect or write mode.
|
|
100
164
|
#
|
|
101
165
|
# In inspect mode:
|
|
@@ -106,7 +170,7 @@ module Docscribe
|
|
|
106
170
|
# - rewrites changed files in place
|
|
107
171
|
# - exits non-zero only if errors occurred
|
|
108
172
|
#
|
|
109
|
-
# @param [
|
|
173
|
+
# @param [Docscribe::CLI::Formatters::opts] options parsed CLI options
|
|
110
174
|
# @param [Docscribe::Config] conf effective config
|
|
111
175
|
# @param [Array<String>] paths Ruby file paths to process
|
|
112
176
|
# @return [Integer] process exit code
|
|
@@ -114,88 +178,109 @@ module Docscribe
|
|
|
114
178
|
$stdout.sync = true
|
|
115
179
|
|
|
116
180
|
state = initial_run_state
|
|
181
|
+
state[:total] = paths.size
|
|
117
182
|
pwd = Pathname.pwd
|
|
118
183
|
|
|
119
184
|
paths.each do |path|
|
|
120
185
|
process_one_file(path, options: options, conf: conf, pwd: pwd, state: state)
|
|
121
186
|
end
|
|
122
187
|
|
|
188
|
+
finalize_run(options, state)
|
|
189
|
+
|
|
190
|
+
run_exit_code(options, state)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
private
|
|
194
|
+
|
|
195
|
+
# Print the check or write summary at the end of a run.
|
|
196
|
+
#
|
|
197
|
+
# @private
|
|
198
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
199
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
200
|
+
# @return [void]
|
|
201
|
+
def finalize_run(options, state)
|
|
202
|
+
formatter = Formatters.for(options[:format])
|
|
203
|
+
|
|
123
204
|
if options[:mode] == :check
|
|
124
|
-
|
|
205
|
+
formatter.format_check_summary(state: state, options: options)
|
|
125
206
|
elsif options[:mode] == :write
|
|
126
|
-
|
|
207
|
+
formatter.format_write_summary(state: state, options: options)
|
|
127
208
|
end
|
|
209
|
+
end
|
|
128
210
|
|
|
129
|
-
|
|
211
|
+
# Determine the process exit code based on run state and mode.
|
|
212
|
+
#
|
|
213
|
+
# @private
|
|
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
|
|
217
|
+
def run_exit_code(options, state)
|
|
218
|
+
return 2 if state[:had_errors]
|
|
130
219
|
return 1 if options[:mode] == :check && state[:changed]
|
|
131
220
|
|
|
132
221
|
0
|
|
133
222
|
end
|
|
134
223
|
|
|
135
|
-
private
|
|
136
|
-
|
|
137
224
|
# Initialize the shared state hash used throughout a run.
|
|
138
225
|
#
|
|
139
226
|
# @private
|
|
140
|
-
# @return [
|
|
227
|
+
# @return [Docscribe::CLI::Formatters::state] initial state with counters and tracking arrays
|
|
141
228
|
def initial_run_state
|
|
142
|
-
|
|
143
|
-
changed: false,
|
|
144
|
-
had_errors: false,
|
|
145
|
-
checked_ok: 0,
|
|
146
|
-
checked_fail: 0,
|
|
147
|
-
corrected: 0,
|
|
148
|
-
fail_paths: [],
|
|
149
|
-
fail_changes: {},
|
|
150
|
-
error_paths: [],
|
|
151
|
-
error_messages: {},
|
|
152
|
-
type_mismatch_paths: [],
|
|
153
|
-
type_mismatch_changes: {}
|
|
154
|
-
}
|
|
229
|
+
Marshal.load(Marshal.dump(INITIAL_RUN_STATE))
|
|
155
230
|
end
|
|
156
231
|
|
|
157
232
|
# Process a single file: read, rewrite, and dispatch to check/write handler.
|
|
158
233
|
#
|
|
159
234
|
# @private
|
|
160
235
|
# @param [String] path file path
|
|
161
|
-
# @param [
|
|
236
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
162
237
|
# @param [Docscribe::Config] conf configuration
|
|
163
238
|
# @param [Pathname] pwd current working directory
|
|
164
|
-
# @param [
|
|
239
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
165
240
|
# @return [void]
|
|
166
241
|
def process_one_file(path, options:, conf:, pwd:, state:)
|
|
167
242
|
display_path = display_path_for(path, pwd: pwd)
|
|
243
|
+
report_progress(state, options, display_path)
|
|
168
244
|
|
|
169
245
|
src = read_source_for_path(path, display_path: display_path, options: options, state: state)
|
|
170
246
|
return unless src
|
|
171
247
|
|
|
172
|
-
|
|
173
|
-
|
|
248
|
+
ctx = { conf: conf, display_path: display_path, options: options, state: state }
|
|
249
|
+
result = rewrite_result_for_path(path, src: src, ctx: ctx)
|
|
174
250
|
return unless result
|
|
175
251
|
|
|
176
|
-
out
|
|
177
|
-
|
|
252
|
+
dispatch_file_result(path, src: src, out: result[:output], file_changes: result[:changes] || [],
|
|
253
|
+
display_path: display_path, options: options, state: state)
|
|
254
|
+
end
|
|
178
255
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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
|
+
|
|
270
|
+
# Dispatch the rewrite result to the check or write handler based on mode.
|
|
271
|
+
#
|
|
272
|
+
# @private
|
|
273
|
+
# @param [String] path file path
|
|
274
|
+
# @param [String] src original source code
|
|
275
|
+
# @param [String] out rewritten source code
|
|
276
|
+
# @param [Array<Docscribe::CLI::Formatters::change>] file_changes structured change records
|
|
277
|
+
# @param [Object] ctx context hash with :options, :state, :display_path, :conf
|
|
278
|
+
# @return [void]
|
|
279
|
+
def dispatch_file_result(path, src:, out:, file_changes:, **ctx)
|
|
280
|
+
if ctx[:options][:mode] == :check
|
|
281
|
+
handle_check_result(path, src: src, out: out, file_changes: file_changes, **ctx)
|
|
282
|
+
elsif ctx[:options][:mode] == :write
|
|
283
|
+
handle_write_result(path, src: src, out: out, file_changes: file_changes, **ctx)
|
|
199
284
|
end
|
|
200
285
|
end
|
|
201
286
|
|
|
@@ -208,7 +293,8 @@ module Docscribe
|
|
|
208
293
|
# @param [String] path file path to display
|
|
209
294
|
# @param [Pathname] pwd current working directory
|
|
210
295
|
# @raise [StandardError]
|
|
211
|
-
# @return [String]
|
|
296
|
+
# @return [String] if StandardError
|
|
297
|
+
# @return [Object] if StandardError
|
|
212
298
|
def display_path_for(path, pwd:)
|
|
213
299
|
abs = Pathname.new(path).expand_path
|
|
214
300
|
|
|
@@ -226,17 +312,18 @@ module Docscribe
|
|
|
226
312
|
# @private
|
|
227
313
|
# @param [String] path file path to read
|
|
228
314
|
# @param [String] display_path path shown in CLI output
|
|
229
|
-
# @param [
|
|
230
|
-
# @param [
|
|
315
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
316
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
231
317
|
# @raise [StandardError]
|
|
232
|
-
# @return [String, nil]
|
|
318
|
+
# @return [String, nil] if StandardError
|
|
319
|
+
# @return [nil] if StandardError
|
|
233
320
|
def read_source_for_path(path, display_path:, options:, state:)
|
|
234
321
|
File.read(path)
|
|
235
322
|
rescue StandardError => e
|
|
236
323
|
state[:had_errors] = true
|
|
237
324
|
state[:error_paths] << path
|
|
238
325
|
state[:error_messages][path] = "#{e.class}: #{e.message}"
|
|
239
|
-
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')
|
|
240
327
|
nil
|
|
241
328
|
end
|
|
242
329
|
|
|
@@ -245,27 +332,43 @@ module Docscribe
|
|
|
245
332
|
# @private
|
|
246
333
|
# @param [String] path file path
|
|
247
334
|
# @param [String] src source code
|
|
248
|
-
# @param [
|
|
249
|
-
# @param [String] display_path path shown in CLI output
|
|
250
|
-
# @param [Hash] options CLI options
|
|
251
|
-
# @param [Hash] state shared processing state
|
|
335
|
+
# @param [Hash<Symbol, Object>] ctx context hash with :conf, :display_path, :options, :state keys
|
|
252
336
|
# @raise [StandardError]
|
|
253
|
-
# @return [Hash, nil]
|
|
254
|
-
|
|
255
|
-
|
|
337
|
+
# @return [Hash<Symbol, Object>, nil] if StandardError
|
|
338
|
+
# @return [nil] if StandardError
|
|
339
|
+
def rewrite_result_for_path(path, src:, ctx:)
|
|
340
|
+
conf = ctx[:conf]
|
|
341
|
+
|
|
342
|
+
core_rbs_provider =
|
|
343
|
+
conf.respond_to?(:core_rbs_provider) ? conf.core_rbs_provider : nil
|
|
344
|
+
|
|
256
345
|
Docscribe::InlineRewriter.rewrite_with_report(
|
|
257
|
-
src,
|
|
258
|
-
strategy: options[:strategy],
|
|
259
|
-
config: conf,
|
|
260
|
-
core_rbs_provider: core_rbs_provider,
|
|
261
|
-
file: path
|
|
346
|
+
src, strategy: ctx[:options][:strategy], config: conf, core_rbs_provider: core_rbs_provider, file: path
|
|
262
347
|
)
|
|
263
348
|
rescue StandardError => e
|
|
349
|
+
record_rewrite_error(path, e, ctx)
|
|
350
|
+
nil
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
# Record a rewrite error in the shared state and print an error indicator.
|
|
354
|
+
#
|
|
355
|
+
# @private
|
|
356
|
+
# @param [String] path file path that caused the error
|
|
357
|
+
# @param [StandardError] error the exception raised during rewriting
|
|
358
|
+
# @param [Hash<Symbol, Object>] ctx context hash with :state, :options, :display_path
|
|
359
|
+
# @return [void]
|
|
360
|
+
def record_rewrite_error(path, error, ctx)
|
|
361
|
+
state = ctx[:state]
|
|
362
|
+
|
|
264
363
|
state[:had_errors] = true
|
|
265
364
|
state[:error_paths] << path
|
|
266
|
-
state[:error_messages][path] = "#{
|
|
267
|
-
|
|
268
|
-
|
|
365
|
+
state[:error_messages][path] = "#{error.class}: #{error.message}"
|
|
366
|
+
|
|
367
|
+
if ctx[:options][:verbose]
|
|
368
|
+
warn "ERR #{ctx[:display_path]}: #{state[:error_messages][path]}"
|
|
369
|
+
else
|
|
370
|
+
$stderr.print('E')
|
|
371
|
+
end
|
|
269
372
|
end
|
|
270
373
|
|
|
271
374
|
# Handle the result of an inspect (check) run.
|
|
@@ -274,36 +377,68 @@ module Docscribe
|
|
|
274
377
|
# @param [String] path file path
|
|
275
378
|
# @param [String] src original source code
|
|
276
379
|
# @param [String] out rewritten source code
|
|
277
|
-
# @param [Array<
|
|
278
|
-
# @param [
|
|
279
|
-
# @param [Hash] options CLI options
|
|
280
|
-
# @param [Hash] state shared processing state
|
|
380
|
+
# @param [Array<Docscribe::CLI::Formatters::change>] file_changes structured change records
|
|
381
|
+
# @param [Object] ctx context hash with :display_path, :options, :state keys
|
|
281
382
|
# @return [void]
|
|
282
|
-
def handle_check_result(path, src:, out:, file_changes:,
|
|
283
|
-
type_mismatches = file_changes
|
|
383
|
+
def handle_check_result(path, src:, out:, file_changes:, **ctx)
|
|
384
|
+
type_mismatches = type_mismatch_changes(file_changes)
|
|
284
385
|
has_real_changes = file_changes.any? { |c| !%i[updated_param updated_return].include?(c[:type]) }
|
|
285
386
|
|
|
286
387
|
if out == src && !has_real_changes
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
state[:type_mismatch_changes][path] = type_mismatches
|
|
290
|
-
options[:verbose] ? puts("MT #{display_path}") : print('M')
|
|
291
|
-
else
|
|
292
|
-
state[:checked_ok] += 1
|
|
293
|
-
options[:verbose] ? puts("OK #{display_path}") : print('.')
|
|
294
|
-
end
|
|
388
|
+
handle_check_no_changes(path, type_mismatches: type_mismatches, display_path: ctx[:display_path],
|
|
389
|
+
options: ctx[:options], state: ctx[:state])
|
|
295
390
|
return
|
|
296
391
|
end
|
|
297
392
|
|
|
393
|
+
handle_check_failed(path, file_changes: file_changes, display_path: ctx[:display_path],
|
|
394
|
+
options: ctx[:options], state: ctx[:state])
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
# Extract type mismatch changes from file_changes.
|
|
398
|
+
#
|
|
399
|
+
# @private
|
|
400
|
+
# @param [Array<Docscribe::CLI::Formatters::change>] file_changes structured change records
|
|
401
|
+
# @return [Array<Docscribe::CLI::Formatters::change>]
|
|
402
|
+
def type_mismatch_changes(file_changes)
|
|
403
|
+
file_changes.select { |c| %i[updated_param updated_return].include?(c[:type]) }
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
# Handle check result when there are no real changes.
|
|
407
|
+
#
|
|
408
|
+
# @private
|
|
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
|
|
414
|
+
# @return [void]
|
|
415
|
+
def handle_check_no_changes(path, type_mismatches:, display_path:, options:, state:)
|
|
416
|
+
if type_mismatches.any?
|
|
417
|
+
state[:type_mismatch_paths] << path
|
|
418
|
+
state[:type_mismatch_changes][path] = type_mismatches
|
|
419
|
+
log_check_verdict('MT', display_path, options)
|
|
420
|
+
else
|
|
421
|
+
state[:checked_ok] += 1
|
|
422
|
+
log_check_verdict('OK', display_path, options)
|
|
423
|
+
end
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
# Handle a failed check (file needs updates).
|
|
427
|
+
# With --verbose, prints the per-file verdict and all change reasons.
|
|
428
|
+
#
|
|
429
|
+
# @private
|
|
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
|
|
435
|
+
# @return [void]
|
|
436
|
+
def handle_check_failed(path, file_changes:, display_path:, options:, state:)
|
|
298
437
|
if options[:verbose]
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
file_changes.each do |change|
|
|
302
|
-
puts(" - #{format_change_reason(change)}")
|
|
303
|
-
end
|
|
304
|
-
end
|
|
438
|
+
warn("FAIL #{display_path}")
|
|
439
|
+
print_check_explanations(file_changes)
|
|
305
440
|
else
|
|
306
|
-
print('F')
|
|
441
|
+
$stderr.print('F')
|
|
307
442
|
end
|
|
308
443
|
|
|
309
444
|
state[:checked_fail] += 1
|
|
@@ -318,122 +453,301 @@ module Docscribe
|
|
|
318
453
|
# @param [String] path file path
|
|
319
454
|
# @param [String] src original source code
|
|
320
455
|
# @param [String] out rewritten source code
|
|
321
|
-
# @param [Array<
|
|
322
|
-
# @param [
|
|
323
|
-
# @param [Hash] options CLI options
|
|
324
|
-
# @param [Hash] state shared processing state
|
|
456
|
+
# @param [Array<Docscribe::CLI::Formatters::change>] file_changes structured change records
|
|
457
|
+
# @param [Object] ctx context hash with :display_path, :options, :state keys
|
|
325
458
|
# @raise [StandardError]
|
|
326
|
-
# @return [void]
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
459
|
+
# @return [void] if StandardError
|
|
460
|
+
# @return [Object] if StandardError
|
|
461
|
+
def handle_write_result(path, src:, out:, file_changes:, **ctx)
|
|
462
|
+
return log_check_verdict('OK', ctx[:display_path], ctx[:options]) if out == src
|
|
463
|
+
|
|
464
|
+
apply_correction(path, out, file_changes, ctx)
|
|
465
|
+
rescue StandardError => e
|
|
466
|
+
record_write_error(path, e, display_path: ctx[:display_path], options: ctx[:options], state: ctx[:state])
|
|
467
|
+
end
|
|
332
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)
|
|
333
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
|
|
334
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
|
+
|
|
496
|
+
# Log a write-mode verdict.
|
|
497
|
+
#
|
|
498
|
+
# @private
|
|
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
|
|
503
|
+
# @return [void]
|
|
504
|
+
def log_write_verdict(verdict, display_path, file_changes, options)
|
|
335
505
|
if options[:verbose]
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
file_changes.each do |change|
|
|
339
|
-
puts(" - #{format_change_reason(change)}")
|
|
340
|
-
end
|
|
341
|
-
end
|
|
506
|
+
warn("#{verdict} #{display_path}")
|
|
507
|
+
print_check_explanations(file_changes)
|
|
342
508
|
else
|
|
343
|
-
print('C')
|
|
509
|
+
$stderr.print('C')
|
|
344
510
|
end
|
|
511
|
+
end
|
|
345
512
|
|
|
346
|
-
|
|
347
|
-
|
|
513
|
+
# Print explanations for file changes.
|
|
514
|
+
#
|
|
515
|
+
# Callers are responsible for gating on --verbose / --explain.
|
|
516
|
+
#
|
|
517
|
+
# @private
|
|
518
|
+
# @param [Array<Docscribe::CLI::Formatters::change>] file_changes structured change records
|
|
519
|
+
# @return [void]
|
|
520
|
+
def print_check_explanations(file_changes)
|
|
521
|
+
file_changes.each do |change|
|
|
522
|
+
warn(" - #{format_change_reason(change)}")
|
|
523
|
+
end
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
# Record a write error in state.
|
|
527
|
+
#
|
|
528
|
+
# @private
|
|
529
|
+
# @param [String] path file path
|
|
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
|
|
534
|
+
# @return [void]
|
|
535
|
+
def record_write_error(path, error, display_path:, options:, state:)
|
|
348
536
|
state[:had_errors] = true
|
|
349
537
|
state[:error_paths] << path
|
|
350
|
-
state[:error_messages][path] = "#{
|
|
351
|
-
|
|
538
|
+
state[:error_messages][path] = "#{error.class}: #{error.message}"
|
|
539
|
+
log_check_verdict('ERR', display_path, options)
|
|
352
540
|
end
|
|
353
541
|
|
|
354
|
-
#
|
|
542
|
+
# Log a per-file check verdict.
|
|
355
543
|
#
|
|
356
544
|
# @private
|
|
357
|
-
# @param [
|
|
358
|
-
# @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
|
|
548
|
+
# @return [void]
|
|
549
|
+
def log_check_verdict(verdict, display_path, options)
|
|
550
|
+
if options[:verbose]
|
|
551
|
+
warn("#{verdict} #{display_path}")
|
|
552
|
+
else
|
|
553
|
+
$stderr.print(if verdict == 'FAIL'
|
|
554
|
+
'F'
|
|
555
|
+
else
|
|
556
|
+
verdict == 'MT' ? 'M' : '.'
|
|
557
|
+
end)
|
|
558
|
+
end
|
|
559
|
+
end
|
|
560
|
+
|
|
561
|
+
# Print the check-mode summary (fail paths, then status line).
|
|
562
|
+
#
|
|
563
|
+
# @private
|
|
564
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
565
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
359
566
|
# @return [void]
|
|
360
567
|
def print_check_summary(state:, options:)
|
|
361
568
|
puts
|
|
569
|
+
print_fail_paths(state, options)
|
|
570
|
+
print_check_status_line(state)
|
|
571
|
+
print_type_mismatch_paths(state, options)
|
|
572
|
+
print_error_paths(state)
|
|
573
|
+
end
|
|
362
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
|
+
|
|
596
|
+
# Print the check-mode status line.
|
|
597
|
+
#
|
|
598
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
599
|
+
# @return [void]
|
|
600
|
+
def print_check_status_line(state)
|
|
363
601
|
checked_error = state[:error_paths].size
|
|
364
602
|
type_mismatch_count = state[:type_mismatch_paths].size
|
|
365
603
|
|
|
366
|
-
if state
|
|
604
|
+
if all_fine?(state, checked_error, type_mismatch_count)
|
|
367
605
|
puts "Docscribe: OK (#{state[:checked_ok]} files checked)"
|
|
368
|
-
|
|
369
|
-
end
|
|
370
|
-
|
|
371
|
-
if state[:checked_fail].zero? && checked_error.zero?
|
|
606
|
+
elsif mismatch_only?(state, checked_error)
|
|
372
607
|
puts "Docscribe: OK (#{state[:checked_ok]} files checked, #{type_mismatch_count} with type mismatches)"
|
|
373
608
|
else
|
|
374
|
-
|
|
375
|
-
parts << "#{type_mismatch_count} type mismatches" if type_mismatch_count.positive?
|
|
376
|
-
parts << "#{checked_error} errors"
|
|
377
|
-
parts << "#{state[:checked_ok]} ok"
|
|
378
|
-
puts "Docscribe: FAILED (#{parts.join(', ')})"
|
|
609
|
+
puts build_failure_line(state, type_mismatch_count, checked_error)
|
|
379
610
|
end
|
|
611
|
+
end
|
|
380
612
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
613
|
+
# Whether no failures, errors, or type mismatches occurred.
|
|
614
|
+
#
|
|
615
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
616
|
+
# @param [Integer] checked_error number of files with errors
|
|
617
|
+
# @param [Integer] type_mismatch_count number of files with type mismatches
|
|
618
|
+
# @return [Boolean]
|
|
619
|
+
def all_fine?(state, checked_error, type_mismatch_count)
|
|
620
|
+
state[:checked_fail].zero? && checked_error.zero? && type_mismatch_count.zero?
|
|
621
|
+
end
|
|
384
622
|
|
|
385
|
-
|
|
623
|
+
# Whether type mismatches exist but no failures or errors.
|
|
624
|
+
#
|
|
625
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
626
|
+
# @param [Integer] checked_error number of files with errors
|
|
627
|
+
# @return [Boolean]
|
|
628
|
+
def mismatch_only?(state, checked_error)
|
|
629
|
+
state[:checked_fail].zero? && checked_error.zero?
|
|
630
|
+
end
|
|
631
|
+
|
|
632
|
+
# Build the human-readable failure summary line for check output.
|
|
633
|
+
#
|
|
634
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
635
|
+
# @param [Integer] type_mismatch_count number of files with type mismatches
|
|
636
|
+
# @param [Integer] checked_error number of files with errors
|
|
637
|
+
# @return [String]
|
|
638
|
+
def build_failure_line(state, type_mismatch_count, checked_error)
|
|
639
|
+
parts = ["#{state[:checked_fail]} need updates"]
|
|
640
|
+
parts << "#{type_mismatch_count} type mismatches" if type_mismatch_count.positive?
|
|
641
|
+
parts << "#{checked_error} errors"
|
|
642
|
+
parts << "#{state[:checked_ok]} ok"
|
|
643
|
+
"Docscribe: FAILED (#{parts.join(', ')})"
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
# Print type mismatch paths from check summary.
|
|
647
|
+
#
|
|
648
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
649
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
650
|
+
# @return [void]
|
|
651
|
+
def print_type_mismatch_paths(state, options)
|
|
652
|
+
return if options[:quiet]
|
|
653
|
+
return unless options[:verbose] || options[:explain]
|
|
654
|
+
|
|
655
|
+
state[:type_mismatch_paths].each do |p|
|
|
656
|
+
warn "Type mismatches: #{p}"
|
|
657
|
+
Array(state[:type_mismatch_changes][p]).each do |change|
|
|
386
658
|
warn " - #{format_change_reason(change)}"
|
|
387
659
|
end
|
|
388
660
|
end
|
|
661
|
+
end
|
|
389
662
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
663
|
+
# Print the write-mode summary (files corrected, errors).
|
|
664
|
+
#
|
|
665
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
666
|
+
# @param [Docscribe::CLI::Formatters::opts] options CLI options
|
|
667
|
+
# @return [void]
|
|
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)
|
|
398
672
|
|
|
399
|
-
state[:
|
|
400
|
-
|
|
401
|
-
|
|
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)}"
|
|
694
|
+
end
|
|
402
695
|
end
|
|
403
696
|
end
|
|
404
697
|
|
|
405
698
|
# Format a structured change record into human-readable CLI output.
|
|
406
699
|
#
|
|
407
|
-
# @
|
|
408
|
-
# @param [Hash] change structured change produced by the inline rewriter
|
|
700
|
+
# @param [Docscribe::CLI::Formatters::change] change structured change produced by the inline rewriter
|
|
409
701
|
# @return [String] human-readable explanation line
|
|
410
702
|
def format_change_reason(change)
|
|
411
|
-
line = change
|
|
412
|
-
method = change
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
:insert_full_doc_block
|
|
419
|
-
"#{change[:message]}#{method}#{line}"
|
|
420
|
-
else
|
|
421
|
-
"#{change[:message] || change[:type].to_s.tr('_', ' ')}#{method}#{line}"
|
|
422
|
-
end
|
|
703
|
+
line = change_line_suffix(change)
|
|
704
|
+
method = change_method_suffix(change)
|
|
705
|
+
|
|
706
|
+
return "unsorted tags#{line}" if change[:type] == :unsorted_tags
|
|
707
|
+
return "#{change[:message]}#{method}#{line}" if direct_message_change?(change)
|
|
708
|
+
|
|
709
|
+
"#{change[:message] || change[:type].to_s.tr('_', ' ')}#{method}#{line}"
|
|
423
710
|
end
|
|
424
711
|
|
|
425
|
-
#
|
|
712
|
+
# Format the line number suffix for a change reason string.
|
|
426
713
|
#
|
|
427
|
-
# @
|
|
428
|
-
# @
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
puts "Docscribe: updated #{state[:corrected]} file(s)" if state[:corrected].positive?
|
|
714
|
+
# @param [Docscribe::CLI::Formatters::change] change structured change record
|
|
715
|
+
# @return [String] " at line N" or empty
|
|
716
|
+
def change_line_suffix(change)
|
|
717
|
+
change[:line] ? " at line #{change[:line]}" : ''
|
|
718
|
+
end
|
|
433
719
|
|
|
434
|
-
|
|
720
|
+
# Format the method name suffix for a change reason string.
|
|
721
|
+
#
|
|
722
|
+
# @param [Docscribe::CLI::Formatters::change] change structured change record
|
|
723
|
+
# @return [String] " for method_name" or empty
|
|
724
|
+
def change_method_suffix(change)
|
|
725
|
+
change[:method] ? " for #{change[:method]}" : ''
|
|
726
|
+
end
|
|
435
727
|
|
|
436
|
-
|
|
728
|
+
# Whether a change type uses its own :message field directly as the reason.
|
|
729
|
+
#
|
|
730
|
+
# @param [Docscribe::CLI::Formatters::change] change structured change record
|
|
731
|
+
# @return [Boolean]
|
|
732
|
+
def direct_message_change?(change)
|
|
733
|
+
%i[
|
|
734
|
+
missing_param
|
|
735
|
+
missing_return
|
|
736
|
+
missing_raise
|
|
737
|
+
missing_visibility
|
|
738
|
+
missing_module_function_note
|
|
739
|
+
insert_full_doc_block
|
|
740
|
+
].include?(change[:type])
|
|
741
|
+
end
|
|
742
|
+
|
|
743
|
+
# Print error paths from check summary.
|
|
744
|
+
#
|
|
745
|
+
# @param [Docscribe::CLI::Formatters::state] state shared processing state
|
|
746
|
+
# @return [void]
|
|
747
|
+
def print_error_paths(state)
|
|
748
|
+
return if state[:error_paths].empty?
|
|
749
|
+
|
|
750
|
+
warn ''
|
|
437
751
|
state[:error_paths].each do |p|
|
|
438
752
|
warn "Error processing: #{p}"
|
|
439
753
|
warn " #{state[:error_messages][p]}" if state[:error_messages][p]
|