sord 2.0.0 → 3.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- 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 +15 -0
- data/CODE_OF_CONDUCT.md +0 -0
- data/Gemfile +0 -0
- data/LICENSE.txt +0 -0
- data/README.md +0 -0
- data/Rakefile +25 -7
- data/exe/sord +42 -6
- data/lib/sord.rb +1 -1
- data/lib/sord/{rbi_generator.rb → generator.rb} +158 -79
- data/lib/sord/logging.rb +0 -0
- data/lib/sord/parlour_plugin.rb +23 -2
- data/lib/sord/resolver.rb +0 -0
- data/lib/sord/type_converter.rb +53 -45
- data/lib/sord/version.rb +1 -1
- data/rbi/sord.rbi +211 -30
- data/sord.gemspec +1 -1
- metadata +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6cfc03da2fe9815159c9041a5afff2a0e1e089567cb92da25bcec87137f9e747
|
4
|
+
data.tar.gz: acd6551c560c205199ec494930f4628c5357a34263b0cce05757033014ba929b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3ef67b5162e55af55f81fd056c0a1f232293c021b145fab2054cd482951c9cd22aa2e9f8874687131c65b209f2217488ce6808f9bd88da75a04928720452a34
|
7
|
+
data.tar.gz: 719461ac9a36dc5c636c4f1b79c22923da4e1decb25032ec8e0c6eef8df60454c3eba6d275c61f91fec9d637d200631d3c3003b1aff981d6bafac3c91323e323
|
File without changes
|
File without changes
|
data/.gitignore
CHANGED
File without changes
|
data/.parlour
CHANGED
data/.rspec
CHANGED
File without changes
|
data/.travis.yml
CHANGED
File without changes
|
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,21 @@ All notable changes to this project will be documented in this file.
|
|
3
3
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
5
5
|
|
6
|
+
## [3.0.0.beta.1] - 2020-09-16
|
7
|
+
### Added
|
8
|
+
- Sord now uses the Parlour 5 beta's RBS generation to generate RBS files!
|
9
|
+
- Added `--rbi` and `--rbs` to select an output format to use (if neither given,
|
10
|
+
tries to infer from file extension).
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
- `RbiGenerator` has been renamed to `Generator`.
|
14
|
+
- `TypeConverter#yard_to_sorbet` is now `TypeConverter#yard_to_parlour`, and
|
15
|
+
returns `Parlour::Types::Type` instances rather than strings.
|
16
|
+
|
17
|
+
### Fixed
|
18
|
+
- `#return [nil]` no longer produces a union of zero types, instead becoming
|
19
|
+
`void` for method returns or `untyped` for attributes.
|
20
|
+
|
6
21
|
## [2.0.0] - 2020-03-16
|
7
22
|
### Added
|
8
23
|
- Sord now supports generating `attr_accessor`, `attr_reader` and `attr_writer`
|
data/CODE_OF_CONDUCT.md
CHANGED
File without changes
|
data/Gemfile
CHANGED
File without changes
|
data/LICENSE.txt
CHANGED
File without changes
|
data/README.md
CHANGED
File without changes
|
data/Rakefile
CHANGED
@@ -24,12 +24,21 @@ namespace :examples do
|
|
24
24
|
require 'rainbow'
|
25
25
|
|
26
26
|
desc "Clone git repositories and run Sord on them as examples"
|
27
|
-
task :seed, [:clean] do |t, args|
|
27
|
+
task :seed, [:mode, :clean] do |t, args|
|
28
28
|
if File.directory?('sord_examples')
|
29
29
|
puts Rainbow('sord_examples directory already exists, please delete the directory or run a reseed!').red
|
30
30
|
exit
|
31
31
|
end
|
32
32
|
|
33
|
+
if args[:mode] == 'rbi'
|
34
|
+
mode_arg = '--rbi'
|
35
|
+
elsif args[:mode] == 'rbs'
|
36
|
+
mode_arg = '--rbs'
|
37
|
+
else
|
38
|
+
puts Rainbow('please specify \'rbi\' or \'rbs\'!').red
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
|
33
42
|
FileUtils.mkdir 'sord_examples'
|
34
43
|
FileUtils.cd 'sord_examples'
|
35
44
|
|
@@ -46,11 +55,11 @@ namespace :examples do
|
|
46
55
|
# Generate sri
|
47
56
|
puts "Generating rbi for #{name}..."
|
48
57
|
if args[:clean]
|
49
|
-
system("bundle exec sord ../#{name}
|
58
|
+
system("bundle exec sord ../#{name}.#{args[:mode]} #{mode_arg} --no-sord-comments --replace-errors-with-untyped --replace-unresolved-with-untyped")
|
50
59
|
else
|
51
|
-
system("bundle exec sord ../#{name}
|
60
|
+
system("bundle exec sord ../#{name}.#{args[:mode]} #{mode_arg}")
|
52
61
|
end
|
53
|
-
puts "#{name}
|
62
|
+
puts "#{name}.#{args[:mode]} generated!"
|
54
63
|
FileUtils.cd '..'
|
55
64
|
end
|
56
65
|
end
|
@@ -59,21 +68,30 @@ namespace :examples do
|
|
59
68
|
end
|
60
69
|
|
61
70
|
desc 'Regenerate the rbi files in sord_examples.'
|
62
|
-
task :reseed, [:clean] do |t, args|
|
71
|
+
task :reseed, [:mode, :clean] do |t, args|
|
63
72
|
if Dir.exist?('sord_examples')
|
64
73
|
FileUtils.cd 'sord_examples'
|
65
74
|
else
|
66
75
|
raise Rainbow("The sord_examples directory does not exist. Have you run the seed task?").red.bold
|
67
76
|
end
|
68
77
|
|
78
|
+
if args[:mode] == 'rbi'
|
79
|
+
mode_arg = '--rbi'
|
80
|
+
elsif args[:mode] == 'rbs'
|
81
|
+
mode_arg = '--rbs'
|
82
|
+
else
|
83
|
+
puts Rainbow('please specify \'rbi\' or \'rbs\'!').red
|
84
|
+
exit
|
85
|
+
end
|
86
|
+
|
69
87
|
REPOS.keys.each do |name|
|
70
88
|
FileUtils.cd name.to_s
|
71
89
|
puts "Regenerating rbi file for #{name}..."
|
72
90
|
Bundler.with_clean_env do
|
73
91
|
if args[:clean]
|
74
|
-
system("bundle exec sord ../#{name}
|
92
|
+
system("bundle exec sord ../#{name}.#{args[:mode]} #{mode_arg} --no-regenerate --no-sord-comments --replace-errors-with-untyped --replace-unresolved-with-untyped")
|
75
93
|
else
|
76
|
-
system("bundle exec sord ../#{name}
|
94
|
+
system("bundle exec sord ../#{name}.#{args[:mode]} #{mode_arg} --no-regenerate")
|
77
95
|
end
|
78
96
|
end
|
79
97
|
FileUtils.cd '..'
|
data/exe/sord
CHANGED
@@ -10,8 +10,10 @@ program :description, 'Generate Sorbet RBIs from YARD documentation'
|
|
10
10
|
default_command :gen
|
11
11
|
command :gen do |c|
|
12
12
|
c.syntax = 'sord gen <output-file> [options]'
|
13
|
-
c.description = 'Generates
|
14
|
-
c.option '--
|
13
|
+
c.description = 'Generates a type signature file from this directory\'s YARD docs'
|
14
|
+
c.option '--rbi', 'Use Sorbet\'s RBI format'
|
15
|
+
c.option '--rbs', 'Use Steep/Ruby 3\'s RBS format'
|
16
|
+
c.option '--[no-]sord-comments', 'Controls informational/warning comments in the file'
|
15
17
|
c.option '--[no-]regenerate', 'Controls whether YARD is executed before Sord runs'
|
16
18
|
c.option '--break-params INTEGER', Integer, 'Break params onto their own lines if there are this many'
|
17
19
|
c.option '--replace-errors-with-untyped', 'Uses T.untyped rather than SORD_ERROR_ constants'
|
@@ -19,11 +21,13 @@ command :gen do |c|
|
|
19
21
|
c.option '--exclude-messages STRING', String, 'Blacklists a comma-separated string of log message types'
|
20
22
|
c.option '--include-messages STRING', String, 'Whitelists a comma-separated string of log message types'
|
21
23
|
c.option '--keep-original-comments', 'Retains original YARD comments rather than converting them to Markdown'
|
22
|
-
c.option '--skip-constants', 'Excludes constants from generated
|
24
|
+
c.option '--skip-constants', 'Excludes constants from generated file'
|
23
25
|
c.option '--use-original-initialize-return', 'Uses the specified return type for #initialize rather than void'
|
24
26
|
|
25
27
|
c.action do |args, options|
|
26
28
|
options.default(
|
29
|
+
rbi: false,
|
30
|
+
rbs: false,
|
27
31
|
sord_comments: true,
|
28
32
|
regenerate: true,
|
29
33
|
break_params: 4,
|
@@ -40,15 +44,47 @@ command :gen do |c|
|
|
40
44
|
Sord::Logging.error('Must specify filename')
|
41
45
|
exit 1
|
42
46
|
end
|
43
|
-
|
47
|
+
|
44
48
|
plugin_options = options.__hash__
|
45
49
|
plugin_options[:exclude_options] = plugin_options[:exclude_options]&.split(',')
|
46
50
|
plugin_options[:include_options] = plugin_options[:include_options]&.split(',')
|
47
51
|
|
52
|
+
if !(plugin_options[:rbi] || plugin_options[:rbs])
|
53
|
+
if args.first
|
54
|
+
if args.first.end_with?('.rbi')
|
55
|
+
Sord::Logging.infer('Assuming from filename you wish to generate in RBI format')
|
56
|
+
plugin_options[:rbi] = true
|
57
|
+
elsif args.first.end_with?('.rbs')
|
58
|
+
Sord::Logging.infer('Assuming from filename you wish to generate in RBS format')
|
59
|
+
plugin_options[:rbs] = true
|
60
|
+
else
|
61
|
+
Sord::Logging.error('An output format could not be inferred from your filename; please specify --rbi or --rbs')
|
62
|
+
exit 1
|
63
|
+
end
|
64
|
+
else
|
65
|
+
Sord::Logging.error('No output format given; please specify --rbi or --rbs')
|
66
|
+
exit 1
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
if (plugin_options[:rbi] && plugin_options[:rbs])
|
71
|
+
Sord::Logging.error('You cannot specify both --rbi and --rbs; please use only one')
|
72
|
+
exit 1
|
73
|
+
end
|
74
|
+
|
48
75
|
plugin = Sord::ParlourPlugin.new(plugin_options)
|
49
|
-
|
76
|
+
|
77
|
+
if plugin_options[:rbi]
|
78
|
+
klass = Parlour::RbiGenerator
|
79
|
+
generator_method = :rbi
|
80
|
+
elsif plugin_options[:rbs]
|
81
|
+
klass = Parlour::RbsGenerator
|
82
|
+
generator_method = :rbs
|
83
|
+
end
|
84
|
+
|
85
|
+
plugin.parlour = klass.new(break_params: plugin_options[:break_params])
|
50
86
|
plugin.generate(plugin.parlour.root)
|
51
87
|
|
52
|
-
File.write(args.first, plugin.parlour.
|
88
|
+
File.write(args.first, plugin.parlour.send(generator_method))
|
53
89
|
end
|
54
90
|
end
|
data/lib/sord.rb
CHANGED
@@ -6,8 +6,11 @@ require 'parlour'
|
|
6
6
|
require 'rainbow'
|
7
7
|
|
8
8
|
module Sord
|
9
|
-
# Converts the current working directory's YARD registry into an
|
10
|
-
|
9
|
+
# Converts the current working directory's YARD registry into an type
|
10
|
+
# signature file.
|
11
|
+
class Generator
|
12
|
+
VALID_MODES = [:rbi, :rbs]
|
13
|
+
|
11
14
|
# @return [Integer] The number of objects this generator has processed so
|
12
15
|
# far.
|
13
16
|
def object_count
|
@@ -19,17 +22,28 @@ module Sord
|
|
19
22
|
# [message, item, line].
|
20
23
|
attr_reader :warnings
|
21
24
|
|
22
|
-
# Create a new
|
25
|
+
# Create a new generator.
|
23
26
|
# @param [Hash] options
|
27
|
+
# @option options [Symbol] mode
|
24
28
|
# @option options [Integer] break_params
|
25
29
|
# @option options [Boolean] replace_errors_with_untyped
|
26
30
|
# @option options [Boolean] replace_unresolved_with_untyped
|
27
31
|
# @option options [Boolean] comments
|
28
|
-
# @option options [Parlour::
|
29
|
-
# @option options [Parlour::
|
32
|
+
# @option options [Parlour::Generator] generator
|
33
|
+
# @option options [Parlour::TypedObject] root
|
30
34
|
# @return [void]
|
31
35
|
def initialize(options)
|
32
|
-
@
|
36
|
+
@mode = options[:mode].to_sym rescue options[:mode]
|
37
|
+
raise "invalid mode #{@mode}, expected one of: #{VALID_MODES.join(', ')}" \
|
38
|
+
unless VALID_MODES.include?(@mode)
|
39
|
+
|
40
|
+
@parlour = options[:parlour] || \
|
41
|
+
case @mode
|
42
|
+
when :rbi
|
43
|
+
Parlour::RbiGenerator.new
|
44
|
+
when :rbs
|
45
|
+
Parlour::RbsGenerator.new
|
46
|
+
end
|
33
47
|
@current_object = options[:root] || @parlour.root
|
34
48
|
|
35
49
|
@namespace_count = 0
|
@@ -42,7 +56,7 @@ module Sord
|
|
42
56
|
@skip_constants = options[:skip_constants]
|
43
57
|
@use_original_initialize_return = options[:use_original_initialize_return]
|
44
58
|
|
45
|
-
# Hook the logger so that messages are added as comments
|
59
|
+
# Hook the logger so that messages are added as comments
|
46
60
|
Logging.add_hook do |type, msg, item|
|
47
61
|
@current_object.add_comment_to_next_child("sord #{type} - #{msg}")
|
48
62
|
end if options[:sord_comments]
|
@@ -67,7 +81,7 @@ module Sord
|
|
67
81
|
end
|
68
82
|
|
69
83
|
# Given a YARD CodeObject, add lines defining its mixins (that is, extends
|
70
|
-
# and includes) to the current
|
84
|
+
# and includes) to the current file. Returns the number of mixins.
|
71
85
|
# @param [YARD::CodeObjects::Base] item
|
72
86
|
# @return [Integer]
|
73
87
|
def add_mixins(item)
|
@@ -85,25 +99,39 @@ module Sord
|
|
85
99
|
# @param [YARD::CodeObjects::NamespaceObject] item
|
86
100
|
# @return [void]
|
87
101
|
def add_constants(item)
|
88
|
-
|
102
|
+
inserted_constant_names = Set.new
|
103
|
+
|
104
|
+
item.constants(included: false).each do |constant|
|
89
105
|
# Take a constant (like "A::B::CONSTANT"), split it on each '::', and
|
90
106
|
# set the constant name to the last string in the array.
|
91
107
|
constant_name = constant.to_s.split('::').last
|
108
|
+
if inserted_constant_names.include?(constant_name) && @mode == :rbs
|
109
|
+
Logging.warn("RBS doesn't support duplicate constants, but '#{constant_name}' was duplicated - dropping future occurences", constant)
|
110
|
+
next
|
111
|
+
end
|
112
|
+
inserted_constant_names << constant_name
|
92
113
|
|
93
114
|
# Add the constant to the current object being generated.
|
94
|
-
@
|
95
|
-
|
115
|
+
case @mode
|
116
|
+
when :rbi
|
117
|
+
@current_object.create_constant(constant_name, value: "T.let(#{constant.value}, T.untyped)") do |c|
|
118
|
+
c.add_comments(constant.docstring.all.split("\n"))
|
119
|
+
end
|
120
|
+
when :rbs
|
121
|
+
@current_object.create_constant(constant_name, type: Parlour::Types::Untyped.new) do |c|
|
122
|
+
c.add_comments(constant.docstring.all.split("\n"))
|
123
|
+
end
|
96
124
|
end
|
97
125
|
end
|
98
126
|
end
|
99
127
|
|
100
|
-
# Adds comments to an
|
128
|
+
# Adds comments to an object based on a docstring.
|
101
129
|
# @param [YARD::CodeObjects::NamespaceObject] item
|
102
|
-
# @param [Parlour::
|
130
|
+
# @param [Parlour::TypedObject] typed_object
|
103
131
|
# @return [void]
|
104
|
-
def add_comments(item,
|
132
|
+
def add_comments(item, typed_object)
|
105
133
|
if @keep_original_comments
|
106
|
-
|
134
|
+
typed_object.add_comments(item.docstring.all.split("\n"))
|
107
135
|
else
|
108
136
|
parser = YARD::Docstring.parser
|
109
137
|
parser.parse(item.docstring.all)
|
@@ -184,12 +212,12 @@ module Sord
|
|
184
212
|
# fix: yard text may contains multiple line. should deal \n.
|
185
213
|
# else generate text will be multiple line and only first line is commented
|
186
214
|
docs_array = docs_array.flat_map {|line| line.empty? ? [""] : line.split("\n")}
|
187
|
-
|
215
|
+
typed_object.add_comments(docs_array)
|
188
216
|
end
|
189
217
|
end
|
190
218
|
|
191
219
|
# Given a YARD NamespaceObject, add lines defining its methods and their
|
192
|
-
# signatures to the current
|
220
|
+
# signatures to the current file.
|
193
221
|
# @param [YARD::CodeObjects::NamespaceObject] item
|
194
222
|
# @return [void]
|
195
223
|
def add_methods(item)
|
@@ -197,7 +225,7 @@ module Sord
|
|
197
225
|
count_method
|
198
226
|
|
199
227
|
# If the method is an alias, skip it so we don't define it as a
|
200
|
-
# separate method.
|
228
|
+
# separate method.
|
201
229
|
if meth.is_alias?
|
202
230
|
next
|
203
231
|
end
|
@@ -221,7 +249,7 @@ module Sord
|
|
221
249
|
name = name_and_default.first
|
222
250
|
|
223
251
|
if tag
|
224
|
-
TypeConverter.
|
252
|
+
TypeConverter.yard_to_parlour(tag.types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
|
225
253
|
elsif name.start_with? '&'
|
226
254
|
# Find yieldparams and yieldreturn
|
227
255
|
yieldparams = meth.tags('yieldparam')
|
@@ -230,18 +258,19 @@ module Sord
|
|
230
258
|
yieldreturn&.first&.downcase == 'void'
|
231
259
|
|
232
260
|
# Create strings
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
261
|
+
params = yieldparams.map do |param|
|
262
|
+
Parlour::Types::Proc::Parameter.new(
|
263
|
+
param.name.gsub('*', ''),
|
264
|
+
TypeConverter.yard_to_parlour(param.types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
|
265
|
+
)
|
266
|
+
end
|
267
|
+
returns = TypeConverter.yard_to_parlour(yieldreturn, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
|
237
268
|
|
238
269
|
# Create proc types, if possible
|
239
270
|
if yieldparams.empty? && yieldreturn.nil?
|
240
|
-
|
241
|
-
elsif yieldreturn.nil?
|
242
|
-
"T.proc#{params_string.empty? ? '' : ".params(#{params_string})"}.void"
|
271
|
+
Parlour::Types::Untyped.new
|
243
272
|
else
|
244
|
-
|
273
|
+
Parlour::Types::Proc.new(params, yieldreturn.nil? ? nil : returns)
|
245
274
|
end
|
246
275
|
elsif meth.path.end_with? '='
|
247
276
|
# Look for the matching getter method
|
@@ -254,22 +283,22 @@ module Sord
|
|
254
283
|
&& meth.tag('param').types
|
255
284
|
|
256
285
|
Logging.infer("argument name in single @param inferred as #{parameter_names_and_defaults_to_tags.first.first.first.inspect}", meth)
|
257
|
-
next TypeConverter.
|
286
|
+
next TypeConverter.yard_to_parlour(meth.tag('param').types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
|
258
287
|
else
|
259
|
-
Logging.omit("no YARD type given for #{name.inspect}, using
|
260
|
-
next
|
288
|
+
Logging.omit("no YARD type given for #{name.inspect}, using untyped", meth)
|
289
|
+
next Parlour::Types::Untyped.new
|
261
290
|
end
|
262
291
|
end
|
263
292
|
|
264
293
|
return_types = getter.tags('return').flat_map(&:types)
|
265
294
|
unless return_types.any?
|
266
|
-
Logging.omit("no YARD type given for #{name.inspect}, using
|
267
|
-
next
|
295
|
+
Logging.omit("no YARD type given for #{name.inspect}, using untyped", meth)
|
296
|
+
next Parlour::Types::Untyped.new
|
268
297
|
end
|
269
|
-
inferred_type = TypeConverter.
|
298
|
+
inferred_type = TypeConverter.yard_to_parlour(
|
270
299
|
return_types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
|
271
300
|
|
272
|
-
Logging.infer("inferred type of parameter #{name.inspect} as #{inferred_type} using getter's return type", meth)
|
301
|
+
Logging.infer("inferred type of parameter #{name.inspect} as #{inferred_type.describe} using getter's return type", meth)
|
273
302
|
inferred_type
|
274
303
|
else
|
275
304
|
# Is this the only argument, and was a @param specified without an
|
@@ -279,10 +308,10 @@ module Sord
|
|
279
308
|
&& meth.tag('param').types
|
280
309
|
|
281
310
|
Logging.infer("argument name in single @param inferred as #{parameter_names_and_defaults_to_tags.first.first.first.inspect}", meth)
|
282
|
-
TypeConverter.
|
311
|
+
TypeConverter.yard_to_parlour(meth.tag('param').types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
|
283
312
|
else
|
284
|
-
Logging.omit("no YARD type given for #{name.inspect}, using
|
285
|
-
|
313
|
+
Logging.omit("no YARD type given for #{name.inspect}, using untyped", meth)
|
314
|
+
Parlour::Types::Untyped.new
|
286
315
|
end
|
287
316
|
end
|
288
317
|
end
|
@@ -291,42 +320,74 @@ module Sord
|
|
291
320
|
returns = if meth.name == :initialize && !@use_original_initialize_return
|
292
321
|
nil
|
293
322
|
elsif return_tags.length == 0
|
294
|
-
Logging.omit("no YARD return type given, using
|
295
|
-
|
296
|
-
elsif return_tags.length == 1 && return_tags&.first&.types&.first&.downcase
|
323
|
+
Logging.omit("no YARD return type given, using untyped", meth)
|
324
|
+
Parlour::Types::Untyped.new
|
325
|
+
elsif return_tags.length == 1 && %w{void nil}.include?(return_tags&.first&.types&.first&.downcase)
|
297
326
|
nil
|
298
327
|
else
|
299
|
-
TypeConverter.
|
328
|
+
TypeConverter.yard_to_parlour(meth.tag('return').types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
|
300
329
|
end
|
301
330
|
|
331
|
+
rbs_block = nil
|
302
332
|
parlour_params = parameter_names_and_defaults_to_tags
|
303
333
|
.zip(parameter_types)
|
304
334
|
.map do |((name, default), _), type|
|
305
335
|
# If the default is "nil" but the type is not nilable, then it
|
306
336
|
# should become nilable
|
307
337
|
# (T.untyped can include nil, so don't alter that)
|
308
|
-
type =
|
309
|
-
if default == 'nil' && !type.
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
338
|
+
type = Parlour::Types::Nilable.new(type) \
|
339
|
+
if default == 'nil' && !type.is_a?(Parlour::Types::Nilable) && !type.is_a?(Parlour::Types::Untyped)
|
340
|
+
|
341
|
+
case @mode
|
342
|
+
when :rbi
|
343
|
+
Parlour::RbiGenerator::Parameter.new(
|
344
|
+
name.to_s,
|
345
|
+
type: type,
|
346
|
+
default: default
|
347
|
+
)
|
348
|
+
when :rbs
|
349
|
+
if name.start_with?('&')
|
350
|
+
rbs_block = type
|
351
|
+
nil
|
352
|
+
else
|
353
|
+
Parlour::RbsGenerator::Parameter.new(
|
354
|
+
name.to_s,
|
355
|
+
type: type,
|
356
|
+
required: default.nil?
|
357
|
+
)
|
358
|
+
end
|
359
|
+
end
|
315
360
|
end
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
361
|
+
.compact
|
362
|
+
|
363
|
+
case @mode
|
364
|
+
when :rbi
|
365
|
+
@current_object.create_method(
|
366
|
+
meth.name.to_s,
|
367
|
+
parameters: parlour_params,
|
368
|
+
returns: returns,
|
369
|
+
class_method: meth.scope == :class
|
370
|
+
) do |m|
|
371
|
+
add_comments(meth, m)
|
372
|
+
end
|
373
|
+
when :rbs
|
374
|
+
@current_object.create_method(
|
375
|
+
meth.name.to_s,
|
376
|
+
[Parlour::RbsGenerator::MethodSignature.new(
|
377
|
+
parlour_params, returns, block: rbs_block && !rbs_block.is_a?(Parlour::Types::Untyped) \
|
378
|
+
? Parlour::RbsGenerator::Block.new(rbs_block, false)
|
379
|
+
: nil
|
380
|
+
)],
|
381
|
+
class_method: meth.scope == :class
|
382
|
+
) do |m|
|
383
|
+
add_comments(meth, m)
|
384
|
+
end
|
385
|
+
end
|
325
386
|
end
|
326
387
|
end
|
327
388
|
|
328
389
|
# Given a YARD NamespaceObject, add lines defining either its class
|
329
|
-
# and instance attributes and their signatures to the current
|
390
|
+
# and instance attributes and their signatures to the current file.
|
330
391
|
# @param [YARD::CodeObjects::NamespaceObject] item
|
331
392
|
# @return [void]
|
332
393
|
def add_attributes(item)
|
@@ -353,13 +414,16 @@ module Sord
|
|
353
414
|
writer.tags('param').flat_map(&:types)
|
354
415
|
end
|
355
416
|
|
356
|
-
# Use
|
357
|
-
# compute
|
417
|
+
# Use untyped if not types specified anywhere, otherwise try to
|
418
|
+
# compute Parlour type given all these types
|
358
419
|
if yard_types.empty?
|
359
|
-
Logging.omit("no YARD type given for #{name.inspect}, using
|
360
|
-
|
420
|
+
Logging.omit("no YARD type given for #{name.inspect}, using untyped", reader || writer)
|
421
|
+
parlour_type = Parlour::Types::Untyped.new
|
422
|
+
elsif yard_types.all? { |x| x == 'nil' }
|
423
|
+
# Nil attributes are extremely unusual, so just use untyped
|
424
|
+
parlour_type = Parlour::Types::Untyped.new
|
361
425
|
else
|
362
|
-
|
426
|
+
parlour_type = TypeConverter.yard_to_parlour(
|
363
427
|
yard_types, reader || writer, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
|
364
428
|
end
|
365
429
|
|
@@ -372,20 +436,35 @@ module Sord
|
|
372
436
|
kind = :writer
|
373
437
|
end
|
374
438
|
|
375
|
-
@
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
439
|
+
case @mode
|
440
|
+
when :rbi
|
441
|
+
@current_object.create_attribute(
|
442
|
+
name.to_s,
|
443
|
+
kind: kind,
|
444
|
+
type: parlour_type,
|
445
|
+
class_attribute: (attr_loc == :class)
|
446
|
+
) do |m|
|
447
|
+
add_comments(reader || writer, m)
|
448
|
+
end
|
449
|
+
when :rbs
|
450
|
+
if attr_loc == :class
|
451
|
+
Logging.warn("RBS doesn't support class attributes, dropping", reader || writer)
|
452
|
+
else
|
453
|
+
@current_object.create_attribute(
|
454
|
+
name.to_s,
|
455
|
+
kind: kind,
|
456
|
+
type: parlour_type,
|
457
|
+
) do |m|
|
458
|
+
add_comments(reader || writer, m)
|
459
|
+
end
|
460
|
+
end
|
382
461
|
end
|
383
462
|
end
|
384
463
|
end
|
385
464
|
end
|
386
465
|
|
387
466
|
# Given a YARD NamespaceObject, add lines defining its mixins, methods
|
388
|
-
# and children to the
|
467
|
+
# and children to the file.
|
389
468
|
# @param [YARD::CodeObjects::NamespaceObject] item
|
390
469
|
# @return [void]
|
391
470
|
def add_namespace(item)
|
@@ -411,7 +490,7 @@ module Sord
|
|
411
490
|
@current_object = parent
|
412
491
|
end
|
413
492
|
|
414
|
-
# Populates the
|
493
|
+
# Populates the generator with the contents of the YARD registry. You
|
415
494
|
# must load the YARD registry first!
|
416
495
|
# @return [void]
|
417
496
|
def populate
|
@@ -421,23 +500,23 @@ module Sord
|
|
421
500
|
.each { |child| add_namespace(child) }
|
422
501
|
end
|
423
502
|
|
424
|
-
# Populates the
|
425
|
-
# uses the loaded Parlour::
|
503
|
+
# Populates the generator with the contents of the YARD registry, then
|
504
|
+
# uses the loaded Parlour::Generator to generate the file. You must
|
426
505
|
# load the YARD registry first!
|
427
506
|
# @return [void]
|
428
507
|
def generate
|
429
508
|
populate
|
430
|
-
@parlour.
|
509
|
+
@parlour.send(@mode)
|
431
510
|
end
|
432
511
|
|
433
|
-
# Loads the YARD registry, populates the
|
512
|
+
# Loads the YARD registry, populates the file, and prints any relevant
|
434
513
|
# final logs.
|
435
514
|
# @return [void]
|
436
515
|
def run
|
437
516
|
# Get YARD ready
|
438
517
|
YARD::Registry.load!
|
439
518
|
|
440
|
-
# Populate the
|
519
|
+
# Populate the type information file
|
441
520
|
populate
|
442
521
|
|
443
522
|
if object_count.zero?
|
@@ -451,9 +530,9 @@ module Sord
|
|
451
530
|
Logging.hooks.clear
|
452
531
|
|
453
532
|
unless warnings.empty?
|
454
|
-
Logging.warn("There were #{warnings.length} important warnings in the
|
533
|
+
Logging.warn("There were #{warnings.length} important warnings in the output file, listed below.")
|
455
534
|
if @replace_errors_with_untyped
|
456
|
-
Logging.warn("The types which caused them have been replaced with
|
535
|
+
Logging.warn("The types which caused them have been replaced with untyped.")
|
457
536
|
else
|
458
537
|
Logging.warn("The types which caused them have been replaced with SORD_ERROR_ constants.")
|
459
538
|
end
|