rbs 3.5.3 → 3.6.0.dev.1

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 (61) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/dependabot.yml +5 -1
  3. data/.github/workflows/ruby.yml +2 -18
  4. data/.github/workflows/windows.yml +26 -0
  5. data/CHANGELOG.md +0 -18
  6. data/core/array.rbs +10 -10
  7. data/core/basic_object.rbs +3 -3
  8. data/core/enumerable.rbs +6 -0
  9. data/core/enumerator.rbs +7 -0
  10. data/core/fiber.rbs +1 -1
  11. data/core/global_variables.rbs +2 -2
  12. data/core/kernel.rbs +67 -38
  13. data/core/method.rbs +98 -7
  14. data/core/module.rbs +2 -2
  15. data/core/proc.rbs +184 -23
  16. data/core/ractor.rbs +1 -1
  17. data/core/range.rbs +30 -0
  18. data/core/refinement.rbs +16 -26
  19. data/core/symbol.rbs +34 -26
  20. data/core/thread.rbs +2 -2
  21. data/core/trace_point.rbs +12 -12
  22. data/core/unbound_method.rbs +1 -1
  23. data/docs/syntax.md +21 -9
  24. data/ext/rbs_extension/parser.c +119 -51
  25. data/ext/rbs_extension/ruby_objs.c +2 -1
  26. data/ext/rbs_extension/ruby_objs.h +1 -1
  27. data/lib/rbs/ast/declarations.rb +36 -0
  28. data/lib/rbs/ast/type_param.rb +71 -15
  29. data/lib/rbs/ast/visitor.rb +137 -0
  30. data/lib/rbs/cli/validate.rb +41 -7
  31. data/lib/rbs/cli.rb +3 -3
  32. data/lib/rbs/definition.rb +2 -1
  33. data/lib/rbs/definition_builder/ancestor_builder.rb +30 -4
  34. data/lib/rbs/definition_builder.rb +21 -6
  35. data/lib/rbs/environment_loader.rb +1 -1
  36. data/lib/rbs/errors.rb +7 -2
  37. data/lib/rbs/file_finder.rb +9 -12
  38. data/lib/rbs/locator.rb +8 -5
  39. data/lib/rbs/prototype/rbi.rb +2 -1
  40. data/lib/rbs/prototype/runtime.rb +3 -2
  41. data/lib/rbs/sorter.rb +9 -6
  42. data/lib/rbs/test/type_check.rb +6 -0
  43. data/lib/rbs/types.rb +11 -0
  44. data/lib/rbs/validator.rb +2 -2
  45. data/lib/rbs/vendorer.rb +3 -3
  46. data/lib/rbs/version.rb +1 -1
  47. data/lib/rbs.rb +1 -0
  48. data/sig/declarations.rbs +6 -0
  49. data/sig/definition.rbs +1 -1
  50. data/sig/definition_builder.rbs +3 -1
  51. data/sig/errors.rbs +3 -2
  52. data/sig/file_finder.rbs +24 -2
  53. data/sig/method_types.rbs +1 -1
  54. data/sig/sorter.rbs +1 -1
  55. data/sig/type_param.rbs +41 -9
  56. data/sig/types.rbs +12 -0
  57. data/sig/visitor.rbs +47 -0
  58. data/stdlib/csv/0/csv.rbs +27 -0
  59. data/stdlib/net-http/0/net-http.rbs +1 -1
  60. data/stdlib/zlib/0/gzip_reader.rbs +5 -1
  61. metadata +5 -2
@@ -3,14 +3,22 @@
3
3
  module RBS
4
4
  module AST
5
5
  class TypeParam
6
- attr_reader :name, :variance, :location, :upper_bound
6
+ attr_reader :name, :variance, :location, :upper_bound_type, :default_type
7
7
 
8
- def initialize(name:, variance:, upper_bound:, location:)
8
+ def initialize(name:, variance:, upper_bound:, location:, default_type: nil)
9
9
  @name = name
10
10
  @variance = variance
11
- @upper_bound = upper_bound
11
+ @upper_bound_type = upper_bound
12
12
  @location = location
13
13
  @unchecked = false
