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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +588 -104
  3. data/lib/docscribe/cli/check_for_comments.rb +183 -0
  4. data/lib/docscribe/cli/config_builder.rb +180 -36
  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 +296 -125
  10. data/lib/docscribe/cli/init.rb +58 -14
  11. data/lib/docscribe/cli/options.rb +410 -133
  12. data/lib/docscribe/cli/rbs_gen.rb +529 -0
  13. data/lib/docscribe/cli/run.rb +503 -189
  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 +35 -9
  17. data/lib/docscribe/config/defaults.rb +16 -12
  18. data/lib/docscribe/config/emit.rb +18 -0
  19. data/lib/docscribe/config/filtering.rb +37 -31
  20. data/lib/docscribe/config/loader.rb +20 -13
  21. data/lib/docscribe/config/plugin.rb +2 -1
  22. data/lib/docscribe/config/rbs.rb +68 -27
  23. data/lib/docscribe/config/sorbet.rb +40 -17
  24. data/lib/docscribe/config/sorting.rb +2 -1
  25. data/lib/docscribe/config/template.rb +10 -1
  26. data/lib/docscribe/config/utils.rb +12 -9
  27. data/lib/docscribe/config.rb +3 -4
  28. data/lib/docscribe/infer/ast_walk.rb +1 -1
  29. data/lib/docscribe/infer/constants.rb +15 -0
  30. data/lib/docscribe/infer/literals.rb +39 -26
  31. data/lib/docscribe/infer/names.rb +24 -16
  32. data/lib/docscribe/infer/params.rb +57 -13
  33. data/lib/docscribe/infer/raises.rb +23 -15
  34. data/lib/docscribe/infer/returns.rb +784 -199
  35. data/lib/docscribe/infer.rb +28 -28
  36. data/lib/docscribe/inline_rewriter/collector.rb +816 -430
  37. data/lib/docscribe/inline_rewriter/doc_block.rb +323 -150
  38. data/lib/docscribe/inline_rewriter/doc_builder.rb +1837 -648
  39. data/lib/docscribe/inline_rewriter/source_helpers.rb +119 -71
  40. data/lib/docscribe/inline_rewriter/tag_sorter.rb +165 -107
  41. data/lib/docscribe/inline_rewriter.rb +1144 -727
  42. data/lib/docscribe/parsing.rb +29 -10
  43. data/lib/docscribe/plugin/base/collector_plugin.rb +3 -3
  44. data/lib/docscribe/plugin/base/tag_plugin.rb +1 -2
  45. data/lib/docscribe/plugin/context.rb +28 -18
  46. data/lib/docscribe/plugin/registry.rb +49 -23
  47. data/lib/docscribe/plugin/tag.rb +9 -14
  48. data/lib/docscribe/plugin.rb +54 -22
  49. data/lib/docscribe/types/provider_chain.rb +4 -2
  50. data/lib/docscribe/types/rbs/collection_loader.rb +2 -3
  51. data/lib/docscribe/types/rbs/provider.rb +127 -62
  52. data/lib/docscribe/types/rbs/type_formatter.rb +286 -77
  53. data/lib/docscribe/types/signature.rb +22 -42
  54. data/lib/docscribe/types/sorbet/base_provider.rb +51 -27
  55. data/lib/docscribe/types/sorbet/rbi_provider.rb +3 -3
  56. data/lib/docscribe/types/sorbet/source_provider.rb +3 -2
  57. data/lib/docscribe/types/yard/formatter.rb +100 -0
  58. data/lib/docscribe/types/yard/parser.rb +240 -0
  59. data/lib/docscribe/types/yard/types.rb +52 -0
  60. data/lib/docscribe/version.rb +1 -1
  61. metadata +34 -2
@@ -10,93 +10,319 @@ module Docscribe
10
10
  module TypeFormatter
11
11
  module_function
12
12
 
13
- # Convert one RBS type object into a YARD-ish string.
13
+ # Dispatch an RBS type object to the appropriate YARD formatter.
14
14
  #
