parlour 5.0.0.beta.4 → 6.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.
@@ -39,7 +39,7 @@ module Parlour
39
39
  @name = name
40
40
 
41
41
  prefix = /^(\*\*|\*|\&)?/.match(name)&.captures&.first || ''
42
- @kind = PREFIXES.rassoc(prefix).first
42
+ @kind = T.must(PREFIXES.rassoc(prefix)).first
43
43
 
44
44
  @kind = :keyword if kind == :normal && name.end_with?(':')
45
45
 
@@ -123,12 +123,12 @@ module Parlour
123
123
  end
124
124
 
125
125
  # A mapping of {kind} values to the characteristic prefixes each kind has.
126
- PREFIXES = {
126
+ PREFIXES = T.let({
127
127
  normal: '',
128
128
  splat: '*',
129
129
  double_splat: '**',
130
130
  block: '&'
131
- }.freeze
131
+ }.freeze, T::Hash[Symbol, String])
132
132
 
133
133
  sig { void }
134
134
  def generalize_from_rbi!
@@ -11,6 +11,7 @@ module Parlour
11
11
  generator: Generator,
12
12
  name: String,
13
13
  final: T::Boolean,
14
+ sealed: T::Boolean,
14
15
  props: T::Array[StructProp],
15
16
  abstract: T::Boolean,
16
17
  block: T.nilable(T.proc.params(x: StructClassNamespace).void)
@@ -22,12 +23,13 @@ module Parlour
22
23
  # @param generator [RbiGenerator] The current RbiGenerator.
23
24
  # @param name [String] The name of this class.
24
25
  # @param final [Boolean] Whether this namespace is final.
26
+ # @param sealed [Boolean] Whether this namespace is sealed.
25
27
  # @param props [Array<StructProp>] The props of the struct.
26
28
  # @param abstract [Boolean] A boolean indicating whether this class is abstract.
27
29
  # @param block A block which the new instance yields itself to.
28
30
  # @return [void]
29
- def initialize(generator, name, final, props, abstract, &block)
30
- super(generator, name, final, 'T::Struct', abstract, &block)
31
+ def initialize(generator, name, final, sealed, props, abstract, &block)
32
+ super(generator, name, final, sealed, 'T::Struct', abstract, &block)
31
33
  @props = props
32
34
  end
33
35
 
@@ -112,9 +112,9 @@ module Parlour
112
112
  attr_reader :redaction
113
113
 
114
114
  # The optional properties available on instances of this class.
115
- EXTRA_PROPERTIES = %i{
115
+ EXTRA_PROPERTIES = T.let(%i{
116
116
  optional enum dont_store foreign default factory immutable array override redaction
117
- }
117
+ }, T::Array[Symbol])
118
118
 
119
119
  sig { returns(String) }
120
120
  # Returns the +prop+ call required to create this property.
@@ -89,7 +89,7 @@ module Parlour
89
89
 
90
90
  # Merge the first signature line, and indent & concat the rest
91
91
  first_line, *rest_lines = *partial_sig_lines
92
- this_sig_lines[0] += first_line
92
+ this_sig_lines[0] = T.unsafe(this_sig_lines[0]) + first_line
93
93
  rest_lines&.each do |line|
94
94
  this_sig_lines << ' ' * definition.length + options.indented(indent_level, line)
95
95
  end
@@ -158,6 +158,7 @@ module Parlour
158
158
 
159
159
  name, superclass, body = *node
160
160
  final = body_has_modifier?(body, :final!)
161
+ sealed = body_has_modifier?(body, :sealed!)
161
162
  abstract = body_has_modifier?(body, :abstract!)
162
163
  includes, extends = body ? body_includes_and_extends(body) : [[], []]
163
164
 
@@ -170,6 +171,7 @@ module Parlour
170
171
  generator,
171
172
  n.to_s,
172
173
  false,
174
+ false,
173
175
  )
174
176
  target.children << new_obj if target
175
177
  target = new_obj
@@ -233,6 +235,7 @@ module Parlour
233
235
  generator,
234
236
  this_name.to_s,
235
237
  final,
238
+ sealed,
236
239
  props,
237
240
  abstract,
238
241
  )
@@ -256,6 +259,7 @@ module Parlour
256
259
  generator,
257
260
  this_name.to_s,
258
261
  final,
262
+ sealed,
259
263
  enums,
