rbs 1.7.0 → 2.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
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