15
- # Supported categories include:
16
- # - base types (`bool`, `nil`, `void`, `untyped`)
17
- # - optional and union types
18
- # - named types with optional generic arguments
19
- # - literal types
20
- # - Proc types
21
- #
22
- # @note module_function: when included, also defines #to_yard (instance visibility: private)
23
- # @param [Object] type RBS type object
24
- # @param [Boolean] collapse_generics whether generic arguments should be omitted
15
+ # @note module_function: defines #to_yard (visibility: private)
16
+ # @param [Docscribe::Types::RBS::TypeFormatter::rbs_type, nil] type the RBS type object to convert
17
+ # @param [Boolean] collapse_generics whether to omit generic type arguments
18
+ # @param [Boolean] collapse_object_generics whether to collapse generics when all inner types are Object
25
19
  # @return [String]
26
- def to_yard(type, collapse_generics: false)
20
+ def to_yard(type, collapse_generics: false, collapse_object_generics: false)
27
21
  return 'Object' unless type
28
22
 
29
- # RBS is loaded lazily by the provider; constants below exist only when rbs is available.
30
- case type
31
- when ::RBS::Types::Bases::Any
32
- 'Object'
33
- when ::RBS::Types::Bases::Bool
34
- 'Boolean'
35
- when ::RBS::Types::Bases::Void
36
- 'void'
37
- when ::RBS::Types::Bases::Nil
38
- 'nil'
39
- when ::RBS::Types::Optional
40
- "#{to_yard(type.type, collapse_generics: collapse_generics)}?"
41
- when ::RBS::Types::Union
42
- format_union(type, collapse_generics: collapse_generics)
43
- when ::RBS::Types::ClassInstance,
23
+ handler = to_yard_formatters.find { |klass, _| type.is_a?(klass) }
24
+ return handler.last.call(type, cg: collapse_generics, cog: collapse_object_generics) if handler
25
+
26
+ if named_type?(type)
27
+ return format_named(type, # steep:ignore
28
+ collapse_generics: collapse_generics,
29
+ collapse_object_generics: collapse_object_generics)
30
+ end
31
+
32
+ fallback_string(type)
33
+ end
34
+
35
+ # Check if the given type object is a named RBS type (class, singleton, interface, or alias).
36
+ #
37
+ # @note module_function: defines #named_type? (visibility: private)
38
+ # @param [Docscribe::Types::RBS::TypeFormatter::rbs_type] type the RBS type object to check
39
+ # @return [Boolean]
40
+ def named_type?(type)
41
+ named_type_classes.any? { |klass| type.is_a?(klass) }
42
+ end
43
+
44
+ # Return or memoize the list of RBS type classes considered named types.
45
+ #
46
+ # @note module_function: defines #named_type_classes (visibility: private)
47
+ # @return [Array<Class>]
48
+ def named_type_classes
49
+ @named_type_classes ||= [
50
+ ::RBS::Types::ClassInstance,
44
51
  ::RBS::Types::ClassSingleton,
45
52
  ::RBS::Types::Interface,
46
53
  ::RBS::Types::Alias
47
- format_named(type, collapse_generics: collapse_generics)
48
- when ::RBS::Types::Literal
49
- literal_to_yard(type.literal)
50
- when ::RBS::Types::Proc
51
- 'Proc'
52
- else
53
- fallback_string(type)
54
+ ].freeze
55
+ end
56
+
57
+ # Fallback conversion of an unrecognized RBS type to a cleaned string representation.
58
+ #
59
+ # @note module_function: defines #fallback_string (visibility: private)
60
+ # @param [Docscribe::Types::RBS::TypeFormatter::rbs_type] type the unrecognized RBS type object
61
+ # @return [String]
62
+ def fallback_string(type)
63
+ type.to_s
64
+ .gsub(/\A::/, '')
65
+ .gsub(/\bbool\b/, 'Boolean')
66
+ .gsub(/\buntyped\b/, 'Object')
67
+ end
68
+
69
+ # Return or memoize the dispatch hash mapping RBS type classes to formatter lambdas.
70
+ #
71
+ # @note module_function: defines #to_yard_formatters (visibility: private)
72
+ # @return [Hash<Class, Docscribe::Types::RBS::TypeFormatter::formatter_fn>]
73
+ def to_yard_formatters
74
+ @to_yard_formatters ||= formatter_pairs.to_h.freeze
75
+ end
76
+
77
+ # Hash of RBS type classes and their YARD formatter lambdas.
78
+ #
79
+ # @note module_function: defines #formatter_pairs (visibility: private)
80
+ # @return [Hash<Class, Docscribe::Types::RBS::TypeFormatter::formatter_fn>]
81
+ def formatter_pairs # steep:ignore # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
82
+ @formatter_pairs ||= {
83
+ ::RBS::Types::Bases::Any => ->(_, **) { format_any },
84
+ ::RBS::Types::Bases::Bool => ->(_, **) { format_bool },
85
+ ::RBS::Types::Bases::Void => ->(_, **) { format_void },
86
+ ::RBS::Types::Bases::Nil => ->(_, **) { format_nil },
87
+ ::RBS::Types::Optional => lambda { |t, cg:, cog:|
88
+ format_optional(t, collapse_generics: cg, collapse_object_generics: cog)
89
+ },
90
+ ::RBS::Types::Union => lambda { |t, cg:, cog:|
91
+ format_union(t, collapse_generics: cg, collapse_object_generics: cog)
92
+ },
93
+ ::RBS::Types::Literal => ->(t, **) { format_literal(t.literal) },
94
+ ::RBS::Types::Proc => ->(_, **) { format_proc },
95
+ ::RBS::Types::Tuple => lambda { |t, cg:, cog:|
96
+ format_tuple(t, collapse_generics: cg, collapse_object_generics: cog)
97
+ },
98
+ ::RBS::Types::Bases::Top => ->(_, **) { format_top },
99
+ ::RBS::Types::Bases::Bottom => ->(_, **) { format_bottom },
100
+ ::RBS::Types::Bases::Self => ->(_, **) { format_self },
101
+ ::RBS::Types::Bases::Instance => ->(_, **) { format_instance },
102
+ ::RBS::Types::Bases::Class => ->(_, **) { format_class_type },
103
+ ::RBS::Types::Variable => ->(t, **) { format_variable(t) },
104
+ ::RBS::Types::Record => lambda { |t, cg:, cog:|
105
+ format_record(t, collapse_generics: cg, collapse_object_generics: cog)
106
+ },
107
+ ::RBS::Types::Intersection => ->(t, cg:, cog:) { format_intersection(t, collapse_generics: cg, collapse_object_generics: cog) }
108
+ }.freeze
109
+ end
110
+
111
+ # Format RBS `any` type as the YARD-equivalent `Object`.
112
+ #
113
+ # @note module_function: defines #format_any (visibility: private)
114
+ # @return [String]
115
+ def format_any
116
+ 'Object'
117
+ end
118
+
119
+ # Format RBS `bool` type as the YARD `Boolean`.
120
+ #
121
+ # @note module_function: defines #format_bool (visibility: private)
122
+ # @return [String]
123
+ def format_bool
124
+ 'Boolean'
125
+ end
126
+
127
+ # Format RBS `void` type as the YARD `void`.
128
+ #
129
+ # @note module_function: defines #format_void (visibility: private)
130
+ # @return [String]
131
+ def format_void
132
+ 'void'
133
+ end
134
+
135
+ # Format RBS `nil` type as the YARD `nil`.
136
+ #
137
+ # @note module_function: defines #format_nil (visibility: private)
138
+ # @return [String]
139
+ def format_nil
140
+ 'nil'
141
+ end
142
+
143
+ # Format an RBS Optional type as a YARD optional type with `?` suffix.
144
+ #
145
+ # @note module_function: defines #format_optional (visibility: private)
146
+ # @param [RBS::Types::Optional] type the optional type to format
147
+ # @param [Boolean] collapse_generics whether to omit generic type arguments
148
+ # @param [Boolean] collapse_object_generics collapse Object generics flag
149
+ # @return [String]
150
+ def format_optional(type, collapse_generics:, collapse_object_generics:)
151
+ "#{to_yard(type.type, collapse_generics: collapse_generics,
152
+ collapse_object_generics: collapse_object_generics)}?"
153
+ end
154
+
155
+ # Map a Ruby literal value to its corresponding YARD type name.
156
+ #
157
+ # @note module_function: defines #format_literal (visibility: private)
158
+ # @param [RBS::Types::Literal] lit a Ruby literal value
159
+ # @return [String]
160
+ def format_literal(lit)
161
+ case lit
162
+ when Integer then 'Integer'
163
+ when Float then 'Float'
164
+ when String then 'String'
165
+ when Symbol then 'Symbol'
166
+ when TrueClass, FalseClass then 'Boolean'
167
+ when NilClass then 'nil'
168
+ else 'Object'
54
169
  end
