rbs 1.7.0 → 2.0.0.pre1

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.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +95 -3
  3. data/core/array.rbs +3 -3
  4. data/core/builtin.rbs +4 -0
  5. data/core/enumerable.rbs +3 -3
  6. data/core/thread.rbs +1 -1
  7. data/docs/collection.md +23 -1
  8. data/docs/syntax.md +117 -61
  9. data/ext/rbs_extension/constants.c +2 -6
  10. data/ext/rbs_extension/constants.h +1 -2
  11. data/ext/rbs_extension/parser.c +221 -185
  12. data/ext/rbs_extension/parserstate.c +6 -2
  13. data/ext/rbs_extension/parserstate.h +10 -0
  14. data/ext/rbs_extension/ruby_objs.c +17 -17
  15. data/ext/rbs_extension/ruby_objs.h +3 -4
  16. data/lib/rbs/ast/declarations.rb +6 -99
  17. data/lib/rbs/ast/type_param.rb +134 -0
  18. data/lib/rbs/cli.rb +33 -5
  19. data/lib/rbs/collection/config/lockfile_generator.rb +26 -18
  20. data/lib/rbs/collection/sources/git.rb +18 -7
  21. data/lib/rbs/collection/sources/rubygems.rb +7 -0
  22. data/lib/rbs/collection/sources/stdlib.rb +6 -0
  23. data/lib/rbs/definition.rb +9 -0
  24. data/lib/rbs/definition_builder.rb +78 -16
  25. data/lib/rbs/environment.rb +32 -8
  26. data/lib/rbs/environment_loader.rb +0 -2
  27. data/lib/rbs/environment_walker.rb +4 -1
  28. data/lib/rbs/errors.rb +31 -6
  29. data/lib/rbs/location_aux.rb +2 -0
  30. data/lib/rbs/method_type.rb +29 -6
  31. data/lib/rbs/prototype/rb.rb +3 -3
  32. data/lib/rbs/prototype/rbi.rb +8 -6
  33. data/lib/rbs/prototype/runtime.rb +4 -4
  34. data/lib/rbs/type_alias_regularity.rb +115 -0
  35. data/lib/rbs/types.rb +100 -23
  36. data/lib/rbs/validator.rb +99 -15
  37. data/lib/rbs/variance_calculator.rb +60 -31
  38. data/lib/rbs/version.rb +1 -1
  39. data/lib/rbs/writer.rb +2 -14
  40. data/lib/rbs.rb +2 -0
  41. data/schema/decls.json +19 -46
  42. data/schema/methodType.json +1 -1
  43. data/schema/typeParam.json +36 -0
  44. data/schema/types.json +8 -2
  45. data/sig/collection/collections.rbs +13 -2
  46. data/sig/collection/config.rbs +2 -2
  47. data/sig/declarations.rbs +15 -62
  48. data/sig/definition.rbs +11 -1
  49. data/sig/definition_builder.rbs +37 -1
  50. data/sig/environment.rbs +7 -1
  51. data/sig/environment_walker.rbs +26 -0
  52. data/sig/errors.rbs +28 -3
  53. data/sig/location.rbs +3 -1
  54. data/sig/locator.rbs +1 -1
  55. data/sig/method_types.rbs +25 -4
  56. data/sig/type_alias_regularity.rbs +92 -0
  57. data/sig/type_param.rbs +74 -0
  58. data/sig/types.rbs +37 -8
  59. data/sig/validator.rbs +38 -2
  60. data/sig/variance_calculator.rbs +50 -0
  61. data/sig/writer.rbs +1 -1
  62. data/stdlib/bigdecimal-math/0/manifest.yaml +2 -0
  63. data/stdlib/csv/0/manifest.yaml +2 -0
  64. data/stdlib/date/0/date.rbs +2 -2
  65. data/stdlib/logger/0/manifest.yaml +2 -0
  66. data/stdlib/net-http/0/manifest.yaml +2 -0
  67. data/stdlib/openssl/0/manifest.yaml +2 -0
  68. data/stdlib/prime/0/manifest.yaml +2 -0
  69. data/stdlib/resolv/0/manifest.yaml +3 -0
  70. data/stdlib/set/0/set.rbs +3 -3
  71. data/stdlib/uri/0/common.rbs +10 -5
  72. data/stdlib/uri/0/ftp.rbs +10 -0
  73. data/stdlib/uri/0/mailto.rbs +5 -0
  74. data/stdlib/uri/0/ws.rbs +10 -0
  75. data/stdlib/uri/0/wss.rbs +7 -0
  76. data/stdlib/yaml/0/manifest.yaml +3 -0
  77. data/steep/Gemfile.lock +10 -10
  78. metadata +21 -5
  79. data/lib/ruby/signature.rb +0 -7
