sord 2.0.0 → 3.0.0.beta.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 +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
|