14
+ @default_type = default_type
15
+ end
16
+
17
+ def upper_bound
18
+ case upper_bound_type
19
+ when Types::ClassInstance, Types::ClassSingleton, Types::Interface
20
+ upper_bound_type
21
+ end
14
22
  end
15
23
 
16
24
  def unchecked!(value = true)
@@ -26,14 +34,15 @@ module RBS
26
34
  other.is_a?(TypeParam) &&
27
35
  other.name == name &&
28
36
  other.variance == variance &&
29
- other.upper_bound == upper_bound &&
37
+ other.upper_bound_type == upper_bound_type &&
38
+ other.default_type == default_type &&
30
39
  other.unchecked? == unchecked?
31
40
  end
32
41
 
33
42
  alias eql? ==
34
43
 
35
44
  def hash
36
- self.class.hash ^ name.hash ^ variance.hash ^ upper_bound.hash ^ unchecked?.hash
45
+ self.class.hash ^ name.hash ^ variance.hash ^ upper_bound_type.hash ^ unchecked?.hash ^ default_type.hash
37
46
  end
38
47
 
39
48
  def to_json(state = JSON::State.new)
@@ -42,7 +51,8 @@ module RBS
42
51
  variance: variance,
43
52
  unchecked: unchecked?,
44
53
  location: location,
45
- upper_bound: upper_bound
54
+ upper_bound: upper_bound_type,
55
+ default_type: default_type
46
56
  }.to_json(state)
47
57
  end
48
58
 
@@ -50,21 +60,27 @@ module RBS
50
60
  TypeParam.new(
51
61
  name: name,
52
62
  variance: variance,
53
- upper_bound: upper_bound,
54
- location: location
63
+ upper_bound: upper_bound_type,
64
+ location: location,
65
+ default_type: default_type
55
66
  ).unchecked!(unchecked?)
56
67
  end
57
68
 
58
69
  def map_type(&block)
59
- if b = upper_bound
60
- _upper_bound = yield(b)
70
+ if b = upper_bound_type
71
+ _upper_bound_type = yield(b)
72
+ end
73
+
74
+ if dt = default_type
75
+ _default_type = yield(dt)
61
76
  end
62
77
 
63
78
  TypeParam.new(
64
79
  name: name,
65
80
  variance: variance,
66
- upper_bound: _upper_bound,
67
- location: location
81
+ upper_bound: _upper_bound_type,
82
+ location: location,
83
+ default_type: _default_type
68
84
  ).unchecked!(unchecked?)
69
85
  end
70
86
 
@@ -101,8 +117,9 @@ module RBS
101
117
  TypeParam.new(
102
118
  name: new_name,
103
119
  variance: param.variance,
104
- upper_bound: param.upper_bound&.map_type {|type| type.sub(subst) },
105
- location: param.location
120
+ upper_bound: param.upper_bound_type&.map_type {|type| type.sub(subst) },
121
+ location: param.location,
122
+ default_type: param.default_type&.map_type {|type| type.sub(subst) }
106
123
  ).unchecked!(param.unchecked?)
107
124
  end
108
125
  end
@@ -125,12 +142,51 @@ module RBS
125
142
 
126
143
  s << name.to_s
127
144
 
128
- if type = upper_bound
145
+ if type = upper_bound_type
129
146
  s << " < #{type}"
130
147
  end
131
148
 
149
+ if dt = default_type
150
+ s << " = #{dt}"
151
+ end
152
+
132
153
  s
133
154
  end
155
+
156
+ def self.application(params, args)
157
+ subst = Substitution.new()
158
+
159
+ if params.empty?
160
+ return nil
161
+ end
162
+
163
+ min_count = params.count { _1.default_type.nil? }
164
+ max_count = params.size
165
+
166
+ unless min_count <= args.size && args.size <= max_count
167
+ raise "Invalid type application: required type params=#{min_count}, optional type params=#{max_count - min_count}, given args=#{args.size}"
168
+ end
169
+
170
+ params.zip(args).each do |param, arg|
171
+ if arg
172
+ subst.add(from: param.name, to: arg)
173
+ else
174
+ subst.add(from: param.name, to: param.default_type || raise)
175
+ end
176
+ end
177
+
178
+ subst
179
+ end
180
+
181
+ def self.normalize_args(params, args)
182
+ params.zip(args).filter_map do |param, arg|
183
+ if arg
184
+ arg
185
+ else
186
+ param.default_type
187
+ end
188
+ end
189
+ end
134
190
  end