55
170
  end
56
171
 
57
- # Format an RBS union type as a comma-separated YARD union.
172
+ # Format RBS Proc type as the YARD `Proc`.
58
173
  #
59
- # Example:
60
- # - `String | Integer | nil` => `"String, Integer, nil"`
174
+ # @note module_function: defines #format_proc (visibility: private)
175
+ # @return [String]
176
+ def format_proc
177
+ 'Proc'
178
+ end
179
+
180
+ # Format an RBS Tuple type as a parenthesized list of YARD types.
61
181
  #
62
- # @note module_function: when included, also defines #format_union (instance visibility: private)
63
- # @param [::RBS::Types::Union] type
64
- # @param [Boolean] collapse_generics
182
+ # @note module_function: defines #format_tuple (visibility: private)
183
+ # @param [RBS::Types::Tuple] type the tuple type to format
184
+ # @param [Boolean] collapse_generics whether to omit generic type arguments
185
+ # @param [Boolean] collapse_object_generics collapse Object generics flag
65
186
  # @return [String]
66
- def format_union(type, collapse_generics:)
67
- type.types.map { |t| to_yard(t, collapse_generics: collapse_generics) }
68
- .uniq
69
- .join(', ')
187
+ def format_tuple(type, collapse_generics:, collapse_object_generics:)
188
+ "(#{type.types.map do |t|
189
+ to_yard(t, collapse_generics: collapse_generics, collapse_object_generics: collapse_object_generics)
190
+ end.join(', ')})"
70
191
  end
