docscribe 1.2.1 → 1.3.1
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 +296 -2
- data/lib/docscribe/cli/config_builder.rb +17 -5
- data/lib/docscribe/cli/generate.rb +309 -0
- data/lib/docscribe/cli/options.rb +8 -1
- data/lib/docscribe/cli/run.rb +52 -51
- data/lib/docscribe/cli.rb +8 -2
- data/lib/docscribe/config/defaults.rb +8 -2
- data/lib/docscribe/config/filtering.rb +2 -2
- data/lib/docscribe/config/plugin.rb +29 -0
- data/lib/docscribe/config/rbs.rb +38 -1
- data/lib/docscribe/config/template.rb +54 -130
- data/lib/docscribe/config.rb +1 -0
- data/lib/docscribe/infer/returns.rb +151 -12
- data/lib/docscribe/infer.rb +7 -2
- data/lib/docscribe/inline_rewriter/collector.rb +144 -97
- data/lib/docscribe/inline_rewriter/doc_block.rb +10 -1
- data/lib/docscribe/inline_rewriter/doc_builder.rb +256 -54
- data/lib/docscribe/inline_rewriter.rb +216 -56
- data/lib/docscribe/plugin/base/collector_plugin.rb +53 -0
- data/lib/docscribe/plugin/base/tag_plugin.rb +38 -0
- data/lib/docscribe/plugin/context.rb +38 -0
- data/lib/docscribe/plugin/registry.rb +69 -0
- data/lib/docscribe/plugin/tag.rb +23 -0
- data/lib/docscribe/plugin.rb +58 -0
- data/lib/docscribe/types/rbs/collection_loader.rb +50 -0
- data/lib/docscribe/types/rbs/provider.rb +3 -0
- data/lib/docscribe/version.rb +1 -1
- metadata +13 -5
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'docscribe/plugin'
|
|
3
4
|
require 'docscribe/infer'
|
|
4
5
|
require 'docscribe/inline_rewriter/source_helpers'
|
|
5
6
|
|
|
@@ -27,9 +28,11 @@ module Docscribe
|
|
|
27
28
|
# @param [Docscribe::Config] config
|
|
28
29
|
# @param [Object, nil] signature_provider provider responding to
|
|
29
30
|
# `signature_for(container:, scope:, name:)`
|
|
31
|
+
# @param [nil] core_rbs_provider Param documentation.
|
|
32
|
+
# @param [nil] param_types Param documentation.
|
|
30
33
|
# @raise [StandardError]
|
|
31
34
|
# @return [String, nil]
|
|
32
|
-
def build(insertion, config:, signature_provider: nil)
|
|
35
|
+
def build(insertion, config:, signature_provider: nil, core_rbs_provider: nil, param_types: nil)
|
|
33
36
|
node = insertion.node
|
|
34
37
|
name = SourceHelpers.node_name(node)
|
|
35
38
|
return nil unless name
|
|
@@ -46,16 +49,20 @@ module Docscribe
|
|
|
46
49
|
name: name
|
|
47
50
|
)
|
|
48
51
|
|
|
52
|
+
effective_param_types =
|
|
53
|
+
param_types || build_param_types_from_node(node, external_sig: external_sig, config: config)
|
|
54
|
+
|
|
49
55
|
if config.emit_param_tags?
|
|
50
|
-
params_lines = build_params_lines(node, indent, external_sig: external_sig,
|
|
51
|
-
config: config)
|
|
56
|
+
params_lines = build_params_lines(node, indent, external_sig: external_sig, config: config)
|
|
52
57
|
end
|
|
53
58
|
raise_types = config.emit_raise_tags? ? Docscribe::Infer.infer_raises_from_node(node) : []
|
|
54
59
|
|
|
55
60
|
returns_spec = Docscribe::Infer.returns_spec_from_node(
|
|
56
61
|
node,
|
|
57
62
|
fallback_type: config.fallback_type,
|
|
58
|
-
nil_as_optional: config.nil_as_optional
|
|
63
|
+
nil_as_optional: config.nil_as_optional?,
|
|
64
|
+
param_types: effective_param_types,
|
|
65
|
+
core_rbs_provider: core_rbs_provider
|
|
59
66
|
)
|
|
60
67
|
|
|
61
68
|
normal_type = external_sig&.return_type || returns_spec[:normal]
|
|
@@ -103,7 +110,10 @@ module Docscribe
|
|
|
103
110
|
lines << "#{indent}# @return [#{rtype}] if #{exceptions.join(', ')}"
|
|
104
111
|
end
|
|
105
112
|
end
|
|
106
|
-
|
|
113
|
+
plugin_tags = Docscribe::Plugin.run_tag_plugins(
|
|
114
|
+
build_plugin_context(insertion, normal_type: normal_type)
|
|
115
|
+
)
|
|
116
|
+
lines.concat(render_plugin_tags(plugin_tags, indent))
|
|
107
117
|
lines.map { |l| "#{l}\n" }.join
|
|
108
118
|
rescue StandardError => e
|
|
109
119
|
debug_warn(e, insertion: insertion, name: name || '(unknown)', phase: 'DocBuilder.build')
|
|
@@ -120,9 +130,12 @@ module Docscribe
|
|
|
120
130
|
# @param [Array<String>] existing_lines
|
|
121
131
|
# @param [Docscribe::Config] config
|
|
122
132
|
# @param [Object, nil] signature_provider
|
|
133
|
+
# @param [nil] core_rbs_provider Param documentation.
|
|
134
|
+
# @param [nil] param_types Param documentation.
|
|
123
135
|
# @raise [StandardError]
|
|
124
136
|
# @return [String, nil]
|
|
125
|
-
def build_merge_additions(insertion, existing_lines:, config:, signature_provider: nil
|
|
137
|
+
def build_merge_additions(insertion, existing_lines:, config:, signature_provider: nil, core_rbs_provider: nil,
|
|
138
|
+
param_types: nil)
|
|
126
139
|
node = insertion.node
|
|
127
140
|
name = SourceHelpers.node_name(node)
|
|
128
141
|
return '' unless name
|
|
@@ -141,7 +154,9 @@ module Docscribe
|
|
|
141
154
|
returns_spec = Docscribe::Infer.returns_spec_from_node(
|
|
142
155
|
node,
|
|
143
156
|
fallback_type: config.fallback_type,
|
|
144
|
-
nil_as_optional: config.nil_as_optional
|
|
157
|
+
nil_as_optional: config.nil_as_optional?,
|
|
158
|
+
param_types: param_types,
|
|
159
|
+
core_rbs_provider: core_rbs_provider
|
|
145
160
|
)
|
|
146
161
|
|
|
147
162
|
normal_type = external_sig&.return_type || returns_spec[:normal]
|
|
@@ -211,9 +226,13 @@ module Docscribe
|
|
|
211
226
|
# @param [Array<String>] existing_lines
|
|
212
227
|
# @param [Docscribe::Config] config
|
|
213
228
|
# @param [Object, nil] signature_provider
|
|
229
|
+
# @param [nil] core_rbs_provider Param documentation.
|
|
230
|
+
# @param [nil] param_types Param documentation.
|
|
231
|
+
# @param [nil] strategy Param documentation.
|
|
214
232
|
# @raise [StandardError]
|
|
215
233
|
# @return [Hash]
|
|
216
|
-
def build_missing_merge_result(insertion, existing_lines:, config:, signature_provider: nil
|
|
234
|
+
def build_missing_merge_result(insertion, existing_lines:, config:, signature_provider: nil,
|
|
235
|
+
core_rbs_provider: nil, param_types: nil, strategy: nil)
|
|
217
236
|
node = insertion.node
|
|
218
237
|
name = SourceHelpers.node_name(node)
|
|
219
238
|
return { lines: [], reasons: [] } unless name
|
|
@@ -232,7 +251,9 @@ module Docscribe
|
|
|
232
251
|
returns_spec = Docscribe::Infer.returns_spec_from_node(
|
|
233
252
|
node,
|
|
234
253
|
fallback_type: config.fallback_type,
|
|
235
|
-
nil_as_optional: config.nil_as_optional
|
|
254
|
+
nil_as_optional: config.nil_as_optional?,
|
|
255
|
+
param_types: param_types,
|
|
256
|
+
core_rbs_provider: core_rbs_provider
|
|
236
257
|
)
|
|
237
258
|
|
|
238
259
|
normal_type = external_sig&.return_type || returns_spec[:normal]
|
|
@@ -263,10 +284,22 @@ module Docscribe
|
|
|
263
284
|
|
|
264
285
|
all_params&.each do |pl|
|
|
265
286
|
pname = extract_param_name_from_param_line(pl)
|
|
266
|
-
next
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
287
|
+
next unless pname
|
|
288
|
+
|
|
289
|
+
if !info[:param_names].include?(pname)
|
|
290
|
+
lines << "#{pl}\n"
|
|
291
|
+
reasons << { type: :missing_param, message: "missing @param #{pname}", extra: { param: pname } }
|
|
292
|
+
elsif info[:param_types][pname] && strategy != :safe
|
|
293
|
+
new_type = extract_param_type_from_param_line(pl)
|
|
294
|
+
if new_type && info[:param_types][pname] != new_type
|
|
295
|
+
lines << "#{pl}\n"
|
|
296
|
+
reasons << {
|
|
297
|
+
type: :updated_param,
|
|
298
|
+
message: "updated @param #{pname} from #{info[:param_types][pname]} to #{new_type}",
|
|
299
|
+
extra: { param: pname }
|
|
300
|
+
}
|
|
301
|
+
end
|
|
302
|
+
end
|
|
270
303
|
end
|
|
271
304
|
end
|
|
272
305
|
|
|
@@ -281,9 +314,17 @@ module Docscribe
|
|
|
281
314
|
end
|
|
282
315
|
end
|
|
283
316
|
|
|
284
|
-
if config.emit_return_tag?(scope, visibility)
|
|
285
|
-
|
|
286
|
-
|
|
317
|
+
if config.emit_return_tag?(scope, visibility)
|
|
318
|
+
if !info[:has_return]
|
|
319
|
+
lines << "#{indent}# @return [#{normal_type}]\n"
|
|
320
|
+
reasons << { type: :missing_return, message: 'missing @return' }
|
|
321
|
+
elsif info[:return_type] && info[:return_type] != normal_type && strategy != :safe
|
|
322
|
+
lines << "#{indent}# @return [#{normal_type}]\n"
|
|
323
|
+
reasons << {
|
|
324
|
+
type: :updated_return,
|
|
325
|
+
message: "updated @return from #{info[:return_type]} to #{normal_type}"
|
|
326
|
+
}
|
|
327
|
+
end
|
|
287
328
|
end
|
|
288
329
|
|
|
289
330
|
if config.emit_rescue_conditional_returns? && !info[:has_return]
|
|
@@ -295,32 +336,58 @@ module Docscribe
|
|
|
295
336
|
}
|
|
296
337
|
end
|
|
297
338
|
end
|
|
339
|
+
plugin_tags = Docscribe::Plugin.run_tag_plugins(
|
|
340
|
+
build_plugin_context(insertion, normal_type: normal_type)
|
|
341
|
+
)
|
|
342
|
+
plugin_tags.each do |tag|
|
|
343
|
+
next if info[:plugin_tags]&.[](tag.name)
|
|
298
344
|
|
|
345
|
+
rendered = render_plugin_tags([tag], indent).first
|
|
346
|
+
lines << "#{rendered}\n"
|
|
347
|
+
reasons << { type: :missing_plugin_tag, message: "missing @#{tag.name}" }
|
|
348
|
+
end
|
|
299
349
|
{ lines: lines, reasons: reasons }
|
|
300
350
|
rescue StandardError => e
|
|
301
351
|
debug_warn(e, insertion: insertion, name: name || '(unknown)', phase: 'DocBuilder.build_missing_merge_result')
|
|
302
352
|
{ lines: [], reasons: [] }
|
|
303
353
|
end
|
|
304
354
|
|
|
305
|
-
#
|
|
355
|
+
# Parse existing doc comment lines and extract known YARD tags.
|
|
356
|
+
#
|
|
357
|
+
# Extracts: `@param` names, `@return`, `@raise`, `@private`, `@protected`,
|
|
358
|
+
# `@module_function` notes, and `@option` lines.
|
|
306
359
|
#
|
|
307
360
|
# @note module_function: when included, also defines #parse_existing_doc_tags (instance visibility: private)
|
|
308
|
-
# @param [
|
|
309
|
-
# @return [Hash]
|
|
361
|
+
# @param [Array<String>] lines existing doc comment lines
|
|
362
|
+
# @return [Hash] parsed tag info
|
|
310
363
|
def parse_existing_doc_tags(lines)
|
|
311
364
|
param_names = {}
|
|
365
|
+
param_types = {}
|
|
312
366
|
has_return = false
|
|
367
|
+
return_type = nil
|
|
313
368
|
has_private = false
|
|
314
369
|
has_protected = false
|
|
315
370
|
has_module_function_note = false
|
|
316
371
|
raise_types = {}
|
|
372
|
+
plugin_tags = {}
|
|
317
373
|
|
|
318
374
|
Array(lines).each do |line|
|
|
375
|
+
if (m = line.match(/^\s*#\s*@(\w+)\b/))
|
|
376
|
+
plugin_tags[m[1]] = true
|
|
377
|
+
end
|
|
319
378
|
if (pname = extract_param_name_from_param_line(line))
|
|
320
379
|
param_names[pname] = true
|
|
380
|
+
if (type_match = line.match(/@param\s+\[([^\]]+)\]\s+\S+/) || line.match(/@param\s+\S+\s+\[([^\]]+)\]/))
|
|
381
|
+
param_types[pname] = type_match[1]
|
|
382
|
+
end
|
|
321
383
|
end
|
|
322
384
|
|
|
323
|
-
|
|
385
|
+
if line.match?(/^\s*#\s*@return\b/)
|
|
386
|
+
has_return = true
|
|
387
|
+
if (m = line.match(/@return\s+\[([^\]]+)\]/))
|
|
388
|
+
return_type = m[1]
|
|
389
|
+
end
|
|
390
|
+
end
|
|
324
391
|
has_private ||= line.match?(/^\s*#\s*@private\b/)
|
|
325
392
|
has_protected ||= line.match?(/^\s*#\s*@protected\b/)
|
|
326
393
|
has_module_function_note ||= line.match?(/^\s*#\s*@note\s+module_function:/)
|
|
@@ -330,21 +397,24 @@ module Docscribe
|
|
|
330
397
|
|
|
331
398
|
{
|
|
332
399
|
param_names: param_names,
|
|
400
|
+
param_types: param_types,
|
|
333
401
|
has_return: has_return,
|
|
402
|
+
return_type: return_type,
|
|
334
403
|
raise_types: raise_types,
|
|
335
404
|
has_private: has_private,
|
|
336
405
|
has_protected: has_protected,
|
|
337
|
-
has_module_function_note: has_module_function_note
|
|
406
|
+
has_module_function_note: has_module_function_note,
|
|
407
|
+
plugin_tags: plugin_tags
|
|
338
408
|
}
|
|
339
409
|
end
|
|
340
410
|
|
|
341
|
-
#
|
|
411
|
+
# Extract exception names from a `@raise` doc line.
|
|
342
412
|
#
|
|
343
413
|
# @note module_function: when included, also defines #extract_raise_types_from_line (instance visibility: private)
|
|
344
|
-
# @param [
|
|
414
|
+
# @param [String] line a `@raise` doc line
|
|
345
415
|
# @raise [StandardError]
|
|
346
|
-
# @return [
|
|
347
|
-
# @return [Array] if StandardError
|
|
416
|
+
# @return [String, nil] the exception name or nil
|
|
417
|
+
# @return [Array] if StandardError or line not matched
|
|
348
418
|
def extract_raise_types_from_line(line)
|
|
349
419
|
return [] unless line.match?(/^\s*#\s*@raise\b/)
|
|
350
420
|
|
|
@@ -359,15 +429,91 @@ module Docscribe
|
|
|
359
429
|
[]
|
|
360
430
|
end
|
|
361
431
|
|
|
362
|
-
#
|
|
432
|
+
# Parse exception names from a `@raise [ExceptionA, ExceptionB]` line.
|
|
363
433
|
#
|
|
364
434
|
# @note module_function: when included, also defines #parse_raise_bracket_list (instance visibility: private)
|
|
365
|
-
# @param [
|
|
366
|
-
# @return [
|
|
435
|
+
# @param [String] s the `@raise` line text
|
|
436
|
+
# @return [Array<String>, nil] the exception names or nil
|
|
367
437
|
def parse_raise_bracket_list(s)
|
|
368
438
|
s.to_s.split(',').map(&:strip).reject(&:empty?)
|
|
369
439
|
end
|
|
370
440
|
|
|
441
|
+
# Build a param name => type map from a method node.
|
|
442
|
+
#
|
|
443
|
+
# @note module_function: when included, also defines #build_param_types_from_node (instance visibility: private)
|
|
444
|
+
# @private
|
|
445
|
+
# @param [Parser::AST::Node] node def or defs node
|
|
446
|
+
# @param [Object, nil] external_sig external signature if available
|
|
447
|
+
# @param [Docscribe::Config] config
|
|
448
|
+
# @return [Hash{String => String}, nil]
|
|
449
|
+
def build_param_types_from_node(node, external_sig:, config:)
|
|
450
|
+
return nil unless node
|
|
451
|
+
|
|
452
|
+
args =
|
|
453
|
+
case node.type
|
|
454
|
+
when :def then node.children[1]
|
|
455
|
+
when :defs then node.children[2]
|
|
456
|
+
end
|
|
457
|
+
|
|
458
|
+
return nil unless args
|
|
459
|
+
|
|
460
|
+
param_types = {}
|
|
461
|
+
|
|
462
|
+
(args.children || []).each do |a|
|
|
463
|
+
case a.type
|
|
464
|
+
when :arg
|
|
465
|
+
pname = a.children.first.to_s
|
|
466
|
+
ty = external_sig&.param_types&.[](pname) ||
|
|
467
|
+
Infer.infer_param_type(
|
|
468
|
+
pname,
|
|
469
|
+
nil,
|
|
470
|
+
fallback_type: config.fallback_type,
|
|
471
|
+
treat_options_keyword_as_hash: config.treat_options_keyword_as_hash?
|
|
472
|
+
)
|
|
473
|
+
param_types[pname] = ty
|
|
474
|
+
|
|
475
|
+
when :optarg
|
|
476
|
+
pname, default = *a
|
|
477
|
+
pname = pname.to_s
|
|
478
|
+
default_src = default&.loc&.expression&.source
|
|
479
|
+
ty = external_sig&.param_types&.[](pname) ||
|
|
480
|
+
Infer.infer_param_type(
|
|
481
|
+
pname,
|
|
482
|
+
default_src,
|
|
483
|
+
fallback_type: config.fallback_type,
|
|
484
|
+
treat_options_keyword_as_hash: config.treat_options_keyword_as_hash?
|
|
485
|
+
)
|
|
486
|
+
param_types[pname] = ty
|
|
487
|
+
|
|
488
|
+
when :kwarg
|
|
489
|
+
pname = a.children.first.to_s
|
|
490
|
+
ty = external_sig&.param_types&.[](pname) ||
|
|
491
|
+
Infer.infer_param_type(
|
|
492
|
+
"#{pname}:",
|
|
493
|
+
nil,
|
|
494
|
+
fallback_type: config.fallback_type,
|
|
495
|
+
treat_options_keyword_as_hash: config.treat_options_keyword_as_hash?
|
|
496
|
+
)
|
|
497
|
+
param_types[pname] = ty
|
|
498
|
+
|
|
499
|
+
when :kwoptarg
|
|
500
|
+
pname, default = *a
|
|
501
|
+
pname = pname.to_s
|
|
502
|
+
default_src = default&.loc&.expression&.source
|
|
503
|
+
ty = external_sig&.param_types&.[](pname) ||
|
|
504
|
+
Infer.infer_param_type(
|
|
505
|
+
"#{pname}:",
|
|
506
|
+
default_src,
|
|
507
|
+
fallback_type: config.fallback_type,
|
|
508
|
+
treat_options_keyword_as_hash: config.treat_options_keyword_as_hash?
|
|
509
|
+
)
|
|
510
|
+
param_types[pname] = ty
|
|
511
|
+
end
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
param_types.empty? ? nil : param_types
|
|
515
|
+
end
|
|
516
|
+
|
|
371
517
|
# Build generated `@param` / `@option` lines for a method node.
|
|
372
518
|
#
|
|
373
519
|
# External signatures take precedence over inferred parameter types.
|
|
@@ -501,15 +647,15 @@ module Docscribe
|
|
|
501
647
|
params.empty? ? nil : params
|
|
502
648
|
end
|
|
503
649
|
|
|
504
|
-
#
|
|
650
|
+
# Format a `@param` tag line using the configured param tag style.
|
|
505
651
|
#
|
|
506
652
|
# @note module_function: when included, also defines #format_param_tag (instance visibility: private)
|
|
507
|
-
# @param [
|
|
508
|
-
# @param [
|
|
509
|
-
# @param [
|
|
510
|
-
# @param [
|
|
511
|
-
# @param [
|
|
512
|
-
# @return [
|
|
653
|
+
# @param [String] indent leading whitespace
|
|
654
|
+
# @param [String] name parameter name
|
|
655
|
+
# @param [String] type parameter type
|
|
656
|
+
# @param [String] documentation optional documentation text
|
|
657
|
+
# @param [String, Symbol] style param tag style (`"name_type"` or `"type_name"`)
|
|
658
|
+
# @return [String]
|
|
513
659
|
def format_param_tag(indent, name, type, documentation, style:)
|
|
514
660
|
doc = documentation.to_s.strip
|
|
515
661
|
type = type.to_s
|
|
@@ -524,22 +670,22 @@ module Docscribe
|
|
|
524
670
|
doc.empty? ? line : "#{line} #{doc}"
|
|
525
671
|
end
|
|
526
672
|
|
|
527
|
-
#
|
|
673
|
+
# Extract keyword argument option pairs from a hash default value.
|
|
528
674
|
#
|
|
529
675
|
# @note module_function: when included, also defines #hash_option_pairs (instance visibility: private)
|
|
530
|
-
# @param [
|
|
531
|
-
# @return [
|
|
676
|
+
# @param [Parser::AST::Node, nil] node a `:hash` node
|
|
677
|
+
# @return [Array<Parser::AST::Node>] the `:pair` children
|
|
532
678
|
def hash_option_pairs(node)
|
|
533
679
|
return [] unless node&.type == :hash
|
|
534
680
|
|
|
535
681
|
node.children.select { |child| child.is_a?(Parser::AST::Node) && child.type == :pair }
|
|
536
682
|
end
|
|
537
683
|
|
|
538
|
-
#
|
|
684
|
+
# Get the symbol name from an option key node.
|
|
539
685
|
#
|
|
540
686
|
# @note module_function: when included, also defines #option_key_name (instance visibility: private)
|
|
541
|
-
# @param [
|
|
542
|
-
# @return [
|
|
687
|
+
# @param [Parser::AST::Node] key_node a `:sym` node
|
|
688
|
+
# @return [String] the option key name
|
|
543
689
|
def option_key_name(key_node)
|
|
544
690
|
case key_node&.type
|
|
545
691
|
when :sym, :str
|
|
@@ -549,20 +695,22 @@ module Docscribe
|
|
|
549
695
|
end
|
|
550
696
|
end
|
|
551
697
|
|
|
552
|
-
#
|
|
698
|
+
# Get the raw source literal for a default value node.
|
|
553
699
|
#
|
|
554
700
|
# @note module_function: when included, also defines #node_default_literal (instance visibility: private)
|
|
555
|
-
# @param [
|
|
556
|
-
# @return [
|
|
701
|
+
# @param [Parser::AST::Node, nil] node a default value node
|
|
702
|
+
# @return [String, nil] the source literal or nil
|
|
557
703
|
def node_default_literal(node)
|
|
558
704
|
node&.loc&.expression&.source
|
|
559
705
|
end
|
|
560
706
|
|
|
561
|
-
#
|
|
707
|
+
# Extract the parameter name from a `@param` doc line.
|
|
708
|
+
#
|
|
709
|
+
# Handles both `"@param [Type] name"` and `"@param name [Type]"` styles.
|
|
562
710
|
#
|
|
563
711
|
# @note module_function: when included, also defines #extract_param_name_from_param_line (instance visibility: private)
|
|
564
|
-
# @param [
|
|
565
|
-
# @return [nil]
|
|
712
|
+
# @param [String] line a `@param` doc line
|
|
713
|
+
# @return [String, nil] the parameter name or nil
|
|
566
714
|
def extract_param_name_from_param_line(line)
|
|
567
715
|
return Regexp.last_match(1) if line =~ /@param\b\s+\[[^\]]+\]\s+(\S+)/
|
|
568
716
|
return Regexp.last_match(1) if line =~ /@param\b\s+(\S+)\s+\[[^\]]+\]/
|
|
@@ -572,12 +720,66 @@ module Docscribe
|
|
|
572
720
|
|
|
573
721
|
# Method documentation.
|
|
574
722
|
#
|
|
575
|
-
# @note module_function: when included, also defines #
|
|
576
|
-
# @param [Object]
|
|
577
|
-
# @param [Object] insertion Param documentation.
|
|
578
|
-
# @param [Object] name Param documentation.
|
|
579
|
-
# @param [Object] phase Param documentation.
|
|
723
|
+
# @note module_function: when included, also defines #extract_param_type_from_param_line (instance visibility: private)
|
|
724
|
+
# @param [Object] line Param documentation.
|
|
580
725
|
# @return [Object]
|
|
726
|
+
def extract_param_type_from_param_line(line)
|
|
727
|
+
if (m = line.match(/@param\s+\[([^\]]+)\]\s+\S+/) || line.match(/@param\s+\S+\s+\[([^\]]+)\]/))
|
|
728
|
+
m[1]
|
|
729
|
+
end
|
|
730
|
+
end
|
|
731
|
+
|
|
732
|
+
# Build a Plugin::Context from a collected insertion.
|
|
733
|
+
#
|
|
734
|
+
# @note module_function
|
|
735
|
+
# @note module_function: when included, also defines #build_plugin_context (instance visibility: private)
|
|
736
|
+
# @param [Docscribe::InlineRewriter::Collector::Insertion] insertion
|
|
737
|
+
# @param [String] normal_type resolved return type
|
|
738
|
+
# @raise [StandardError]
|
|
739
|
+
# @return [Docscribe::Plugin::Context]
|
|
740
|
+
def build_plugin_context(insertion, normal_type:)
|
|
741
|
+
node = insertion.node
|
|
742
|
+
source = begin
|
|
743
|
+
node.loc.expression.source
|
|
744
|
+
rescue StandardError
|
|
745
|
+
''
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
Docscribe::Plugin::Context.new(
|
|
749
|
+
node: node,
|
|
750
|
+
container: insertion.container,
|
|
751
|
+
scope: insertion.scope,
|
|
752
|
+
visibility: insertion.visibility,
|
|
753
|
+
method_name: SourceHelpers.node_name(node),
|
|
754
|
+
inferred_params: {},
|
|
755
|
+
inferred_return: normal_type,
|
|
756
|
+
source: source
|
|
757
|
+
)
|
|
758
|
+
end
|
|
759
|
+
|
|
760
|
+
# Render plugin tags as indented comment lines.
|
|
761
|
+
#
|
|
762
|
+
# @note module_function
|
|
763
|
+
# @note module_function: when included, also defines #render_plugin_tags (instance visibility: private)
|
|
764
|
+
# @param [Array<Docscribe::Plugin::Tag>] tags
|
|
765
|
+
# @param [String] indent
|
|
766
|
+
# @return [Array<String>]
|
|
767
|
+
def render_plugin_tags(tags, indent)
|
|
768
|
+
tags.map do |tag|
|
|
769
|
+
type_part = tag.types&.any? ? " [#{tag.types.join(', ')}]" : ''
|
|
770
|
+
text_part = tag.text ? " #{tag.text}" : ''
|
|
771
|
+
"#{indent}# @#{tag.name}#{type_part}#{text_part}"
|
|
772
|
+
end
|
|
773
|
+
end
|
|
774
|
+
|
|
775
|
+
# Print a debug warning for a failed doc build phase.
|
|
776
|
+
#
|
|
777
|
+
# @note module_function: when included, also defines #debug_warn (instance visibility: private)
|
|
778
|
+
# @param [StandardError] e the error that occurred
|
|
779
|
+
# @param [Collector::Insertion] insertion the method insertion being processed
|
|
780
|
+
# @param [String] name the method name
|
|
781
|
+
# @param [String] phase the processing phase
|
|
782
|
+
# @return [void]
|
|
581
783
|
def debug_warn(e, insertion:, name:, phase:)
|
|
582
784
|
return unless debug?
|
|
583
785
|
|
|
@@ -595,10 +797,10 @@ module Docscribe
|
|
|
595
797
|
warn "Docscribe DEBUG: #{phase} failed at #{where}: #{e.class}: #{e.message}"
|
|
596
798
|
end
|
|
597
799
|
|
|
598
|
-
#
|
|
800
|
+
# Check whether debug mode is enabled.
|
|
599
801
|
#
|
|
600
802
|
# @note module_function: when included, also defines #debug? (instance visibility: private)
|
|
601
|
-
# @return [
|
|
803
|
+
# @return [Boolean]
|
|
602
804
|
def debug?
|
|
603
805
|
ENV['DOCSCRIBE_DEBUG'] == '1'
|
|
604
806
|
end
|