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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +465 -130
  3. data/lib/docscribe/cli/check_for_comments.rb +183 -0
  4. data/lib/docscribe/cli/config_builder.rb +107 -53
  5. data/lib/docscribe/cli/formatters/json.rb +294 -0
  6. data/lib/docscribe/cli/formatters/sarif.rb +235 -0
  7. data/lib/docscribe/cli/formatters/text.rb +208 -0
  8. data/lib/docscribe/cli/formatters.rb +26 -0
  9. data/lib/docscribe/cli/generate.rb +45 -45
  10. data/lib/docscribe/cli/init.rb +14 -6
  11. data/lib/docscribe/cli/options.rb +190 -88
  12. data/lib/docscribe/cli/rbs_gen.rb +529 -0
  13. data/lib/docscribe/cli/run.rb +210 -152
  14. data/lib/docscribe/cli/sigs.rb +366 -0
  15. data/lib/docscribe/cli/update_types.rb +103 -0
  16. data/lib/docscribe/cli.rb +21 -13
  17. data/lib/docscribe/config/defaults.rb +5 -1
  18. data/lib/docscribe/config/emit.rb +17 -0
  19. data/lib/docscribe/config/filtering.rb +18 -25
  20. data/lib/docscribe/config/loader.rb +15 -11
  21. data/lib/docscribe/config/plugin.rb +1 -1
  22. data/lib/docscribe/config/rbs.rb +41 -9
  23. data/lib/docscribe/config/sorbet.rb +9 -12
  24. data/lib/docscribe/config/sorting.rb +1 -1
  25. data/lib/docscribe/config/template.rb +9 -1
  26. data/lib/docscribe/config/utils.rb +11 -9
  27. data/lib/docscribe/config.rb +2 -4
  28. data/lib/docscribe/infer/ast_walk.rb +1 -1
  29. data/lib/docscribe/infer/literals.rb +6 -11
  30. data/lib/docscribe/infer/names.rb +2 -3
  31. data/lib/docscribe/infer/params.rb +15 -17
  32. data/lib/docscribe/infer/raises.rb +3 -5
  33. data/lib/docscribe/infer/returns.rb +542 -140
  34. data/lib/docscribe/infer.rb +22 -23
  35. data/lib/docscribe/inline_rewriter/collector.rb +159 -164
  36. data/lib/docscribe/inline_rewriter/doc_block.rb +145 -115
  37. data/lib/docscribe/inline_rewriter/doc_builder.rb +1026 -723
  38. data/lib/docscribe/inline_rewriter/source_helpers.rb +49 -49
  39. data/lib/docscribe/inline_rewriter/tag_sorter.rb +82 -85
  40. data/lib/docscribe/inline_rewriter.rb +495 -492
  41. data/lib/docscribe/parsing.rb +29 -10
  42. data/lib/docscribe/plugin/base/collector_plugin.rb +2 -1
  43. data/lib/docscribe/plugin/base/tag_plugin.rb +0 -1
  44. data/lib/docscribe/plugin/context.rb +28 -18
  45. data/lib/docscribe/plugin/registry.rb +26 -27
  46. data/lib/docscribe/plugin/tag.rb +9 -14
  47. data/lib/docscribe/plugin.rb +17 -16
  48. data/lib/docscribe/types/provider_chain.rb +4 -2
  49. data/lib/docscribe/types/rbs/collection_loader.rb +2 -2
  50. data/lib/docscribe/types/rbs/provider.rb +60 -44
  51. data/lib/docscribe/types/rbs/type_formatter.rb +224 -83
  52. data/lib/docscribe/types/signature.rb +22 -42
  53. data/lib/docscribe/types/sorbet/base_provider.rb +24 -19
  54. data/lib/docscribe/types/sorbet/rbi_provider.rb +3 -3
  55. data/lib/docscribe/types/sorbet/source_provider.rb +3 -2
  56. data/lib/docscribe/types/yard/formatter.rb +100 -0
  57. data/lib/docscribe/types/yard/parser.rb +240 -0
  58. data/lib/docscribe/types/yard/types.rb +52 -0
  59. data/lib/docscribe/version.rb +1 -1
  60. metadata +33 -1
@@ -19,48 +19,59 @@ module Docscribe
19
19
  # - receiver-based containers (`def Foo.bar`, `class << Foo`)
20
20
  # - Sorbet-aware anchoring for methods with leading `sig` declarations
21
21
  class Collector < Parser::AST::Processor