260
264
  abstract,
261
265
  )
@@ -264,6 +268,7 @@ module Parlour
264
268
  generator,
265
269
  this_name.to_s,
266
270
  final,
271
+ sealed,
267
272
  node_to_s(superclass),
268
273
  abstract,
269
274
  )
@@ -275,7 +280,7 @@ module Parlour
275
280
 
276
281
  if target
277
282
  target.children << final_obj
278
- [top_level]
283
+ [T.must(top_level)]
279
284
  else
280
285
  [final_obj]
281
286
  end
@@ -283,7 +288,9 @@ module Parlour
283
288
  parse_err 'cannot declare modules in an eigenclass', node if is_within_eigenclass
284
289
 
285
290
  name, body = *node
291
+ abstract = body_has_modifier?(body, :abstract!)
286
292
  final = body_has_modifier?(body, :final!)
293
+ sealed = body_has_modifier?(body, :sealed!)
287
294
  interface = body_has_modifier?(body, :interface!)
288
295
  includes, extends = body ? body_includes_and_extends(body) : [[], []]
289
296
 
@@ -296,6 +303,7 @@ module Parlour
296
303
  generator,
297
304
  n.to_s,
298
305
  false,
306
+ false,
299
307
  )
300
308
  target.children << new_obj if target
301
309
  target = new_obj
@@ -306,7 +314,9 @@ module Parlour
306
314
  generator,
307
315
  this_name.to_s,
308
316
  final,
317
+ sealed,
309
318
  interface,
319
+ abstract,
310
320
  ) do |m|
311
321
  m.children.concat(parse_path_to_object(path.child(1))) if body
312
322
  m.create_includes(includes)
@@ -315,7 +325,7 @@ module Parlour
315
325
 
316
326
  if target
317
327
  target.children << final_obj
318
- [top_level]
328
+ [T.must(top_level)]
319
329
  else
320
330
  [final_obj]
321
331
  end
@@ -721,7 +731,7 @@ module Parlour
721
731
  end
722
732
 
723
733
  sig { params(node: Parser::AST::Node).returns(Types::Type) }
724
- # Given an AST node representing an RBI type (such as 'T::Array[String]'),
734
+ # Given an AST node representing an RBI type (such as 'T::Array[String]'),
725
735
  # parses it into a generic type.
726
736
  #
727
737
  # @param [Parser::AST::Node] node
@@ -736,9 +746,9 @@ module Parlour
736
746
  names = constant_names(target)
737
747
  known_single_element_collections = [:Array, :Set, :Range, :Enumerator, :Enumerable]
738
748
 
739
- if names.length == 2 && names[0] == :T &&
749
+ if names.length == 2 && names[0] == :T &&
740
750
  known_single_element_collections.include?(names[1])
741
-
751
+
742
752
  parse_err "no type in T::#{names[1]}[...]", node if args.nil? || args.empty?
743
753
  parse_err "too many types in T::#{names[1]}[...]", node unless args.length == 1
744
754
  return T.must(Types.const_get(T.must(names[1]))).new(parse_node_to_type(T.must(args.first)))
@@ -749,9 +759,17 @@ module Parlour
749
759
  parse_node_to_type(args[0]), parse_node_to_type(args[1])
750
760
  )
751
761
  else
752
- # TODO
753
- warning "user-defined generic types not implemented, treating #{names.last} as untyped", node
754
- return Types::Untyped.new
762
+ type = names.join('::')
763
+ if args.nil?
764
+ parse_err(
765
+ "user defined generic '#{type}' requires at least one type parameter",
766
+ node
767
+ )
768
+ end
769
+ return Types::Generic.new(
770
+ type,
771
+ args.map { |arg| parse_node_to_type(arg) }
772
+ )
755
773
  end
756
774
  end
757
775
 
@@ -760,7 +778,7 @@ module Parlour
760
778
  # something pretty cursed with procs to break this
761
779
  # This checks for (send (send (send (const nil :T) :proc) ...) ...)
762
780
  # That's the right amount of nesting for T.proc.params(...).returns(...)
763
- if node.to_a[0].type == :send &&
781
+ if node.to_a[0].type == :send &&
764
782
  node.to_a[0].to_a[0].type == :send &&
765
783
  node.to_a[0].to_a[0].to_a[1] == :proc &&
766
784
  node.to_a[0].to_a[0].to_a[0].type == :const &&