135
191
  end
136
192
  end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RBS
4
+ module AST
5
+ # The Visitor class implements the Visitor pattern for traversing the RBS Abstract Syntax Tree (AST).
6
+ #
7
+ # It provides methods to visit each type of node in the AST, allowing for custom processing of each node type.
8
+ #
9
+ # This class is designed to be subclassed, with specific visit methods overridden to implement custom behavior for
10
+ # different node types.
11
+ #
12
+ # Example usage:
13
+ #
14
+ # ~~~rb
15
+ # class MyVisitor < RBS::AST::Visitor
16
+ # def visit_declaration_class(node)
17
+ # puts "Visiting class: #{node.name}"
18
+ #
19
+ # super # call `super` to run the default visiting behavior
20
+ # end
21
+ # end
22
+ #
23
+ # visitor = MyVisitor.new
24
+ # visitor.visit(ast_node)
25
+ # ~~~
26
+ class Visitor
27
+ def visit(node)
28
+ case node
29
+ when Declarations::Global
30
+ visit_declaration_global(node)
31
+ when Declarations::Class
32
+ visit_declaration_class(node)
33
+ when Declarations::Module
34
+ visit_declaration_module(node)
35
+ when Declarations::Constant
36
+ visit_declaration_constant(node)
37
+ when Declarations::TypeAlias
38
+ visit_declaration_type_alias(node)
39
+ when Declarations::Interface
40
+ visit_declaration_interface(node)
41
+ when Members::Alias
42
+ visit_member_alias(node)
43
+ when Members::ClassInstanceVariable
44
+ visit_member_class_instance_variable(node)
45
+ when Members::ClassVariable
46
+ visit_member_class_variable(node)
47
+ when Members::InstanceVariable
48
+ visit_member_instance_variable(node)
49
+ when Members::Private
50
+ visit_member_private(node)
51
+ when Members::Public
52
+ visit_member_public(node)
53
+ when Members::MethodDefinition
54
+ visit_member_method_definition(node)
55
+ when Members::AttrReader
56
+ visit_member_attr_reader(node)
57
+ when Members::AttrWriter
58
+ visit_member_attr_writer(node)
59
+ when Members::AttrAccessor
60
+ visit_member_attr_accessor(node)
61
+ when Members::Include
62
+ visit_member_include(node)
63
+ when Members::Prepend
64
+ visit_member_prepend(node)
65
+ when Members::Extend
66
+ visit_member_extend(node)
67
+ end
68
+ end
69
+
70
+ def visit_all(nodes)
71
+ nodes.each do |node|
72
+ visit(node)
73
+ end
74
+ end
75
+
76
+ def visit_declaration_global(node)
77
+ end
78
+
79
+ def visit_declaration_class(node)
80
+ visit_all(node.members)
81
+ end
82
+
83
+ def visit_declaration_module(node)
84
+ visit_all(node.members)
85
+ end
86
+
87
+ def visit_declaration_constant(node)
88
+ end
89
+
90
+ def visit_declaration_type_alias(node)
91
+ end
92
+
93
+ def visit_declaration_interface(node)
94
+ visit_all(node.members)
95
+ end
96
+
97
+ def visit_member_alias(node)
98
+ end
99
+
100
+ def visit_member_class_instance_variable(node)
101
+ end
102
+
103
+ def visit_member_class_variable(node)
104
+ end
105
+
106
+ def visit_member_instance_variable(node)
107
+ end
108
+
109
+ def visit_member_private(node)
110
+ end
111
+
112
+ def visit_member_public(node)
113
+ end
114
+
115
+ def visit_member_method_definition(node)
116
+ end
117
+
118
+ def visit_member_attr_reader(node)
119
+ end
120
+
121
+ def visit_member_attr_writer(node)
122
+ end
123
+
124
+ def visit_member_attr_accessor(node)
125
+ end
126
+
127
+ def visit_member_include(node)
128
+ end
129
+
130
+ def visit_member_prepend(node)
131
+ end
132
+
133
+ def visit_member_extend(node)
134
+ end
135
+ end
136
+ end
137
+ end
@@ -94,7 +94,7 @@ EOU
94
94
  private
