rbs 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +7 -1
  3. data/.gitignore +1 -1
  4. data/CHANGELOG.md +7 -0
  5. data/Gemfile +12 -0
  6. data/README.md +86 -47
  7. data/Rakefile +54 -21
  8. data/bin/rbs-prof +9 -0
  9. data/bin/run_in_md.rb +49 -0
  10. data/lib/rbs.rb +2 -0
  11. data/lib/rbs/ast/declarations.rb +62 -7
  12. data/lib/rbs/ast/members.rb +41 -17
  13. data/lib/rbs/cli.rb +299 -121
  14. data/lib/rbs/constant.rb +4 -4
  15. data/lib/rbs/constant_table.rb +50 -44
  16. data/lib/rbs/definition.rb +175 -59
  17. data/lib/rbs/definition_builder.rb +647 -603
  18. data/lib/rbs/environment.rb +338 -209
  19. data/lib/rbs/environment_walker.rb +14 -23
  20. data/lib/rbs/errors.rb +141 -3
  21. data/lib/rbs/parser.y +14 -9
  22. data/lib/rbs/prototype/rb.rb +100 -112
  23. data/lib/rbs/prototype/rbi.rb +4 -2
  24. data/lib/rbs/prototype/runtime.rb +10 -6
  25. data/lib/rbs/substitution.rb +8 -1
  26. data/lib/rbs/test/hook.rb +2 -2
  27. data/lib/rbs/test/setup.rb +3 -1
  28. data/lib/rbs/test/test_helper.rb +2 -5
  29. data/lib/rbs/test/type_check.rb +1 -2
  30. data/lib/rbs/type_name_resolver.rb +58 -0
  31. data/lib/rbs/types.rb +94 -2
  32. data/lib/rbs/validator.rb +51 -0
  33. data/lib/rbs/variance_calculator.rb +12 -2
  34. data/lib/rbs/version.rb +1 -1
  35. data/lib/rbs/writer.rb +125 -89
  36. data/rbs.gemspec +0 -10
  37. data/schema/decls.json +15 -0
  38. data/schema/members.json +3 -0
  39. data/stdlib/benchmark/benchmark.rbs +151 -151
  40. data/stdlib/builtin/enumerable.rbs +1 -1
  41. data/stdlib/builtin/file.rbs +0 -3
  42. data/stdlib/builtin/io.rbs +4 -4
  43. data/stdlib/builtin/thread.rbs +2 -2
  44. data/stdlib/csv/csv.rbs +4 -6
  45. data/stdlib/fiber/fiber.rbs +1 -1
  46. data/stdlib/json/json.rbs +1 -1
  47. data/stdlib/mutex_m/mutex_m.rbs +77 -0
  48. data/stdlib/pathname/pathname.rbs +6 -6
  49. data/stdlib/prime/integer-extension.rbs +1 -1
  50. data/stdlib/prime/prime.rbs +44 -44
  51. data/stdlib/tmpdir/tmpdir.rbs +1 -1
  52. metadata +8 -129
@@ -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.class?(module_name.absolute!)
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.comment,
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
@@ -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
@@ -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.name.absolute! == type_name
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&.name&.absolute! == type_name || name == :new
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
@@ -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.find_class(type_name)
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
@@ -17,9 +17,7 @@ module RBS
17
17
  loader.add library: lib
18
18
  end
19
19
 
20
- RBS::Environment.new.tap do |env|
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.declaration.type_params.each.map(&:name),
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
@@ -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
- decl = builder.env.find_class(type.name)
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
@@ -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; end
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