71
192
 
72
- # Format a named RBS type, optionally preserving generic arguments.
193
+ # Format RBS top type as YARD `Object`.
73
194
  #
74
- # Examples:
75
- # - `::String` => `"String"`
76
- # - `::Hash[::Symbol, untyped]` => `"Hash<Symbol, Object>"`
77
- # - with `collapse_generics: true` => `"Hash"`
195
+ # @note module_function: defines #format_top (visibility: private)
196
+ # @return [String]
197
+ def format_top
198
+ 'Object'
199
+ end
200
+
201
+ # Format RBS bottom type as YARD `Object`.
78
202
  #
79
- # @note module_function: when included, also defines #format_named (instance visibility: private)
80
- # @param [Object] type named RBS type
81
- # @param [Boolean] collapse_generics
203
+ # @note module_function: defines #format_bottom (visibility: private)
82
204
  # @return [String]
83
- def format_named(type, collapse_generics:)
205
+ def format_bottom
206
+ 'Object'
207
+ end
208
+
209
+ # Format RBS self type as YARD `self`.
210
+ #
211
+ # @note module_function: defines #format_self (visibility: private)
212
+ # @return [String]
213
+ def format_self
214
+ 'self'
215
+ end
216
+
217
+ # Format RBS instance type as YARD `Object`.
218
+ #
219
+ # @note module_function: defines #format_instance (visibility: private)
220
+ # @return [String]
221
+ def format_instance
222
+ 'Object'
223
+ end
224
+
225
+ # Format RBS class type as YARD `Class`.
226
+ #
227
+ # @note module_function: defines #format_class_type (visibility: private)
228
+ # @return [String]
229
+ def format_class_type
230
+ 'Class'
231
+ end
232
+
233
+ # Format an RBS type variable as its name string.
234
+ #
235
+ # @note module_function: defines #format_variable (visibility: private)
236
+ # @param [RBS::Types::Variable] type the variable type
237
+ # @return [String]
238
+ def format_variable(type)
239
+ type.name.to_s
240
+ end
241
+
242
+ # Format an RBS Record type as a YARD `Hash<Symbol, ValueType>`.
243
+ #
244
+ # @note module_function: defines #format_record (visibility: private)
245
+ # @param [RBS::Types::Record] type the record type
246
+ # @param [Boolean] collapse_generics whether to omit generic type arguments
247
+ # @param [Boolean] collapse_object_generics collapse Object generics flag
248
+ # @return [String]
249
+ def format_record(type, collapse_generics:, collapse_object_generics:)
250
+ value_types = type.all_fields.values.map do |(ty, _)|
251
+ to_yard(ty, collapse_generics: collapse_generics, collapse_object_generics: collapse_object_generics)
252
+ end.uniq
253
+ "Hash<Symbol, #{value_types.join(', ')}>"
254
+ end
255
+
256
+ # Format an RBS Intersection type as `Type & Type` list.
257
+ #
258
+ # @note module_function: defines #format_intersection (visibility: private)
259
+ # @param [RBS::Types::Intersection] type the intersection type
260
+ # @param [Boolean] collapse_generics whether to omit generic type arguments
261
+ # @param [Boolean] collapse_object_generics collapse Object generics flag
262
+ # @return [String]
263
+ def format_intersection(type, collapse_generics:, collapse_object_generics:)
264
+ type.types.map do |t|
265
+ to_yard(t, collapse_generics: collapse_generics, collapse_object_generics: collapse_object_generics)
266
+ end.join(' & ')
267
+ end
268
+
269
+ # Format an RBS Union type as a comma-separated list of YARD types.
270
+ #
271
+ # @note module_function: defines #format_union (visibility: private)
272
+ # @param [RBS::Types::Union] type the union type to format
273
+ # @param [Boolean] collapse_generics whether to omit generic type arguments
274
+ # @param [Boolean] collapse_object_generics collapse Object generics flag
275
+ # @return [String]
276
+ def format_union(type, collapse_generics:, collapse_object_generics:)
277
+ type.types.map do |t|
278
+ to_yard(t, collapse_generics: collapse_generics, collapse_object_generics: collapse_object_generics)
279
+ end
280
+ .uniq
281
+ .join(', ')
282
+ end
283
+
284
+ # Format an RBS named type (class, interface, alias) with optional generic arguments.
285
+ #
286
+ # @note module_function: defines #format_named (visibility: private)
287
+ # @param [Docscribe::Types::RBS::TypeFormatter::named_rbs_type] type the unrecognized RBS type object
288
+ # @param [Boolean] collapse_generics whether to omit generic type arguments
289
+ # @param [Boolean] collapse_object_generics whether to collapse generics when all inner types are Object
290
+ # @return [String]
291
+ def format_named(type, collapse_generics:, collapse_object_generics:)
84
292
  name = type.name.to_s.delete_prefix('::')