95
95
 
96
96
  def validate_class_module_definition
97
- @env.class_decls.each do |name, decl|
97
+ @env.class_decls.each do |name, entry|
98
98
  RBS.logger.info "Validating class/module definition: `#{name}`..."
99
99
  @builder.build_instance(name).each_type do |type|
100
100
  @validator.validate_type type, context: nil
@@ -107,30 +107,47 @@ EOU
107
107
  @errors.add(error)
108
108
  end
109
109
 
110
- case decl
110
+ case entry
111
111
  when Environment::ClassEntry
112
- decl.decls.each do |decl|
112
+ entry.decls.each do |decl|
113
113
  if super_class = decl.decl.super_class
114
114
  super_class.args.each do |arg|
115
115
  void_type_context_validator(arg, true)
116
116
  no_self_type_validator(arg)
117
117
  no_classish_type_validator(arg)
118
+ @validator.validate_type(arg, context: nil)
119
+ end
120
+
121
+ if super_entry = @env.normalized_class_entry(super_class.name)
122
+ InvalidTypeApplicationError.check!(type_name: super_class.name, args: super_class.args, params: super_entry.type_params, location: super_class.location)
118
123
  end
119
124
  end
120
125
  end
121
126
  when Environment::ModuleEntry
122
- decl.decls.each do |decl|
127
+ entry.decls.each do |decl|
123
128
  decl.decl.self_types.each do |self_type|
124
129
  self_type.args.each do |arg|
125
130
  void_type_context_validator(arg, true)
126
131
  no_self_type_validator(arg)
127
132
  no_classish_type_validator(arg)
133
+ @validator.validate_type(arg, context: nil)
134
+ end
135
+
136
+ self_params =
137
+ if self_type.name.class?
138
+ @env.normalized_module_entry(self_type.name)&.type_params
139
+ else
140
+ @env.interface_decls[self_type.name]&.decl&.type_params
141
+ end
142
+
143
+ if self_params
144
+ InvalidTypeApplicationError.check!(type_name: self_type.name, params: self_params, args: self_type.args, location: self_type.location)
128
145
  end
129
146
  end
130
147
  end
131
148
  end
132
149
 
133
- d = decl.primary.decl
150
+ d = entry.primary.decl
134
151
 
135
152
  @validator.validate_type_params(
136
153
  d.type_params,
@@ -139,14 +156,22 @@ EOU
139
156
  )
140
157
 
141
158
  d.type_params.each do |param|
142
- if ub = param.upper_bound
159
+ if ub = param.upper_bound_type
143
160
  void_type_context_validator(ub)
144
161
  no_self_type_validator(ub)
145
162
  no_classish_type_validator(ub)
163
+ @validator.validate_type(ub, context: nil)
164
+ end
165
+
166
+ if dt = param.default_type
167
+ void_type_context_validator(dt)
168
+ no_self_type_validator(dt)
169
+ no_classish_type_validator(dt)
170
+ @validator.validate_type(dt, context: nil)
146
171
  end
147
172
  end
148
173
 
149
- decl.decls.each do |d|
174
+ entry.decls.each do |d|
150
175
  d.decl.each_member do |member|
151
176
  case member
152
177
  when AST::Members::MethodDefinition
@@ -163,6 +188,15 @@ EOU
163
188
  void_type_context_validator(arg, true)
164
189
  end
165
190
  end
191
+ params =
192
+ if member.name.class?
193
+ module_decl = @env.normalized_module_entry(member.name) or raise
194
+ module_decl.type_params
195
+ else
196
+ interface_decl = @env.interface_decls.fetch(member.name)
197
+ interface_decl.decl.type_params
198
+ end
199
+ InvalidTypeApplicationError.check!(type_name: member.name, params: params, args: member.args, location: member.location)
166
200
  when AST::Members::Var
167
201
  void_type_context_validator(member.type)
168
202
  if member.is_a?(AST::Members::ClassVariable)
data/lib/rbs/cli.rb CHANGED
@@ -109,7 +109,7 @@ module RBS
109
109
  end
110
110
 
111
111
  def has_parser?
112
- defined?(RubyVM::AbstractSyntaxTree)
112
+ defined?(RubyVM::AbstractSyntaxTree) ? true : false
113
113
  end
