rbs 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile +1 -0
- data/README.md +1 -1
- data/docs/syntax.md +14 -1
- data/lib/rbs/ast/members.rb +3 -8
- data/lib/rbs/cli.rb +62 -1
- data/lib/rbs/definition.rb +11 -3
- data/lib/rbs/definition_builder.rb +18 -12
- data/lib/rbs/environment.rb +0 -1
- data/lib/rbs/environment_loader.rb +55 -35
- data/lib/rbs/parser.y +2 -4
- data/lib/rbs/prototype/rb.rb +0 -1
- data/lib/rbs/prototype/rbi.rb +0 -2
- data/lib/rbs/prototype/runtime.rb +0 -4
- data/lib/rbs/test/setup.rb +5 -1
- data/lib/rbs/test/setup_helper.rb +15 -0
- data/lib/rbs/test/tester.rb +7 -5
- data/lib/rbs/test/type_check.rb +14 -2
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/writer.rb +1 -2
- data/stdlib/builtin/array.rbs +2 -1
- data/stdlib/builtin/hash.rbs +1 -1
- data/stdlib/date/date.rbs +1056 -0
- data/stdlib/date/date_time.rbs +582 -0
- data/stdlib/zlib/zlib.rbs +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe2c03d38ca9869e7c7bdf283f56e61e5ccbad3831b524ba14c6fd31941985e2
|
4
|
+
data.tar.gz: d9cc6563f7eb3173410209daeda05a8216d2ade261a3f05d3f258d0782a08e64
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb4391906260a8414e2c2ef44ded8fda974c495830fb6c2335204052cba67260f1f0d0fd44dd560c3c05b7cdcaffa20ee24d7d16a529c37f900689bb084ce198
|
7
|
+
data.tar.gz: 68cb88ea29edbce815a6887b716f20c640b651628b55b9b3e660e6bc93c218081464888632f9df7bc42da49700c253bc74fb9d01970f7bf13a2425742890431e
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 0.11.0 (2020-08-31)
|
6
|
+
|
7
|
+
* Signature update for `date/datetime` [#367](https://github.com/ruby/rbs/pull/367)
|
8
|
+
* Add test double support for runtime type checker [#380](https://github.com/ruby/rbs/pull/380)
|
9
|
+
* Add `rbs test` command for runtime type checking [#366](https://github.com/ruby/rbs/pull/366)
|
10
|
+
* Fix runtime type checking for record types [#365](https://github.com/ruby/rbs/pull/365)
|
11
|
+
* Improve EnvironmentLoader API [#370](https://github.com/ruby/rbs/pull/370)
|
12
|
+
* Allow overloading from super methods [#364](https://github.com/ruby/rbs/pull/364)
|
13
|
+
|
5
14
|
## 0.10.0 (2020-08-10)
|
6
15
|
|
7
16
|
* Signature update for `Zlib`
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -123,7 +123,7 @@ puts singleton.methods[:gsub]
|
|
123
123
|
|
124
124
|
## Development
|
125
125
|
|
126
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
126
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
127
127
|
|
128
128
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
129
129
|
|
data/docs/syntax.md
CHANGED
@@ -212,7 +212,7 @@ _method-type_ ::= `(` _parameters_ `) ->` _type_
|
|
212
212
|
|
213
213
|
_parameters_ ::= _required-positionals_ _optional-positionals_ _rest-positional_ _trailing-positionals_ _keywords_
|
214
214
|
|
215
|
-
|
215
|
+
_parameter_ ::= _type_ _var-name_ # Parameter with var name
|
216
216
|
| _type_ # Parameter without var name
|
217
217
|
_required-positionals_ ::= _parameter_ `,` ...
|
218
218
|
_optional-positionals_ ::= `?` _parameter_ `,` ...
|
@@ -529,3 +529,16 @@ You can declare a global variable.
|
|
529
529
|
$LOAD_PATH: Array[String]
|
530
530
|
```
|
531
531
|
|
532
|
+
### Comments
|
533
|
+
|
534
|
+
You can write single line comments. Comments must be on their own line. Comments can lead with whitespace.
|
535
|
+
|
536
|
+
```
|
537
|
+
# This if interface Foo
|
538
|
+
# Usage of Foo is bar
|
539
|
+
interface _Foo
|
540
|
+
# New foo is a method
|
541
|
+
# it will return foo.
|
542
|
+
def new: () -> Foo
|
543
|
+
end
|
544
|
+
```
|
data/lib/rbs/ast/members.rb
CHANGED
@@ -11,17 +11,15 @@ module RBS
|
|
11
11
|
attr_reader :annotations
|
12
12
|
attr_reader :location
|
13
13
|
attr_reader :comment
|
14
|
-
attr_reader :attributes
|
15
14
|
attr_reader :overload
|
16
15
|
|
17
|
-
def initialize(name:, kind:, types:, annotations:, location:, comment:,
|
16
|
+
def initialize(name:, kind:, types:, annotations:, location:, comment:, overload:)
|
18
17
|
@name = name
|
19
18
|
@kind = kind
|
20
19
|
@types = types
|
21
20
|
@annotations = annotations
|
22
21
|
@location = location
|
23
22
|
@comment = comment
|
24
|
-
@attributes = attributes
|
25
23
|
@overload = overload
|
26
24
|
end
|
27
25
|
|
@@ -30,14 +28,13 @@ module RBS
|
|
30
28
|
other.name == name &&
|
31
29
|
other.kind == kind &&
|
32
30
|
other.types == types &&
|
33
|
-
other.attributes == attributes &&
|
34
31
|
other.overload == overload
|
35
32
|
end
|
36
33
|
|
37
34
|
alias eql? ==
|
38
35
|
|
39
36
|
def hash
|
40
|
-
self.class.hash ^ name.hash ^ kind.hash ^ types.hash ^
|
37
|
+
self.class.hash ^ name.hash ^ kind.hash ^ types.hash ^ overload.hash
|
41
38
|
end
|
42
39
|
|
43
40
|
def instance?
|
@@ -52,7 +49,7 @@ module RBS
|
|
52
49
|
overload
|
53
50
|
end
|
54
51
|
|
55
|
-
def update(name: self.name, kind: self.kind, types: self.types, annotations: self.annotations, location: self.location, comment: self.comment,
|
52
|
+
def update(name: self.name, kind: self.kind, types: self.types, annotations: self.annotations, location: self.location, comment: self.comment, overload: self.overload)
|
56
53
|
self.class.new(
|
57
54
|
name: name,
|
58
55
|
kind: kind,
|
@@ -60,7 +57,6 @@ module RBS
|
|
60
57
|
annotations: annotations,
|
61
58
|
location: location,
|
62
59
|
comment: comment,
|
63
|
-
attributes: attributes,
|
64
60
|
overload: overload
|
65
61
|
)
|
66
62
|
end
|
@@ -73,7 +69,6 @@ module RBS
|
|
73
69
|
annotations: annotations,
|
74
70
|
location: location,
|
75
71
|
comment: comment,
|
76
|
-
attributes: attributes,
|
77
72
|
overload: overload
|
78
73
|
}.to_json(*a)
|
79
74
|
end
|
data/lib/rbs/cli.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "optparse"
|
2
|
+
require "shellwords"
|
2
3
|
|
3
4
|
module RBS
|
4
5
|
class CLI
|
@@ -36,7 +37,7 @@ module RBS
|
|
36
37
|
@stderr = stderr
|
37
38
|
end
|
38
39
|
|
39
|
-
COMMANDS = [:ast, :list, :ancestors, :methods, :method, :validate, :constant, :paths, :prototype, :vendor, :parse]
|
40
|
+
COMMANDS = [:ast, :list, :ancestors, :methods, :method, :validate, :constant, :paths, :prototype, :vendor, :parse, :test]
|
40
41
|
|
41
42
|
def library_parse(opts, options:)
|
42
43
|
opts.on("-r LIBRARY", "Load RBS files of the library") do |lib|
|
@@ -750,5 +751,65 @@ Examples:
|
|
750
751
|
TypeName.new(name: last, namespace: namespace.parent)
|
751
752
|
end
|
752
753
|
end
|
754
|
+
|
755
|
+
def test_opt options
|
756
|
+
opt_string = options.dirs.map { |dir| "-I #{Shellwords.escape(dir)}"}.concat(options.libs.map { |lib| "-r#{Shellwords.escape(lib)}"}).join(' ')
|
757
|
+
opt_string.empty? ? nil : opt_string
|
758
|
+
end
|
759
|
+
|
760
|
+
def run_test(args, options)
|
761
|
+
unchecked_classes = []
|
762
|
+
targets = []
|
763
|
+
sample_size = nil
|
764
|
+
double_suite = nil
|
765
|
+
|
766
|
+
(opts = OptionParser.new do |opts|
|
767
|
+
opts.banner = <<EOB
|
768
|
+
Usage: rbs [rbs options...] test [test options...] COMMAND
|
769
|
+
|
770
|
+
Examples:
|
771
|
+
|
772
|
+
$ rbs test rake test
|
773
|
+
$ rbs --log-level=debug test --target SomeModule::* rspec
|
774
|
+
$ rbs test --target SomeModule::* --target AnotherModule::* --target SomeClass rake test
|
775
|
+
|
776
|
+
Options:
|
777
|
+
EOB
|
778
|
+
opts.on("--target TARGET", "Sets the runtime test target") do |target|
|
779
|
+
targets << target
|
780
|
+
end
|
781
|
+
|
782
|
+
opts.on("--sample-size SAMPLE_SIZE", "Sets the sample size") do |size|
|
783
|
+
sample_size = size
|
784
|
+
end
|
785
|
+
|
786
|
+
opts.on("--unchecked-class UNCHECKED_CLASS", "Sets the class that would not be checked") do |unchecked_class|
|
787
|
+
unchecked_classes << unchecked_class
|
788
|
+
end
|
789
|
+
|
790
|
+
opts.on("--double-suite DOUBLE_SUITE", "Sets the double suite in use (currently supported: rspec | minitest)") do |suite|
|
791
|
+
double_suite = suite
|
792
|
+
end
|
793
|
+
|
794
|
+
end).order!(args)
|
795
|
+
|
796
|
+
if args.length.zero?
|
797
|
+
stdout.puts opts.help
|
798
|
+
exit 1
|
799
|
+
end
|
800
|
+
|
801
|
+
env_hash = {
|
802
|
+
'RUBYOPT' => "#{ENV['RUBYOPT']} -rrbs/test/setup",
|
803
|
+
'RBS_TEST_OPT' => test_opt(options),
|
804
|
+
'RBS_TEST_LOGLEVEL' => RBS.logger_level,
|
805
|
+
'RBS_TEST_SAMPLE_SIZE' => sample_size,
|
806
|
+
'RBS_TEST_DOUBLE_SUITE' => double_suite,
|
807
|
+
'RBS_TEST_UNCHECKED_CLASSES' => (unchecked_classes.join(',') unless unchecked_classes.empty?),
|
808
|
+
'RBS_TEST_TARGET' => (targets.join(',') unless targets.empty?)
|
809
|
+
}
|
810
|
+
|
811
|
+
system(env_hash, *args)
|
812
|
+
$?
|
813
|
+
end
|
753
814
|
end
|
754
815
|
end
|
data/lib/rbs/definition.rb
CHANGED
@@ -45,6 +45,15 @@ module RBS
|
|
45
45
|
def update(type: self.type, member: self.member, defined_in: self.defined_in, implemented_in: self.implemented_in)
|
46
46
|
TypeDef.new(type: type, member: member, defined_in: defined_in, implemented_in: implemented_in)
|
47
47
|
end
|
48
|
+
|
49
|
+
def overload?
|
50
|
+
case member
|
51
|
+
when AST::Members::MethodDefinition
|
52
|
+
member.overload?
|
53
|
+
else
|
54
|
+
false
|
55
|
+
end
|
56
|
+
end
|
48
57
|
end
|
49
58
|
|
50
59
|
attr_reader :super_method
|
@@ -79,9 +88,8 @@ module RBS
|
|
79
88
|
@annotations ||= @extra_annotations + defs.flat_map(&:annotations)
|
80
89
|
end
|
81
90
|
|
82
|
-
|
83
|
-
|
84
|
-
[]
|
91
|
+
def members
|
92
|
+
@members ||= defs.map(&:member).uniq
|
85
93
|
end
|
86
94
|
|
87
95
|
def public?
|
@@ -569,7 +569,7 @@ module RBS
|
|
569
569
|
member, visibility = array[0]
|
570
570
|
result[method_name] = [visibility, nil, member]
|
571
571
|
|
572
|
-
|
572
|
+
else
|
573
573
|
visibilities = array.group_by {|pair| pair[1] }
|
574
574
|
|
575
575
|
if visibilities.size > 1
|
@@ -583,14 +583,6 @@ module RBS
|
|
583
583
|
|
584
584
|
overloads, primary = array.map(&:first).partition(&:overload?)
|
585
585
|
result[method_name] = [array[0][1], nil, *primary, *overloads]
|
586
|
-
|
587
|
-
else
|
588
|
-
raise InvalidOverloadMethodError.new(
|
589
|
-
type_name: type_name,
|
590
|
-
method_name: method_name,
|
591
|
-
kind: :instance,
|
592
|
-
members: array.map(&:first)
|
593
|
-
)
|
594
586
|
end
|
595
587
|
end
|
596
588
|
end
|
@@ -973,8 +965,15 @@ module RBS
|
|
973
965
|
Substitution.build([], [])
|
974
966
|
end
|
975
967
|
|
968
|
+
kind = case ancestor
|
969
|
+
when Definition::Ancestor::Instance
|
970
|
+
:instance
|
971
|
+
when Definition::Ancestor::Singleton
|
972
|
+
:singleton
|
973
|
+
end
|
974
|
+
|
976
975
|
current_definition.methods.each do |name, method|
|
977
|
-
merge_method definition.methods, name, method, sub
|
976
|
+
merge_method type_name, definition.methods, name, method, sub, kind: kind
|
978
977
|
end
|
979
978
|
|
980
979
|
current_definition.instance_variables.each do |name, variable|
|
@@ -998,13 +997,20 @@ module RBS
|
|
998
997
|
)
|
999
998
|
end
|
1000
999
|
|
1001
|
-
def merge_method(methods, name, method, sub)
|
1000
|
+
def merge_method(type_name, methods, name, method, sub, kind:)
|
1002
1001
|
super_method = methods[name]
|
1003
1002
|
|
1003
|
+
defs = if method.defs.all? {|d| d.overload? }
|
1004
|
+
raise InvalidOverloadMethodError.new(type_name: type_name, method_name: name, kind: kind, members: method.members) unless super_method
|
1005
|
+
method.defs + super_method.defs
|
1006
|
+
else
|
1007
|
+
method.defs
|
1008
|
+
end
|
1009
|
+
|
1004
1010
|
methods[name] = Definition::Method.new(
|
1005
1011
|
super_method: super_method,
|
1006
1012
|
accessibility: method.accessibility,
|
1007
|
-
defs: sub.mapping.empty? ?
|
1013
|
+
defs: sub.mapping.empty? ? defs : defs.map {|defn| defn.update(type: defn.type.sub(sub)) }
|
1008
1014
|
)
|
1009
1015
|
end
|
1010
1016
|
|
data/lib/rbs/environment.rb
CHANGED
@@ -75,29 +75,16 @@ module RBS
|
|
75
75
|
self.class.gem_sig_path(name, version)
|
76
76
|
end
|
77
77
|
|
78
|
-
def each_signature(path
|
78
|
+
def each_signature(path, immediate: true, &block)
|
79
79
|
if block_given?
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
yield path
|
85
|
-
end
|
86
|
-
when path.directory?
|
87
|
-
path.children.each do |child|
|
88
|
-
each_signature child, immediate: false, &block
|
89
|
-
end
|
80
|
+
case
|
81
|
+
when path.file?
|
82
|
+
if path.extname == ".rbs" || immediate
|
83
|
+
yield path
|
90
84
|
end
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
when Pathname
|
95
|
-
each_signature path, immediate: immediate, &block
|
96
|
-
when LibraryPath
|
97
|
-
each_signature path.path, immediate: immediate, &block
|
98
|
-
when GemPath
|
99
|
-
each_signature path.path, immediate: immediate, &block
|
100
|
-
end
|
85
|
+
when path.directory?
|
86
|
+
path.children.each do |child|
|
87
|
+
each_signature child, immediate: false, &block
|
101
88
|
end
|
102
89
|
end
|
103
90
|
else
|
@@ -105,32 +92,65 @@ module RBS
|
|
105
92
|
end
|
106
93
|
end
|
107
94
|
|
108
|
-
def
|
109
|
-
|
95
|
+
def each_library_path
|
96
|
+
paths.each do |path|
|
97
|
+
case path
|
98
|
+
when Pathname
|
99
|
+
yield path, path
|
100
|
+
when LibraryPath
|
101
|
+
yield path, path.path
|
102
|
+
when GemPath
|
103
|
+
yield path, path.path
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def no_builtin!(skip = true)
|
109
|
+
@no_builtin = skip
|
110
|
+
self
|
110
111
|
end
|
111
112
|
|
112
113
|
def no_builtin?
|
113
114
|
@no_builtin
|
114
115
|
end
|
115
116
|
|
116
|
-
def
|
117
|
-
|
117
|
+
def each_decl
|
118
|
+
if block_given?
|
119
|
+
signature_files = []
|
118
120
|
|
119
|
-
|
120
|
-
|
121
|
-
|
121
|
+
unless no_builtin?
|
122
|
+
each_signature(stdlib_root + "builtin") do |path|
|
123
|
+
signature_files << [:stdlib, path]
|
124
|
+
end
|
125
|
+
end
|
122
126
|
|
123
|
-
|
124
|
-
|
127
|
+
each_library_path do |library_path, pathname|
|
128
|
+
each_signature(pathname) do |path|
|
129
|
+
signature_files << [library_path, path]
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
signature_files.each do |lib_path, file_path|
|
134
|
+
buffer = Buffer.new(name: file_path.to_s, content: file_path.read)
|
135
|
+
Parser.parse_signature(buffer).each do |decl|
|
136
|
+
yield decl, buffer, file_path, lib_path
|
137
|
+
end
|
138
|
+
end
|
139
|
+
else
|
140
|
+
enum_for :each_decl
|
125
141
|
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def load(env:)
|
145
|
+
loadeds = []
|
126
146
|
|
127
|
-
|
128
|
-
buffer = Buffer.new(name: file.to_s, content: file.read)
|
147
|
+
each_decl do |decl, buffer, file_path, lib_path|
|
129
148
|
env.buffers.push(buffer)
|
130
|
-
|
131
|
-
|
132
|
-
end
|
149
|
+
env << decl
|
150
|
+
loadeds << [decl, file_path, lib_path]
|
133
151
|
end
|
152
|
+
|
153
|
+
loadeds
|
134
154
|
end
|
135
155
|
end
|
136
156
|
end
|
data/lib/rbs/parser.y
CHANGED
@@ -458,16 +458,14 @@ rule
|
|
458
458
|
types: val[6],
|
459
459
|
annotations: val[0],
|
460
460
|
location: location,
|
461
|
-
comment: leading_comment(val[0].first&.location || val[
|
462
|
-
attributes: val[1].map(&:value),
|
461
|
+
comment: leading_comment(val[0].first&.location || val[2]&.location || val[3].location),
|
463
462
|
overload: overload || !!val[2]
|
464
463
|
)
|
465
464
|
}
|
466
465
|
|
467
466
|
attributes:
|
468
|
-
{ result = [] }
|
469
467
|
| attributes kINCOMPATIBLE {
|
470
|
-
|
468
|
+
RBS.logger.warn "`incompatible` method attribute is deprecated and ignored."
|
471
469
|
}
|
472
470
|
|
473
471
|
method_kind:
|