docscribe 1.4.1 → 1.4.2
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 +149 -0
- data/lib/docscribe/cli/config_builder.rb +125 -35
- data/lib/docscribe/cli/generate.rb +288 -117
- data/lib/docscribe/cli/init.rb +49 -13
- data/lib/docscribe/cli/options.rb +302 -127
- data/lib/docscribe/cli/run.rb +391 -135
- data/lib/docscribe/cli.rb +23 -5
- data/lib/docscribe/config/defaults.rb +11 -11
- data/lib/docscribe/config/emit.rb +1 -0
- data/lib/docscribe/config/filtering.rb +24 -11
- data/lib/docscribe/config/loader.rb +7 -4
- data/lib/docscribe/config/plugin.rb +1 -0
- data/lib/docscribe/config/rbs.rb +31 -22
- data/lib/docscribe/config/sorbet.rb +41 -15
- data/lib/docscribe/config/sorting.rb +1 -0
- data/lib/docscribe/config/template.rb +1 -0
- data/lib/docscribe/config/utils.rb +1 -0
- data/lib/docscribe/config.rb +1 -0
- data/lib/docscribe/infer/constants.rb +15 -0
- data/lib/docscribe/infer/literals.rb +43 -25
- data/lib/docscribe/infer/names.rb +24 -15
- data/lib/docscribe/infer/params.rb +52 -6
- data/lib/docscribe/infer/raises.rb +24 -14
- data/lib/docscribe/infer/returns.rb +365 -182
- data/lib/docscribe/infer.rb +10 -9
- data/lib/docscribe/inline_rewriter/collector.rb +766 -375
- data/lib/docscribe/inline_rewriter/doc_block.rb +217 -74
- data/lib/docscribe/inline_rewriter/doc_builder.rb +1488 -602
- data/lib/docscribe/inline_rewriter/source_helpers.rb +100 -52
- data/lib/docscribe/inline_rewriter/tag_sorter.rb +109 -48
- data/lib/docscribe/inline_rewriter.rb +1009 -595
- data/lib/docscribe/plugin/base/collector_plugin.rb +2 -3
- data/lib/docscribe/plugin/base/tag_plugin.rb +1 -1
- data/lib/docscribe/plugin/registry.rb +34 -7
- data/lib/docscribe/plugin.rb +48 -17
- data/lib/docscribe/types/rbs/collection_loader.rb +0 -1
- data/lib/docscribe/types/rbs/provider.rb +75 -26
- data/lib/docscribe/types/rbs/type_formatter.rb +127 -59
- data/lib/docscribe/types/sorbet/base_provider.rb +31 -12
- data/lib/docscribe/version.rb +1 -1
- metadata +2 -2
|
@@ -40,9 +40,8 @@ module Docscribe
|
|
|
40
40
|
# Each result is a Hash with:
|
|
41
41
|
# - :anchor_node => Parser::AST::Node — node above which to insert doc
|
|
42
42
|
# - :doc => String — complete doc block including newlines
|
|
43
|
-
#
|
|
44
|
-
# @param [
|
|
45
|
-
# @param [Object] _buffer Param documentation.
|
|
43
|
+
# @param [Parser::AST::Node] _ast AST node to analyze
|
|
44
|
+
# @param [Parser::Source::Buffer] _buffer source buffer
|
|
46
45
|
# @return [Array<Hash>]
|
|
47
46
|
def collect(_ast, _buffer)
|
|
48
47
|
[]
|
|
@@ -27,7 +27,7 @@ module Docscribe
|
|
|
27
27
|
# nothing to add for this particular method.
|
|
28
28
|
#
|
|
29
29
|
# @param [Docscribe::Plugin::Context] context method context snapshot
|
|
30
|
-
# @param [
|
|
30
|
+
# @param [Docscribe::Plugin::Context] _context method context snapshot (unused in default)
|
|
31
31
|
# @return [Array<Docscribe::Plugin::Tag>]
|
|
32
32
|
def call(_context)
|
|
33
33
|
[]
|
|
@@ -45,16 +45,43 @@ module Docscribe
|
|
|
45
45
|
# @raise [StandardError]
|
|
46
46
|
# @return [void]
|
|
47
47
|
def register(plugin, priority: 0)
|
|
48
|
-
prio =
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
prio = parse_priority(priority)
|
|
49
|
+
entry = create_entry(plugin, prio)
|
|
50
|
+
route_entry(entry, plugin)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Parse and validate plugin priority.
|
|
54
|
+
#
|
|
55
|
+
# @note module_function: when included, also defines #parse_priority (instance visibility: private)
|
|
56
|
+
# @param [Object] priority
|
|
57
|
+
# @raise [ArgumentError]
|
|
58
|
+
# @raise [StandardError]
|
|
59
|
+
# @return [Integer]
|
|
60
|
+
def parse_priority(priority)
|
|
61
|
+
Integer(priority)
|
|
62
|
+
rescue StandardError
|
|
63
|
+
raise ArgumentError, "priority must be an Integer-like value, got: #{priority.inspect}"
|
|
64
|
+
end
|
|
54
65
|
|
|
66
|
+
# Create a new Entry with the next order number.
|
|
67
|
+
#
|
|
68
|
+
# @note module_function: when included, also defines #create_entry (instance visibility: private)
|
|
69
|
+
# @param [Object] plugin
|
|
70
|
+
# @param [Integer] priority
|
|
71
|
+
# @return [Entry]
|
|
72
|
+
def create_entry(plugin, priority)
|
|
55
73
|
@order_seq += 1
|
|
56
|
-
|
|
74
|
+
Entry.new(plugin: plugin, priority: priority, order: @order_seq)
|
|
75
|
+
end
|
|
57
76
|
|
|
77
|
+
# Route entry to tag or collector list.
|
|
78
|
+
#
|
|
79
|
+
# @note module_function: when included, also defines #route_entry (instance visibility: private)
|
|
80
|
+
# @param [Entry] entry
|
|
81
|
+
# @param [Object] plugin
|
|
82
|
+
# @raise [ArgumentError]
|
|
83
|
+
# @return [void]
|
|
84
|
+
def route_entry(entry, plugin)
|
|
58
85
|
if plugin.is_a?(Base::CollectorPlugin) || plugin.respond_to?(:collect)
|
|
59
86
|
@collector_entries << entry
|
|
60
87
|
elsif plugin.is_a?(Base::TagPlugin) || plugin.respond_to?(:call)
|
data/lib/docscribe/plugin.rb
CHANGED
|
@@ -48,25 +48,56 @@ module Docscribe
|
|
|
48
48
|
# @raise [StandardError]
|
|
49
49
|
# @return [Array<Hash>]
|
|
50
50
|
def self.run_collector_plugins(ast, buffer)
|
|
51
|
-
Registry.collector_entries.flat_map
|
|
52
|
-
|
|
51
|
+
Registry.collector_entries.flat_map { |entry| process_single_plugin_result(entry, ast, buffer) }
|
|
52
|
+
end
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
# Process a single collector plugin's result.
|
|
55
|
+
#
|
|
56
|
+
# Merges plugin metadata into each hash insertion and handles errors.
|
|
57
|
+
#
|
|
58
|
+
# @param [Entry] entry
|
|
59
|
+
# @param [Parser::AST::Node] ast
|
|
60
|
+
# @param [Parser::Source::Buffer] buffer
|
|
61
|
+
# @raise [StandardError]
|
|
62
|
+
# @return [Array<Hash>]
|
|
63
|
+
def self.process_single_plugin_result(entry, ast, buffer)
|
|
64
|
+
plugin = entry.plugin
|
|
65
|
+
results = Array(plugin.collect(ast, buffer))
|
|
66
|
+
process_plugin_insertions(results, entry, plugin)
|
|
67
|
+
rescue StandardError => e
|
|
68
|
+
warn "Docscribe: CollectorPlugin #{plugin.class} raised #{e.class}: #{e.message}" if debug?
|
|
69
|
+
[]
|
|
70
|
+
end
|
|
59
71
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
# Merge plugin metadata into collector results and filter invalid ones.
|
|
73
|
+
#
|
|
74
|
+
# @param [Array] results collector plugin results to process
|
|
75
|
+
# @param [Entry] entry registry entry with priority and order metadata
|
|
76
|
+
# @param [Base::CollectorPlugin] plugin the collector plugin instance
|
|
77
|
+
# @return [Array<Hash>]
|
|
78
|
+
def self.process_plugin_insertions(results, entry, plugin)
|
|
79
|
+
results.map do |insertion|
|
|
80
|
+
next nil unless valid_plugin_result?(insertion, plugin)
|
|
81
|
+
|
|
82
|
+
insertion.merge(
|
|
83
|
+
__docscribe_priority: entry.priority,
|
|
84
|
+
__docscribe_plugin_class: plugin.class.name,
|
|
85
|
+
__docscribe_plugin_order: entry.order
|
|
86
|
+
)
|
|
87
|
+
end.compact
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Validate a CollectorPlugin result is a Hash.
|
|
91
|
+
#
|
|
92
|
+
# @private
|
|
93
|
+
# @param [Object] insertion
|
|
94
|
+
# @param [Object] plugin
|
|
95
|
+
# @return [Boolean]
|
|
96
|
+
def self.valid_plugin_result?(insertion, plugin)
|
|
97
|
+
return true if insertion.is_a?(Hash)
|
|
98
|
+
|
|
99
|
+
warn "Docscribe: CollectorPlugin #{plugin.class} returned #{insertion.class}, expected Hash" if debug?
|
|
100
|
+
false
|
|
70
101
|
end
|
|
71
102
|
|
|
72
103
|
# @return [Boolean]
|
|
@@ -44,24 +44,12 @@ module Docscribe
|
|
|
44
44
|
# @return [Docscribe::Types::MethodSignature, nil]
|
|
45
45
|
def signature_for(container:, scope:, name:)
|
|
46
46
|
load_env!
|
|
47
|
-
|
|
48
|
-
definition = definition_for(container: container, scope: scope)
|
|
49
|
-
method_def = definition.methods[name.to_sym]
|
|
50
|
-
return nil unless method_def
|
|
51
|
-
|
|
52
|
-
method_type = method_def.method_types.first
|
|
53
|
-
return nil unless method_type
|
|
54
|
-
|
|
55
|
-
func = method_type.type
|
|
56
|
-
build_signature(func)
|
|
47
|
+
lookup_signature(container, scope, name)
|
|
57
48
|
rescue ::RBS::BaseError => e
|
|
58
|
-
|
|
49
|
+
handle_rbs_error(e, 'RBS error')
|
|
59
50
|
nil
|
|
60
51
|
rescue StandardError => e
|
|
61
|
-
|
|
62
|
-
'Docscribe: RBS integration failed (falling back to inference): ' \
|
|
63
|
-
"#{e.class}: #{e.message}\nFeel free to open an issue on github."
|
|
64
|
-
)
|
|
52
|
+
handle_rbs_error(e, 'RBS integration failed (falling back to inference)')
|
|
65
53
|
nil
|
|
66
54
|
end
|
|
67
55
|
|
|
@@ -81,16 +69,50 @@ module Docscribe
|
|
|
81
69
|
def load_env!
|
|
82
70
|
return if @env && @builder
|
|
83
71
|
|
|
84
|
-
@env =
|
|
72
|
+
@env = try_with_fallback_build_env(
|
|
73
|
+
@sig_dirs + @collection_dirs,
|
|
74
|
+
@collection_dirs
|
|
75
|
+
)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Look up a method signature from the loaded RBS definition builder.
|
|
79
|
+
#
|
|
80
|
+
# @private
|
|
81
|
+
# @param [String] container fully qualified class/module name
|
|
82
|
+
# @param [Symbol] scope :instance or :class
|
|
83
|
+
# @param [Symbol, String] name method name to look up
|
|
84
|
+
# @return [Docscribe::Types::MethodSignature, nil]
|
|
85
|
+
def lookup_signature(container, scope, name)
|
|
86
|
+
definition = definition_for(container: container, scope: scope)
|
|
87
|
+
method_def = definition.methods[name.to_sym]
|
|
88
|
+
return nil unless method_def
|
|
89
|
+
|
|
90
|
+
method_type = method_def.method_types.first
|
|
91
|
+
return nil unless method_type
|
|
92
|
+
|
|
93
|
+
build_signature(method_type.type)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Try building an environment from combined dirs, falling back to
|
|
97
|
+
# user-only dirs on failure when collection dirs are present.
|
|
98
|
+
#
|
|
99
|
+
# @private
|
|
100
|
+
# @param [Array<String>] all_dirs combined sig and collection dirs
|
|
101
|
+
# @param [Array<String>] collection_dirs
|
|
102
|
+
# @raise [::RBS::BaseError]
|
|
103
|
+
# @raise [StandardError]
|
|
104
|
+
# @return [::RBS::Environment]
|
|
105
|
+
def try_with_fallback_build_env(all_dirs, collection_dirs)
|
|
106
|
+
build_env(all_dirs)
|
|
85
107
|
rescue ::RBS::BaseError => e
|
|
86
|
-
raise unless
|
|
108
|
+
raise unless collection_dirs.any? && !@collection_dropped
|
|
87
109
|
|
|
88
110
|
@collection_dropped = true
|
|
89
111
|
if ENV['DOCSCRIBE_RBS_DEBUG'] == '1'
|
|
90
112
|
warn "Docscribe: RBS collection error (#{e.class}), dropping collection dirs. " \
|
|
91
113
|
'Set DOCSCRIBE_RBS_DEBUG=1 for details.'
|
|
92
114
|
end
|
|
93
|
-
|
|
115
|
+
build_env(@sig_dirs)
|
|
94
116
|
end
|
|
95
117
|
|
|
96
118
|
# Build an RBS environment from the given directories.
|
|
@@ -121,7 +143,7 @@ module Docscribe
|
|
|
121
143
|
# @return [Object]
|
|
122
144
|
def definition_for(container:, scope:)
|
|
123
145
|
type_name = parse_type_name(absolute_const(container))
|
|
124
|
-
scope == :class ? @builder
|
|
146
|
+
scope == :class ? @builder&.build_singleton(type_name) : @builder&.build_instance(type_name)
|
|
125
147
|
end
|
|
126
148
|
|
|
127
149
|
# Parse a fully-qualified constant string into an RBS TypeName.
|
|
@@ -135,6 +157,7 @@ module Docscribe
|
|
|
135
157
|
def parse_type_name(string)
|
|
136
158
|
absolute = string.start_with?('::')
|
|
137
159
|
*path, name = string.delete_prefix('::').split('::').map(&:to_sym)
|
|
160
|
+
name ||= :Object
|
|
138
161
|
::RBS::TypeName.new(
|
|
139
162
|
name: name,
|
|
140
163
|
namespace: ::RBS::Namespace.new(path: path, absolute: absolute)
|
|
@@ -172,21 +195,28 @@ module Docscribe
|
|
|
172
195
|
# @param [::RBS::Types::Function] func
|
|
173
196
|
# @return [Hash{String => String}]
|
|
174
197
|
def build_param_types(func)
|
|
175
|
-
param_types = {}
|
|
198
|
+
param_types = {} #: Hash[String, String]
|
|
176
199
|
|
|
177
200
|
add_positionals!(param_types, func.required_positionals)
|
|
178
201
|
add_positionals!(param_types, func.optional_positionals)
|
|
179
202
|
add_positionals!(param_types, func.trailing_positionals)
|
|
180
203
|
|
|
181
|
-
func.required_keywords
|
|
182
|
-
|
|
183
|
-
|
|
204
|
+
add_keywords!(param_types, func.required_keywords)
|
|
205
|
+
add_keywords!(param_types, func.optional_keywords)
|
|
206
|
+
|
|
207
|
+
param_types
|
|
208
|
+
end
|
|
184
209
|
|
|
185
|
-
|
|
210
|
+
# Add keyword parameters to the normalized parameter map.
|
|
211
|
+
#
|
|
212
|
+
# @private
|
|
213
|
+
# @param [Hash{String => String}] param_types
|
|
214
|
+
# @param [Hash{Symbol => Object}] keywords
|
|
215
|
+
# @return [void]
|
|
216
|
+
def add_keywords!(param_types, keywords)
|
|
217
|
+
keywords.each do |kw, p|
|
|
186
218
|
param_types[kw.to_s] = format_type(p.type)
|
|
187
219
|
end
|
|
188
|
-
|
|
189
|
-
param_types
|
|
190
220
|
end
|
|
191
221
|
|
|
192
222
|
# Add named positional parameters to the normalized parameter map.
|
|
@@ -246,6 +276,25 @@ module Docscribe
|
|
|
246
276
|
)
|
|
247
277
|
end
|
|
248
278
|
|
|
279
|
+
# Emit a formatted RBS error warning with context-specific messaging.
|
|
280
|
+
#
|
|
281
|
+
# @private
|
|
282
|
+
# @param [StandardError] e the raised exception
|
|
283
|
+
# @param [String] context human-readable context label
|
|
284
|
+
# @param [StandardError] error the raised exception
|
|
285
|
+
# @return [void]
|
|
286
|
+
def handle_rbs_error(error, context)
|
|
287
|
+
case error
|
|
288
|
+
when ::RBS::BaseError
|
|
289
|
+
warn_once("Docscribe: #{context}: #{error.class}: #{error.message}")
|
|
290
|
+
else
|
|
291
|
+
warn_once(
|
|
292
|
+
"Docscribe: #{context}: #{error.class}: #{error.message}\n" \
|
|
293
|
+
'Feel free to open an issue on github.'
|
|
294
|
+
)
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
249
298
|
# Print one debug warning per provider instance when debugging is enabled.
|
|
250
299
|
#
|
|
251
300
|
# @private
|
|
@@ -10,58 +10,97 @@ module Docscribe
|
|
|
10
10
|
module TypeFormatter
|
|
11
11
|
module_function
|
|
12
12
|
|
|
13
|
-
#
|
|
13
|
+
# rubocop:disable Metrics/AbcSize, Layout/LineLength
|
|
14
|
+
# Return or memoize the dispatch hash mapping RBS type classes to formatter lambdas.
|
|
14
15
|
#
|
|
15
|
-
#
|
|
16
|
-
#
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
16
|
+
# @note module_function: when included, also defines #to_yard_formatters (instance visibility: private)
|
|
17
|
+
# @return [Hash{Class=>Proc}]
|
|
18
|
+
def to_yard_formatters
|
|
19
|
+
@to_yard_formatters ||= {
|
|
20
|
+
::RBS::Types::Bases::Any => ->(_, **) { format_any },
|
|
21
|
+
::RBS::Types::Bases::Bool => ->(_, **) { format_bool },
|
|
22
|
+
::RBS::Types::Bases::Void => ->(_, **) { format_void },
|
|
23
|
+
::RBS::Types::Bases::Nil => ->(_, **) { format_nil },
|
|
24
|
+
::RBS::Types::Optional => ->(t, collapse_generics:) { format_optional(t, collapse_generics: collapse_generics) },
|
|
25
|
+
::RBS::Types::Union => ->(t, collapse_generics:) { format_union(t, collapse_generics: collapse_generics) },
|
|
26
|
+
::RBS::Types::Literal => ->(t, **) { format_literal(t.literal) },
|
|
27
|
+
::RBS::Types::Proc => ->(_, **) { format_proc }
|
|
28
|
+
}.freeze
|
|
29
|
+
end
|
|
30
|
+
# rubocop:enable Metrics/AbcSize, Layout/LineLength
|
|
31
|
+
|
|
32
|
+
# Format RBS `any` type as the YARD-equivalent `Object`.
|
|
21
33
|
#
|
|
22
|
-
# @note module_function: when included, also defines #
|
|
23
|
-
# @param [Object] type RBS type object
|
|
24
|
-
# @param [Boolean] collapse_generics whether generic arguments should be omitted
|
|
34
|
+
# @note module_function: when included, also defines #format_any (instance visibility: private)
|
|
25
35
|
# @return [String]
|
|
26
|
-
def
|
|
27
|
-
|
|
36
|
+
def format_any
|
|
37
|
+
'Object'
|
|
38
|
+
end
|
|
28
39
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
40
|
+
# Format RBS `bool` type as the YARD `Boolean`.
|
|
41
|
+
#
|
|
42
|
+
# @note module_function: when included, also defines #format_bool (instance visibility: private)
|
|
43
|
+
# @return [String]
|
|
44
|
+
def format_bool
|
|
45
|
+
'Boolean'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Format RBS `void` type as the YARD `void`.
|
|
49
|
+
#
|
|
50
|
+
# @note module_function: when included, also defines #format_void (instance visibility: private)
|
|
51
|
+
# @return [String]
|
|
52
|
+
def format_void
|
|
53
|
+
'void'
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Format RBS `nil` type as the YARD `nil`.
|
|
57
|
+
#
|
|
58
|
+
# @note module_function: when included, also defines #format_nil (instance visibility: private)
|
|
59
|
+
# @return [String]
|
|
60
|
+
def format_nil
|
|
61
|
+
'nil'
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Format an RBS Optional type as a YARD optional type with `?` suffix.
|
|
65
|
+
#
|
|
66
|
+
# @note module_function: when included, also defines #format_optional (instance visibility: private)
|
|
67
|
+
# @param [::RBS::Types::Optional] type the optional type to format
|
|
68
|
+
# @param [Boolean] collapse_generics whether to omit generic type arguments
|
|
69
|
+
# @return [String]
|
|
70
|
+
def format_optional(type, collapse_generics:)
|
|
71
|
+
"#{to_yard(type.type, collapse_generics: collapse_generics)}?"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Map a Ruby literal value to its corresponding YARD type name.
|
|
75
|
+
#
|
|
76
|
+
# @note module_function: when included, also defines #format_literal (instance visibility: private)
|
|
77
|
+
# @param [Object] lit a Ruby literal value
|
|
78
|
+
# @return [String]
|
|
79
|
+
def format_literal(lit)
|
|
80
|
+
case lit
|
|
81
|
+
when Integer then 'Integer'
|
|
82
|
+
when Float then 'Float'
|
|
83
|
+
when String then 'String'
|
|
84
|
+
when Symbol then 'Symbol'
|
|
85
|
+
when TrueClass, FalseClass then 'Boolean'
|
|
86
|
+
when NilClass then 'nil'
|
|
87
|
+
else 'Object'
|
|
54
88
|
end
|
|
55
89
|
end
|
|
56
90
|
|
|
57
|
-
# Format
|
|
91
|
+
# Format RBS Proc type as the YARD `Proc`.
|
|
58
92
|
#
|
|
59
|
-
#
|
|
60
|
-
#
|
|
93
|
+
# @note module_function: when included, also defines #format_proc (instance visibility: private)
|
|
94
|
+
# @return [String]
|
|
95
|
+
def format_proc
|
|
96
|
+
'Proc'
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Format an RBS Union type as a comma-separated list of YARD types.
|
|
61
100
|
#
|
|
62
101
|
# @note module_function: when included, also defines #format_union (instance visibility: private)
|
|
63
|
-
# @param [::RBS::Types::Union] type
|
|
64
|
-
# @param [Boolean] collapse_generics
|
|
102
|
+
# @param [::RBS::Types::Union] type the union type to format
|
|
103
|
+
# @param [Boolean] collapse_generics whether to omit generic type arguments
|
|
65
104
|
# @return [String]
|
|
66
105
|
def format_union(type, collapse_generics:)
|
|
67
106
|
type.types.map { |t| to_yard(t, collapse_generics: collapse_generics) }
|
|
@@ -69,20 +108,15 @@ module Docscribe
|
|
|
69
108
|
.join(', ')
|
|
70
109
|
end
|
|
71
110
|
|
|
72
|
-
# Format
|
|
73
|
-
#
|
|
74
|
-
# Examples:
|
|
75
|
-
# - `::String` => `"String"`
|
|
76
|
-
# - `::Hash[::Symbol, untyped]` => `"Hash<Symbol, Object>"`
|
|
77
|
-
# - with `collapse_generics: true` => `"Hash"`
|
|
111
|
+
# Format an RBS named type (class, interface, alias) with optional generic arguments.
|
|
78
112
|
#
|
|
79
113
|
# @note module_function: when included, also defines #format_named (instance visibility: private)
|
|
80
|
-
# @param [
|
|
81
|
-
# @param [Boolean] collapse_generics
|
|
114
|
+
# @param [::RBS::Types::ClassInstance, ::RBS::Types::Interface, ::RBS::Types::Alias] type
|
|
115
|
+
# @param [Boolean] collapse_generics whether to omit generic type arguments
|
|
82
116
|
# @return [String]
|
|
83
117
|
def format_named(type, collapse_generics:)
|
|
84
118
|
name = type.name.to_s.delete_prefix('::')
|
|
85
|
-
args = type.respond_to?(:args) ? type.args : []
|
|
119
|
+
args = type.respond_to?(:args) ? type.args : [] #: Array[untyped]
|
|
86
120
|
|
|
87
121
|
if args && !args.empty?
|
|
88
122
|
return name if collapse_generics
|
|
@@ -93,10 +127,10 @@ module Docscribe
|
|
|
93
127
|
end
|
|
94
128
|
end
|
|
95
129
|
|
|
96
|
-
#
|
|
130
|
+
# Convert a Ruby literal value to its YARD type name string.
|
|
97
131
|
#
|
|
98
132
|
# @note module_function: when included, also defines #literal_to_yard (instance visibility: private)
|
|
99
|
-
# @param [Object] lit literal value
|
|
133
|
+
# @param [Object] lit a Ruby literal value
|
|
100
134
|
# @return [String]
|
|
101
135
|
def literal_to_yard(lit)
|
|
102
136
|
case lit
|
|
@@ -110,15 +144,49 @@ module Docscribe
|
|
|
110
144
|
end
|
|
111
145
|
end
|
|
112
146
|
|
|
113
|
-
#
|
|
147
|
+
# Dispatch an RBS type object to the appropriate YARD formatter.
|
|
114
148
|
#
|
|
115
|
-
#
|
|
116
|
-
#
|
|
117
|
-
#
|
|
118
|
-
#
|
|
149
|
+
# @note module_function: when included, also defines #to_yard (instance visibility: private)
|
|
150
|
+
# @param [::RBS::Type] type the RBS type object to convert
|
|
151
|
+
# @param [Boolean] collapse_generics whether to omit generic type arguments
|
|
152
|
+
# @return [String]
|
|
153
|
+
def to_yard(type, collapse_generics: false)
|
|
154
|
+
return 'Object' unless type
|
|
155
|
+
|
|
156
|
+
handler = to_yard_formatters.find { |klass, _| type.is_a?(klass) }
|
|
157
|
+
return handler.last.call(type, collapse_generics: collapse_generics) if handler
|
|
158
|
+
|
|
159
|
+
return format_named(type, collapse_generics: collapse_generics) if named_type?(type)
|
|
160
|
+
|
|
161
|
+
fallback_string(type)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Check if the given type object is a named RBS type (class, singleton, interface, or alias).
|
|
165
|
+
#
|
|
166
|
+
# @note module_function: when included, also defines #named_type? (instance visibility: private)
|
|
167
|
+
# @param [::RBS::Type] type the RBS type object to check
|
|
168
|
+
# @return [Boolean]
|
|
169
|
+
def named_type?(type)
|
|
170
|
+
named_type_classes.any? { |klass| type.is_a?(klass) }
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
# Return or memoize the list of RBS type classes considered named types.
|
|
174
|
+
#
|
|
175
|
+
# @note module_function: when included, also defines #named_type_classes (instance visibility: private)
|
|
176
|
+
# @return [Array<Class>]
|
|
177
|
+
def named_type_classes
|
|
178
|
+
@named_type_classes ||= [
|
|
179
|
+
::RBS::Types::ClassInstance,
|
|
180
|
+
::RBS::Types::ClassSingleton,
|
|
181
|
+
::RBS::Types::Interface,
|
|
182
|
+
::RBS::Types::Alias
|
|
183
|
+
].freeze
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Fallback conversion of an unrecognized RBS type to a cleaned string representation.
|
|
119
187
|
#
|
|
120
188
|
# @note module_function: when included, also defines #fallback_string (instance visibility: private)
|
|
121
|
-
# @param [
|
|
189
|
+
# @param [::RBS::Type] type the unrecognized RBS type object
|
|
122
190
|
# @return [String]
|
|
123
191
|
def fallback_string(type)
|
|
124
192
|
type.to_s
|
|
@@ -74,18 +74,25 @@ module Docscribe
|
|
|
74
74
|
next unless decl.respond_to?(:members)
|
|
75
75
|
|
|
76
76
|
container = normalize_container(decl.name.to_s)
|
|
77
|
+
decl.members.each { |member| process_method_member(container, member) }
|
|
78
|
+
end
|
|
79
|
+
end
|
|
77
80
|
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
# Process a single method definition member into the index.
|
|
82
|
+
#
|
|
83
|
+
# @private
|
|
84
|
+
# @param [String] container normalized container name
|
|
85
|
+
# @param [Object] member
|
|
86
|
+
# @return [void]
|
|
87
|
+
def process_method_member(container, member)
|
|
88
|
+
return unless method_definition_member?(member)
|
|
80
89
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
90
|
+
scope = member.kind == :singleton ? :class : :instance
|
|
91
|
+
overload = member.overloads&.first
|
|
92
|
+
return unless overload
|
|
84
93
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
end
|
|
88
|
-
end
|
|
94
|
+
func = overload.method_type.type
|
|
95
|
+
@index[[container, scope, member.name.to_s.to_sym]] = build_signature(func)
|
|
89
96
|
end
|
|
90
97
|
|
|
91
98
|
# @private
|
|
@@ -116,18 +123,30 @@ module Docscribe
|
|
|
116
123
|
# @param [::RBS::Types::Function] func
|
|
117
124
|
# @return [Hash{String => String}]
|
|
118
125
|
def build_param_types(func)
|
|
119
|
-
param_types = {}
|
|
126
|
+
param_types = {} #: Hash[String, String]
|
|
120
127
|
|
|
121
128
|
add_positionals!(param_types, func.required_positionals)
|
|
122
129
|
add_positionals!(param_types, func.optional_positionals)
|
|
123
130
|
add_positionals!(param_types, func.trailing_positionals)
|
|
124
131
|
|
|
125
|
-
func.required_keywords
|
|
126
|
-
func.optional_keywords
|
|
132
|
+
add_keywords!(param_types, func.required_keywords)
|
|
133
|
+
add_keywords!(param_types, func.optional_keywords)
|
|
127
134
|
|
|
128
135
|
param_types
|
|
129
136
|
end
|
|
130
137
|
|
|
138
|
+
# Add keyword parameters to the normalized parameter map.
|
|
139
|
+
#
|
|
140
|
+
# @private
|
|
141
|
+
# @param [Hash{String => String}] param_types
|
|
142
|
+
# @param [Hash{Symbol => Object}] keywords
|
|
143
|
+
# @return [void]
|
|
144
|
+
def add_keywords!(param_types, keywords)
|
|
145
|
+
keywords.each do |kw, p|
|
|
146
|
+
param_types[kw.to_s] = format_type(p.type)
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
131
150
|
# Add positional parameters with names to the normalized param map.
|
|
132
151
|
#
|
|
133
152
|
# @private
|
data/lib/docscribe/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: docscribe
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.4.
|
|
4
|
+
version: 1.4.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- unurgunite
|
|
@@ -213,7 +213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
213
213
|
- !ruby/object:Gem::Version
|
|
214
214
|
version: '0'
|
|
215
215
|
requirements: []
|
|
216
|
-
rubygems_version: 4.0.
|
|
216
|
+
rubygems_version: 4.0.13
|
|
217
217
|
specification_version: 4
|
|
218
218
|
summary: Auto-generate inline YARD documentation for Ruby by analyzing code AST. Supports
|
|
219
219
|
RBS and Sorbet type signatures.
|