114
114
 
115
115
  def run(args)
@@ -909,7 +909,7 @@ Options:
909
909
  syntax_error = false
910
910
  bufs = args.flat_map do |path|
911
911
  path = Pathname(path)
912
- FileFinder.each_file(path, skip_hidden: false, immediate: true).map do |file_path|
912
+ FileFinder.each_file(path, skip_hidden: false).map do |file_path|
913
913
  Buffer.new(content: file_path.read, name: file_path)
914
914
  end
915
915
  end
@@ -1193,7 +1193,7 @@ EOB
1193
1193
  end
1194
1194
 
1195
1195
  minuend_paths.each do |minuend_path|
1196
- FileFinder.each_file(Pathname(minuend_path), immediate: true, skip_hidden: true) do |rbs_path|
1196
+ FileFinder.each_file(Pathname(minuend_path), skip_hidden: true) do |rbs_path|
1197
1197
  buf = Buffer.new(name: rbs_path, content: rbs_path.read)
1198
1198
  _, dirs, decls = Parser.parse_signature(buf)
1199
1199
  subtracted = Subtractor.new(decls, subtrahend).call
@@ -238,10 +238,11 @@ module RBS
238
238
  end
239
239
 
240
240
  def apply(args, location:)
241
+ # Assume default types of type parameters are already added to `args`
241
242
  InvalidTypeApplicationError.check!(
242
243
  type_name: type_name,
243
244
  args: args,
244
- params: params,
245
+ params: params.map { AST::TypeParam.new(name: _1, variance: :invariant, upper_bound: nil, location: nil, default_type: nil) },
245
246
  location: location
246
247
  )
247
248
 
@@ -213,12 +213,15 @@ module RBS
213
213
  end
214
214
 
215
215
  super_name = env.normalize_module_name(super_name)
216
-
216
+
217
217
  NoSuperclassFoundError.check!(super_name, env: env, location: primary.decl.location)
218
218
  if super_class
219
219
  InheritModuleError.check!(super_class, env: env)
220
220
  end
221
221
 