85
- args = type.respond_to?(:args) ? type.args : []
293
+ args = type.respond_to?(:args) ? type.args : [] #: Array[untyped]
86
294
 
87
295
  if args && !args.empty?
88
- return name if collapse_generics
89
-
90
- "#{name}<#{args.map { |a| to_yard(a, collapse_generics: collapse_generics) }.join(', ')}>"
296
+ format_generic_args(name, args, collapse_generics: collapse_generics,
297
+ collapse_object_generics: collapse_object_generics)
91
298
  else
92
299
  name
93
300
  end
94
301
  end
95
302
 
96
- # Map a literal Ruby value from an RBS literal type into a YARD-ish type name.
303
+ # Format generic type arguments for a named type.
304
+ #
305
+ # @note module_function: defines #format_generic_args (visibility: private)
306
+ # @param [String] name the type name
307
+ # @param [Array<Docscribe::Types::RBS::TypeFormatter::rbs_type>] args the generic type arguments
308
+ # @param [Boolean] collapse_generics whether to omit generic type arguments
309
+ # @param [Boolean] collapse_object_generics whether to collapse generics when all inner types are Object
310
+ # @return [String]
311
+ def format_generic_args(name, args, collapse_generics:, collapse_object_generics:)
312
+ return name if collapse_generics
313
+
314
+ formatted = args.map do |a|
315
+ to_yard(a, collapse_generics: collapse_generics, collapse_object_generics: collapse_object_generics)
316
+ end
317
+ return name if collapse_object_generics && formatted.all? { |s| s == 'Object' }
318
+
319
+ "#{name}<#{formatted.join(', ')}>"
320
+ end
321
+
322
+ # Convert a Ruby literal value to its YARD type name string.
97
323
  #