@@ -39,22 +39,29 @@ module RBS
39
39
 
40
40
  def validate_type_params
41
41
  unless decls.empty?
42
+ # @type var hd_decl: MultiEntry::D[module_decl]
43
+ # @type var tl_decls: Array[MultiEntry::D[module_decl]]
42
44
  hd_decl, *tl_decls = decls
43
45
  raise unless hd_decl
44
46
 
45
47
  hd_params = hd_decl.decl.type_params
46
- hd_names = hd_params.params.map(&:name)
47
48
 
48
49
  tl_decls.each do |tl_decl|
49
50
  tl_params = tl_decl.decl.type_params
50
51
 
51
- unless hd_params.size == tl_params.size && hd_params == tl_params.rename_to(hd_names)
52
+ unless compatible_params?(hd_params, tl_params)
52
53
  raise GenericParameterMismatchError.new(name: name, decl: tl_decl.decl)
53
54
  end
54
55
  end
55
56
  end
56
57
  end
57
58
 
59
+ def compatible_params?(ps1, ps2)
60
+ if ps1.size == ps2.size
61
+ ps1 == AST::TypeParam.rename(ps2, new_names: ps1.map(&:name))
62
+ end
63
+ end
64
+
58
65
  def type_params
59
66
  primary.decl.type_params
60
67
  end
@@ -240,17 +247,19 @@ module RBS
240
247
  array.unshift(head + decl.name.to_namespace)
241
248
  end
242
249
 
250
+ outer_context = context.drop(1)
251
+
243
252
  case decl
244
253
  when AST::Declarations::Class
245
254
  outer_ = outer + [decl]
246
255
  prefix_ = prefix + decl.name.to_namespace