22
- PROCESS_STMT_HANDLERS = {
23
- def: :process_def_stmt,
24
- defs: :process_defs_stmt,
25
- sclass: :process_sclass_stmt,
26
- send: :process_send_stmt
27
- }.freeze
28
-
29
- # One method that Docscribe intends to document.
30
- #
31
- # @!attribute node
32
- # @return [Parser::AST::Node] the `:def` or `:defs` node
33
- # @!attribute scope
34
- # @return [Symbol] :instance or :class
35
- # @!attribute visibility
36
- # @return [Symbol] :public, :protected, or :private
37
- # @!attribute container
38
- # @return [String] container name, e.g. "MyModule::MyClass"
39
- # @!attribute module_function
40
- # @return [Boolean, nil] true if documented under module_function semantics
41
- # @!attribute included_instance_visibility
42
- # @return [Symbol, nil] included instance visibility under module_function
43
- # @!attribute anchor_node
44
- # @return [Parser::AST::Node] first leading Sorbet `sig` if present, else the method node
22
+ # @!attribute [rw] node
23
+ # @return [Parser::AST::Node]
24
+ # @param [Parser::AST::Node] value
25
+ #
26
+ # @!attribute [rw] scope
27
+ # @return [Symbol]
28
+ # @param [Symbol] value
29
+ #
30
+ # @!attribute [rw] visibility
31
+ # @return [Symbol]
32
+ # @param [Symbol] value
33
+ #
34
+ # @!attribute [rw] container
35
+ # @return [String]
36
+ # @param [String] value
37
+ #
38
+ # @!attribute [rw] module_function
39
+ # @return [Boolean, Symbol, nil]
40
+ # @param [Boolean, Symbol, nil] value
41
+ #
42
+ # @!attribute [rw] included_instance_visibility
43
+ # @return [Symbol, nil]
44
+ # @param [Symbol, nil] value
45
+ #
46
+ # @!attribute [rw] anchor_node
47
+ # @return [Parser::AST::Node]
48
+ # @param [Parser::AST::Node] value
45
49
  Insertion = Struct.new(:node, :scope, :visibility, :container, :module_function, :included_instance_visibility,
46
50
  :anchor_node)
47
51
 
48
- # One attribute macro call that Docscribe intends to document.
49
- #
50
- # This corresponds to an `attr_reader`, `attr_writer`, or `attr_accessor` call in Ruby source.
51
- #
52
- # @!attribute node
53
- # @return [Parser::AST::Node] the `:send` node (e.g. `attr_reader :name`)
54
- # @!attribute scope
55
- # @return [Symbol] :instance or :class (class when inside `class << self`)
56
- # @!attribute visibility
57
- # @return [Symbol] :public, :protected, or :private
58
- # @!attribute container
59
- # @return [String] container name, e.g. "MyModule::MyClass"
60
- # @!attribute access
61
- # @return [Symbol] :r, :w, or :rw (reader/writer/accessor)
62
- # @!attribute names
63
- # @return [Array<Symbol>] attribute names
52
+ # @!attribute [rw] node
53
+ # @return [Parser::AST::Node]
54
+ # @param [Parser::AST::Node] value
55
+ #
56
+ # @!attribute [rw] scope
57
+ # @return [Symbol]
58
+ # @param [Symbol] value
59
+ #
60
+ # @!attribute [rw] visibility
61
+ # @return [Symbol]
62
+ # @param [Symbol] value
63
+ #
64
+ # @!attribute [rw] container
65
+ # @return [String]
66
+ # @param [String] value
67
+ #
68
+ # @!attribute [rw] access
69
+ # @return [Symbol]
70
+ # @param [Symbol] value
71
+ #
72
+ # @!attribute [rw] names
73
+ # @return [Array<Symbol>]
74
+ # @param [Array<Symbol>] value
64
75
  AttrInsertion = Struct.new(:node, :scope, :visibility, :container, :access, :names)
65
76
 
66
77
  # Tracks visibility and container state while walking a class/module body.
@@ -73,50 +84,50 @@ module Docscribe
73
84
  # - retroactive visibility updates
74
85
  class VisibilityCtx
75
86
  # @!attribute [rw] default_instance_vis
76
- # @return [Object]
77
- # @param value [Object]
87
+ # @return [Symbol]
88
+ # @param [Symbol] value
78
89
  attr_accessor :default_instance_vis
79
90
 
80
91
  # @!attribute [rw] default_class_vis
81
- # @return [Object]
82
- # @param value [Object]
92
+ # @return [Symbol]
93
+ # @param [Symbol] value
83
94
  attr_accessor :default_class_vis
84
95
 
85
96
  # @!attribute [rw] inside_sclass
86
- # @return [Object]
87
- # @param value [Object]
97
+ # @return [Boolean]
98
+ # @param [Boolean] value
88
99
  attr_accessor :inside_sclass
89
100
 
90
101
  # @!attribute [rw] module_function_default
91
- # @return [Object]
92
- # @param value [Object]
102
+ # @return [Boolean]
103
+ # @param [Boolean] value
93
104
  attr_accessor :module_function_default
94
105
 
95
106
  # @!attribute [rw] container_override
96
- # @return [Object]
97
- # @param value [Object]
107
+ # @return [String?]
108
+ # @param [String?] value
98
109
  attr_accessor :container_override
99
110
 
100
111
  # @!attribute [r] explicit_instance
101
- # @return [Object]
112
+ # @return [Hash<Symbol, Symbol>]
102
113
  attr_reader :explicit_instance
103
114
 
104
115
  # @!attribute [r] explicit_class
105
- # @return [Object]
116
+ # @return [Hash<Symbol, Symbol>]
106
117
  attr_reader :explicit_class
107
118
 
108
119
  # @!attribute [r] module_function_explicit
109
- # @return [Object]
120
+ # @return [Hash<Symbol, Boolean>]
110
121
  attr_reader :module_function_explicit
111
122
 
112
123
  # @!attribute [rw] container_is_module
113
- # @return [Object]
114
- # @param value [Object]
124
+ # @return [Boolean]
125
+ # @param [Boolean] value
115
126
  attr_accessor :container_is_module