@@ -797,7 +815,7 @@ module Parlour
797
815
  # The other options for a valid call are all "T.something" methods
798
816
  parse_err "unexpected call #{node_to_s(node).inspect} in type", node \
799
817
  unless target.type == :const && target.to_a == [nil, :T]
800
-
818
+
801
819
  case message
802
820
  when :nilable
803
821
  parse_err 'no argument to T.nilable', node if args.nil? || args.empty?
@@ -828,7 +846,7 @@ module Parlour
828
846
  else
829
847
  warning "unknown method T.#{message}, treating as untyped", node
830
848
  Types::Untyped.new
831
- end
849
+ end
832
850
  when :const
833
851
  # Special case: T::Boolean
834
852
  if constant_names(node) == [:T, :Boolean]
@@ -20,7 +20,7 @@ module Parlour
20
20
  # @return [Plugin, nil]
21
21
  attr_reader :generated_by
22
22
 
23
- sig { returns(String) }
23
+ sig { returns(String).checked(:never) }
24
24
  # The name of this object.
25
25
  # @return [String]
26
26
  attr_reader :name
@@ -84,4 +84,4 @@ module Parlour
84
84
  : []
85
85
  end
86
86
  end
87
- end
87
+ end
data/lib/parlour/types.rb CHANGED
@@ -196,6 +196,45 @@ module Parlour
196
196
  end
197
197
  end
198
198
 
199
+ # A user-defined generic class with an arbitrary number of type
200
+ # parameters. This class assumes at least one type_param is
201
+ # provided, otherwise output will have empty type param lists.
202
+ class Generic < Type
203
+ sig { params(type: TypeLike, type_params: T::Array[TypeLike]).void }
204
+ def initialize(type, type_params)
205
+ @type = to_type(type)
206
+ @type_params = type_params.map { |p| to_type(p) }
207
+ end
208
+
209
+ sig { params(other: Object).returns(T::Boolean) }
210
+ def ==(other)
211
+ self.class === other &&
212
+ type == other.type &&
213
+ type_params == other.type_params
214
+ end
215
+
216
+ sig { returns(Type) }
217
+ attr_reader :type
218
+
219
+ sig { returns(T::Array[Type]) }
220
+ attr_reader :type_params
221
+
222
+ sig { override.returns(String) }
223
+ def generate_rbi
224
+ "#{type.generate_rbi}[#{type_params.map(&:generate_rbi).join(', ')}]"
225
+ end
226
+
227
+ sig { override.returns(String) }
228
+ def generate_rbs
229
+ "#{type.generate_rbs}[#{type_params.map(&:generate_rbs).join(', ')}]"
230
+ end
231
+
232
+ sig { override.returns(String) }
233
+ def describe
234
+ "#{type.describe}<#{type_params.map(&:describe).join(', ')}>"
235
+ end
236
+ end
237
+
199
238
  class SingleElementCollection < Type
200
239
  abstract!
201
240
 
@@ -217,7 +256,7 @@ module Parlour
217
256
 
218
257
  sig { override.returns(String) }
219
258
  def generate_rbs
220
- "#{collection_name}[#{element.generate_rbs}]"
259
+ "::#{collection_name}[#{element.generate_rbs}]"
221
260
  end
222
261
 
223
262
  sig { override.returns(String) }
@@ -230,7 +269,7 @@ module Parlour
230
269
  class Array < SingleElementCollection
231
270
  sig { override.returns(String) }
232
271
  def collection_name
233
- '::Array'
272
+ 'Array'
234
273
  end
235
274
 
236
275
  sig { params(other: Object).returns(T::Boolean) }
@@ -243,7 +282,7 @@ module Parlour
243
282
  class Set < SingleElementCollection
244
283
  sig { override.returns(String) }
245
284
  def collection_name
246
- '::Set'
285
+ 'Set'
247
286
  end
248
287
 
249
288
  sig { params(other: Object).returns(T::Boolean) }
@@ -256,7 +295,7 @@ module Parlour
256
295
  class Range < SingleElementCollection
257
296
  sig { override.returns(String) }
258
297
  def collection_name
259
- '::Range'
298
+ 'Range'
260
299
  end
261
300
 
262
301
  sig { params(other: Object).returns(T::Boolean) }
@@ -269,7 +308,7 @@ module Parlour
269
308
  class Enumerable < SingleElementCollection