98
- # @note module_function: when included, also defines #literal_to_yard (instance visibility: private)
99
- # @param [Object] lit literal value
324
+ # @note module_function: defines #literal_to_yard (visibility: private)
325
+ # @param [Object] lit a Ruby literal value
100
326
  # @return [String]
101
327
  def literal_to_yard(lit)
102
328
  case lit
@@ -109,23 +335,6 @@ module Docscribe
109
335
  else 'Object'
110
336
  end
111
337
  end
112
-
113
- # Fallback string conversion for unsupported or unexpected RBS type objects.
114
- #
115
- # Performs a few normalizations for nicer YARD output:
116
- # - strips leading `::`
117
- # - converts `bool` to `Boolean`
118
- # - converts `untyped` to `Object`
119
- #
120
- # @note module_function: when included, also defines #fallback_string (instance visibility: private)
121
- # @param [Object] type
122
- # @return [String]
123
- def fallback_string(type)
124
- type.to_s
125
- .gsub(/\A::/, '')
126
- .gsub(/\bbool\b/, 'Boolean')
127
- .gsub(/\buntyped\b/, 'Object')
128
- end
129
338
  end
130
339
  end
131
340
  end
@@ -2,64 +2,44 @@
2
2
 
3
3
  module Docscribe
4
4
  module Types
5
- # Simplified view of an RBS method signature for Docscribe.
6
- #
7
- # @!attribute return_type
8
- # @return [String] formatted return type for YARD output
9
- # @!attribute param_types
10
- # @return [Hash{String=>String}] mapping of parameter name to formatted type
11
- # @!attribute rest_positional
12
- # @return [RestPositional, nil] info for `*args`
13
- # @!attribute rest_keywords
14
- # @return [RestKeywords, nil] info for `**kwargs`
15
- #
16
5
  # @!attribute [rw] return_type
17
- # @return [Object]
18
- # @param [Object] value
6
+ # @return [String]
7
+ # @param [String] value
19
8
  #
20
9
  # @!attribute [rw] param_types
21
- # @return [Object]
22
- # @param [Object] value
10
+ # @return [Hash<String, String>]
11
+ # @param [Hash<String, String>] value
12
+ #
13
+ # @!attribute [rw] positional_types
14
+ # @return [Array<String>]
15
+ # @param [Array<String>] value
23
16
  #
24
17
  # @!attribute [rw] rest_positional
25
- # @return [Object]
26
- # @param [Object] value
18
+ # @return [Docscribe::Types::RestPositional, nil]
19
+ # @param [Docscribe::Types::RestPositional, nil] value
27
20
  #
28
21
  # @!attribute [rw] rest_keywords
29
- # @return [Object]
30
- # @param [Object] value
31
- MethodSignature = Struct.new(:return_type, :param_types, :rest_positional, :rest_keywords, keyword_init: true)
22
+ # @return [Docscribe::Types::RestKeywords, nil]
23
+ # @param [Docscribe::Types::RestKeywords, nil] value
24
+ MethodSignature = Struct.new(:return_type, :param_types, :positional_types, :rest_positional, :rest_keywords,
25
+ keyword_init: true)
32
26
 
33
- # Simplified representation of an RBS rest-positional parameter.
34
- #
35
- # @!attribute name
36
- # @return [String, nil] parameter name in RBS, if present
37
- # @!attribute element_type
38
- # @return [String] formatted element type
39
- #
40
27
  # @!attribute [rw] name
41
- # @return [Object]
42
- # @param [Object] value
28
+ # @return [String, nil]
29
+ # @param [String, nil] value
43
30
  #
44
31
  # @!attribute [rw] element_type
45
- # @return [Object]
46
- # @param [Object] value
32
+ # @return [String]
33
+ # @param [String] value
47
34
  RestPositional = Struct.new(:name, :element_type, keyword_init: true)
48
35
 
49
- # Simplified representation of an RBS rest-keyword parameter.
50
- #
51
- # @!attribute name
52
- # @return [String, nil] parameter name in RBS, if present
53
- # @!attribute type
54
- # @return [String] formatted kwargs type
55
- #
56
36
  # @!attribute [rw] name