116
127
 
117
128
  # @!attribute [rw] extend_self
118
- # @return [Object]
119
- # @param value [Object]
129
+ # @return [Boolean]
130
+ # @param [Boolean] value
120
131
  attr_accessor :extend_self
121
132
 
122
133
  # Create a fresh visibility context with Ruby-like defaults.
@@ -137,7 +148,7 @@ module Docscribe
137
148
 
138
149
  # Duplicate the context so nested bodies can mutate state independently.
139
150
  #
140
- # @return [VisibilityCtx]
151
+ # @return [Docscribe::InlineRewriter::Collector::VisibilityCtx]
141
152
  def dup
142
153
  VisibilityCtx.new.tap do |ctx|
143
154
  copy_visibility_state(ctx)
@@ -151,7 +162,7 @@ module Docscribe
151
162
  # Copy default instance/class visibility and sclass state into a new context.
152
163
  #
153
164
  # @private
154
- # @param [VisibilityCtx] ctx the target context to copy state into
165
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx the target context to copy state into
155
166
  # @return [void]
156
167
  def copy_visibility_state(ctx)
157
168
  ctx.default_instance_vis = default_instance_vis
@@ -165,7 +176,7 @@ module Docscribe
165
176
  # Copy module_function default and explicit state into a new context.
166
177
  #
167
178
  # @private
168
- # @param [VisibilityCtx] ctx the target context to copy state into
179
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx the target context to copy state into
169
180
  # @return [void]
170
181
  def copy_module_function_state(ctx)
171
182
  ctx.module_function_default = module_function_default
@@ -175,7 +186,7 @@ module Docscribe
175
186
  # Copy container override, module flag, and extend_self state into a new context.
176
187
  #
177
188
  # @private
178
- # @param [VisibilityCtx] ctx the target context to copy state into
189
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx the target context to copy state into
179
190
  # @return [void]
180
191
  def copy_container_state(ctx)
181
192
  ctx.container_override = container_override
@@ -185,17 +196,17 @@ module Docscribe
185
196
  end
186
197
 
187
198
  # @!attribute [r] insertions
188
- # @return [Array<Insertion>]
199
+ # @return [Array<Docscribe::InlineRewriter::Collector::Insertion>]
189
200
  attr_reader :insertions
190
201
 
191
202
  # @!attribute [r] attr_insertions
192
- # @return [Array<AttrInsertion>]
203
+ # @return [Array<Docscribe::InlineRewriter::Collector::AttrInsertion>]
193
204
  attr_reader :attr_insertions
194
205
 
195
206
  # Create a collector for the given source buffer.
196
207
  #
197
208
  # @param [Parser::Source::Buffer] buffer source buffer for anchor location lookups
198
- # @return [Collector]
209
+ # @return [void]
199
210
  def initialize(buffer)
200
211
  super()
201
212
  @buffer = buffer
@@ -214,7 +225,7 @@ module Docscribe
214
225
 
215
226
  # Enter a class body and collect documentation targets from its contents.
216
227
  #
217
- # @param [Parser::AST::Node] node
228
+ # @param [Parser::AST::Node] node an AST node
218
229
  # @return [Parser::AST::Node]
219
230
  def on_class(node)
220
231
  cname_node, super_node, body = *node
@@ -235,7 +246,7 @@ module Docscribe
235
246
  # This also carries `extend self` state across reopened modules in the same
236
247
  # file.
237
248
  #
238
- # @param [Parser::AST::Node] node
249
+ # @param [Parser::AST::Node] node an AST node
239
250
  # @return [Parser::AST::Node]
240
251
  def on_module(node)
241
252
  cname_node, body = *node
@@ -279,7 +290,7 @@ module Docscribe
279
290
  # that +def foo+ declared outside of any class or module is still picked
280
291
  # up by the collector.
281
292
  #
282
- # @param [Parser::AST::Node] node
293
+ # @param [Parser::AST::Node] node an AST node
283
294
  # @return [Parser::AST::Node]
284
295
  def on_def(node)
285
296
  return node unless @name_stack.empty?
@@ -295,7 +306,7 @@ module Docscribe
295
306
  # Handles the case of +def self.foo+ declared at the top level, outside
296
307
  # of any class or module body.
297
308
  #
298
- # @param [Parser::AST::Node] node
309
+ # @param [Parser::AST::Node] node an AST node
299
310
  # @return [Parser::AST::Node]
300
311
  def on_defs(node)
301
312
  return node unless @name_stack.empty?
@@ -311,9 +322,9 @@ module Docscribe
311
322
  # Process a `:def` node for documentation insertion.
312
323
  #
313
324
  # @private
314
- # @param [Parser::AST::Node] node
315
- # @param [VisibilityCtx] ctx
316
- # @param [Parser::AST::Node, nil] pending_sig_anchor
325
+ # @param [Parser::AST::Node] node an AST node
326
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
327
+ # @param [Parser::AST::Node?] pending_sig_anchor Sorbet `sig` node waiting for a method
317
328
  # @return [void]
318
329
  def process_def_stmt(node, ctx, pending_sig_anchor:)
319
330
  name, = *node
@@ -331,8 +342,8 @@ module Docscribe
331
342
  #
