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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +46 -0
- data/CHANGELOG.md +77 -22
- data/README.md +2 -0
- data/ci/check_rbi.sh +9 -0
- data/lib/parlour/rbi_generator/class_namespace.rb +4 -2
- data/lib/parlour/rbi_generator/enum_class_namespace.rb +4 -2
- data/lib/parlour/rbi_generator/module_namespace.rb +19 -7
- data/lib/parlour/rbi_generator/namespace.rb +46 -23
- data/lib/parlour/rbi_generator/parameter.rb +3 -3
- data/lib/parlour/rbi_generator/struct_class_namespace.rb +4 -2
- data/lib/parlour/rbi_generator/struct_prop.rb +2 -2
- data/lib/parlour/rbs_generator/method.rb +1 -1
- data/lib/parlour/type_parser.rb +29 -11
- data/lib/parlour/typed_object.rb +2 -2
- data/lib/parlour/types.rb +50 -11
- data/lib/parlour/version.rb +1 -1
- data/parlour.gemspec +2 -1
- metadata +21 -7
- data/.travis.yml +0 -28
- data/rbi/parlour.rbi +0 -1856
@@ -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]
|
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
|
data/lib/parlour/type_parser.rb
CHANGED
@@ -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
|
-
|
753
|
-
|
754
|
-
|
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]
|
data/lib/parlour/typed_object.rb
CHANGED
@@ -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
|
-
"
|
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
|
-
'
|
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
|
-
'
|
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
|
-
'
|
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
|
-
'
|
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
|
-
'
|
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
|
+
|
data/lib/parlour/version.rb
CHANGED
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:
|
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:
|
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:
|
243
|
+
version: '0'
|
230
244
|
requirements: []
|
231
|
-
rubygems_version: 3.0.
|
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
|