222
+ super_entry = env.normalized_class_entry(super_name) or raise
223
+ super_args = AST::TypeParam.normalize_args(super_entry.type_params, super_args)
224
+
222
225
  ancestors = OneAncestors.class_instance(
223
226
  type_name: type_name,
224
227
  params: params,
@@ -243,9 +246,17 @@ module RBS
243
246
 
244
247
  module_name = module_self.name
245
248
  if module_name.class?
246
- module_name = env.normalize_module_name(module_name)
249
+ module_entry = env.normalized_module_class_entry(module_name) or raise
250
+ module_name = module_entry.name
251
+ self_args = AST::TypeParam.normalize_args(module_entry.type_params, module_self.args)
252
+ end
253
+ if module_name.interface?
254
+ interface_entry = env.interface_decls.fetch(module_name)
255
+ self_args = AST::TypeParam.normalize_args(interface_entry.decl.type_params, module_self.args)
247
256
  end
248
- self_types.push Definition::Ancestor::Instance.new(name: module_name, args: module_self.args, source: module_self)
257
+ self_args or raise
258
+
259
+ self_types.push Definition::Ancestor::Instance.new(name: module_name, args: self_args, source: module_self)
249
260
  end
250
261
  end
251
262
  end
@@ -346,11 +357,17 @@ module RBS
346
357
  MixinClassError.check!(type_name: type_name, env: env, member: member)
347
358
  NoMixinFoundError.check!(member.name, env: env, member: member)
348
359
 
360
+ module_decl = env.normalized_module_entry(module_name) or raise
361
+ module_args = AST::TypeParam.normalize_args(module_decl.type_params, module_args)
362
+
349
363
  module_name = env.normalize_module_name(module_name)
350
364
  included_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
351
365
  when member.name.interface? && included_interfaces
352
366
  NoMixinFoundError.check!(member.name, env: env, member: member)
353
367
 
368
+ interface_decl = env.interface_decls.fetch(module_name)
369
+ module_args = AST::TypeParam.normalize_args(interface_decl.decl.type_params, module_args)
370
+
354
371
  included_interfaces << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
355
372
  end
356
373
 
@@ -359,8 +376,11 @@ module RBS
359
376
  MixinClassError.check!(type_name: type_name, env: env, member: member)
360
377
  NoMixinFoundError.check!(member.name, env: env, member: member)
361
378
 
362
- module_name = env.normalize_module_name(member.name)
379
+ module_decl = env.normalized_module_entry(member.name) or raise
380
+ module_name = module_decl.name
381
+
363
382
  module_args = member.args.map {|type| align_params ? type.sub(align_params) : type }
383
+ module_args = AST::TypeParam.normalize_args(module_decl.type_params, module_args)
364
384
 
365
385
  prepended_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
366
386
  end
@@ -374,11 +394,17 @@ module RBS
374
394
  MixinClassError.check!(type_name: type_name, env: env, member: member)
375
395
  NoMixinFoundError.check!(member.name, env: env, member: member)
376
396
 
397
+ module_decl = env.normalized_module_entry(module_name) or raise
398
+ module_args = AST::TypeParam.normalize_args(module_decl.type_params, module_args)
399
+
377
400
  module_name = env.normalize_module_name(module_name)
378
401
  extended_modules << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
379
402
  when member.name.interface? && extended_interfaces
380
403
  NoMixinFoundError.check!(member.name, env: env, member: member)
381
404
 
405
+ interface_decl = env.interface_decls.fetch(module_name)
406
+ module_args = AST::TypeParam.normalize_args(interface_decl.decl.type_params, module_args)
407
+
382
408
  extended_interfaces << Definition::Ancestor::Instance.new(name: module_name, args: module_args, source: member)
383
409
  end
384
410
  end
@@ -37,7 +37,7 @@ module RBS
37
37
  interface_methods = interface_methods(included_interfaces)
38
38
  methods = method_builder.build_interface(type_name)
39
39
 
40
- import_methods(definition, type_name, methods, interface_methods, subst)
40
+ import_methods(definition, type_name, methods, interface_methods, subst, nil)
41
41
  end
42
42
 
43
43
  def build_interface(type_name)
@@ -86,6 +86,19 @@ module RBS
86
86
  one_ancestors = ancestor_builder.one_instance_ancestors(type_name)
87
87
  methods = method_builder.build_instance(type_name)
88
88
 
89
+ self_type_methods = one_ancestors.each_self_type.with_object({}) do |self_type, hash| #$ Hash[Symbol, Definition::Method]
90
+ self_type.args.each do |arg|
91
+ validate_type_presence(arg)
92
+ end
93
+
94
+ self_type_defn = self_type.name.interface? ? build_interface(self_type.name) : build_instance(self_type.name)
95
+
96
+ s = subst + tapp_subst(self_type.name, self_type.args)
97
+ self_type_defn.methods.each do |method_name, method_def|
98
+ hash[method_name] = method_def.sub(s)
99
+ end
100
+ end
101
+
89
102
  one_ancestors.each_included_module do |mod|
90
103
  mod.args.each do |arg|
91
104
  validate_type_presence(arg)
@@ -100,7 +113,7 @@ module RBS
100
113
  [interface, *other_interfaces]
101
114
  end
102
115
  interface_methods = interface_methods(all_interfaces)
103
- import_methods(definition, type_name, methods, interface_methods, subst)
116
+ import_methods(definition, type_name, methods, interface_methods, subst, self_type_methods)
104
117
 
105
118
  one_ancestors.each_prepended_module do |mod|
106
119
  mod.args.each do |arg|
@@ -254,7 +267,7 @@ module RBS
254
267
  [interface, *other_interfaces]
255
268
  end
256
269
  interface_methods = interface_methods(all_interfaces)
257
- import_methods(definition, type_name, methods, interface_methods, Substitution.new)
270
+ import_methods(definition, type_name, methods, interface_methods, Substitution.new, nil)
258
271
 
259
272
  entry.decls.each do |d|
260
273
  d.decl.members.each do |member|
@@ -529,7 +542,7 @@ module RBS
529
542
  )
530
543
  end
531
544
 
532
- def import_methods(definition, module_name, module_methods, interfaces_methods, subst)
545
+ def import_methods(definition, module_name, module_methods, interfaces_methods, subst, self_type_methods)
533
546
  new_methods = {} #: Hash[Symbol, Definition::Method]