332
343
  # @private
333
344
  # @param [Parser::AST::Node] node the `:defs` AST node
334
- # @param [VisibilityCtx] ctx current visibility context
335
- # @param [Parser::AST::Node, nil] pending_sig_anchor Sorbet `sig` node waiting for a method
345
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
346
+ # @param [Parser::AST::Node?] pending_sig_anchor Sorbet `sig` node waiting for a method
336
347
  # @return [void]
337
348
  def process_defs_stmt(node, ctx, pending_sig_anchor:)
338
349
  recv, name, _args, _body = *node
@@ -351,10 +362,11 @@ module Docscribe
351
362
  # Process a `:sclass` node for documentation insertion.
352
363
  #
353
364
  # @private
354
- # @param [Parser::AST::Node] node
355
- # @param [VisibilityCtx] ctx
365
+ # @param [Parser::AST::Node] node an AST node
366
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
367
+ # @param [Parser::AST::Node?] pending_sig_anchor pending Sorbet sig anchor
356
368
  # @return [void]
357
- def process_sclass_stmt(node, ctx)
369
+ def process_sclass_stmt(node, ctx, pending_sig_anchor: nil) # rubocop:disable Lint/UnusedMethodArgument
358
370
  # `class << self` — affects default visibility for singleton methods and changes scope.
359
371
  recv, body = *node
360
372
  inner_ctx = ctx.dup
@@ -367,7 +379,7 @@ module Docscribe
367
379
  # Configure the new context with sclass receiver tracking and container override.
368
380
  #
369
381
  # @private
370
- # @param [VisibilityCtx] ctx the inner context to configure
382
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx the inner context to configure
371
383
  # @param [Parser::AST::Node] recv the receiver node of `class <<`
372
384
  # @return [void]
373
385
  def configure_sclass_context(ctx, recv)
@@ -388,7 +400,7 @@ module Docscribe
388
400
  #
389
401
  # @private
390
402
  # @param [Parser::AST::Node] recv the receiver node of `class <<`
391
- # @return [String, nil] the container name for constant receivers, nil for `self`
403
+ # @return [String?] the container name for constant receivers, nil for `self`
392
404
  def sclass_container_override(recv)
393
405
  return nil if self_node?(recv)
394
406
  return const_name(recv) if const_receiver?(recv)
@@ -399,9 +411,9 @@ module Docscribe
399
411
  # Process a `:send` node for documentation insertion.
400
412
  #
401
413
  # @private
402
- # @param [Parser::AST::Node] node
403
- # @param [VisibilityCtx] ctx
404
- # @param [Parser::AST::Node, nil] pending_sig_anchor
414
+ # @param [Parser::AST::Node] node an AST node
415
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
416
+ # @param [Parser::AST::Node?] pending_sig_anchor Sorbet `sig` node waiting for a method
405
417
  # @return [void]
406
418
  def process_send_stmt(node, ctx, pending_sig_anchor:)
407
419
  if process_attr_send?(node, ctx)
@@ -421,7 +433,7 @@ module Docscribe
421
433
  #
422
434
  # @private
423
435
  # @param [Parser::AST::Node] node the class declaration node
424
- # @param [Parser::AST::Node, nil] super_node the superclass expression
436
+ # @param [Parser::AST::Node?] super_node the superclass expression
425
437
  # @return [void]
426
438
  def process_struct_class(node, super_node)
427
439
  return unless struct_new_node?(super_node)
@@ -436,7 +448,7 @@ module Docscribe
436
448
  #
437
449
  # @private
438
450
  # @param [Parser::AST::Node] node a `:send` node
439
- # @param [VisibilityCtx] ctx current visibility context
451
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
440
452
  # @return [Boolean] true if the node was an attr_* call
441
453
  def process_attr_send?(node, ctx)
442
454
  recv, meth, *args = *node
@@ -458,7 +470,7 @@ module Docscribe
458
470
  #
459
471
  # @private
460
472
  # @param [Parser::AST::Node] node a `:send` node
461
- # @param [VisibilityCtx] ctx current visibility context
473
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
462
474
  # @return [Boolean] true if `extend self` was detected
463
475
  def process_extend_self_send?(node, ctx)
464
476
  recv, meth, *args = *node
@@ -473,7 +485,7 @@ module Docscribe
473
485
  # Mark the context and module state as using `extend self`.
474
486
  #
475
487
  # @private
476
- # @param [VisibilityCtx] ctx current visibility context
488
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
477
489
  # @return [void]
478
490
  def persist_extend_self(ctx)
479
491
  ctx.extend_self = true
@@ -485,8 +497,8 @@ module Docscribe
485
497
  # Check if a `:send` node is an `extend self` call inside a module.
486
498
  #
487
499
  # @private
488
- # @param [VisibilityCtx] ctx current visibility context
489
- # @param [Parser::AST::Node, nil] recv the receiver of the send node
500
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
501
+ # @param [Parser::AST::Node?] recv the receiver of the send node
490
502
  # @param [Symbol] meth the method name being called
491
503
  # @param [Array<Parser::AST::Node>] args the arguments to the method call
492
504
  # @return [Boolean]
@@ -501,7 +513,7 @@ module Docscribe
501
513
  # Check if a node is a constant or `::` (cbase) receiver.
