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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 14900bd9ce64eda2373d0844e42032ea041b44dd10a6ca6a82bd66c31b2b0c9b
4
- data.tar.gz: 983e467e872f0e455da6ca618b2a2ffb159d81f6cc1456e8370e33ecd42179bf
3
+ metadata.gz: 6cfc03da2fe9815159c9041a5afff2a0e1e089567cb92da25bcec87137f9e747
4
+ data.tar.gz: acd6551c560c205199ec494930f4628c5357a34263b0cce05757033014ba929b
5
5
  SHA512:
6
- metadata.gz: 6a63ef228f6763653b2be68d46c16f20793118a67adec93d6cc2ec016ed9df254803e3b1fb1bc5c5b26a248020715ee72836c3b4fab6bb07e2d1223e685af97b
7
- data.tar.gz: b9a86b1af67cdfd6d73eb28f2b6b46d10b5e61418d2118693e2103da1d5e9d506c8046b069922b908d1d4ecd908abf832ad4a480868b6720650a386fb010d766
6
+ metadata.gz: a3ef67b5162e55af55f81fd056c0a1f232293c021b145fab2054cd482951c9cd22aa2e9f8874687131c65b209f2217488ce6808f9bd88da75a04928720452a34
7
+ data.tar.gz: 719461ac9a36dc5c636c4f1b79c22923da4e1decb25032ec8e0c6eef8df60454c3eba6d275c61f91fec9d637d200631d3c3003b1aff981d6bafac3c91323e323
File without changes
File without changes
data/.gitignore CHANGED
File without changes
data/.parlour CHANGED
@@ -1,7 +1,11 @@
1
- output_file: rbi/sord.rbi
1
+ parser: false
2
+
3
+ output_file:
4
+ rbi: rbi/sord.rbi
2
5
 
3
6
  requires:
4
7
  - sord
5
8
 
6
9
  plugins:
7
- Sord::ParlourPlugin: {}
10
+ Sord::ParlourPlugin:
11
+ rbi: yes
data/.rspec CHANGED
File without changes
File without changes
@@ -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`
File without changes
data/Gemfile CHANGED
File without changes
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}.rbi --no-sord-comments --replace-errors-with-untyped --replace-unresolved-with-untyped")
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}.rbi")
60
+ system("bundle exec sord ../#{name}.#{args[:mode]} #{mode_arg}")
52
61
  end
53
- puts "#{name}.rbi generated!"
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}.rbi --no-regenerate --no-sord-comments --replace-errors-with-untyped --replace-unresolved-with-untyped")
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}.rbi --no-regenerate")
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 an RBI file from this directory\'s YARD docs'
14
- c.option '--[no-]sord-comments', 'Controls informational/warning comments in the RBI file'
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 RBI'
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
- plugin.parlour = Parlour::RbiGenerator.new(break_params: plugin_options[:break_params])
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.rbi)
88
+ File.write(args.first, plugin.parlour.send(generator_method))
53
89
  end
54
90
  end
@@ -1,6 +1,6 @@
1
1
  # typed: strong
2
2
  require 'sord/version'
3
- require 'sord/rbi_generator'
3
+ require 'sord/generator'
4
4
  require 'sord/parlour_plugin'
5
5
  require 'yard'
6
6
  require 'sorbet-runtime'
@@ -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 RBI file.
10
- class RbiGenerator
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 RBI generator.
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::RbiGenerator] generator
29
- # @option options [Parlour::RbiGenerator::Namespace] root
32
+ # @option options [Parlour::Generator] generator
33
+ # @option options [Parlour::TypedObject] root
30
34
  # @return [void]
31
35
  def initialize(options)
32
- @parlour = options[:parlour] || Parlour::RbiGenerator.new
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 to the RBI file
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 RBI file. Returns the number of mixins.
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
- item.constants.each do |constant|
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
- @current_object.create_constant(constant_name, value: "T.let(#{constant.value}, T.untyped)") do |c|
95
- c.add_comments(constant.docstring.all.split("\n"))
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 RBI object based on a docstring.
128
+ # Adds comments to an object based on a docstring.
101
129
  # @param [YARD::CodeObjects::NamespaceObject] item
102
- # @param [Parlour::RbiGenerator::RbiObject] rbi_object
130
+ # @param [Parlour::TypedObject] typed_object
103
131
  # @return [void]
104
- def add_comments(item, rbi_object)
132
+ def add_comments(item, typed_object)
105
133
  if @keep_original_comments
106
- rbi_object.add_comments(item.docstring.all.split("\n"))
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
- rbi_object.add_comments(docs_array)
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 RBI file.
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. Sorbet will handle it automatically.
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.yard_to_sorbet(tag.types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
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
- params_string = yieldparams.map do |param|
234
- "#{param.name.gsub('*', '')}: #{TypeConverter.yard_to_sorbet(param.types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)}" unless param.name.nil?
235
- end.join(', ')
236
- return_string = TypeConverter.yard_to_sorbet(yieldreturn, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
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
- 'T.untyped'
241
- elsif yieldreturn.nil?
242
- "T.proc#{params_string.empty? ? '' : ".params(#{params_string})"}.void"
271
+ Parlour::Types::Untyped.new
243
272
  else
244
- "T.proc#{params_string.empty? ? '' : ".params(#{params_string})"}.returns(#{return_string})"
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.yard_to_sorbet(meth.tag('param').types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
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 T.untyped", meth)
260
- next 'T.untyped'
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 T.untyped", meth)
267
- next 'T.untyped'
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.yard_to_sorbet(
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.yard_to_sorbet(meth.tag('param').types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
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 T.untyped", meth)
285
- 'T.untyped'
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 T.untyped", meth)
295
- 'T.untyped'
296
- elsif return_tags.length == 1 && return_tags&.first&.types&.first&.downcase == "void"
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.yard_to_sorbet(meth.tag('return').types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
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 = "T.nilable(#{type})" \
309
- if default == 'nil' && !type.start_with?('T.nilable') && type != 'T.untyped'
310
- Parlour::RbiGenerator::Parameter.new(
311
- name.to_s,
312
- type: type,
313
- default: default
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
- @current_object.create_method(
318
- meth.name.to_s,
319
- parameters: parlour_params,
320
- returns: returns,
321
- class_method: meth.scope == :class
322
- ) do |m|
323
- add_comments(meth, m)
324
- end
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 RBI file.
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 T.untyped if not types specified anywhere, otherwise try to
357
- # compute Sorbet type given all these types
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 T.untyped", reader || writer)
360
- sorbet_type = 'T.untyped'
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
- sorbet_type = TypeConverter.yard_to_sorbet(
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
- @current_object.create_attribute(
376
- name.to_s,
377
- kind: kind,
378
- type: sorbet_type,
379
- class_attribute: (attr_loc == :class)
380
- ) do |m|
381
- add_comments(reader || writer, m)
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 RBI file.
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 RBI generator with the contents of the YARD registry. You
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 RBI generator with the contents of the YARD registry, then
425
- # uses the loaded Parlour::RbiGenerator to generate the RBI file. You must
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.rbi
509
+ @parlour.send(@mode)
431
510
  end
432
511
 
433
- # Loads the YARD registry, populates the RBI file, and prints any relevant
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 RBI
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 RBI file, listed below.")
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 T.untyped.")
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