parlour 2.0.0 → 2.1.0
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/.travis.yml +1 -0
- data/CHANGELOG.md +12 -0
- data/lib/parlour/rbi_generator/namespace.rb +19 -10
- data/lib/parlour/type_loader.rb +9 -2
- data/lib/parlour/type_parser.rb +38 -17
- data/lib/parlour/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 889d6730ffefc764887706e5dadc4441e66cdf32e4567e809f7e634f511b7dfc
|
4
|
+
data.tar.gz: 9e9ab14b6618c209c8d194bf6e5557398689f0656247cac9561064dbcd541a6a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea57b34b827ced92fdd1d28387217c0a5bc7027d94319cac6ffb238847a2820e9c164df86c9b2c43e60826cb1b362000c7c2bfc7f1f63b9b998959c70a3be377
|
7
|
+
data.tar.gz: fb10c8c783aea69e412d1a6eb67dd736f3db377168a21f8025e28fdb76acfc94ed20f1f7b9a17dafbac39ebcc2d36846b350d04c3e59882b546143df374b9f41
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -3,6 +3,18 @@ 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
|
+
## [2.1.0] - 2020-03-22
|
7
|
+
### Added
|
8
|
+
- Files can now be excluded from the `TypeLoader`.
|
9
|
+
|
10
|
+
### Changed
|
11
|
+
- A block argument in the definition but not in the signature no longer causes
|
12
|
+
an error in the `TypeParser`.
|
13
|
+
- Sorting of namespace children is now a stable sort.
|
14
|
+
|
15
|
+
### Fixed
|
16
|
+
- Type parameters are now parsed by the `TypeParser`.
|
17
|
+
|
6
18
|
## [2.0.0] - 2020-02-10
|
7
19
|
### Added
|
8
20
|
- Parlour can now load types back out of RBI files or Ruby source files by
|
@@ -247,13 +247,13 @@ module Parlour
|
|
247
247
|
#
|
248
248
|
# @param name [String] The name of this method. You should not specify +self.+ in
|
249
249
|
# this - use the +class_method+ parameter instead.
|
250
|
-
# @param parameters [Array<Parameter>] An array of {Parameter} instances representing this
|
250
|
+
# @param parameters [Array<Parameter>] An array of {Parameter} instances representing this
|
251
251
|
# method's parameters.
|
252
252
|
# @param return_type [String, nil] A Sorbet string of what this method returns, such as
|
253
253
|
# +"String"+ or +"T.untyped"+. Passing nil denotes a void return.
|
254
254
|
# @param returns [String, nil] Same as return_type.
|
255
255
|
# @param abstract [Boolean] Whether this method is abstract.
|
256
|
-
# @param implementation [Boolean] DEPRECATED: Whether this method is an
|
256
|
+
# @param implementation [Boolean] DEPRECATED: Whether this method is an
|
257
257
|
# implementation of a parent abstract method.
|
258
258
|
# @param override [Boolean] Whether this method is overriding a parent overridable
|
259
259
|
# method, or implementing a parent abstract method.
|
@@ -544,25 +544,25 @@ module Parlour
|
|
544
544
|
# can be merged into each other, as they lack definitions for themselves,
|
545
545
|
# so there is nothing to conflict. (This isn't the case for subclasses
|
546
546
|
# such as {ClassNamespace}.)
|
547
|
-
#
|
547
|
+
#
|
548
548
|
# @param others [Array<RbiGenerator::RbiObject>] An array of other {Namespace} instances.
|
549
549
|
# @return [true] Always true.
|
550
550
|
def mergeable?(others)
|
551
551
|
true
|
552
552
|
end
|
553
553
|
|
554
|
-
sig do
|
554
|
+
sig do
|
555
555
|
override.overridable.params(
|
556
556
|
others: T::Array[RbiGenerator::RbiObject]
|
557
557
|
).void
|
558
558
|
end
|
559
559
|
# Given an array of {Namespace} instances, merges them into this one.
|
560
|
-
# All children, constants, extends and includes are copied into this
|
560
|
+
# All children, constants, extends and includes are copied into this
|
561
561
|
# instance.
|
562
562
|
#
|
563
563
|
# There may also be {RbiGenerator::Method} instances in the stream, which
|
564
564
|
# are ignored.
|
565
|
-
#
|
565
|
+
#
|
566
566
|
# @param others [Array<RbiGenerator::RbiObject>] An array of other {Namespace} instances.
|
567
567
|
# @return [void]
|
568
568
|
def merge_into_self(others)
|
@@ -616,10 +616,19 @@ module Parlour
|
|
616
616
|
end
|
617
617
|
|
618
618
|
# Process singleton class attributes
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
619
|
+
sorted_children = (
|
620
|
+
if options.sort_namespaces
|
621
|
+
# sort_by can be unstable (and is in current MRI).
|
622
|
+
# Use the this work around to preserve order for ties
|
623
|
+
children.sort_by.with_index { |child, i| [child.name, i] }
|
624
|
+
else
|
625
|
+
children
|
626
|
+
end
|
627
|
+
)
|
628
|
+
class_attributes, remaining_children = sorted_children.partition do |child|
|
629
|
+
child.is_a?(Attribute) && child.class_attribute
|
630
|
+
end
|
631
|
+
|
623
632
|
if class_attributes.any?
|
624
633
|
result << options.indented(indent_level, 'class << self')
|
625
634
|
|
data/lib/parlour/type_loader.rb
CHANGED
@@ -30,7 +30,7 @@ module Parlour
|
|
30
30
|
load_source(File.read(filename), filename)
|
31
31
|
end
|
32
32
|
|
33
|
-
sig { params(root: String).returns(RbiGenerator::Namespace) }
|
33
|
+
sig { params(root: String, exclusions: T::Array[String]).returns(RbiGenerator::Namespace) }
|
34
34
|
# Loads an entire Sorbet project using Sorbet's file table, obeying any
|
35
35
|
# "typed: ignore" sigils, into a tree of objects.
|
36
36
|
#
|
@@ -39,8 +39,12 @@ module Parlour
|
|
39
39
|
#
|
40
40
|
# @param [String] root The root of the project; where the "sorbet" directory
|
41
41
|
# and "Gemfile" are located.
|
42
|
+
# @param [Array<String>] exclusions A list of files to exclude when loading
|
43
|
+
# the project, relative to the given root.
|
42
44
|
# @return [RbiGenerator::Namespace] The root of the object tree.
|
43
|
-
def self.load_project(root)
|
45
|
+
def self.load_project(root, exclusions: [])
|
46
|
+
expanded_exclusions = exclusions.map { |e| File.expand_path(e, root) }
|
47
|
+
|
44
48
|
stdin, stdout, stderr, wait_thr = T.unsafe(Open3).popen3(
|
45
49
|
'bundle exec srb tc -p file-table-json',
|
46
50
|
chdir: root
|
@@ -58,6 +62,9 @@ module Parlour
|
|
58
62
|
next if rel_path.start_with?('./sorbet/rbi/hidden-definitions/')
|
59
63
|
path = File.expand_path(rel_path, root)
|
60
64
|
|
65
|
+
# Skip this file if it was excluded
|
66
|
+
next if expanded_exclusions.include?(path)
|
67
|
+
|
61
68
|
# There are some entries which are URLs to stdlib
|
62
69
|
next unless File.exist?(path)
|
63
70
|
|
data/lib/parlour/type_parser.rb
CHANGED
@@ -107,7 +107,7 @@ module Parlour
|
|
107
107
|
def self.from_source(filename, source)
|
108
108
|
buffer = Parser::Source::Buffer.new(filename)
|
109
109
|
buffer.source = source
|
110
|
-
|
110
|
+
|
111
111
|
TypeParser.new(Parser::CurrentRuby.new.parse(buffer))
|
112
112
|
end
|
113
113
|
|
@@ -117,7 +117,7 @@ module Parlour
|
|
117
117
|
|
118
118
|
sig { returns(T::Boolean) }
|
119
119
|
# @return [Boolean] Whether to raise an error if a node of an unknown kind
|
120
|
-
# is encountered.
|
120
|
+
# is encountered.
|
121
121
|
attr_reader :unknown_node_errors
|
122
122
|
|
123
123
|
# Parses the entire source file and returns the resulting root namespace.
|
@@ -134,7 +134,7 @@ module Parlour
|
|
134
134
|
# represents and returns it, recursing to any child namespaces and parsing
|
135
135
|
# any methods within.
|
136
136
|
#
|
137
|
-
# If the node directly represents several nodes, such as being a
|
137
|
+
# If the node directly represents several nodes, such as being a
|
138
138
|
# (begin ...) node, they are all returned.
|
139
139
|
#
|
140
140
|
# @param [NodePath] path The path to the namespace definition. Do not pass
|
@@ -144,7 +144,7 @@ module Parlour
|
|
144
144
|
sig { params(path: NodePath, is_within_eigenclass: T::Boolean).returns(T::Array[RbiGenerator::RbiObject]) }
|
145
145
|
def parse_path_to_object(path, is_within_eigenclass: false)
|
146
146
|
node = path.traverse(ast)
|
147
|
-
|
147
|
+
|
148
148
|
case node.type
|
149
149
|
when :class
|
150
150
|
parse_err 'cannot declare classes in an eigenclass', node if is_within_eigenclass
|
@@ -158,7 +158,7 @@ module Parlour
|
|
158
158
|
*parent_names, this_name = constant_names(name)
|
159
159
|
target = T.let(nil, T.nilable(RbiGenerator::Namespace))
|
160
160
|
top_level = T.let(nil, T.nilable(RbiGenerator::Namespace))
|
161
|
-
parent_names.each do |n|
|
161
|
+
parent_names.each do |n|
|
162
162
|
new_obj = RbiGenerator::Namespace.new(
|
163
163
|
DetachedRbiGenerator.new,
|
164
164
|
n.to_s,
|
@@ -199,7 +199,7 @@ module Parlour
|
|
199
199
|
*parent_names, this_name = constant_names(name)
|
200
200
|
target = T.let(nil, T.nilable(RbiGenerator::Namespace))
|
201
201
|
top_level = T.let(nil, T.nilable(RbiGenerator::Namespace))
|
202
|
-
parent_names.each do |n|
|
202
|
+
parent_names.each do |n|
|
203
203
|
new_obj = RbiGenerator::Namespace.new(
|
204
204
|
DetachedRbiGenerator.new,
|
205
205
|
n.to_s,
|
@@ -236,7 +236,7 @@ module Parlour
|
|
236
236
|
when :def, :defs
|
237
237
|
# TODO: Support for defs without sigs
|
238
238
|
# If so, we need some kind of state machine to determine whether
|
239
|
-
# they've already been dealt with by the "when :send" clause and
|
239
|
+
# they've already been dealt with by the "when :send" clause and
|
240
240
|
# #parse_sig_into_methods.
|
241
241
|
# If not, just ignore this.
|
242
242
|
[]
|
@@ -246,7 +246,7 @@ module Parlour
|
|
246
246
|
when :begin
|
247
247
|
# Just map over all the things
|
248
248
|
node.to_a.length.times.map do |c|
|
249
|
-
parse_path_to_object(path.child(c), is_within_eigenclass: is_within_eigenclass)
|
249
|
+
parse_path_to_object(path.child(c), is_within_eigenclass: is_within_eigenclass)
|
250
250
|
end.flatten
|
251
251
|
else
|
252
252
|
if unknown_node_errors
|
@@ -259,6 +259,7 @@ module Parlour
|
|
259
259
|
|
260
260
|
# A parsed sig, not associated with a method.
|
261
261
|
class IntermediateSig < T::Struct
|
262
|
+
prop :type_parameters, T.nilable(T::Array[Symbol])
|
262
263
|
prop :overridable, T::Boolean
|
263
264
|
prop :override, T::Boolean
|
264
265
|
prop :abstract, T::Boolean
|
@@ -318,7 +319,18 @@ module Parlour
|
|
318
319
|
arg.to_a
|
319
320
|
end
|
320
321
|
|
322
|
+
# Find type parameters if they were used
|
323
|
+
type_parameters = sig_chain
|
324
|
+
.find { |(n, _)| n == :type_parameters }
|
325
|
+
&.then do |(_, a)|
|
326
|
+
a.map do |arg|
|
327
|
+
parse_err 'type parameter must be a symbol', arg if arg.type != :sym
|
328
|
+
arg.to_a[0]
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
321
332
|
IntermediateSig.new(
|
333
|
+
type_parameters: type_parameters,
|
322
334
|
overridable: overridable,
|
323
335
|
override: override,
|
324
336
|
abstract: abstract,
|
@@ -370,7 +382,7 @@ module Parlour
|
|
370
382
|
|| target != nil
|
371
383
|
|
372
384
|
parse_err 'typed attribute should have at least one name', def_node if parameters&.length == 0
|
373
|
-
|
385
|
+
|
374
386
|
kind = :attr
|
375
387
|
attr_direction = method_name.to_s.gsub('attr_', '').to_sym
|
376
388
|
def_names = T.must(parameters).map { |param| param.to_a[0].to_s }
|
@@ -389,6 +401,13 @@ module Parlour
|
|
389
401
|
return_type = this_sig.return_type
|
390
402
|
|
391
403
|
if kind == :def
|
404
|
+
# Sorbet allows a trailing blockarg that's not in the sig
|
405
|
+
if params &&
|
406
|
+
def_params.length == params.length + 1 &&
|
407
|
+
def_params[-1].type == :blockarg
|
408
|
+
def_params = def_params[0...-1]
|
409
|
+
end
|
410
|
+
|
392
411
|
parse_err 'mismatching number of arguments in sig and def', sig_block_node \
|
393
412
|
if params && def_params.length != params.length
|
394
413
|
|
@@ -399,6 +418,7 @@ module Parlour
|
|
399
418
|
parameters = params \
|
400
419
|
? zip_by(params, ->x{ x.to_a[0].to_a[0] }, def_params, ->x{ x.to_a[0] })
|
401
420
|
.map do |sig_arg, def_param|
|
421
|
+
|
402
422
|
arg_name = def_param.to_a[0]
|
403
423
|
|
404
424
|
# TODO: anonymous restarg
|
@@ -422,6 +442,7 @@ module Parlour
|
|
422
442
|
def_name,
|
423
443
|
parameters,
|
424
444
|
return_type,
|
445
|
+
type_parameters: this_sig.type_parameters,
|
425
446
|
override: this_sig.override,
|
426
447
|
overridable: this_sig.overridable,
|
427
448
|
abstract: this_sig.abstract,
|
@@ -437,7 +458,7 @@ module Parlour
|
|
437
458
|
|
438
459
|
parse_err "attr_#{attr_direction} sig should have non-void return", sig_block_node \
|
439
460
|
unless return_type
|
440
|
-
|
461
|
+
|
441
462
|
attr_type = return_type
|
442
463
|
when :writer
|
443
464
|
# These are special and can only have one name
|
@@ -476,7 +497,7 @@ module Parlour
|
|
476
497
|
# A::B::C), converts that node into an array of the constant names which
|
477
498
|
# are accessed. For example, A::B::C would become [:A, :B, :C].
|
478
499
|
#
|
479
|
-
# @param [Parser::AST::Node, nil] node The node to convert. This must
|
500
|
+
# @param [Parser::AST::Node, nil] node The node to convert. This must
|
480
501
|
# consist only of nested (:const) nodes.
|
481
502
|
# @return [Array<Symbol>] The chain of constant names.
|
482
503
|
def constant_names(node)
|
@@ -524,13 +545,13 @@ module Parlour
|
|
524
545
|
def body_has_modifier?(node, modifier)
|
525
546
|
return false unless node
|
526
547
|
|
527
|
-
(node.type == :send && node.to_a == [nil, modifier]) ||
|
548
|
+
(node.type == :send && node.to_a == [nil, modifier]) ||
|
528
549
|
(node.type == :begin &&
|
529
550
|
node.to_a.any? { |c| c.type == :send && c.to_a == [nil, modifier] })
|
530
551
|
end
|
531
552
|
|
532
553
|
sig { params(node: Parser::AST::Node).returns([T::Array[String], T::Array[String]]) }
|
533
|
-
# Given an AST node representing the body of a class or module, returns two
|
554
|
+
# Given an AST node representing the body of a class or module, returns two
|
534
555
|
# arrays of the includes and extends contained within the body.
|
535
556
|
#
|
536
557
|
# @param [Parser::AST::Node] node The body of the namespace.
|
@@ -568,7 +589,7 @@ module Parlour
|
|
568
589
|
raise ParseError.new(buffer, range), desc
|
569
590
|
end
|
570
591
|
|
571
|
-
sig do
|
592
|
+
sig do
|
572
593
|
type_parameters(:A, :B)
|
573
594
|
.params(
|
574
595
|
a: T::Array[T.type_parameter(:A)],
|
@@ -580,7 +601,7 @@ module Parlour
|
|
580
601
|
end
|
581
602
|
# Given two arrays and functions to get a key for each item in the two
|
582
603
|
# arrays, joins the two arrays into one array of pairs by that key.
|
583
|
-
#
|
604
|
+
#
|
584
605
|
# The arrays should both be the same length, and the key functions should
|
585
606
|
# never return duplicate keys for two different items.
|
586
607
|
#
|
@@ -588,7 +609,7 @@ module Parlour
|
|
588
609
|
# @param [A -> Any] fa A function to obtain a key for any element in the
|
589
610
|
# first array.
|
590
611
|
# @param [Array<B>] b The second array.
|
591
|
-
# @param [B -> Any] fb A function to obtain a key for any element in the
|
612
|
+
# @param [B -> Any] fb A function to obtain a key for any element in the
|
592
613
|
# second array.
|
593
614
|
# @return [Array<(A, B)>] An array of pairs, where the left of the pair is
|
594
615
|
# an element from A and the right is the element from B with the
|
@@ -606,4 +627,4 @@ module Parlour
|
|
606
627
|
end
|
607
628
|
end
|
608
629
|
end
|
609
|
-
end
|
630
|
+
end
|
data/lib/parlour/version.rb
CHANGED
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: 2.
|
4
|
+
version: 2.1.0
|
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-
|
11
|
+
date: 2020-03-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sorbet-runtime
|
@@ -201,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
201
201
|
- !ruby/object:Gem::Version
|
202
202
|
version: '0'
|
203
203
|
requirements: []
|
204
|
-
rubygems_version: 3.
|
204
|
+
rubygems_version: 3.0.3
|
205
205
|
signing_key:
|
206
206
|
specification_version: 4
|
207
207
|
summary: An RBI generator, merger and parser for Sorbet
|