502
514
  #
503
515
  # @private
504
- # @param [Parser::AST::Node, nil] node an AST node
516
+ # @param [Parser::AST::Node?] node an AST node
505
517
  # @return [Boolean]
506
518
  def const_receiver?(node)
507
519
  return false unless node.is_a?(Parser::AST::Node)
@@ -512,7 +524,7 @@ module Docscribe
512
524
  # Check if a send node is an attr_reader/attr_writer/attr_accessor call.
513
525
  #
514
526
  # @private
515
- # @param [Parser::AST::Node, nil] recv the receiver of the send node
527
+ # @param [Parser::AST::Node?] recv the receiver of the send node
516
528
  # @param [Symbol] meth the method name being called
517
529
  # @return [Boolean]
518
530
  def attr_send?(recv, meth)
@@ -522,8 +534,8 @@ module Docscribe
522
534
  # Determine the scope and visibility for an attribute based on sclass context.
523
535
  #
524
536
  # @private
525
- # @param [VisibilityCtx] ctx current visibility context
526
- # @return [Array(Symbol, Symbol)] the scope (:instance/:class) and visibility (:public/:protected/:private)
537
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
538
+ # @return [(Symbol, Symbol)]
527
539
  def attr_scope_visibility(ctx)
528
540
  if ctx.inside_sclass
529
541
  [:class, ctx.default_class_vis]
@@ -549,7 +561,7 @@ module Docscribe
549
561
  #
550
562
  # @private
551
563
  # @param [Parser::AST::Node] node the `:send` node
552
- # @param [VisibilityCtx] ctx current visibility context
564
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
553
565
  # @return [Boolean] true if the node was a module_function call
554
566
  def process_module_function_send?(node, ctx)
555
567
  recv, meth, *args = *node
@@ -567,7 +579,7 @@ module Docscribe
567
579
  # Enable default module_function for all subsequent method definitions in the module.
568
580
  #
569
581
  # @private
570
- # @param [VisibilityCtx] ctx current visibility context
582
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
571
583
  # @return [Boolean] true
572
584
  def enable_default_module_function?(ctx)
573
585
  ctx.module_function_default = true
@@ -578,7 +590,7 @@ module Docscribe
578
590
  #
579
591
  # @private
580
592
  # @param [Array<Parser::AST::Node>] args the named method arguments
581
- # @param [VisibilityCtx] ctx current visibility context
593
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
582
594
  # @return [void]
583
595
  def process_named_module_function(args, ctx)
584
596
  args.map { |arg| extract_name_sym(arg) }
@@ -618,7 +630,7 @@ module Docscribe
618
630
  #
619
631
  # @private
620
632
  # @param [Parser::AST::Node] node a `:send` node
621
- # @param [VisibilityCtx] ctx current visibility context
633
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
622
634
  # @return [Boolean] true if the node was a class visibility modifier
623
635
  def process_class_method_visibility_send?(node, ctx)
624
636
  recv, meth, *args = *node
@@ -633,7 +645,7 @@ module Docscribe
633
645
  # Check if a send node is a private/protected/public_class_method call.
634
646
  #
635
647
  # @private
636
- # @param [Parser::AST::Node, nil] recv the receiver of the send node
648
+ # @param [Parser::AST::Node?] recv the receiver of the send node
637
649
  # @param [Symbol] meth the method name being called
638
650
  # @return [Boolean]
639
651
  def class_visibility_send?(recv, meth)
@@ -665,7 +677,7 @@ module Docscribe
665
677
  #
666
678
  # @private
667
679
  # @param [Array<Parser::AST::Node>] args the method name nodes
668
- # @param [VisibilityCtx] ctx current visibility context
680
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
669
681
  # @param [Symbol] visibility the visibility to apply (:public, :protected, :private)
670
682
  # @param [String] container the container name
671
683
  # @return [void]
@@ -688,8 +700,8 @@ module Docscribe
688
700
  #
689
701
  # @private
690
702
  # @param [Parser::AST::Node] node a `:send` node
691
- # @param [VisibilityCtx] ctx current visibility context
692
- # @param [Parser::AST::Node, nil] pending_sig_anchor Sorbet `sig` node
703
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
704
+ # @param [Parser::AST::Node?] pending_sig_anchor Sorbet `sig` node
693
705
  # @return [void]
694
706
  def process_visibility_send(node, ctx, pending_sig_anchor: nil)
695
707
  recv, meth, *args = *node
@@ -702,7 +714,7 @@ module Docscribe
702
714
  # Check if a send node is a private/protected/public call with no receiver.
703
715
  #
704
716
  # @private
705
- # @param [Parser::AST::Node, nil] recv the receiver of the send node
717
+ # @param [Parser::AST::Node?] recv the receiver of the send node
706
718
  # @param [Symbol] meth the method name being called
707
719
  # @return [Boolean]
708
720
  def visibility_send?(recv, meth)
@@ -713,10 +725,10 @@ module Docscribe
713
725
  #
714
726
  # @private
715
727
  # @param [Array<Parser::AST::Node>] args the arguments to the visibility modifier
716
- # @param [VisibilityCtx] ctx current visibility context
728
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
717
729
  # @param [Symbol] meth the visibility method (:private, :protected, :public)
718
730
  # @param [String] container the container name