57
- # @return [Object]
58
- # @param [Object] value
37
+ # @return [String, nil]
38
+ # @param [String, nil] value
59
39
  #
60
40
  # @!attribute [rw] type
61
- # @return [Object]
62
- # @param [Object] value
41
+ # @return [String]
42
+ # @param [String] value
63
43
  RestKeywords = Struct.new(:name, :type, keyword_init: true)
64
44
  end
65
45
  end
@@ -15,9 +15,10 @@ module Docscribe
15
15
  # - SourceProvider => inline `sig` declarations in the current Ruby file
16
16
  # - RBIProvider => project RBI files
17
17
  class BaseProvider
18
+ # Initialize
19
+ #
18
20
  # @param [Boolean] collapse_generics whether generic container details
19
- # should be simplified during formatting
20
- # @return [Object]
21
+ # @return [void]
21
22
  def initialize(collapse_generics: false)
22
23
  require 'rbs'
23
24
  @collapse_generics = !!collapse_generics
@@ -49,7 +50,9 @@ module Docscribe
49
50
  # @raise [::RBS::BaseError]
50
51
  # @raise [SyntaxError]
51
52
  # @raise [StandardError]
52
- # @return [void]
53
+ # @return [void] if ::RBS::BaseError, SyntaxError, StandardError
54
+ # @return [nil] if LoadError
55
+ # @return [nil] if ::RBS::BaseError, SyntaxError, StandardError
53
56
  def load_from_string(source, label:)
54
57
  return unless defined?(RubyVM::AbstractSyntaxTree)
55
58
 
@@ -74,23 +77,32 @@ module Docscribe
74
77
  next unless decl.respond_to?(:members)
75
78
 
76
79
  container = normalize_container(decl.name.to_s)
80
+ decl.members.each { |member| process_method_member(container, member) }
81
+ end
82
+ end
77
83
 
78
- decl.members.each do |member|
79
- next unless method_definition_member?(member)
84
+ # Process a single method definition member into the index.
85
+ #
86
+ # @private
87
+ # @param [String] container normalized container name
88
+ # @param [Object] member RBS method definition member
89
+ # @return [void]
90
+ def process_method_member(container, member)
91
+ return unless method_definition_member?(member)
80
92
 
81
- scope = member.kind == :singleton ? :class : :instance
82
- overload = member.overloads&.first
83
- next unless overload
93
+ scope = member.kind == :singleton ? :class : :instance
94
+ overload = member.overloads&.first
95
+ return unless overload
84
96
 
85
- func = overload.method_type.type
86
- @index[[container, scope, member.name.to_s.to_sym]] = build_signature(func)
87
- end
88
- end
97
+ func = overload.method_type.type #: ::RBS::Types::Function
98
+ @index[[container, scope, member.name.to_s.to_sym]] = build_signature(func)
89
99
  end
90
100
 
101
+ # Method definition member
102
+ #
91
103
  # @private
92
- # @param [Object] member
93
- # @return [Boolean]
104
+ # @param [Object] member member to check for method def
105
+ # @return [Boolean, nil]
94
106
  def method_definition_member?(member)
95
107
  defined?(::RBS::AST::Members::MethodDefinition) &&
96
108
  member.is_a?(::RBS::AST::Members::MethodDefinition)
@@ -99,7 +111,7 @@ module Docscribe
99
111
  # Convert an RBS function type into Docscribe's simplified signature model.
100
112
  #
101
113
  # @private
102
- # @param [::RBS::Types::Function] func
114
+ # @param [RBS::Types::Function] func RBS function type to convert
103
115
  # @return [Docscribe::Types::MethodSignature]
104
116
  def build_signature(func)
