rbs 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +7 -1
- data/.gitignore +1 -1
- data/CHANGELOG.md +7 -0
- data/Gemfile +12 -0
- data/README.md +86 -47
- data/Rakefile +54 -21
- data/bin/rbs-prof +9 -0
- data/bin/run_in_md.rb +49 -0
- data/lib/rbs.rb +2 -0
- data/lib/rbs/ast/declarations.rb +62 -7
- data/lib/rbs/ast/members.rb +41 -17
- data/lib/rbs/cli.rb +299 -121
- data/lib/rbs/constant.rb +4 -4
- data/lib/rbs/constant_table.rb +50 -44
- data/lib/rbs/definition.rb +175 -59
- data/lib/rbs/definition_builder.rb +647 -603
- data/lib/rbs/environment.rb +338 -209
- data/lib/rbs/environment_walker.rb +14 -23
- data/lib/rbs/errors.rb +141 -3
- data/lib/rbs/parser.y +14 -9
- data/lib/rbs/prototype/rb.rb +100 -112
- data/lib/rbs/prototype/rbi.rb +4 -2
- data/lib/rbs/prototype/runtime.rb +10 -6
- data/lib/rbs/substitution.rb +8 -1
- data/lib/rbs/test/hook.rb +2 -2
- data/lib/rbs/test/setup.rb +3 -1
- data/lib/rbs/test/test_helper.rb +2 -5
- data/lib/rbs/test/type_check.rb +1 -2
- data/lib/rbs/type_name_resolver.rb +58 -0
- data/lib/rbs/types.rb +94 -2
- data/lib/rbs/validator.rb +51 -0
- data/lib/rbs/variance_calculator.rb +12 -2
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/writer.rb +125 -89
- data/rbs.gemspec +0 -10
- data/schema/decls.json +15 -0
- data/schema/members.json +3 -0
- data/stdlib/benchmark/benchmark.rbs +151 -151
- data/stdlib/builtin/enumerable.rbs +1 -1
- data/stdlib/builtin/file.rbs +0 -3
- data/stdlib/builtin/io.rbs +4 -4
- data/stdlib/builtin/thread.rbs +2 -2
- data/stdlib/csv/csv.rbs +4 -6
- data/stdlib/fiber/fiber.rbs +1 -1
- data/stdlib/json/json.rbs +1 -1
- data/stdlib/mutex_m/mutex_m.rbs +77 -0
- data/stdlib/pathname/pathname.rbs +6 -6
- data/stdlib/prime/integer-extension.rbs +1 -1
- data/stdlib/prime/prime.rbs +44 -44
- data/stdlib/tmpdir/tmpdir.rbs +1 -1
- metadata +8 -129
data/lib/rbs/prototype/rbi.rb
CHANGED
@@ -173,7 +173,8 @@ module RBS
|
|
173
173
|
types: types,
|
174
174
|
kind: :singleton,
|
175
175
|
comment: comment,
|
176
|
-
attributes: []
|
176
|
+
attributes: [],
|
177
|
+
overload: false
|
177
178
|
)
|
178
179
|
end
|
179
180
|
|
@@ -193,7 +194,8 @@ module RBS
|
|
193
194
|
types: types,
|
194
195
|
kind: :instance,
|
195
196
|
comment: comment,
|
196
|
-
attributes: []
|
197
|
+
attributes: [],
|
198
|
+
overload: false
|
197
199
|
)
|
198
200
|
end
|
199
201
|
|
@@ -128,7 +128,7 @@ module RBS
|
|
128
128
|
|
129
129
|
def merge_rbs(module_name, members, instance: nil, singleton: nil)
|
130
130
|
if merge
|
131
|
-
if env.
|
131
|
+
if env.class_decls[module_name.absolute!]
|
132
132
|
case
|
133
133
|
when instance
|
134
134
|
method = builder.build_instance(module_name.absolute!).methods[instance]
|
@@ -152,9 +152,10 @@ module RBS
|
|
152
152
|
},
|
153
153
|
kind: kind,
|
154
154
|
location: nil,
|
155
|
-
comment: method.
|
155
|
+
comment: method.comments[0],
|
156
156
|
annotations: method.annotations,
|
157
|
-
attributes: method.attributes
|
157
|
+
attributes: method.attributes,
|
158
|
+
overload: false
|
158
159
|
)
|
159
160
|
return
|
160
161
|
end
|
@@ -192,7 +193,8 @@ module RBS
|
|
192
193
|
location: nil,
|
193
194
|
comment: nil,
|
194
195
|
annotations: [],
|
195
|
-
attributes: []
|
196
|
+
attributes: [],
|
197
|
+
overload: false
|
196
198
|
)
|
197
199
|
end
|
198
200
|
else
|
@@ -225,7 +227,8 @@ module RBS
|
|
225
227
|
location: nil,
|
226
228
|
comment: nil,
|
227
229
|
annotations: [],
|
228
|
-
attributes: []
|
230
|
+
attributes: [],
|
231
|
+
overload: false
|
229
232
|
)
|
230
233
|
end
|
231
234
|
else
|
@@ -259,7 +262,8 @@ module RBS
|
|
259
262
|
location: nil,
|
260
263
|
comment: nil,
|
261
264
|
annotations: [],
|
262
|
-
attributes: []
|
265
|
+
attributes: [],
|
266
|
+
overload: false
|
263
267
|
)
|
264
268
|
end
|
265
269
|
else
|
data/lib/rbs/substitution.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module RBS
|
2
2
|
class Substitution
|
3
3
|
attr_reader :mapping
|
4
|
+
attr_accessor :instance_type
|
4
5
|
|
5
6
|
def initialize()
|
6
7
|
@mapping = {}
|
@@ -10,7 +11,7 @@ module RBS
|
|
10
11
|
mapping[from] = to
|
11
12
|
end
|
12
13
|
|
13
|
-
def self.build(variables, types, &block)
|
14
|
+
def self.build(variables, types, instance_type: Types::Bases::Instance.new(location: nil), &block)
|
14
15
|
unless variables.size == types.size
|
15
16
|
raise "Broken substitution: variables=#{variables}, types=#{types}"
|
16
17
|
end
|
@@ -22,6 +23,8 @@ module RBS
|
|
22
23
|
type = block_given? ? yield(t) : t
|
23
24
|
subst.add(from: v, to: type)
|
24
25
|
end
|
26
|
+
|
27
|
+
subst.instance_type = instance_type
|
25
28
|
end
|
26
29
|
end
|
27
30
|
|
@@ -29,6 +32,8 @@ module RBS
|
|
29
32
|
case ty
|
30
33
|
when Types::Variable
|
31
34
|
mapping[ty.name] || ty
|
35
|
+
when Types::Bases::Instance
|
36
|
+
instance_type
|
32
37
|
else
|
33
38
|
ty
|
34
39
|
end
|
@@ -40,6 +45,8 @@ module RBS
|
|
40
45
|
vars.each do |var|
|
41
46
|
subst.mapping.delete(var)
|
42
47
|
end
|
48
|
+
|
49
|
+
subst.instance_type = self.instance_type
|
43
50
|
end
|
44
51
|
end
|
45
52
|
end
|
data/lib/rbs/test/hook.rb
CHANGED
@@ -94,7 +94,7 @@ module RBS
|
|
94
94
|
|
95
95
|
builder.build_instance(type_name).tap do |definition|
|
96
96
|
definition.methods.each do |name, method|
|
97
|
-
if method.defined_in
|
97
|
+
if method.defined_in == type_name
|
98
98
|
unless method.annotations.any? {|a| a.string == "rbs:test:skip" }
|
99
99
|
logger.info "Installing a hook on #{type_name}##{name}: #{method.method_types.join(" | ")}"
|
100
100
|
verify instance_method: name, types: method.method_types
|
@@ -107,7 +107,7 @@ module RBS
|
|
107
107
|
|
108
108
|
builder.build_singleton(type_name).tap do |definition|
|
109
109
|
definition.methods.each do |name, method|
|
110
|
-
if method.defined_in
|
110
|
+
if method.defined_in == type_name || name == :new
|
111
111
|
unless method.annotations.any? {|a| a.string == "rbs:test:skip" }
|
112
112
|
logger.info "Installing a hook on #{type_name}.#{name}: #{method.method_types.join(" | ")}"
|
113
113
|
verify singleton_method: name, types: method.method_types
|
data/lib/rbs/test/setup.rb
CHANGED
@@ -33,6 +33,8 @@ OptionParser.new do |opts|
|
|
33
33
|
end.parse!(opts)
|
34
34
|
loader.load(env: env)
|
35
35
|
|
36
|
+
env = env.resolve_type_names
|
37
|
+
|
36
38
|
def match(filter, name)
|
37
39
|
if filter.end_with?("*")
|
38
40
|
name.start_with?(filter[0, filter.size - 1]) || name == filter[0, filter.size-3]
|
@@ -48,7 +50,7 @@ TracePoint.trace :end do |tp|
|
|
48
50
|
if filter.any? {|f| match(f, class_name) } && skips.none? {|f| match(f, class_name) }
|
49
51
|
type_name = RBS::Namespace.parse(class_name).absolute!.to_type_name
|
50
52
|
if hooks.none? {|hook| hook.klass == tp.self }
|
51
|
-
if env.
|
53
|
+
if env.class_decls.key?(type_name)
|
52
54
|
logger.info "Setting up hooks for #{class_name}"
|
53
55
|
hooks << RBS::Test::Hook.install(env, tp.self, logger: logger).verify_all.raise_on_error!(raise_on_error)
|
54
56
|
end
|
data/lib/rbs/test/test_helper.rb
CHANGED
@@ -17,9 +17,7 @@ module RBS
|
|
17
17
|
loader.add library: lib
|
18
18
|
end
|
19
19
|
|
20
|
-
RBS::Environment.
|
21
|
-
loader.load(env: env)
|
22
|
-
end
|
20
|
+
RBS::Environment.from_loader(loader).resolve_type_names
|
23
21
|
end
|
24
22
|
end
|
25
23
|
|
@@ -126,8 +124,7 @@ module RBS
|
|
126
124
|
type, definition = target
|
127
125
|
method_types = case
|
128
126
|
when definition.instance_type?
|
129
|
-
subst = Substitution.build(definition.
|
130
|
-
type.args)
|
127
|
+
subst = Substitution.build(definition.type_params, type.args)
|
131
128
|
definition.methods[method].method_types.map do |method_type|
|
132
129
|
method_type.sub(subst)
|
133
130
|
end
|
data/lib/rbs/test/type_check.rb
CHANGED
@@ -220,8 +220,7 @@ module RBS
|
|
220
220
|
val == klass
|
221
221
|
when Types::Interface
|
222
222
|
methods = Set.new(Test.call(val, METHODS))
|
223
|
-
|
224
|
-
if (definition = builder.build_interface(type.name, decl))
|
223
|
+
if (definition = builder.build_interface(type.name))
|
225
224
|
definition.methods.each_key.all? do |method_name|
|
226
225
|
methods.member?(method_name)
|
227
226
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module RBS
|
2
|
+
class TypeNameResolver
|
3
|
+
Query = Struct.new(:type_name, :context, keyword_init: true)
|
4
|
+
|
5
|
+
attr_reader :all_names
|
6
|
+
attr_reader :cache
|
7
|
+
|
8
|
+
def initialize()
|
9
|
+
@all_names = Set[]
|
10
|
+
@cache = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.from_env(env)
|
14
|
+
new.add_names(env.class_decls.keys)
|
15
|
+
.add_names(env.interface_decls.keys)
|
16
|
+
.add_names(env.alias_decls.keys)
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_names(names)
|
20
|
+
all_names.merge(names)
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def try_cache(query)
|
25
|
+
cache.fetch(query) do
|
26
|
+
result = yield
|
27
|
+
cache[query] = result
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def resolve(type_name, context:)
|
32
|
+
if type_name.absolute?
|
33
|
+
return type_name
|
34
|
+
end
|
35
|
+
|
36
|
+
query = Query.new(type_name: type_name, context: context)
|
37
|
+
try_cache(query) do
|
38
|
+
path_head, *path_tail = type_name.to_namespace.path
|
39
|
+
name_head = TypeName.new(name: path_head, namespace: Namespace.empty)
|
40
|
+
|
41
|
+
absolute_head = context.each.find do |namespace|
|
42
|
+
full_name = name_head.with_prefix(namespace)
|
43
|
+
has_name?(full_name) and break full_name
|
44
|
+
end
|
45
|
+
|
46
|
+
if absolute_head
|
47
|
+
has_name?(Namespace.new(path: absolute_head.to_namespace.path.push(*path_tail), absolute: true).to_type_name)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def has_name?(full_name)
|
53
|
+
if all_names.include?(full_name)
|
54
|
+
full_name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/rbs/types.rb
CHANGED
@@ -12,6 +12,12 @@ module RBS
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
+
module NoTypeName
|
16
|
+
def map_type_name
|
17
|
+
self
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
15
21
|
module EmptyEachType
|
16
22
|
def each_type
|
17
23
|
if block_given?
|
@@ -43,6 +49,7 @@ module RBS
|
|
43
49
|
include NoFreeVariables
|
44
50
|
include NoSubst
|
45
51
|
include EmptyEachType
|
52
|
+
include NoTypeName
|
46
53
|
|
47
54
|
def to_json(*a)
|
48
55
|
klass = to_s.to_sym
|
@@ -82,7 +89,11 @@ module RBS
|
|
82
89
|
class Top < Base; end
|
83
90
|
class Bottom < Base; end
|
84
91
|
class Self < Base; end
|
85
|
-
class Instance < Base
|
92
|
+
class Instance < Base
|
93
|
+
def sub(s)
|
94
|
+
s.apply(self)
|
95
|
+
end
|
96
|
+
end
|
86
97
|
class Class < Base; end
|
87
98
|
end
|
88
99
|
|
@@ -90,6 +101,8 @@ module RBS
|
|
90
101
|
attr_reader :name
|
91
102
|
attr_reader :location
|
92
103
|
|
104
|
+
include NoTypeName
|
105
|
+
|
93
106
|
def initialize(name:, location:)
|
94
107
|
@name = name
|
95
108
|
@location = location
|
@@ -174,6 +187,13 @@ module RBS
|
|
174
187
|
end
|
175
188
|
|
176
189
|
include EmptyEachType
|
190
|
+
|
191
|
+
def map_type_name
|
192
|
+
ClassSingleton.new(
|
193
|
+
name: yield(name, location, self),
|
194
|
+
location: location
|
195
|
+
)
|
196
|
+
end
|
177
197
|
end
|
178
198
|
|
179
199
|
module Application
|
@@ -235,6 +255,14 @@ module RBS
|
|
235
255
|
args: args.map {|ty| ty.sub(s) },
|
236
256
|
location: location)
|
237
257
|
end
|
258
|
+
|
259
|
+
def map_type_name(&block)
|
260
|
+
Interface.new(
|
261
|
+
name: yield(name, location, self),
|
262
|
+
args: args.map {|type| type.map_type_name(&block) },
|
263
|
+
location: location
|
264
|
+
)
|
265
|
+
end
|
238
266
|
end
|
239
267
|
|
240
268
|
class ClassInstance
|
@@ -257,6 +285,14 @@ module RBS
|
|
257
285
|
args: args.map {|ty| ty.sub(s) },
|
258
286
|
location: location)
|
259
287
|
end
|
288
|
+
|
289
|
+
def map_type_name(&block)
|
290
|
+
ClassInstance.new(
|
291
|
+
name: yield(name, location, self),
|
292
|
+
args: args.map {|type| type.map_type_name(&block) },
|
293
|
+
location: location
|
294
|
+
)
|
295
|
+
end
|
260
296
|
end
|
261
297
|
|
262
298
|
class Alias
|
@@ -290,6 +326,13 @@ module RBS
|
|
290
326
|
end
|
291
327
|
|
292
328
|
include EmptyEachType
|
329
|
+
|
330
|
+
def map_type_name
|
331
|
+
Alias.new(
|
332
|
+
name: yield(name, location, self),
|
333
|
+
location: location
|
334
|
+
)
|
335
|
+
end
|
293
336
|
end
|
294
337
|
|
295
338
|
class Tuple
|
@@ -343,6 +386,13 @@ module RBS
|
|
343
386
|
enum_for :each_type
|
344
387
|
end
|
345
388
|
end
|
389
|
+
|
390
|
+
def map_type_name(&block)
|
391
|
+
Tuple.new(
|
392
|
+
types: types.map {|type| type.map_type_name(&block) },
|
393
|
+
location: location
|
394
|
+
)
|
395
|
+
end
|
346
396
|
end
|
347
397
|
|
348
398
|
class Record
|
@@ -401,6 +451,13 @@ module RBS
|
|
401
451
|
enum_for :each_type
|
402
452
|
end
|
403
453
|
end
|
454
|
+
|
455
|
+
def map_type_name(&block)
|
456
|
+
Record.new(
|
457
|
+
fields: fields.transform_values {|ty| ty.map_type_name(&block) },
|
458
|
+
location: location
|
459
|
+
)
|
460
|
+
end
|
404
461
|
end
|
405
462
|
|
406
463
|
class Optional
|
@@ -449,6 +506,13 @@ module RBS
|
|
449
506
|
enum_for :each_type
|
450
507
|
end
|
451
508
|
end
|
509
|
+
|
510
|
+
def map_type_name(&block)
|
511
|
+
Optional.new(
|
512
|
+
type: type.map_type_name(&block),
|
513
|
+
location: location
|
514
|
+
)
|
515
|
+
end
|
452
516
|
end
|
453
517
|
|
454
518
|
class Union
|
@@ -510,6 +574,13 @@ module RBS
|
|
510
574
|
enum_for :map_type
|
511
575
|
end
|
512
576
|
end
|
577
|
+
|
578
|
+
def map_type_name(&block)
|
579
|
+
Union.new(
|
580
|
+
types: types.map {|type| type.map_type_name(&block) },
|
581
|
+
location: location
|
582
|
+
)
|
583
|
+
end
|
513
584
|
end
|
514
585
|
|
515
586
|
class Intersection
|
@@ -572,6 +643,13 @@ module RBS
|
|
572
643
|
enum_for :map_type
|
573
644
|
end
|
574
645
|
end
|
646
|
+
|
647
|
+
def map_type_name(&block)
|
648
|
+
Intersection.new(
|
649
|
+
types: types.map {|type| type.map_type_name(&block) },
|
650
|
+
location: location
|
651
|
+
)
|
652
|
+
end
|
575
653
|
end
|
576
654
|
|
577
655
|
class Function
|
@@ -648,7 +726,7 @@ module RBS
|
|
648
726
|
other.required_keywords == required_keywords &&
|
649
727
|
other.optional_keywords == optional_keywords &&
|
650
728
|
other.rest_keywords == rest_keywords &&
|
651
|
-
return_type == return_type
|
729
|
+
other.return_type == return_type
|
652
730
|
end
|
653
731
|
|
654
732
|
alias eql? ==
|
@@ -710,6 +788,12 @@ module RBS
|
|
710
788
|
end
|
711
789
|
end
|
712
790
|
|
791
|
+
def map_type_name(&block)
|
792
|
+
map_type do |type|
|
793
|
+
type.map_type_name(&block)
|
794
|
+
end
|
795
|
+
end
|
796
|
+
|
713
797
|
def each_type
|
714
798
|
if block_given?
|
715
799
|
required_positionals.each {|param| yield param.type }
|
@@ -899,6 +983,13 @@ module RBS
|
|
899
983
|
enum_for :each_type
|
900
984
|
end
|
901
985
|
end
|
986
|
+
|
987
|
+
def map_type_name(&block)
|
988
|
+
Proc.new(
|
989
|
+
type: type.map_type_name(&block),
|
990
|
+
location: location
|
991
|
+
)
|
992
|
+
end
|
902
993
|
end
|
903
994
|
|
904
995
|
class Literal
|
@@ -923,6 +1014,7 @@ module RBS
|
|
923
1014
|
include NoFreeVariables
|
924
1015
|
include NoSubst
|
925
1016
|
include EmptyEachType
|
1017
|
+
include NoTypeName
|
926
1018
|
|
927
1019
|
def to_json(*a)
|
928
1020
|
{ class: :literal, literal: literal.inspect, location: location }.to_json(*a)
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module RBS
|
2
|
+
class Validator
|
3
|
+
attr_reader :env
|
4
|
+
attr_reader :resolver
|
5
|
+
|
6
|
+
def initialize(env:, resolver:)
|
7
|
+
@env = env
|
8
|
+
@resolver = resolver
|
9
|
+
end
|
10
|
+
|
11
|
+
def absolute_type(type, context:)
|
12
|
+
type.map_type_name do |type_name, _, type|
|
13
|
+
resolver.resolve(type_name, context: context) || yield(type)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Validates presence of the relative type, and application arity match.
|
18
|
+
def validate_type(type, context:)
|
19
|
+
case type
|
20
|
+
when Types::ClassInstance, Types::Interface
|
21
|
+
if type.name.namespace.relative?
|
22
|
+
type = absolute_type(type, context: context) do |type|
|
23
|
+
NoTypeFoundError.check!(type.name.absolute!, env: env, location: type.location)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
type_params = case type
|
28
|
+
when Types::ClassInstance
|
29
|
+
env.class_decls[type.name]&.type_params
|
30
|
+
when Types::Interface
|
31
|
+
env.interface_decls[type.name]&.decl&.type_params
|
32
|
+
end
|
33
|
+
|
34
|
+
unless type_params
|
35
|
+
raise NoTypeFoundError.new(type_name: type.name, location: type.location)
|
36
|
+
end
|
37
|
+
|
38
|
+
InvalidTypeApplicationError.check!(
|
39
|
+
type_name: type.name,
|
40
|
+
args: type.args,
|
41
|
+
params: type_params.each.map(&:name),
|
42
|
+
location: type.location
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
type.each_type do |type|
|
47
|
+
validate_type(type, context: context)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|