247
256
  AST::Declarations::Class.new(
248
257
  name: decl.name.with_prefix(prefix),
249
- type_params: decl.type_params,
258
+ type_params: resolve_type_params(resolver, decl.type_params, context: context),
250
259
  super_class: decl.super_class&.yield_self do |super_class|
251
260
  AST::Declarations::Class::Super.new(
252
- name: absolute_type_name(resolver, super_class.name, context: context),
253
- args: super_class.args.map {|type| absolute_type(resolver, type, context: context) },
261
+ name: absolute_type_name(resolver, super_class.name, context: outer_context),
262
+ args: super_class.args.map {|type| absolute_type(resolver, type, context: outer_context) },
254
263
  location: super_class.location
255
264
  )
256
265
  end,
@@ -278,7 +287,7 @@ module RBS
278
287
  prefix_ = prefix + decl.name.to_namespace
279
288
  AST::Declarations::Module.new(
280
289
  name: decl.name.with_prefix(prefix),
281
- type_params: decl.type_params,
290
+ type_params: resolve_type_params(resolver, decl.type_params, context: context),
282
291
  self_types: decl.self_types.map do |module_self|
283
292
  AST::Declarations::Module::Self.new(
284
293
  name: absolute_type_name(resolver, module_self.name, context: context),
@@ -308,7 +317,7 @@ module RBS
308
317
  when AST::Declarations::Interface
309
318
  AST::Declarations::Interface.new(
310
319
  name: decl.name.with_prefix(prefix),
311
- type_params: decl.type_params,
320
+ type_params: resolve_type_params(resolver, decl.type_params, context: context),
312
321
  members: decl.members.map do |member|
313
322
  resolve_member(resolver, member, context: context)
314
323
  end,
@@ -319,6 +328,7 @@ module RBS
319
328
  when AST::Declarations::Alias
320
329
  AST::Declarations::Alias.new(
321
330
  name: decl.name.with_prefix(prefix),
331
+ type_params: resolve_type_params(resolver, decl.type_params, context: context),
322
332
  type: absolute_type(resolver, decl.type, context: context),
323
333
  location: decl.location,
324
334
  annotations: decl.annotations,
@@ -342,7 +352,7 @@ module RBS
342
352
  name: member.name,
343
353
  kind: member.kind,
344
354
  types: member.types.map do |type|
345
- type.map_type {|ty| absolute_type(resolver, ty, context: context) }
355
+ resolve_method_type(resolver, type, context: context)
346
356
  end,
347
357
  comment: member.comment,
348
358
  overload: member.overload?,
@@ -429,6 +439,20 @@ module RBS
429
439
  end
430
440
  end
431
441
 
442
+ def resolve_method_type(resolver, type, context:)
443
+ type.map_type do |ty|
444
+ absolute_type(resolver, ty, context: context)
445
+ end.map_type_bound do |bound|
446
+ _ = absolute_type(resolver, bound, context: context)
447
+ end
448
+ end
449
+
450
+ def resolve_type_params(resolver, params, context:)
451
+ params.map do |param|
452
+ param.map_type {|type| _ = absolute_type(resolver, type, context: context) }
453
+ end
454
+ end
455
+
432
456
  def absolute_type_name(resolver, type_name, context:)
433
457
  resolver.resolve(type_name, context: context) || type_name
434
458
  end
@@ -48,8 +48,6 @@ module RBS
48
48
  end
49
49
 
50
50
  def add_collection(collection_config)
51
- warn "warning: rbs collection is experimental, and the behavior may change until RBS v2.0"
52
-
53
51
  collection_config.check_rbs_availability!
54
52
 
55
53
  repository.add(collection_config.repo_path)
@@ -57,7 +57,7 @@ module RBS
57
57
  end
58
58
  end
59
59
  when name.alias?
60
- each_type_node builder.expand_alias(name), &block
60
+ each_type_node builder.expand_alias1(name), &block
61
61
  else
62
62
  raise "Unexpected TypeNameNode with type_name=#{name}"
63
63
  end
@@ -126,6 +126,9 @@ module RBS
126
126
  end
127
127
  when RBS::Types::Alias
128
128
  yield TypeNameNode.new(type_name: type.name)
129
+ type.args.each do |ty|
130
+ each_type_node(ty, &block)
131
+ end
129
132
  when RBS::Types::Union, RBS::Types::Intersection, RBS::Types::Tuple
130
133
  type.types.each do |ty|
131
134
  each_type_node ty, &block
data/lib/rbs/errors.rb CHANGED
@@ -14,11 +14,11 @@ module RBS
14
14
  end
15
15
  end
16
16
 
17
- class ErrorBase < StandardError; end
18
- class LoadingError < ErrorBase; end
19
- class DefinitionError < ErrorBase; end
17
+ class BaseError < StandardError; end
18
+ class LoadingError < BaseError; end
19
+ class DefinitionError < BaseError; end
20
20
 
21
- class ParsingError < ErrorBase
21
+ class ParsingError < BaseError
22
22
  attr_reader :location
23
23
  attr_reader :error_message
24
24
  attr_reader :token_type
@@ -105,7 +105,7 @@ module RBS
105
105
  end
106
106
  end
107
107
 
108
- class NoTypeFoundError < ErrorBase
108
+ class NoTypeFoundError < BaseError
109
109
  attr_reader :type_name
110
110
  attr_reader :location
111
111
 
@@ -416,7 +416,7 @@ module RBS
416
416
  end
417
417
  end
418
418
 
419
- class RecursiveTypeAliasError < LoadingError
419
+ class RecursiveTypeAliasError < BaseError
420
420
  attr_reader :alias_names
421
421
  attr_reader :location
422
422
 
@@ -431,4 +431,29 @@ module RBS
431
431
  @alias_names.map(&:name).join(', ')
432
432
  end
433
433
  end
434
+
435
+ class NonregularTypeAliasError < BaseError
436
+ attr_reader :diagnostic
437
+ attr_reader :location
438
+
439
+ def initialize(diagnostic:, location:)
440
+ @diagnostic = diagnostic
441
+ @location = location
442
+
443
+ super "#{Location.to_string location}: Nonregular generic type alias is prohibited: #{diagnostic.type_name}, #{diagnostic.nonregular_type}"
444
+ end
445
+ end
446
+
447
+ class CyclicTypeParameterBound < BaseError
448
+ attr_reader :params, :type_name, :method_name, :location
449
+
450
+ def initialize(type_name:, method_name:, params:, location:)
451
+ @type_name = type_name
452
+ @method_name = method_name
453
+ @params = params
454
+ @location = location
455
+
456
+ super "#{Location.to_string(location)}: Cyclic type parameter bound is prohibited"
457
+ end
458
+ end
434
459
  end
@@ -17,6 +17,8 @@ module RBS
17
17
  end
18
18
  end
19
19
 
20
+ alias aref []
21
+
20
22
  WithChildren = self
21
23
 
22
24
  def name
@@ -29,11 +29,18 @@ module RBS
29
29
  end
30
30
 
31
31
  def sub(s)
32
- s.without(*type_params).yield_self do |sub|
33
- map_type do |ty|
34
- ty.sub(sub)
35
- end
36
- end
32
+ sub = s.without(*type_param_names)
33
+
34
+ self.class.new(
35
+ type_params: type_params.map do |param|
36
+ param.map_type do |bound|
37
+ bound.map_type {|ty| ty.sub(sub) }
38
+ end
39
+ end,
40
+ type: type.sub(sub),
41
+ block: block&.sub(sub),
42
+ location: location
43
+ )
37
44
  end
38
45
 
39
46
  def update(type_params: self.type_params, type: self.type, block: self.block, location: self.location)
@@ -48,7 +55,7 @@ module RBS
48
55
  def free_variables(set = Set.new)
49
56
  type.free_variables(set)
50
57
  block&.type&.free_variables(set)
51
- set.subtract(type_params)
58
+ set.subtract(type_param_names)
52
59
  end
53
60
 
54
61
  def map_type(&block)
@@ -62,6 +69,18 @@ module RBS
62
69
  )
63
70
  end
64
71
 
72
+ def map_type_bound(&block)
73
+ if type_params.empty?
74
+ self
75
+ else
76
+ self.update(
77
+ type_params: type_params.map {|param|
78
+ param.map_type(&block)
79
+ }
80
+ )
81
+ end
82
+ end
83
+
65
84
  def each_type(&block)
66
85
  if block
67
86
  type.each_type(&block)
@@ -89,5 +108,9 @@ module RBS
89
108
  "[#{type_params.join(", ")}] #{s}"
90
109
  end
91
110
  end
111
+
112
+ def type_param_names
113
+ type_params.map(&:name)
114
+ end
92
115
  end
93
116
  end
@@ -49,7 +49,7 @@ module RBS
49
49
  annotations: [],
50
50
  comment: nil,
51
51
  location: nil,
52
- type_params: AST::Declarations::ModuleTypeParams.empty
52
+ type_params: []
53
53
  )
54
54
  decls << top
55
55
  end
@@ -88,7 +88,7 @@ module RBS
88
88
  kls = AST::Declarations::Class.new(
89
89
  name: const_to_name(class_name),
90
90
  super_class: super_class && AST::Declarations::Class::Super.new(name: const_to_name(super_class), args: [], location: nil),
91
- type_params: AST::Declarations::ModuleTypeParams.empty,
91
+ type_params: [],
92
92
  members: [],
93
93
  annotations: [],
94
94
  location: nil,
@@ -108,7 +108,7 @@ module RBS
108
108
 
109
109
  mod = AST::Declarations::Module.new(
110
110
  name: const_to_name(module_name),
111
- type_params: AST::Declarations::ModuleTypeParams.empty,
111
+ type_params: [],
112
112
  self_types: [],
113
113
  members: [],
114
114
  annotations: [],
@@ -48,7 +48,7 @@ module RBS
48
48
  modules.push AST::Declarations::Class.new(
49
49
  name: nested_name(name),
50
50
  super_class: super_class && AST::Declarations::Class::Super.new(name: const_to_name(super_class), args: [], location: nil),
51
- type_params: AST::Declarations::ModuleTypeParams.empty,
51
+ type_params: [],
52
52
  members: [],
53
53
  annotations: [],
54
54
  location: nil,
@@ -65,7 +65,7 @@ module RBS
65
65
  def push_module(name, comment:)
66
66
  modules.push AST::Declarations::Module.new(
67
67
  name: nested_name(name),
68
- type_params: AST::Declarations::ModuleTypeParams.empty,
68
+ type_params: [],
69
69
  members: [],
70
70
  annotations: [],
71
71
  location: nil,
@@ -212,10 +212,12 @@ module RBS
212
212
  end
213
213
  end
214
214
 
215
- current_module.type_params.add(
216
- AST::Declarations::ModuleTypeParams::TypeParam.new(name: node.children[0],
217
- variance: variance || :invariant,
218
- skip_validation: false))
215
+ current_module.type_params << AST::TypeParam.new(
216
+ name: node.children[0],
217
+ variance: variance || :invariant,
218
+ location: nil,
219
+ upper_bound: nil
220
+ )
219
221
  end
220
222
  else
221
223
  name = node.children[0].yield_self do |n|
@@ -371,7 +371,7 @@ module RBS
371
371
  unless decl
372
372
  decl = AST::Declarations::Class.new(
373
373
  name: to_type_name(only_name(mod)),
374
- type_params: AST::Declarations::ModuleTypeParams.empty,
374
+ type_params: [],
375
375
  super_class: generate_super_class(mod),
376
376
  members: [],
377
377
  annotations: [],
@@ -425,7 +425,7 @@ module RBS
425
425
  unless decl
426
426
  decl = AST::Declarations::Module.new(
427
427
  name: to_type_name(only_name(mod)),
428
- type_params: AST::Declarations::ModuleTypeParams.empty,
428
+ type_params: [],
429
429
  self_types: [],
430
430
  members: [],
431
431
  annotations: [],
@@ -479,7 +479,7 @@ module RBS
479
479
  if outer_module.is_a?(Class)
480
480
  outer_decl = AST::Declarations::Class.new(
481
481
  name: to_type_name(outer_module_name),
482
- type_params: AST::Declarations::ModuleTypeParams.empty,
482
+ type_params: [],
483
483
  super_class: generate_super_class(outer_module),
484
484
  members: [],
485
485
  annotations: [],
@@ -489,7 +489,7 @@ module RBS
489
489
  else
490
490
  outer_decl = AST::Declarations::Module.new(
491
491
  name: to_type_name(outer_module_name),
492
- type_params: AST::Declarations::ModuleTypeParams.empty,
492
+ type_params: [],
493
493
  self_types: [],
494
494
  members: [],
495
495
  annotations: [],
@@ -0,0 +1,115 @@
1
+ module RBS
2
+ class TypeAliasRegularity
3
+ class Diagnostic
4
+ attr_reader :type_name, :nonregular_type
5
+
6
+ def initialize(type_name:, nonregular_type:)
7
+ @type_name = type_name
8
+ @nonregular_type = nonregular_type
9
+ end
10
+ end
11
+
12
+ attr_reader :env, :builder, :diagnostics
13
+
14
+ def initialize(env:)
15
+ @env = env
16
+ @builder = DefinitionBuilder.new(env: env)
17
+ @diagnostics = {}
18
+ end
19
+
20
+ def validate
21
+ diagnostics.clear
22
+
23
+ each_mutual_alias_defs do |names|
24
+ # Find the first generic type alias in strongly connected component.
25
+ # This is to skip the regularity check when the alias is not generic.
26
+ names.each do |name|
27
+ # @type break: nil
28
+ if type = build_alias_type(name)
29
+ # Running validation only once from the first generic type is enough, because they are mutual recursive definition.
30
+ validate_alias_type(type, names, {})
31
+ break
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ def validate_alias_type(alias_type, names, types)
38
+ if names.include?(alias_type.name)
39
+ if ex_type = types[alias_type.name]
40
+ unless compatible_args?(ex_type.args, alias_type.args)
41
+ diagnostics[alias_type.name] ||=
42
+ Diagnostic.new(type_name: alias_type.name, nonregular_type: alias_type)
43
+ end
44
+
45
+ return
46
+ else
47
+ types[alias_type.name] = alias_type
48
+ end
49
+
50
+ expanded = builder.expand_alias2(alias_type.name, alias_type.args)
51
+ each_alias_type(expanded) do |at|
52
+ validate_alias_type(at, names, types)
53
+ end
54
+ end
55
+ end
56
+
57
+ def build_alias_type(name)
58
+ entry = env.alias_decls[name] or raise "Unknown alias name: #{name}"
59
+ unless entry.decl.type_params.empty?
60
+ as = entry.decl.type_params.each.map {|param| Types::Variable.new(name: param.name, location: nil) }
61
+ Types::Alias.new(name: name, args: as, location: nil)
62
+ end
63
+ end
64
+
65
+ def compatible_args?(args1, args2)
66
+ if args1.size == args2.size
67
+ args1.zip(args2).all? do |t1, t2|
68
+ t1.is_a?(Types::Bases::Any) ||
69
+ t2.is_a?(Types::Bases::Any) ||
70
+ t1 == t2
71
+ end
72
+ end
73
+ end
74
+
75
+ def nonregular?(type_name)
76
+ diagnostics[type_name]
77
+ end
78
+
79
+ def each_mutual_alias_defs(&block)
80
+ # @type var each_node: TSort::_EachNode[TypeName]
81
+ each_node = __skip__ = -> (&block) do
82
+ env.alias_decls.each_value do |decl|
83
+ block[decl.name]
84
+ end
85
+ end
86
+ # @type var each_child: TSort::_EachChild[TypeName]
87
+ each_child = __skip__ = -> (name, &block) do
88
+ type = builder.expand_alias1(name)
89
+ each_alias_type(type) do |ty|
90
+ block[ty.name]
91
+ end
92
+ end
93
+
94
+ TSort.each_strongly_connected_component(each_node, each_child) do |names|
95
+ yield Set.new(names)
96
+ end
97
+ end
98
+
99
+ def each_alias_type(type, &block)
100
+ if type.is_a?(RBS::Types::Alias)
101
+ yield type
102
+ end
103
+
104
+ type.each_type do |ty|
105
+ each_alias_type(ty, &block)
106
+ end
107
+ end
108
+
109
+ def self.validate(env:)
110
+ self.new(env: env).tap do |validator|
111
+ validator.validate()
112
+ end
113
+ end
114
+ end
115
+ end
data/lib/rbs/types.rb CHANGED
@@ -26,6 +26,14 @@ module RBS
26
26
  enum_for :each_type
27
27
  end
28
28
  end
29
+
30
+ def map_type(&block)
31
+ if block
32
+ _ = self
33
+ else
34
+ enum_for(:map_type)
35
+ end
36
+ end
29
37
  end
30
38
 
31
39
  module Bases
@@ -261,6 +269,18 @@ module RBS
261
269
  location: location
262
270
  )
263
271
  end
272
+
273
+ def map_type(&block)
274
+ if block
275
+ Interface.new(
276
+ name: name,
277
+ args: args.map {|type| yield type },
278
+ location: location
279
+ )
280
+ else
281
+ enum_for(:map_type)
282
+ end
283
+ end
264
284
  end
265
285
 
266
286
  class ClassInstance
@@ -291,46 +311,58 @@ module RBS
291
311
  location: location
292
312
  )
293
313
  end
314
+
315
+ def map_type(&block)
316
+ if block
317
+ ClassInstance.new(
318
+ name: name,
319
+ args: args.map {|type| yield type },
320
+ location: location
321
+ )
322
+ else
323
+ enum_for :map_type
324
+ end
325
+ end
294
326
  end
295
327
 
296
328
  class Alias
297
329
  attr_reader :location
298
- attr_reader :name
299
330
 
300
- def initialize(name:, location:)
331
+ include Application
332
+
333
+ def initialize(name:, args:, location:)
301
334
  @name = name
335
+ @args = args
302
336
  @location = location
303
337
  end
304
338
 
305
- def ==(other)
306
- other.is_a?(Alias) && other.name == name
307
- end
308
-
309
- alias eql? ==
310
-
311
- def hash
312
- self.class.hash ^ name.hash
313
- end
314
-
315
- include NoFreeVariables
316
- include NoSubst
317
-
318
339
  def to_json(state = _ = nil)
319
- { class: :alias, name: name, location: location }.to_json(state)
340
+ { class: :alias, name: name, args: args, location: location }.to_json(state)
320
341
  end
321
342
 
322
- def to_s(level = 0)
323
- name.to_s
343
+ def sub(s)
344
+ Alias.new(name: name, args: args.map {|ty| ty.sub(s) }, location: location)
324
345
  end
325
346
 
326
- include EmptyEachType
327
-
328
- def map_type_name
347
+ def map_type_name(&block)
329
348
  Alias.new(
330
349
  name: yield(name, location, self),
350
+ args: args.map {|arg| arg.map_type_name(&block) },
331
351
  location: location
332
352
  )
333
353
  end
354
+
355
+ def map_type(&block)
356
+ if block
357
+ Alias.new(
358
+ name: name,
359
+ args: args.map {|type| yield type },
360
+ location: location
361
+ )
362
+ else
363
+ enum_for :map_type
364
+ end
365
+ end
334
366
  end
335
367
 
336
368
  class Tuple
@@ -391,6 +423,17 @@ module RBS
391
423
  location: location
392
424
  )
393
425
  end
426
+
427
+ def map_type(&block)
428
+ if block
429
+ Tuple.new(
430
+ types: types.map {|type| yield type },
431
+ location: location
432
+ )
433
+ else
434
+ enum_for :map_type
435
+ end
436
+ end
394
437
  end
395
438
 
396
439
  class Record
@@ -433,7 +476,7 @@ module RBS
433
476
  return "{ }" if self.fields.empty?
434
477
 
435
478
  fields = self.fields.map do |key, type|
436
- if key.is_a?(Symbol) && key.match?(/\A[A-Za-z_][A-Za-z_]*\z/) && !Parser::KEYWORDS.include?(key)
479
+ if key.is_a?(Symbol) && key.match?(/\A[A-Za-z_][A-Za-z_]*\z/)
437
480
  "#{key}: #{type}"
438
481
  else
439
482
  "#{key.inspect} => #{type}"
@@ -456,6 +499,17 @@ module RBS
456
499
  location: location
457
500
  )
458
501
  end
502
+
503
+ def map_type(&block)
504
+ if block
505
+ Record.new(
506
+ fields: fields.transform_values {|type| yield type },
507
+ location: location
508
+ )
509
+ else
510
+ enum_for :map_type
511
+ end
512
+ end
459
513
  end
460
514
 
461
515
  class Optional
@@ -515,6 +569,17 @@ module RBS
515
569
  location: location
516
570
  )
517
571
  end
572
+
573
+ def map_type(&block)
574
+ if block
575
+ Optional.new(
576
+ type: yield(type),
577
+ location: location
578
+ )
579
+ else
580
+ enum_for :map_type
581
+ end
582
+ end
518
583
  end
519
584
 
520
585
  class Union
@@ -690,7 +755,7 @@ module RBS
690
755
 
691
756
  def to_s
692
757
  if name
693
- if Parser::KEYWORDS.include?(name)
758
+ if Parser::KEYWORDS.include?(name.to_s)
694
759
  "#{type} `#{name}`"
695
760
  else
696
761
  "#{type} #{name}"
@@ -1058,6 +1123,18 @@ module RBS
1058
1123
  location: location
1059
1124
  )
1060
1125
  end
1126
+
1127
+ def map_type(&block)
1128
+ if block
1129
+ Proc.new(
1130
+ type: type.map_type(&block),
1131
+ block: self.block&.map_type(&block),
1132
+ location: location
1133
+ )
1134
+ else
1135
+ enum_for :map_type
1136
+ end
1137
+ end
1061
1138
  end
1062
1139
 
1063
1140
  class Literal