719
- # @param [Parser::AST::Node, nil] pending_sig_anchor Sorbet `sig` node waiting for a method
731
+ # @param [Parser::AST::Node?] pending_sig_anchor Sorbet `sig` node waiting for a method
720
732
  # @return [void]
721
733
  def process_visibility_args(args, ctx, meth, container, pending_sig_anchor)
722
734
  if args.empty?
@@ -742,8 +754,8 @@ module Docscribe
742
754
  # Process a bare visibility modifier (no args).
743
755
  #
744
756
  # @private
745
- # @param [VisibilityCtx] ctx
746
- # @param [Symbol] meth
757
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
758
+ # @param [Symbol] meth the visibility method (:private, :protected, :public)
747
759
  # @return [void]
748
760
  def process_visibility_bare_modifier(ctx, meth)
749
761
  if ctx.inside_sclass
@@ -756,11 +768,11 @@ module Docscribe
756
768
  # Process an inline visibility modifier (private def foo).
757
769
  #
758
770
  # @private
759
- # @param [Parser::AST::Node] def_node
760
- # @param [VisibilityCtx] ctx
761
- # @param [Symbol] meth
762
- # @param [String] container
763
- # @param [Parser::AST::Node, nil] pending_sig_anchor
771
+ # @param [Parser::AST::Node] def_node method definition node
772
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
773
+ # @param [Symbol] meth the visibility method (:private, :protected, :public)
774
+ # @param [String] container the container name
775
+ # @param [Parser::AST::Node?] pending_sig_anchor Sorbet `sig` node waiting for a method
764
776
  # @return [void]
765
777
  def process_visibility_inline_modifier(def_node, ctx, meth, container, pending_sig_anchor)
766
778
  anchor_node = pending_sig_anchor || def_node
@@ -776,11 +788,11 @@ module Docscribe
776
788
  # Process an inline def under a visibility modifier.
777
789
  #
778
790
  # @private
779
- # @param [Parser::AST::Node] def_node
780
- # @param [VisibilityCtx] ctx
781
- # @param [Symbol] meth
782
- # @param [String] container
783
- # @param [Parser::AST::Node] anchor_node
791
+ # @param [Parser::AST::Node] def_node method definition node
792
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
793
+ # @param [Symbol] meth the visibility method (:private, :protected, :public)
794
+ # @param [String] container the container name
795
+ # @param [Parser::AST::Node] anchor_node the anchor node for comment placement
784
796
  # @return [void]
785
797
  def process_visibility_inline_def(def_node, ctx, meth, container, anchor_node)
786
798
  name, = *def_node
@@ -798,10 +810,10 @@ module Docscribe
798
810
  # Process a named visibility modifier (private :foo).
799
811
  #
800
812
  # @private
801
- # @param [Array<Parser::AST::Node>] args
802
- # @param [VisibilityCtx] ctx
803
- # @param [Symbol] meth
804
- # @param [String] container
813
+ # @param [Array<Parser::AST::Node>] args the destructured arguments from Struct.new
814
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
815
+ # @param [Symbol] meth the visibility method (:private, :protected, :public)
816
+ # @param [String] container the container name
805
817
  # @return [void]
806
818
  def process_visibility_named_modifier(args, ctx, meth, container)
807
819
  args.each do |arg|
@@ -813,7 +825,7 @@ module Docscribe
813
825
  #
814
826
  # @private
815
827
  # @param [Parser::AST::Node] arg the AST node for the method name
816
- # @param [VisibilityCtx] ctx current visibility context
828
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
817
829
  # @param [Symbol] meth the visibility method (:private, :protected, :public)
818
830
  # @param [String] container the container name
819
831
  # @return [void]
@@ -832,7 +844,7 @@ module Docscribe
832
844
  #
833
845
  # @private
834
846
  # @param [Symbol] sym the method name
835
- # @param [VisibilityCtx] ctx current visibility context
847
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
836
848
  # @param [Symbol] meth the visibility method (:private, :protected, :public)
837
849
  # @param [String] container the container name
838
850
  # @return [void]
@@ -846,7 +858,7 @@ module Docscribe
846
858
  #
847
859
  # @private
848
860
  # @param [Symbol] sym the method name
849
- # @param [VisibilityCtx] ctx current visibility context
861
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
850
862
  # @param [Symbol] meth the visibility method (:private, :protected, :public)
851
863
  # @param [String] container the container name
852
864
  # @return [void]
@@ -878,7 +890,7 @@ module Docscribe
878
890
  # Check if `module_function` semantics apply to a method at the current position.
879
891
  #
880
892
  # @private
881
- # @param [VisibilityCtx] ctx current visibility context
893
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
882
894
  # @param [Symbol] name the method name
883
895
  # @return [Boolean]
884
896
  def module_function_applies?(ctx, name)
@@ -892,7 +904,7 @@ module Docscribe
892
904
  # @private
893
905
  # @param [Parser::AST::Node] node the `:def` AST node
894
906
  # @param [Symbol] name the method name
895
- # @param [VisibilityCtx] ctx current visibility context
907
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
896
908
  # @param [Parser::AST::Node] anchor_node the anchor node for comment placement
897
909
  # @return [void]
898
910
  def process_module_function_def(node, name, ctx, anchor_node)
