rbs 3.5.3 → 3.6.0.dev.1

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