270
309
  sig { override.returns(String) }
271
310
  def collection_name
272
- '::Enumerable'
311
+ 'Enumerable'
273
312
  end
274
313
 
275
314
  sig { params(other: Object).returns(T::Boolean) }
@@ -282,7 +321,7 @@ module Parlour
282
321
  class Enumerator < SingleElementCollection
283
322
  sig { override.returns(String) }
284
323
  def collection_name
285
- '::Enumerator'
324
+ 'Enumerator'
286
325
  end
287
326
 
288
327
  sig { params(other: Object).returns(T::Boolean) }
@@ -436,9 +475,9 @@ module Parlour
436
475
  def describe
437
476
  "self"
438
477
  end
439
- end
478
+ end
440
479
 
441
- # The explicit lack of a type.
480
+ # The explicit lack of a type.
442
481
  class Untyped < Type
443
482
  sig { params(other: Object).returns(T::Boolean) }
444
483
  def ==(other)
@@ -487,9 +526,9 @@ module Parlour
487
526
  def ==(other)
488
527
  Parameter === other && name == other.name && type == other.type &&
489
528
  default == other.default
490
- end
529
+ end
491
530
  end
492
-
531
+
493
532
  sig { params(parameters: T::Array[Parameter], return_type: T.nilable(TypeLike)).void }
494
533
  def initialize(parameters, return_type)
495
534
  @parameters = parameters
@@ -536,4 +575,4 @@ module Parlour
536
575
  end
537
576
  end
538
577
  end
539
-
578
+
@@ -1,5 +1,5 @@
1
1
  # typed: strong
2
2
  module Parlour
3
3
  # The library version.
4
- VERSION = '5.0.0.beta.4'
4
+ VERSION = '6.0.1'
5
5
  end
data/parlour.gemspec CHANGED
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
16
16
  # Specify which files should be added to the gem when it is released.
17
17
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
18
18
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
19
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|sorbet)/}) }
19
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features|sorbet|rbi)/}) }
20
20
  end
21
21
  spec.bindir = "exe"
22
22
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
@@ -32,4 +32,5 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency "rspec", "~> 3.0"
33
33
  spec.add_development_dependency "sorbet"
34
34
  spec.add_development_dependency "simplecov"
35
+ spec.add_development_dependency "yard"
35
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parlour
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0.beta.4
4
+ version: 6.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aaron Christiansen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-22 00:00:00.000000000 Z
11
+ date: 2021-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sorbet-runtime
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: yard
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
139
153
  description:
140
154
  email:
141
155
  - hello@aaronc.cc
@@ -146,16 +160,17 @@ extra_rdoc_files: []
146
160
  files:
147
161
  - ".github/ISSUE_TEMPLATE/bug-report.md"
148
162
  - ".github/ISSUE_TEMPLATE/feature-request.md"
163
+ - ".github/workflows/ruby.yml"
149
164
  - ".gitignore"
150
165
  - ".parlour"
151
166
  - ".rspec"
152
- - ".travis.yml"
153
167
  - CHANGELOG.md
154
168
  - CODE_OF_CONDUCT.md
155
169
  - Gemfile
156
170
  - LICENSE.txt
157
171
  - README.md
158
172
  - Rakefile
173
+ - ci/check_rbi.sh
159
174
  - exe/parlour
160
175
  - lib/parlour.rb
161
176
  - lib/parlour/conflict_resolver.rb
@@ -208,7 +223,6 @@ files:
208
223
  - lib/parlour/version.rb
209
224
  - parlour.gemspec
210
225
  - plugin_examples/foobar_plugin.rb
211
- - rbi/parlour.rbi
212
226
  homepage: https://github.com/AaronC81/parlour
213
227
  licenses:
214
228
  - MIT
@@ -224,11 +238,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
224
238
  version: '0'
225
239
  required_rubygems_version: !ruby/object:Gem::Requirement
226
240
  requirements:
227
- - - ">"
241
+ - - ">="
228
242
  - !ruby/object:Gem::Version
229
- version: 1.3.1
243
+ version: '0'
230
244
  requirements: []
231
- rubygems_version: 3.0.3
245
+ rubygems_version: 3.2.0.rc.1
232
246
  signing_key:
233
247
  specification_version: 4
234
248
  summary: A type information generator, merger and parser for Sorbet and Ruby 3/Steep