@@ -904,7 +916,7 @@ module Docscribe
904
916
  # Check if extend self semantics should apply to the current definition.
905
917
  #
906
918
  # @private
907
- # @param [VisibilityCtx] ctx current visibility context
919
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
908
920
  # @return [Boolean]
909
921
  def extend_self_applies?(ctx)
910
922
  ctx.container_is_module && ctx.extend_self && !ctx.inside_sclass
@@ -915,7 +927,7 @@ module Docscribe
915
927
  # @private
916
928
  # @param [Parser::AST::Node] node the `:def` AST node
917
929
  # @param [Symbol] name the method name
918
- # @param [VisibilityCtx] ctx current visibility context
930
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
919
931
  # @param [Parser::AST::Node] anchor_node the anchor node for comment placement
920
932
  # @return [void]
921
933
  def process_extend_self_def(node, name, ctx, anchor_node)
@@ -926,9 +938,9 @@ module Docscribe
926
938
  # Determine scope and visibility for a def based on sclass context and explicit visibility.
927
939
  #
928
940
  # @private
929
- # @param [VisibilityCtx] ctx current visibility context
941
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
930
942
  # @param [Symbol] name the method name
931
- # @return [Array(Symbol, Symbol)] the scope (:instance/:class) and visibility (:public/:protected/:private)
943
+ # @return [(Symbol, Symbol)]
932
944
  def def_scope_visibility(ctx, name)
933
945
  if ctx.inside_sclass
934
946
  [:class, ctx.explicit_class[name] || ctx.default_class_vis]
@@ -958,7 +970,7 @@ module Docscribe
958
970
  # Check if an Insertion matches the given scope and container for visibility updates.
959
971
  #
960
972
  # @private
961
- # @param [Insertion] insertion the Insertion struct to check
973
+ # @param [Docscribe::InlineRewriter::Collector::Insertion] insertion the Insertion struct to check
962
974
  # @param [Symbol] scope the scope to match (:instance or :class)
963
975
  # @param [String] container the container name to match
964
976
  # @return [Boolean]
@@ -970,7 +982,7 @@ module Docscribe
970
982
  #
971
983
  # @private
972
984
  # @param [Parser::AST::Node] node the `:def` or `:defs` AST node
973
- # @return [Symbol, nil] the method name
985
+ # @return [Symbol?] the method name
974
986
  def insertion_method_name(node)
975
987
  case node.type
976
988
  when :def
@@ -983,7 +995,7 @@ module Docscribe
983
995
  # Check if a node is a `self` literal.
984
996
  #
985
997
  # @private
986
- # @param [Parser::AST::Node, nil] node an AST node
998
+ # @param [Parser::AST::Node?] node an AST node
987
999
  # @return [Boolean]
988
1000
  def self_node?(node)
989
1001
  !!(node && node.type == :self)
@@ -995,8 +1007,8 @@ module Docscribe
995
1007
  # next method definition.
996
1008
  #
997
1009
  # @private
998
- # @param [Parser::AST::Node, nil] body the body node
999
- # @param [VisibilityCtx] ctx current visibility context
1010
+ # @param [Parser::AST::Node?] body the body node
1011
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
1000
1012
  # @return [void]
1001
1013
  def process_body(body, ctx)
1002
1014
  return unless body
@@ -1013,7 +1025,7 @@ module Docscribe
1013
1025
  #
1014
1026
  # @private
1015
1027
  # @param [Parser::AST::Node] child the child AST node to process
1016
- # @param [VisibilityCtx] ctx current visibility context
1028
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
1017
1029
  # @param [Array<Parser::AST::Node>] pending_sig_nodes accumulator for Sorbet sig nodes
1018
1030
  # @return [void]
1019
1031
  def process_body_child(child, ctx, pending_sig_nodes)
@@ -1033,18 +1045,17 @@ module Docscribe
1033
1045
  # `Insertion` objects for methods that need documentation.
1034
1046
  #
1035
1047
  # @private
1036
- # @param [Parser::AST::Node, nil] node the AST node to process
1037
- # @param [VisibilityCtx] ctx current visibility and container context
1038
- # @param [Parser::AST::Node, nil] pending_sig_anchor Sorbet `sig` node waiting for a method
1048
+ # @param [Parser::AST::Node?] node the AST node to process
1049
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility and container context
1050
+ # @param [Parser::AST::Node?] pending_sig_anchor Sorbet `sig` node waiting for a method
1039
1051
  # @return [void]
1040
1052
  def process_stmt(node, ctx, pending_sig_anchor: nil)
1041
1053
  return unless node
1042
1054
  return process_casgn_stmt(node) if node.type == :casgn
1043
1055
 
1044
- handler = PROCESS_STMT_HANDLERS[node.type]
1045
-
1046
- if handler
1047
- dispatch_process_stmt(handler, node, ctx, pending_sig_anchor)
1056
+ method_name = :"process_#{node.type}_stmt"
1057
+ if respond_to?(method_name, true)
1058
+ __send__(method_name, node, ctx, pending_sig_anchor: pending_sig_anchor)
1048
1059
  else
1049
1060
  process(node)
1050
1061
  end
@@ -1059,22 +1070,6 @@ module Docscribe
1059
1070
  process(node) unless process_struct_casgn?(node)