534
547
  interface_method_duplicates = Set[] #: Set[Symbol]
535
548
 
@@ -567,6 +580,7 @@ module RBS
567
580
  definition,
568
581
  method,
569
582
  subst_,
583
+ nil,
570
584
  defined_in: interface.name,
571
585
  implemented_in: module_name
572
586
  )
@@ -579,6 +593,7 @@ module RBS
579
593
  definition,
580
594
  method,
581
595
  subst,
596
+ self_type_methods,
582
597
  defined_in: module_name,
583
598
  implemented_in: module_name.interface? ? nil : module_name
584
599
  )
@@ -587,12 +602,12 @@ module RBS
587
602
  definition.methods.merge!(new_methods)
588
603
  end
589
604
 
590
- def define_method(methods, definition, method, subst, defined_in:, implemented_in: defined_in)
605
+ def define_method(methods, definition, method, subst, self_type_methods, defined_in:, implemented_in: defined_in)
591
606
  existing_method = methods[method.name] || definition.methods[method.name]
592
607
 
593
608
  case original = method.original
594
609
  when AST::Members::Alias
595
- original_method = methods[original.old_name] || definition.methods[original.old_name]
610
+ original_method = methods[original.old_name] || definition.methods[original.old_name] || self_type_methods&.fetch(original.old_name, nil)
596
611
 
597
612
  unless original_method
598
613
  raise UnknownMethodAliasError.new(
@@ -152,7 +152,7 @@ module RBS
152
152
  each_dir do |source, dir|
153
153
  skip_hidden = !source.is_a?(Pathname)
154
154
 
155
- FileFinder.each_file(dir, skip_hidden: skip_hidden, immediate: true) do |path|
155
+ FileFinder.each_file(dir, skip_hidden: skip_hidden) do |path|
156
156
  next if files.include?(path)
157
157
 
158
158
  files << path
data/lib/rbs/errors.rb CHANGED
@@ -68,18 +68,23 @@ module RBS
68
68
  attr_reader :type_name
69
69
  attr_reader :args
70
70
  attr_reader :params
71
+ attr_reader :type_params
71
72
  attr_reader :location
72
73
 
73
74
  def initialize(type_name:, args:, params:, location:)
74
75
  @type_name = type_name
75
76
  @args = args
76
- @params = params
77
+ @type_params = params
78
+ @params = params.map(&:name)
77
79
  @location = location
78
80
  super "#{Location.to_string location}: #{type_name} expects parameters [#{params.join(", ")}], but given args [#{args.join(", ")}]"
79
81
  end
80
82
 
81
83
  def self.check!(type_name:, args:, params:, location:)
82
- unless args.size == params.size
84
+ min_arity = params.count { _1.default_type.nil? }
85
+ max_arity = params.size
86
+
87
+ unless min_arity <= args.size && args.size <= max_arity
83
88
  raise new(type_name: type_name, args: args, params: params, location: location)
84
89
  end
85
90
  end
@@ -4,27 +4,24 @@ module RBS
4
4
  module FileFinder
5
5
  module_function
6
6
 
7
- def self.each_file(path, immediate:, skip_hidden:, &block)
7
+ def self.each_file(path, immediate: nil, skip_hidden:, &block)
8
8
  return enum_for((__method__ or raise), path, immediate: immediate, skip_hidden: skip_hidden) unless block
9
9
 
10
10
  case
11
11
  when path.file?
12
- if path.extname == ".rbs" || immediate
13
- yield path
14
- end
12
+ yield path
15
13
 
16
14
  when path.directory?
17
- if path.basename.to_s.start_with?("_")
18
- if skip_hidden
19
- unless immediate
20
- return
21
- end
15
+ paths = Pathname.glob("#{path}/**/*.rbs")
16
+
17
+ if skip_hidden
18
+ paths.select! do |child|
19
+ child.relative_path_from(path).ascend.drop(1).none? { _1.basename.to_s.start_with?("_") }
22
20
  end
23
21
  end
22
+ paths.sort_by!(&:to_s)
24
23
 
25
- path.children.sort.each do |child|
26
- each_file(child, immediate: false, skip_hidden: skip_hidden, &block)
27
- end
24
+ paths.each(&block)
28
25
  end
29
26
  end
30
27
  end