docscribe 1.4.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +588 -104
- data/lib/docscribe/cli/check_for_comments.rb +183 -0
- data/lib/docscribe/cli/config_builder.rb +180 -36
- data/lib/docscribe/cli/formatters/json.rb +294 -0
- data/lib/docscribe/cli/formatters/sarif.rb +235 -0
- data/lib/docscribe/cli/formatters/text.rb +208 -0
- data/lib/docscribe/cli/formatters.rb +26 -0
- data/lib/docscribe/cli/generate.rb +296 -125
- data/lib/docscribe/cli/init.rb +58 -14
- data/lib/docscribe/cli/options.rb +410 -133
- data/lib/docscribe/cli/rbs_gen.rb +529 -0
- data/lib/docscribe/cli/run.rb +503 -189
- data/lib/docscribe/cli/sigs.rb +366 -0
- data/lib/docscribe/cli/update_types.rb +103 -0
- data/lib/docscribe/cli.rb +35 -9
- data/lib/docscribe/config/defaults.rb +16 -12
- data/lib/docscribe/config/emit.rb +18 -0
- data/lib/docscribe/config/filtering.rb +37 -31
- data/lib/docscribe/config/loader.rb +20 -13
- data/lib/docscribe/config/plugin.rb +2 -1
- data/lib/docscribe/config/rbs.rb +68 -27
- data/lib/docscribe/config/sorbet.rb +40 -17
- data/lib/docscribe/config/sorting.rb +2 -1
- data/lib/docscribe/config/template.rb +10 -1
- data/lib/docscribe/config/utils.rb +12 -9
- data/lib/docscribe/config.rb +3 -4
- data/lib/docscribe/infer/ast_walk.rb +1 -1
- data/lib/docscribe/infer/constants.rb +15 -0
- data/lib/docscribe/infer/literals.rb +39 -26
- data/lib/docscribe/infer/names.rb +24 -16
- data/lib/docscribe/infer/params.rb +57 -13
- data/lib/docscribe/infer/raises.rb +23 -15
- data/lib/docscribe/infer/returns.rb +784 -199
- data/lib/docscribe/infer.rb +28 -28
- data/lib/docscribe/inline_rewriter/collector.rb +816 -430
- data/lib/docscribe/inline_rewriter/doc_block.rb +323 -150
- data/lib/docscribe/inline_rewriter/doc_builder.rb +1837 -648
- data/lib/docscribe/inline_rewriter/source_helpers.rb +119 -71
- data/lib/docscribe/inline_rewriter/tag_sorter.rb +165 -107
- data/lib/docscribe/inline_rewriter.rb +1144 -727
- data/lib/docscribe/parsing.rb +29 -10
- data/lib/docscribe/plugin/base/collector_plugin.rb +3 -3
- data/lib/docscribe/plugin/base/tag_plugin.rb +1 -2
- data/lib/docscribe/plugin/context.rb +28 -18
- data/lib/docscribe/plugin/registry.rb +49 -23
- data/lib/docscribe/plugin/tag.rb +9 -14
- data/lib/docscribe/plugin.rb +54 -22
- data/lib/docscribe/types/provider_chain.rb +4 -2
- data/lib/docscribe/types/rbs/collection_loader.rb +2 -3
- data/lib/docscribe/types/rbs/provider.rb +127 -62
- data/lib/docscribe/types/rbs/type_formatter.rb +286 -77
- data/lib/docscribe/types/signature.rb +22 -42
- data/lib/docscribe/types/sorbet/base_provider.rb +51 -27
- data/lib/docscribe/types/sorbet/rbi_provider.rb +3 -3
- data/lib/docscribe/types/sorbet/source_provider.rb +3 -2
- data/lib/docscribe/types/yard/formatter.rb +100 -0
- data/lib/docscribe/types/yard/parser.rb +240 -0
- data/lib/docscribe/types/yard/types.rb +52 -0
- data/lib/docscribe/version.rb +1 -1
- metadata +34 -2
|
@@ -14,18 +14,19 @@ module Docscribe
|
|
|
14
14
|
# The provider returns Docscribe's normalized signature model so the rest of
|
|
15
15
|
# the pipeline can stay independent of the underlying signature source.
|
|
16
16
|
class Provider
|
|
17
|
+
# Initialize
|
|
18
|
+
#
|
|
17
19
|
# @param [Array<String>] sig_dirs directories containing `.rbs` files
|
|
18
20
|
# @param [Array<String>] collection_dirs RBS collection directories
|
|
19
|
-
# (loaded separately; on error they are silently dropped and only
|
|
20
|
-
# user sig_dirs are used)
|
|
21
21
|
# @param [Boolean] collapse_generics whether generic container types
|
|
22
|
-
#
|
|
23
|
-
# @return [
|
|
24
|
-
def initialize(sig_dirs:, collection_dirs: [], collapse_generics: false)
|
|
22
|
+
# @param [Boolean] collapse_object_generics collapse Object generics flag
|
|
23
|
+
# @return [void]
|
|
24
|
+
def initialize(sig_dirs:, collection_dirs: [], collapse_generics: false, collapse_object_generics: false)
|
|
25
25
|
require 'rbs'
|
|
26
26
|
@sig_dirs = Array(sig_dirs).map(&:to_s)
|
|
27
27
|
@collection_dirs = Array(collection_dirs).map(&:to_s)
|
|
28
28
|
@collapse_generics = !!collapse_generics
|
|
29
|
+
@collapse_object_generics = !!collapse_object_generics
|
|
29
30
|
@env = nil
|
|
30
31
|
@builder = nil
|
|
31
32
|
@warned = false
|
|
@@ -41,27 +42,17 @@ module Docscribe
|
|
|
41
42
|
# @param [Symbol, String] name method name
|
|
42
43
|
# @raise [::RBS::BaseError]
|
|
43
44
|
# @raise [StandardError]
|
|
44
|
-
# @return [Docscribe::Types::MethodSignature, nil]
|
|
45
|
+
# @return [Docscribe::Types::MethodSignature, nil] if StandardError
|
|
46
|
+
# @return [nil] if ::RBS::BaseError
|
|
47
|
+
# @return [nil] if StandardError
|
|
45
48
|
def signature_for(container:, scope:, name:)
|
|
46
49
|
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)
|
|
50
|
+
lookup_signature(container, scope, name)
|
|
57
51
|
rescue ::RBS::BaseError => e
|
|
58
|
-
|
|
52
|
+
handle_rbs_error(e, 'RBS error')
|
|
59
53
|
nil
|
|
60
54
|
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
|
-
)
|
|
55
|
+
handle_rbs_error(e, 'RBS integration failed (falling back to inference)')
|
|
65
56
|
nil
|
|
66
57
|
end
|
|
67
58
|
|
|
@@ -75,33 +66,69 @@ module Docscribe
|
|
|
75
66
|
# dirs are dropped and only user sig_dirs are used.
|
|
76
67
|
#
|
|
77
68
|
# @private
|
|
78
|
-
# @raise [::RBS::BaseError]
|
|
79
|
-
# @raise [StandardError]
|
|
80
69
|
# @return [void]
|
|
81
70
|
def load_env!
|
|
82
71
|
return if @env && @builder
|
|
83
72
|
|
|
84
|
-
@env =
|
|
73
|
+
@env = try_with_fallback_build_env(
|
|
74
|
+
@sig_dirs + @collection_dirs,
|
|
75
|
+
@collection_dirs
|
|
76
|
+
)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Look up a method signature from the loaded RBS definition builder.
|
|
80
|
+
#
|
|
81
|
+
# @private
|
|
82
|
+
# @param [String] container fully qualified class/module name
|
|
83
|
+
# @param [Symbol] scope :instance or :class
|
|
84
|
+
# @param [Symbol, String] name method name to look up
|
|
85
|
+
# @return [Docscribe::Types::MethodSignature, nil]
|
|
86
|
+
def lookup_signature(container, scope, name)
|
|
87
|
+
definition = definition_for(container: container, scope: scope)
|
|
88
|
+
return nil unless definition
|
|
89
|
+
|
|
90
|
+
method_def = definition.methods[name.to_sym]
|
|
91
|
+
return nil unless method_def
|
|
92
|
+
|
|
93
|
+
method_type = method_def.method_types.first
|
|
94
|
+
return nil unless method_type
|
|
95
|
+
|
|
96
|
+
func = method_type.type #: ::RBS::Types::Function
|
|
97
|
+
build_signature(func)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Try building an environment from combined dirs, falling back to
|
|
101
|
+
# user-only dirs on failure when collection dirs are present.
|
|
102
|
+
#
|
|
103
|
+
# @private
|
|
104
|
+
# @param [Array<String>] all_dirs combined sig and collection dirs
|
|
105
|
+
# @param [Array<String>] collection_dirs RBS collection directories
|
|
106
|
+
# @raise [::RBS::BaseError]
|
|
107
|
+
# @raise [StandardError]
|
|
108
|
+
# @return [RBS::Environment] if ::RBS::BaseError
|
|
109
|
+
# @return [Object] if ::RBS::BaseError
|
|
110
|
+
def try_with_fallback_build_env(all_dirs, collection_dirs)
|
|
111
|
+
build_env(all_dirs)
|
|
85
112
|
rescue ::RBS::BaseError => e
|
|
86
|
-
raise unless
|
|
113
|
+
raise unless collection_dirs.any? && !@collection_dropped
|
|
87
114
|
|
|
88
115
|
@collection_dropped = true
|
|
89
116
|
if ENV['DOCSCRIBE_RBS_DEBUG'] == '1'
|
|
90
117
|
warn "Docscribe: RBS collection error (#{e.class}), dropping collection dirs. " \
|
|
91
118
|
'Set DOCSCRIBE_RBS_DEBUG=1 for details.'
|
|
92
119
|
end
|
|
93
|
-
|
|
120
|
+
build_env(@sig_dirs)
|
|
94
121
|
end
|
|
95
122
|
|
|
96
123
|
# Build an RBS environment from the given directories.
|
|
97
124
|
#
|
|
98
125
|
# @private
|
|
99
|
-
# @param [Array<String>] dirs
|
|
100
|
-
# @return [
|
|
126
|
+
# @param [Array<String>] dirs directories to load RBS from
|
|
127
|
+
# @return [RBS::Environment]
|
|
101
128
|
def build_env(dirs)
|
|
102
129
|
loader = ::RBS::EnvironmentLoader.new
|
|
103
130
|
# Load core types transitively
|
|
104
|
-
loader.add(library: 'rbs')
|
|
131
|
+
loader.add(library: 'rbs') # steep:ignore
|
|
105
132
|
|
|
106
133
|
dirs.each do |dir|
|
|
107
134
|
path = Pathname(dir)
|
|
@@ -116,12 +143,12 @@ module Docscribe
|
|
|
116
143
|
# Build the appropriate instance or singleton definition for a container.
|
|
117
144
|
#
|
|
118
145
|
# @private
|
|
119
|
-
# @param [String] container
|
|
120
|
-
# @param [Symbol] scope
|
|
121
|
-
# @return [
|
|
146
|
+
# @param [String] container fully qualified class/module name
|
|
147
|
+
# @param [Symbol] scope :instance or :class
|
|
148
|
+
# @return [RBS::Definition, nil]
|
|
122
149
|
def definition_for(container:, scope:)
|
|
123
150
|
type_name = parse_type_name(absolute_const(container))
|
|
124
|
-
scope == :class ? @builder
|
|
151
|
+
scope == :class ? @builder&.build_singleton(type_name) : @builder&.build_instance(type_name)
|
|
125
152
|
end
|
|
126
153
|
|
|
127
154
|
# Parse a fully-qualified constant string into an RBS TypeName.
|
|
@@ -131,10 +158,11 @@ module Docscribe
|
|
|
131
158
|
#
|
|
132
159
|
# @private
|
|
133
160
|
# @param [String] string e.g. "::Irb::Autosuggestions"
|
|
134
|
-
# @return [
|
|
161
|
+
# @return [RBS::TypeName]
|
|
135
162
|
def parse_type_name(string)
|
|
136
163
|
absolute = string.start_with?('::')
|
|
137
164
|
*path, name = string.delete_prefix('::').split('::').map(&:to_sym)
|
|
165
|
+
name ||= :Object
|
|
138
166
|
::RBS::TypeName.new(
|
|
139
167
|
name: name,
|
|
140
168
|
namespace: ::RBS::Namespace.new(path: path, absolute: absolute)
|
|
@@ -144,7 +172,7 @@ module Docscribe
|
|
|
144
172
|
# Normalize a container name into an absolute constant path.
|
|
145
173
|
#
|
|
146
174
|
# @private
|
|
147
|
-
# @param [String] container
|
|
175
|
+
# @param [String] container fully qualified class/module name
|
|
148
176
|
# @return [String]
|
|
149
177
|
def absolute_const(container)
|
|
150
178
|
s = container.to_s
|
|
@@ -155,58 +183,76 @@ module Docscribe
|
|
|
155
183
|
# model.
|
|
156
184
|
#
|
|
157
185
|
# @private
|
|
158
|
-
# @param [
|
|
186
|
+
# @param [RBS::Types::Function] func RBS function type to convert
|
|
159
187
|
# @return [Docscribe::Types::MethodSignature]
|
|
160
188
|
def build_signature(func)
|
|
189
|
+
param_types, positional_types = build_param_types(func)
|
|
161
190
|
MethodSignature.new(
|
|
162
191
|
return_type: format_type(func.return_type),
|
|
163
|
-
param_types:
|
|
192
|
+
param_types: param_types,
|
|
193
|
+
positional_types: positional_types,
|
|
164
194
|
rest_positional: build_rest_positional(func),
|
|
165
195
|
rest_keywords: build_rest_keywords(func)
|
|
166
196
|
)
|
|
167
197
|
end
|
|
168
198
|
|
|
169
|
-
# Build a name => type map
|
|
199
|
+
# Build a name => type map and positional type list for all
|
|
200
|
+
# positional and keyword parameters.
|
|
201
|
+
#
|
|
202
|
+
# Returns [param_types (Hash), positional_types (Array)].
|
|
203
|
+
# positional_types includes ALL positional params in order (named
|
|
204
|
+
# and unnamed) so callers can fall back to positional matching when
|
|
205
|
+
# the RBS signature omits parameter names.
|
|
170
206
|
#
|
|
171
207
|
# @private
|
|
172
|
-
# @param [
|
|
173
|
-
# @return [Hash
|
|
208
|
+
# @param [RBS::Types::Function] func RBS function to extract params
|
|
209
|
+
# @return [(Hash<String, String>, Array<String>)]
|
|
174
210
|
def build_param_types(func)
|
|
175
|
-
param_types = {}
|
|
211
|
+
param_types = {} #: Hash[String, String]
|
|
212
|
+
positional_types = [] #: Array[String]
|
|
176
213
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
214
|
+
collect_positionals!(param_types, positional_types, func.required_positionals)
|
|
215
|
+
collect_positionals!(param_types, positional_types, func.optional_positionals)
|
|
216
|
+
collect_positionals!(param_types, positional_types, func.trailing_positionals)
|
|
180
217
|
|
|
181
|
-
func.required_keywords
|
|
182
|
-
|
|
183
|
-
end
|
|
218
|
+
add_keywords!(param_types, func.required_keywords)
|
|
219
|
+
add_keywords!(param_types, func.optional_keywords)
|
|
184
220
|
|
|
185
|
-
|
|
221
|
+
[param_types, positional_types]
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
# Add keyword parameters to the normalized parameter map.
|
|
225
|
+
#
|
|
226
|
+
# @private
|
|
227
|
+
# @param [Hash<String, String>] param_types normalized param type map
|
|
228
|
+
# @param [Hash<Symbol, RBS::Types::Function::Param>] keywords keyword parameter entries
|
|
229
|
+
# @return [void]
|
|
230
|
+
def add_keywords!(param_types, keywords)
|
|
231
|
+
keywords.each do |kw, p|
|
|
186
232
|
param_types[kw.to_s] = format_type(p.type)
|
|
187
233
|
end
|
|
188
|
-
|
|
189
|
-
param_types
|
|
190
234
|
end
|
|
191
235
|
|
|
192
|
-
#
|
|
236
|
+
# Collect positional parameter types into both the name-keyed hash
|
|
237
|
+
# (when a name is available) and the ordered-position list (always).
|
|
193
238
|
#
|
|
194
239
|
# @private
|
|
195
|
-
# @param [Hash
|
|
196
|
-
# @param [Array<
|
|
240
|
+
# @param [Hash<String, String>] param_types normalized param type map
|
|
241
|
+
# @param [Array<String>] positional_types ordered type list
|
|
242
|
+
# @param [Array<RBS::Types::Function::Param>] list positional parameter objects
|
|
197
243
|
# @return [void]
|
|
198
|
-
def
|
|
244
|
+
def collect_positionals!(param_types, positional_types, list)
|
|
199
245
|
list.each do |p|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
param_types[p.name.to_s] =
|
|
246
|
+
type_str = format_type(p.type)
|
|
247
|
+
positional_types << type_str
|
|
248
|
+
param_types[p.name.to_s] = type_str if p.name
|
|
203
249
|
end
|
|
204
250
|
end
|
|
205
251
|
|
|
206
252
|
# Build normalized `*args` metadata.
|
|
207
253
|
#
|
|
208
254
|
# @private
|
|
209
|
-
# @param [
|
|
255
|
+
# @param [RBS::Types::Function] func RBS function for rest params
|
|
210
256
|
# @return [Docscribe::Types::RestPositional, nil]
|
|
211
257
|
def build_rest_positional(func)
|
|
212
258
|
rp = func.rest_positionals
|
|
@@ -221,7 +267,7 @@ module Docscribe
|
|
|
221
267
|
# Build normalized `**kwargs` metadata.
|
|
222
268
|
#
|
|
223
269
|
# @private
|
|
224
|
-
# @param [
|
|
270
|
+
# @param [RBS::Types::Function] func RBS function for rest keywords
|
|
225
271
|
# @return [Docscribe::Types::RestKeywords, nil]
|
|
226
272
|
def build_rest_keywords(func)
|
|
227
273
|
rk = func.rest_keywords
|
|
@@ -237,19 +283,38 @@ module Docscribe
|
|
|
237
283
|
# generated comments.
|
|
238
284
|
#
|
|
239
285
|
# @private
|
|
240
|
-
# @param [
|
|
286
|
+
# @param [Docscribe::Types::RBS::TypeFormatter::rbs_type] type RBS type object to format
|
|
241
287
|
# @return [String]
|
|
242
288
|
def format_type(type)
|
|
243
289
|
Docscribe::Types::RBS::TypeFormatter.to_yard(
|
|
244
290
|
type,
|
|
245
|
-
collapse_generics: @collapse_generics
|
|
291
|
+
collapse_generics: @collapse_generics,
|
|
292
|
+
collapse_object_generics: @collapse_object_generics
|
|
246
293
|
)
|
|
247
294
|
end
|
|
248
295
|
|
|
296
|
+
# Emit a formatted RBS error warning with context-specific messaging.
|
|
297
|
+
#
|
|
298
|
+
# @private
|
|
299
|
+
# @param [RBS::BaseError, StandardError] error the raised exception
|
|
300
|
+
# @param [String] context human-readable context label
|
|
301
|
+
# @return [void]
|
|
302
|
+
def handle_rbs_error(error, context)
|
|
303
|
+
case error
|
|
304
|
+
when ::RBS::BaseError
|
|
305
|
+
warn_once("Docscribe: #{context}: #{error.class}: #{error.message}")
|
|
306
|
+
else
|
|
307
|
+
warn_once(
|
|
308
|
+
"Docscribe: #{context}: #{error.class}: #{error.message}\n" \
|
|
309
|
+
'Feel free to open an issue on github.'
|
|
310
|
+
)
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
249
314
|
# Print one debug warning per provider instance when debugging is enabled.
|
|
250
315
|
#
|
|
251
316
|
# @private
|
|
252
|
-
# @param [String] msg
|
|
317
|
+
# @param [String] msg warning message text
|
|
253
318
|
# @return [void]
|
|
254
319
|
def warn_once(msg)
|
|
255
320
|
return unless ENV['DOCSCRIBE_RBS_DEBUG'] == '1'
|