1060
1071
  end
1061
1072
 
1062
- # Dispatch the statement to the appropriate handler method based on node type.
1063
- #
1064
- # @private
1065
- # @param [Symbol] handler the method name to dispatch to
1066
- # @param [Parser::AST::Node] node the AST node to process
1067
- # @param [VisibilityCtx] ctx current visibility context
1068
- # @param [Parser::AST::Node, nil] pending_sig_anchor Sorbet `sig` node waiting for a method
1069
- # @return [void]
1070
- def dispatch_process_stmt(handler, node, ctx, pending_sig_anchor)
1071
- if %i[process_def_stmt process_defs_stmt process_send_stmt].include?(handler)
1072
- __send__(handler, node, ctx, pending_sig_anchor: pending_sig_anchor)
1073
- else
1074
- __send__(handler, node, ctx)
1075
- end
1076
- end
1077
-
1078
1073
  # Check if a constant assignment is `Struct.new` and extract attribute insertions.
1079
1074
  #
1080
1075
  # @private
@@ -1095,7 +1090,7 @@ module Docscribe
1095
1090
  # Check if a node represents a `Struct.new` call.
1096
1091
  #
1097
1092
  # @private
1098
- # @param [Parser::AST::Node, nil] node an AST node
1093
+ # @param [Parser::AST::Node?] node an AST node
1099
1094
  # @return [Boolean]
1100
1095
  def struct_new_node?(node)
1101
1096
  return false unless node.is_a?(Parser::AST::Node)
@@ -1112,7 +1107,7 @@ module Docscribe
1112
1107
  # If `extend self` is active for this module, document all instance defs as module methods (M.foo).
1113
1108
  #
1114
1109
  # @private
1115
- # @param [VisibilityCtx] ctx current visibility context
1110
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
1116
1111
  # @param [String] container the container name
1117
1112
  # @return [void]
1118
1113
  def persist_extend_self_state(ctx, container)
@@ -1125,11 +1120,11 @@ module Docscribe
1125
1120
  # Extract member names from a `Struct.new` call, stripping the type string argument if present.
1126
1121
  #
1127
1122
  # @private
1128
- # @param [Parser::AST::Node] struct_new_node a `:send` node representing `Struct.new`
1123
+ # @param [Parser::AST::Node?] struct_new_node a `:send` node representing `Struct.new`
1129
1124
  # @return [Array<Symbol>] extracted member names
1130
1125
  def extract_struct_member_names(struct_new_node)
1131
1126
  _recv, _meth, *args = *struct_new_node
1132
- args ||= []
1127
+ args ||= [] #: Array[Parser::AST::Node]
1133
1128
 
1134
1129
  args.reject! { |arg| arg.is_a?(Parser::AST::Node) && arg.type == :hash }
1135
1130
 
@@ -1141,7 +1136,7 @@ module Docscribe
1141
1136
  # Drop the first argument if it is a string (e.g. Struct.new("Name", ...)).
1142
1137
  #
1143
1138
  # @private
1144
- # @param [Array] args the destructured arguments from Struct.new
1139
+ # @param [Array<Parser::AST::Node>] args the destructured arguments from Struct.new
1145
1140
  # @return [void]
1146
1141
  def drop_first_if_str!(args)
1147
1142
  return unless args.first.is_a?(Parser::AST::Node)
@@ -1174,7 +1169,7 @@ module Docscribe
1174
1169
  #
1175
1170
  # @private
1176
1171
  # @param [Parser::AST::Node] arg an AST node
1177
- # @return [Symbol, nil] the extracted name or nil
1172
+ # @return [Symbol?] the extracted name or nil
1178
1173
  def extract_name_sym(arg)
1179
1174
  case arg.type
1180
1175
  when :sym then arg.children.first
@@ -1185,7 +1180,7 @@ module Docscribe
1185
1180
  # Build the fully qualified name for a constant node.
1186
1181
  #
1187
1182
  # @private
1188
- # @param [Parser::AST::Node, nil] node a `:const` or `:cbase` node
1183
+ # @param [Parser::AST::Node?] node a `:const` or `:cbase` node
1189
1184
  # @return [String] the resolved constant name
1190
1185
  def const_name(node)
1191
1186
  return 'Object' unless node
@@ -1214,7 +1209,7 @@ module Docscribe
1214
1209
  # Get the effective container name, using `container_override` when set.
1215
1210
  #
1216
1211
  # @private
1217
- # @param [VisibilityCtx] ctx current visibility context
1212
+ # @param [Docscribe::InlineRewriter::Collector::VisibilityCtx] ctx current visibility context
1218
1213
  # @return [String] the container name
1219
1214
  def container_for(ctx)
1220
1215
  ctx.container_override || current_container
@@ -1231,7 +1226,7 @@ module Docscribe
1231
1226
  # Check if a node is a Sorbet `sig` declaration (bare `sig` send or `sig { ... }` block).
1232
1227
  #
1233
1228
  # @private
1234
- # @param [Parser::AST::Node, nil] node an AST node
1229
+ # @param [Parser::AST::Node?] node an AST node
1235
1230
  # @return [Boolean]
1236
1231
  def sorbet_sig_node?(node)
1237
1232
  return false unless node.is_a?(Parser::AST::Node)