sord 1.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- data/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
- data/.gitignore +0 -0
- data/.parlour +6 -2
- data/.rspec +0 -0
- data/.travis.yml +0 -0
- data/CHANGELOG.md +58 -0
- data/CODE_OF_CONDUCT.md +0 -0
- data/Gemfile +0 -0
- data/LICENSE.txt +0 -0
- data/README.md +71 -43
- data/Rakefile +25 -7
- data/exe/sord +45 -7
- data/lib/sord.rb +1 -1
- data/lib/sord/generator.rb +601 -0
- data/lib/sord/logging.rb +0 -0
- data/lib/sord/parlour_plugin.rb +23 -2
- data/lib/sord/resolver.rb +4 -0
- data/lib/sord/type_converter.rb +71 -63
- data/lib/sord/version.rb +1 -1
- data/rbi/sord.rbi +211 -30
- data/sord.gemspec +1 -1
- metadata +10 -10
- data/lib/sord/rbi_generator.rb +0 -437
data/sord.gemspec
CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_dependency 'yard'
|
26
26
|
spec.add_dependency 'sorbet-runtime'
|
27
27
|
spec.add_dependency 'commander', '~> 4.5'
|
28
|
-
spec.add_dependency 'parlour', '~>
|
28
|
+
spec.add_dependency 'parlour', '~> 5.0'
|
29
29
|
|
30
30
|
spec.add_development_dependency "bundler", "~> 2.0"
|
31
31
|
spec.add_development_dependency "rake", "~> 10.0"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sord
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aaron Christiansen
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-12-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: yard
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '5.0'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '5.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: bundler
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,7 +136,7 @@ dependencies:
|
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
|
-
description:
|
139
|
+
description:
|
140
140
|
email:
|
141
141
|
- aaronc20000@gmail.com
|
142
142
|
executables:
|
@@ -158,9 +158,9 @@ files:
|
|
158
158
|
- Rakefile
|
159
159
|
- exe/sord
|
160
160
|
- lib/sord.rb
|
161
|
+
- lib/sord/generator.rb
|
161
162
|
- lib/sord/logging.rb
|
162
163
|
- lib/sord/parlour_plugin.rb
|
163
|
-
- lib/sord/rbi_generator.rb
|
164
164
|
- lib/sord/resolver.rb
|
165
165
|
- lib/sord/type_converter.rb
|
166
166
|
- lib/sord/version.rb
|
@@ -170,7 +170,7 @@ homepage: https://github.com/AaronC81/sord
|
|
170
170
|
licenses:
|
171
171
|
- MIT
|
172
172
|
metadata: {}
|
173
|
-
post_install_message:
|
173
|
+
post_install_message:
|
174
174
|
rdoc_options: []
|
175
175
|
require_paths:
|
176
176
|
- lib
|
@@ -185,8 +185,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
185
185
|
- !ruby/object:Gem::Version
|
186
186
|
version: '0'
|
187
187
|
requirements: []
|
188
|
-
rubygems_version: 3.
|
189
|
-
signing_key:
|
188
|
+
rubygems_version: 3.0.3
|
189
|
+
signing_key:
|
190
190
|
specification_version: 4
|
191
191
|
summary: Generate Sorbet RBI files from YARD documentation
|
192
192
|
test_files: []
|
data/lib/sord/rbi_generator.rb
DELETED
@@ -1,437 +0,0 @@
|
|
1
|
-
# typed: true
|
2
|
-
require 'yard'
|
3
|
-
require 'sord/type_converter'
|
4
|
-
require 'sord/logging'
|
5
|
-
require 'parlour'
|
6
|
-
require 'rainbow'
|
7
|
-
|
8
|
-
module Sord
|
9
|
-
# Converts the current working directory's YARD registry into an RBI file.
|
10
|
-
class RbiGenerator
|
11
|
-
# @return [Integer] The number of objects this generator has processed so
|
12
|
-
# far.
|
13
|
-
def object_count
|
14
|
-
@namespace_count + @method_count
|
15
|
-
end
|
16
|
-
|
17
|
-
# @return [Array<Array(String, YARD::CodeObjects::Base, Integer)>] The
|
18
|
-
# errors encountered by by the generator. Each element is of the form
|
19
|
-
# [message, item, line].
|
20
|
-
attr_reader :warnings
|
21
|
-
|
22
|
-
# Create a new RBI generator.
|
23
|
-
# @param [Hash] options
|
24
|
-
# @option options [Integer] break_params
|
25
|
-
# @option options [Boolean] replace_errors_with_untyped
|
26
|
-
# @option options [Boolean] replace_unresolved_with_untyped
|
27
|
-
# @option options [Boolean] comments
|
28
|
-
# @option options [Parlour::RbiGenerator] generator
|
29
|
-
# @option options [Parlour::RbiGenerator::Namespace] root
|
30
|
-
# @return [void]
|
31
|
-
def initialize(options)
|
32
|
-
@parlour = options[:parlour] || Parlour::RbiGenerator.new
|
33
|
-
@current_object = options[:root] || @parlour.root
|
34
|
-
|
35
|
-
@namespace_count = 0
|
36
|
-
@method_count = 0
|
37
|
-
@warnings = []
|
38
|
-
|
39
|
-
@replace_errors_with_untyped = options[:replace_errors_with_untyped]
|
40
|
-
@replace_unresolved_with_untyped = options[:replace_unresolved_with_untyped]
|
41
|
-
@keep_original_comments = options[:keep_original_comments]
|
42
|
-
@skip_constants = options[:skip_constants]
|
43
|
-
|
44
|
-
# Hook the logger so that messages are added as comments to the RBI file
|
45
|
-
Logging.add_hook do |type, msg, item|
|
46
|
-
@current_object.add_comment_to_next_child("sord #{type} - #{msg}")
|
47
|
-
end if options[:sord_comments]
|
48
|
-
|
49
|
-
# Hook the logger so that warnings are collected
|
50
|
-
Logging.add_hook do |type, msg, item|
|
51
|
-
# TODO: is it possible to get line numbers here?
|
52
|
-
warnings << [msg, item, 0] if type == :warn
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
# Increment the namespace counter.
|
57
|
-
# @return [void]
|
58
|
-
def count_namespace
|
59
|
-
@namespace_count += 1
|
60
|
-
end
|
61
|
-
|
62
|
-
# Increment the method counter.
|
63
|
-
# @return [void]
|
64
|
-
def count_method
|
65
|
-
@method_count += 1
|
66
|
-
end
|
67
|
-
|
68
|
-
# Given a YARD CodeObject, add lines defining its mixins (that is, extends
|
69
|
-
# and includes) to the current RBI file. Returns the number of mixins.
|
70
|
-
# @param [YARD::CodeObjects::Base] item
|
71
|
-
# @return [Integer]
|
72
|
-
def add_mixins(item)
|
73
|
-
item.instance_mixins.reverse_each do |i|
|
74
|
-
@current_object.create_include(i.path.to_s)
|
75
|
-
end
|
76
|
-
item.class_mixins.reverse_each do |e|
|
77
|
-
@current_object.create_extend(e.path.to_s)
|
78
|
-
end
|
79
|
-
|
80
|
-
item.instance_mixins.length + item.class_mixins.length
|
81
|
-
end
|
82
|
-
|
83
|
-
# Given a YARD NamespaceObject, add lines defining constants.
|
84
|
-
# @param [YARD::CodeObjects::NamespaceObject] item
|
85
|
-
# @return [void]
|
86
|
-
def add_constants(item)
|
87
|
-
item.constants.each do |constant|
|
88
|
-
# Take a constant (like "A::B::CONSTANT"), split it on each '::', and
|
89
|
-
# set the constant name to the last string in the array.
|
90
|
-
constant_name = constant.to_s.split('::').last
|
91
|
-
|
92
|
-
# Add the constant to the current object being generated.
|
93
|
-
@current_object.create_constant(constant_name, value: "T.let(#{constant.value}, T.untyped)") do |c|
|
94
|
-
c.add_comments(constant.docstring.all.split("\n"))
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
# Given a YARD NamespaceObject, add lines defining its methods and their
|
100
|
-
# signatures to the current RBI file.
|
101
|
-
# @param [YARD::CodeObjects::NamespaceObject] item
|
102
|
-
# @return [void]
|
103
|
-
def add_methods(item)
|
104
|
-
item.meths(inherited: false).each do |meth|
|
105
|
-
count_method
|
106
|
-
|
107
|
-
# If the method is an alias, skip it so we don't define it as a
|
108
|
-
# separate method. Sorbet will handle it automatically.
|
109
|
-
if meth.is_alias?
|
110
|
-
next
|
111
|
-
end
|
112
|
-
|
113
|
-
# Sort parameters
|
114
|
-
meth.parameters.reverse.sort! { |pair1, pair2| sort_params(pair1, pair2) }
|
115
|
-
# This is better than iterating over YARD's "@param" tags directly
|
116
|
-
# because it includes parameters without documentation
|
117
|
-
# (The gsubs allow for better splat-argument compatibility)
|
118
|
-
parameter_names_and_defaults_to_tags = meth.parameters.map do |name, default|
|
119
|
-
[[name, default], meth.tags('param')
|
120
|
-
.find { |p| p.name&.gsub('*', '')&.gsub(':', '') == name.gsub('*', '').gsub(':', '') }]
|
121
|
-
end.to_h
|
122
|
-
|
123
|
-
parameter_types = parameter_names_and_defaults_to_tags.map do |name_and_default, tag|
|
124
|
-
name = name_and_default.first
|
125
|
-
|
126
|
-
if tag
|
127
|
-
TypeConverter.yard_to_sorbet(tag.types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
|
128
|
-
elsif name.start_with? '&'
|
129
|
-
# Find yieldparams and yieldreturn
|
130
|
-
yieldparams = meth.tags('yieldparam')
|
131
|
-
yieldreturn = meth.tag('yieldreturn')&.types
|
132
|
-
yieldreturn = nil if yieldreturn&.length == 1 &&
|
133
|
-
yieldreturn&.first&.downcase == 'void'
|
134
|
-
|
135
|
-
# Create strings
|
136
|
-
params_string = yieldparams.map do |param|
|
137
|
-
"#{param.name.gsub('*', '')}: #{TypeConverter.yard_to_sorbet(param.types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)}" unless param.name.nil?
|
138
|
-
end.join(', ')
|
139
|
-
return_string = TypeConverter.yard_to_sorbet(yieldreturn, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
|
140
|
-
|
141
|
-
# Create proc types, if possible
|
142
|
-
if yieldparams.empty? && yieldreturn.nil?
|
143
|
-
'T.untyped'
|
144
|
-
elsif yieldreturn.nil?
|
145
|
-
"T.proc#{params_string.empty? ? '' : ".params(#{params_string})"}.void"
|
146
|
-
else
|
147
|
-
"T.proc#{params_string.empty? ? '' : ".params(#{params_string})"}.returns(#{return_string})"
|
148
|
-
end
|
149
|
-
elsif meth.path.end_with? '='
|
150
|
-
# Look for the matching getter method
|
151
|
-
getter_path = meth.path[0...-1]
|
152
|
-
getter = item.meths.find { |m| m.path == getter_path }
|
153
|
-
|
154
|
-
unless getter
|
155
|
-
if parameter_names_and_defaults_to_tags.length == 1 \
|
156
|
-
&& meth.tags('param').length == 1 \
|
157
|
-
&& meth.tag('param').types
|
158
|
-
|
159
|
-
Logging.infer("argument name in single @param inferred as #{parameter_names_and_defaults_to_tags.first.first.first.inspect}", meth)
|
160
|
-
next TypeConverter.yard_to_sorbet(meth.tag('param').types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
|
161
|
-
else
|
162
|
-
Logging.omit("no YARD type given for #{name.inspect}, using T.untyped", meth)
|
163
|
-
next 'T.untyped'
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
return_types = getter.tags('return').flat_map(&:types)
|
168
|
-
unless return_types.any?
|
169
|
-
Logging.omit("no YARD type given for #{name.inspect}, using T.untyped", meth)
|
170
|
-
next 'T.untyped'
|
171
|
-
end
|
172
|
-
inferred_type = TypeConverter.yard_to_sorbet(
|
173
|
-
return_types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
|
174
|
-
|
175
|
-
Logging.infer("inferred type of parameter #{name.inspect} as #{inferred_type} using getter's return type", meth)
|
176
|
-
inferred_type
|
177
|
-
else
|
178
|
-
# Is this the only argument, and was a @param specified without an
|
179
|
-
# argument name? If so, infer it
|
180
|
-
if parameter_names_and_defaults_to_tags.length == 1 \
|
181
|
-
&& meth.tags('param').length == 1 \
|
182
|
-
&& meth.tag('param').types
|
183
|
-
|
184
|
-
Logging.infer("argument name in single @param inferred as #{parameter_names_and_defaults_to_tags.first.first.first.inspect}", meth)
|
185
|
-
TypeConverter.yard_to_sorbet(meth.tag('param').types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
|
186
|
-
else
|
187
|
-
Logging.omit("no YARD type given for #{name.inspect}, using T.untyped", meth)
|
188
|
-
'T.untyped'
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
return_tags = meth.tags('return')
|
194
|
-
returns = if return_tags.length == 0
|
195
|
-
Logging.omit("no YARD return type given, using T.untyped", meth)
|
196
|
-
'T.untyped'
|
197
|
-
elsif return_tags.length == 1 && return_tags&.first&.types&.first&.downcase == "void"
|
198
|
-
nil
|
199
|
-
else
|
200
|
-
TypeConverter.yard_to_sorbet(meth.tag('return').types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
|
201
|
-
end
|
202
|
-
|
203
|
-
parlour_params = parameter_names_and_defaults_to_tags
|
204
|
-
.zip(parameter_types)
|
205
|
-
.map do |((name, default), _), type|
|
206
|
-
# If the default is "nil" but the type is not nilable, then it
|
207
|
-
# should become nilable
|
208
|
-
# (T.untyped can include nil, so don't alter that)
|
209
|
-
type = "T.nilable(#{type})" \
|
210
|
-
if default == 'nil' && !type.start_with?('T.nilable') && type != 'T.untyped'
|
211
|
-
Parlour::RbiGenerator::Parameter.new(
|
212
|
-
name.to_s,
|
213
|
-
type: type,
|
214
|
-
default: default
|
215
|
-
)
|
216
|
-
end
|
217
|
-
|
218
|
-
@current_object.create_method(
|
219
|
-
meth.name.to_s,
|
220
|
-
parameters: parlour_params,
|
221
|
-
returns: returns,
|
222
|
-
class_method: meth.scope == :class
|
223
|
-
) do |m|
|
224
|
-
if @keep_original_comments
|
225
|
-
m.add_comments(meth.docstring.all.split("\n"))
|
226
|
-
else
|
227
|
-
parser = YARD::Docstring.parser
|
228
|
-
parser.parse(meth.docstring.all)
|
229
|
-
|
230
|
-
docs_array = parser.text.split("\n")
|
231
|
-
|
232
|
-
# Add @param tags if there are any with names and descriptions.
|
233
|
-
params = parser.tags.select { |tag| tag.tag_name == 'param' && tag.is_a?(YARD::Tags::Tag) && !tag.name.nil? }
|
234
|
-
# Add a blank line if there's anything before the params.
|
235
|
-
docs_array << '' if docs_array.length.positive? && params.length.positive?
|
236
|
-
params.each do |param|
|
237
|
-
docs_array << '' if docs_array.last != '' && docs_array.length.positive?
|
238
|
-
# Output params in the form of:
|
239
|
-
# _@param_ `foo` — Lorem ipsum.
|
240
|
-
# _@param_ `foo`
|
241
|
-
if param.text.nil? || param.text == ''
|
242
|
-
docs_array << "_@param_ `#{param.name}`"
|
243
|
-
else
|
244
|
-
docs_array << "_@param_ `#{param.name}` — #{param.text.gsub("\n", " ")}"
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
# Add @return tags (there could possibly be more than one, despite this not being supported)
|
249
|
-
returns = parser.tags.select { |tag| tag.tag_name == 'return' && tag.is_a?(YARD::Tags::Tag) && !tag.text.nil? && tag.text.strip != '' }
|
250
|
-
# Add a blank line if there's anything before the returns.
|
251
|
-
docs_array << '' if docs_array.length.positive? && returns.length.positive?
|
252
|
-
returns.each do |retn|
|
253
|
-
docs_array << '' if docs_array.last != '' && docs_array.length.positive?
|
254
|
-
# Output returns in the form of:
|
255
|
-
# _@return_ — Lorem ipsum.
|
256
|
-
docs_array << "_@return_ — #{retn.text}"
|
257
|
-
end
|
258
|
-
|
259
|
-
# Iterate through the @example tags for a given YARD doc and output them in Markdown codeblocks.
|
260
|
-
examples = parser.tags.select { |tag| tag.tag_name == 'example' && tag.is_a?(YARD::Tags::Tag) }
|
261
|
-
examples.each do |example|
|
262
|
-
# Only add a blank line if there's anything before the example.
|
263
|
-
docs_array << '' if docs_array.length.positive?
|
264
|
-
# Include the example's 'name' if there is one.
|
265
|
-
docs_array << example.name unless example.name.nil? || example.name == ""
|
266
|
-
docs_array << "```ruby"
|
267
|
-
docs_array.concat(example.text.split("\n"))
|
268
|
-
docs_array << "```"
|
269
|
-
end if examples.length.positive?
|
270
|
-
|
271
|
-
# Add @note and @deprecated tags.
|
272
|
-
notice_tags = parser.tags.select { |tag| ['note', 'deprecated'].include?(tag.tag_name) && tag.is_a?(YARD::Tags::Tag) }
|
273
|
-
# Add a blank line if there's anything before the params.
|
274
|
-
docs_array << '' if docs_array.last != '' && docs_array.length.positive? && notice_tags.length.positive?
|
275
|
-
notice_tags.each do |notice_tag|
|
276
|
-
docs_array << '' if docs_array.last != ''
|
277
|
-
# Output note/deprecated/see in the form of:
|
278
|
-
# _@note_ — Lorem ipsum.
|
279
|
-
# _@note_
|
280
|
-
if notice_tag.text.nil?
|
281
|
-
docs_array << "_@#{notice_tag.tag_name}_"
|
282
|
-
else
|
283
|
-
docs_array << "_@#{notice_tag.tag_name}_ — #{notice_tag.text}"
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
# Add @see tags.
|
288
|
-
see_tags = parser.tags.select { |tag| tag.tag_name == 'see' && tag.is_a?(YARD::Tags::Tag) }
|
289
|
-
# Add a blank line if there's anything before the params.
|
290
|
-
docs_array << '' if docs_array.last != '' && docs_array.length.positive? && see_tags.length.positive?
|
291
|
-
see_tags.each do |see_tag|
|
292
|
-
docs_array << '' if docs_array.last != ''
|
293
|
-
# Output note/deprecated/see in the form of:
|
294
|
-
# _@see_ `B` — Lorem ipsum.
|
295
|
-
# _@see_ `B`
|
296
|
-
if see_tag.text.nil?
|
297
|
-
docs_array << "_@see_ `#{see_tag.name}`"
|
298
|
-
else
|
299
|
-
docs_array << "_@see_ `#{see_tag.name}` — #{see_tag.text}"
|
300
|
-
end
|
301
|
-
end
|
302
|
-
|
303
|
-
# fix: yard text may contains multiple line. should deal \n.
|
304
|
-
# else generate text will be multiple line and only first line is commented
|
305
|
-
docs_array = docs_array.flat_map {|line| line.empty? ? [""] : line.split("\n")}
|
306
|
-
m.add_comments(docs_array)
|
307
|
-
end
|
308
|
-
end
|
309
|
-
end
|
310
|
-
end
|
311
|
-
|
312
|
-
# Given a YARD NamespaceObject, add lines defining its mixins, methods
|
313
|
-
# and children to the RBI file.
|
314
|
-
# @param [YARD::CodeObjects::NamespaceObject] item
|
315
|
-
# @return [void]
|
316
|
-
def add_namespace(item)
|
317
|
-
count_namespace
|
318
|
-
|
319
|
-
superclass = nil
|
320
|
-
superclass = item.superclass.path.to_s if item.type == :class && item.superclass.to_s != "Object"
|
321
|
-
|
322
|
-
parent = @current_object
|
323
|
-
@current_object = item.type == :class \
|
324
|
-
? parent.create_class(item.name.to_s, superclass: superclass)
|
325
|
-
: parent.create_module(item.name.to_s)
|
326
|
-
@current_object.add_comments(item.docstring.all.split("\n"))
|
327
|
-
|
328
|
-
add_mixins(item)
|
329
|
-
add_methods(item)
|
330
|
-
add_constants(item) unless @skip_constants
|
331
|
-
|
332
|
-
item.children.select { |x| [:class, :module].include?(x.type) }
|
333
|
-
.each { |child| add_namespace(child) }
|
334
|
-
|
335
|
-
@current_object = parent
|
336
|
-
end
|
337
|
-
|
338
|
-
# Populates the RBI generator with the contents of the YARD registry. You
|
339
|
-
# must load the YARD registry first!
|
340
|
-
# @return [void]
|
341
|
-
def populate
|
342
|
-
# Generate top-level modules, which recurses to all modules
|
343
|
-
YARD::Registry.root.children
|
344
|
-
.select { |x| [:class, :module].include?(x.type) }
|
345
|
-
.each { |child| add_namespace(child) }
|
346
|
-
end
|
347
|
-
|
348
|
-
# Populates the RBI generator with the contents of the YARD registry, then
|
349
|
-
# uses the loaded Parlour::RbiGenerator to generate the RBI file. You must
|
350
|
-
# load the YARD registry first!
|
351
|
-
# @return [void]
|
352
|
-
def generate
|
353
|
-
populate
|
354
|
-
@parlour.rbi
|
355
|
-
end
|
356
|
-
|
357
|
-
# Loads the YARD registry, populates the RBI file, and prints any relevant
|
358
|
-
# final logs.
|
359
|
-
# @return [void]
|
360
|
-
def run
|
361
|
-
# Get YARD ready
|
362
|
-
YARD::Registry.load!
|
363
|
-
|
364
|
-
# Populate the RBI
|
365
|
-
populate
|
366
|
-
|
367
|
-
if object_count.zero?
|
368
|
-
Logging.warn("No objects processed.")
|
369
|
-
Logging.warn("Have you definitely generated the YARD documentation for this project?")
|
370
|
-
Logging.warn("Run `yard` to generate docs.")
|
371
|
-
end
|
372
|
-
|
373
|
-
Logging.done("Processed #{object_count} objects (#{@namespace_count} namespaces and #{@method_count} methods)")
|
374
|
-
|
375
|
-
Logging.hooks.clear
|
376
|
-
|
377
|
-
unless warnings.empty?
|
378
|
-
Logging.warn("There were #{warnings.length} important warnings in the RBI file, listed below.")
|
379
|
-
if @replace_errors_with_untyped
|
380
|
-
Logging.warn("The types which caused them have been replaced with T.untyped.")
|
381
|
-
else
|
382
|
-
Logging.warn("The types which caused them have been replaced with SORD_ERROR_ constants.")
|
383
|
-
end
|
384
|
-
Logging.warn("Please edit the file to fix these errors.")
|
385
|
-
Logging.warn("Alternatively, edit your YARD documentation so that your types are valid and re-run Sord.")
|
386
|
-
warnings.each do |(msg, item, _)|
|
387
|
-
puts " (#{Rainbow(item&.path).bold}) #{msg}"
|
388
|
-
end
|
389
|
-
end
|
390
|
-
rescue
|
391
|
-
Logging.error($!)
|
392
|
-
$@.each do |line|
|
393
|
-
puts " #{line}"
|
394
|
-
end
|
395
|
-
end
|
396
|
-
|
397
|
-
# Given two pairs of arrays representing method parameters, in the form
|
398
|
-
# of ["variable_name", "default_value"], sort the parameters so they're
|
399
|
-
# valid for Sorbet. Sorbet requires that, e.g. required kwargs go before
|
400
|
-
# optional kwargs.
|
401
|
-
#
|
402
|
-
# @param [Array] pair1
|
403
|
-
# @param [Array] pair2
|
404
|
-
# @return Integer
|
405
|
-
def sort_params(pair1, pair2)
|
406
|
-
pair1_type, pair2_type = [pair1, pair2].map do |pair|
|
407
|
-
if pair[0].start_with?('&')
|
408
|
-
:blk
|
409
|
-
elsif pair[0].start_with?('**')
|
410
|
-
:doublesplat
|
411
|
-
elsif pair[0].start_with?('*')
|
412
|
-
:splat
|
413
|
-
elsif !pair[0].end_with?(':') && pair[1].nil?
|
414
|
-
:required_ordered_param
|
415
|
-
elsif !pair[0].end_with?(':') && !pair[1].nil?
|
416
|
-
:optional_ordered_param
|
417
|
-
elsif pair[0].end_with?(':') && pair[1].nil?
|
418
|
-
:required_kwarg
|
419
|
-
elsif pair[0].end_with?(':') && !pair[1].nil?
|
420
|
-
:optional_kwarg
|
421
|
-
end
|
422
|
-
end
|
423
|
-
|
424
|
-
pair_type_order = {
|
425
|
-
required_ordered_param: 1,
|
426
|
-
optional_ordered_param: 2,
|
427
|
-
splat: 3,
|
428
|
-
required_kwarg: 4,
|
429
|
-
optional_kwarg: 5,
|
430
|
-
doublesplat: 6,
|
431
|
-
blk: 7
|
432
|
-
}
|
433
|
-
|
434
|
-
return pair_type_order[pair1_type] <=> pair_type_order[pair2_type]
|
435
|
-
end
|
436
|
-
end
|
437
|
-
end
|