105
117
  MethodSignature.new(
@@ -113,26 +125,38 @@ module Docscribe
113
125
  # Build a name => type map for ordinary positional/keyword parameters.
114
126
  #
115
127
  # @private
116
- # @param [::RBS::Types::Function] func
117
- # @return [Hash{String => String}]
128
+ # @param [RBS::Types::Function] func RBS function to extract params
129
+ # @return [Hash<String, String>]
118
130
  def build_param_types(func)
119
- param_types = {}
131
+ param_types = {} #: Hash[String, String]
120
132
 
121
133
  add_positionals!(param_types, func.required_positionals)
122
134
  add_positionals!(param_types, func.optional_positionals)
123
135
  add_positionals!(param_types, func.trailing_positionals)
124
136
 
125
- func.required_keywords.each { |kw, p| param_types[kw.to_s] = format_type(p.type) }
126
- func.optional_keywords.each { |kw, p| param_types[kw.to_s] = format_type(p.type) }
137
+ add_keywords!(param_types, func.required_keywords)
138
+ add_keywords!(param_types, func.optional_keywords)
127
139
 
128
140
  param_types
129
141
  end
130
142
 
143
+ # Add keyword parameters to the normalized parameter map.
144
+ #
145
+ # @private
146
+ # @param [Hash<String, String>] param_types normalized param type map
147
+ # @param [Hash<Symbol, RBS::Types::Function::Param>] keywords keyword parameter entries
148
+ # @return [void]
149
+ def add_keywords!(param_types, keywords)
150
+ keywords.each do |kw, p|
151
+ param_types[kw.to_s] = format_type(p.type)
152
+ end
153
+ end
154
+
131
155
  # Add positional parameters with names to the normalized param map.
132
156
  #
133
157
  # @private
134
- # @param [Hash{String => String}] param_types
135
- # @param [Array<Object>] list
158
+ # @param [Hash<String, String>] param_types normalized param type map
159
+ # @param [Array<RBS::Types::Function::Param>] list positional parameter objects
136
160
  # @return [void]
137
161
  def add_positionals!(param_types, list)
138
162
  list.each do |p|
@@ -145,7 +169,7 @@ module Docscribe
145
169
  # Build normalized `*args` metadata.
146
170
  #
147
171
  # @private
148
- # @param [::RBS::Types::Function] func
172
+ # @param [RBS::Types::Function] func RBS function for rest params
149
173
  # @return [Docscribe::Types::RestPositional, nil]
150
174
  def build_rest_positional(func)
151
175
  rp = func.rest_positionals
@@ -163,7 +187,7 @@ module Docscribe
163
187
  # YARD output, we expose that as a Hash keyed by Symbol.
164
188
  #
165
189
  # @private
166
- # @param [::RBS::Types::Function] func
190
+ # @param [RBS::Types::Function] func RBS function for rest keywords
167
191
  # @return [Docscribe::Types::RestKeywords, nil]
168
192
  def build_rest_keywords(func)
169
193
  rk = func.rest_keywords
@@ -181,7 +205,7 @@ module Docscribe
181
205
  # generated comments.
182
206
  #
183
207
  # @private
184
- # @param [Object] type
208
+ # @param [Docscribe::Types::RBS::TypeFormatter::rbs_type] type RBS type object to format
185
209
  # @return [String]
186
210
  def format_type(type)
187
211
  Docscribe::Types::RBS::TypeFormatter.to_yard(
@@ -193,7 +217,7 @@ module Docscribe
193
217
  # Normalize container names so lookups are consistent.
194
218
  #
195
219
  # @private
196
- # @param [String] name
220
+ # @param [String] name method name
197
221
  # @return [String]
198
222
  def normalize_container(name)
199
223
  name.to_s.delete_prefix('::')
@@ -202,7 +226,7 @@ module Docscribe
202
226
  # Print one debug warning per provider instance when debugging is enabled.
203
227
  #
204
228
  # @private
205
- # @param [String] msg
229
+ # @param [String] msg warning message text
206
230
  # @return [void]
207
231
  def warn_once(msg)
208
232
  return unless ENV['DOCSCRIBE_RBS_DEBUG'] == '1'
@@ -12,11 +12,11 @@ module Docscribe
12
12
  # any signatures that can be parsed are indexed into Docscribe's normalized
13
13
  # signature model.
14
14
  class RBIProvider < BaseProvider
15
+ # Initialize
16
+ #
15
17
  # @param [Array<String>] rbi_dirs directories scanned recursively for
16
- # `.rbi` files
17
18
  # @param [Boolean] collapse_generics whether generic container types
18
- # should be simplified during formatting
19
- # @return [Object]
19
+ # @return [void]
20
20
  def initialize(rbi_dirs:, collapse_generics: false)
21
21
  super(collapse_generics: collapse_generics)
22
22