rbs 0.18.0 → 1.0.0.pre

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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/Rakefile +4 -0
  4. data/core/builtin.rbs +4 -0
  5. data/core/file.rbs +0 -4
  6. data/core/hash.rbs +1 -3
  7. data/core/io.rbs +159 -6
  8. data/core/kernel.rbs +1 -1
  9. data/core/time.rbs +0 -12
  10. data/goodcheck.yml +20 -0
  11. data/lib/rbs.rb +2 -0
  12. data/lib/rbs/ast/declarations.rb +7 -2
  13. data/lib/rbs/ast/members.rb +10 -4
  14. data/lib/rbs/cli.rb +10 -10
  15. data/lib/rbs/definition.rb +70 -3
  16. data/lib/rbs/definition_builder.rb +544 -989
  17. data/lib/rbs/definition_builder/ancestor_builder.rb +476 -0
  18. data/lib/rbs/definition_builder/method_builder.rb +217 -0
  19. data/lib/rbs/environment.rb +5 -1
  20. data/lib/rbs/environment_loader.rb +1 -1
  21. data/lib/rbs/environment_walker.rb +16 -10
  22. data/lib/rbs/errors.rb +71 -66
  23. data/lib/rbs/method_type.rb +1 -31
  24. data/lib/rbs/parser.rb +1000 -894
  25. data/lib/rbs/parser.y +108 -57
  26. data/lib/rbs/prototype/rb.rb +14 -3
  27. data/lib/rbs/prototype/rbi.rb +6 -6
  28. data/lib/rbs/prototype/runtime.rb +53 -33
  29. data/lib/rbs/substitution.rb +4 -0
  30. data/lib/rbs/test.rb +3 -1
  31. data/lib/rbs/test/hook.rb +24 -7
  32. data/lib/rbs/types.rb +63 -6
  33. data/lib/rbs/validator.rb +4 -2
  34. data/lib/rbs/variance_calculator.rb +5 -1
  35. data/lib/rbs/version.rb +1 -1
  36. data/lib/rbs/writer.rb +9 -1
  37. data/schema/members.json +5 -1
  38. data/sig/definition.rbs +6 -1
  39. data/sig/definition_builder.rbs +3 -0
  40. data/sig/errors.rbs +20 -0
  41. data/sig/members.rbs +4 -1
  42. data/sig/method_types.rbs +3 -16
  43. data/sig/type_name_resolver.rbs +4 -2
  44. data/sig/types.rbs +17 -1
  45. data/sig/validator.rbs +12 -0
  46. data/stdlib/dbm/0/dbm.rbs +0 -2
  47. data/stdlib/logger/0/log_device.rbs +1 -2
  48. data/stdlib/monitor/0/monitor.rbs +119 -0
  49. data/stdlib/time/0/time.rbs +327 -0
  50. data/stdlib/tsort/0/tsort.rbs +8 -0
  51. data/stdlib/uri/0/common.rbs +401 -0
  52. data/stdlib/uri/0/rfc2396_parser.rbs +9 -0
  53. data/stdlib/uri/0/rfc3986_parser.rbs +2 -0
  54. data/steep/Gemfile.lock +13 -14
  55. metadata +14 -5
@@ -0,0 +1,217 @@
1
+ module RBS
2
+ class DefinitionBuilder
3
+ class MethodBuilder
4
+ class Methods
5
+ Definition = Struct.new(:name, :type, :originals, :overloads, :accessibilities, keyword_init: true) do
6
+ def original
7
+ originals[0]
8
+ end
9
+
10
+ def accessibility
11
+ accessibilities[0]
12
+ end
13
+
14
+ def self.empty(name:, type:)
15
+ new(type: type, name: name, originals: [], overloads: [], accessibilities: [])
16
+ end
17
+ end
18
+
19
+ attr_reader :type
20
+ attr_reader :methods
21
+
22
+ def initialize(type:)
23
+ @type = type
24
+ @methods = {}
25
+ end
26
+
27
+ def validate!
28
+ methods.each_value do |defn|
29
+ if defn.originals.size > 1
30
+ raise DuplicatedMethodDefinitionError.new(
31
+ type: type,
32
+ method_name: defn.name,
33
+ members: defn.originals
34
+ )
35
+ end
36
+ end
37
+
38
+ self
39
+ end
40
+
41
+ def each
42
+ if block_given?
43
+ Sorter.new(methods).each_strongly_connected_component do |scc|
44
+ if scc.size > 1
45
+ raise RecursiveAliasDefinitionError.new(type: type, defs: scc)
46
+ end
47
+
48
+ yield scc[0]
49
+ end
50
+ else
51
+ enum_for :each
52
+ end
53
+ end
54
+
55
+ class Sorter
56
+ include TSort
57
+
58
+ attr_reader :methods
59
+
60
+ def initialize(methods)
61
+ @methods = methods
62
+ end
63
+
64
+ def tsort_each_node(&block)
65
+ methods.each_value(&block)
66
+ end
67
+
68
+ def tsort_each_child(defn)
69
+ if (member = defn.original).is_a?(AST::Members::Alias)
70
+ if old = methods[member.old_name]
71
+ yield old
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ attr_reader :env
79
+ attr_reader :instance_methods
80
+ attr_reader :singleton_methods
81
+ attr_reader :interface_methods
82
+
83
+ def initialize(env:)
84
+ @env = env
85
+
86
+ @instance_methods = {}
87
+ @singleton_methods = {}
88
+ @interface_methods = {}
89
+ end
90
+
91
+ def build_instance(type_name)
92
+ instance_methods[type_name] ||=
93
+ begin
94
+ entry = env.class_decls[type_name]
95
+ args = Types::Variable.build(entry.type_params.each.map(&:name))
96
+ type = Types::ClassInstance.new(name: type_name, args: args, location: nil)
97
+ Methods.new(type: type).tap do |methods|
98
+ entry.decls.each do |d|
99
+ each_member_with_accessibility(d.decl.members) do |member, accessibility|
100
+ case member
101
+ when AST::Members::MethodDefinition
102
+ if member.instance?
103
+ build_method(methods, type, member: member, accessibility: accessibility)
104
+ end
105
+ when AST::Members::AttrReader, AST::Members::AttrWriter, AST::Members::AttrAccessor
106
+ if member.kind == :instance
107
+ build_attribute(methods, type, member: member, accessibility: accessibility)
108
+ end
109
+ when AST::Members::Alias
110
+ if member.kind == :instance
111
+ build_alias(methods, type, member: member, accessibility: accessibility)
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end.validate!
117
+ end
118
+ end
119
+
120
+ def build_singleton(type_name)
121
+ singleton_methods[type_name] ||=
122
+ begin
123
+ entry = env.class_decls[type_name]
124
+ type = Types::ClassSingleton.new(name: type_name, location: nil)
125
+
126
+ Methods.new(type: type).tap do |methods|
127
+ entry.decls.each do |d|
128
+ each_member_with_accessibility(d.decl.members) do |member, accessibility|
129
+ case member
130
+ when AST::Members::MethodDefinition
131
+ if member.singleton?
132
+ build_method(methods, type, member: member, accessibility: accessibility)
133
+ end
134
+ when AST::Members::AttrReader, AST::Members::AttrWriter, AST::Members::AttrAccessor
135
+ if member.kind == :singleton
136
+ build_attribute(methods, type, member: member, accessibility: accessibility)
137
+ end
138
+ when AST::Members::Alias
139
+ if member.kind == :singleton
140
+ build_alias(methods, type, member: member, accessibility: accessibility)
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end.validate!
146
+ end
147
+ end
148
+
149
+ def build_interface(type_name)
150
+ interface_methods[type_name] ||=
151
+ begin
152
+ entry = env.interface_decls[type_name]
153
+ args = Types::Variable.build(entry.decl.type_params.each.map(&:name))
154
+ type = Types::Interface.new(name: type_name, args: args, location: nil)
155
+
156
+ Methods.new(type: type).tap do |methods|
157
+ entry.decl.members.each do |member|
158
+ case member
159
+ when AST::Members::MethodDefinition
160
+ build_method(methods, type, member: member, accessibility: :public)
161
+ when AST::Members::Alias
162
+ build_alias(methods, type, member: member, accessibility: :public)
163
+ end
164
+ end
165
+ end.validate!
166
+ end
167
+ end
168
+
169
+ def build_alias(methods, type, member:, accessibility:)
170
+ defn = methods.methods[member.new_name] ||= Methods::Definition.empty(type: type, name: member.new_name)
171
+
172
+ defn.originals << member
173
+ defn.accessibilities << accessibility
174
+ end
175
+
176
+ def build_attribute(methods, type, member:, accessibility:)
177
+ if member.is_a?(AST::Members::AttrReader) || member.is_a?(AST::Members::AttrAccessor)
178
+ defn = methods.methods[member.name] ||= Methods::Definition.empty(type: type, name: member.name)
179
+
180
+ defn.accessibilities << accessibility
181
+ defn.originals << member
182
+ end
183
+
184
+ if member.is_a?(AST::Members::AttrWriter) || member.is_a?(AST::Members::AttrAccessor)
185
+ defn = methods.methods[:"#{member.name}="] ||= Methods::Definition.empty(type: type, name: :"#{member.name}=")
186
+
187
+ defn.accessibilities << accessibility
188
+ defn.originals << member
189
+ end
190
+ end
191
+
192
+ def build_method(methods, type, member:, accessibility:)
193
+ defn = methods.methods[member.name] ||= Methods::Definition.empty(type: type, name: member.name)
194
+
195
+ if member.overload?
196
+ defn.overloads << member
197
+ else
198
+ defn.accessibilities << accessibility
199
+ defn.originals << member
200
+ end
201
+ end
202
+
203
+ def each_member_with_accessibility(members, accessibility: :public)
204
+ members.each do |member|
205
+ case member
206
+ when AST::Members::Public
207
+ accessibility = :public
208
+ when AST::Members::Private
209
+ accessibility = :private
210
+ else
211
+ yield member, accessibility
212
+ end
213
+ end
214
+ end
215
+ end
216
+ end
217
+ end
@@ -244,7 +244,8 @@ module RBS
244
244
  super_class: decl.super_class&.yield_self do |super_class|
245
245
  AST::Declarations::Class::Super.new(
246
246
  name: absolute_type_name(resolver, super_class.name, context: context),
247
- args: super_class.args.map {|type| absolute_type(resolver, type, context: context) }
247
+ args: super_class.args.map {|type| absolute_type(resolver, type, context: context) },
248
+ location: super_class.location
248
249
  )
249
250
  end,
250
251
  members: decl.members.map do |member|
@@ -349,6 +350,7 @@ module RBS
349
350
  AST::Members::AttrAccessor.new(
350
351
  name: member.name,
351
352
  type: absolute_type(resolver, member.type, context: context),
353
+ kind: member.kind,
352
354
  annotations: member.annotations,
353
355
  comment: member.comment,
354
356
  location: member.location,
@@ -358,6 +360,7 @@ module RBS
358
360
  AST::Members::AttrReader.new(
359
361
  name: member.name,
360
362
  type: absolute_type(resolver, member.type, context: context),
363
+ kind: member.kind,
361
364
  annotations: member.annotations,
362
365
  comment: member.comment,
363
366
  location: member.location,
@@ -367,6 +370,7 @@ module RBS
367
370
  AST::Members::AttrWriter.new(
368
371
  name: member.name,
369
372
  type: absolute_type(resolver, member.type, context: context),
373
+ kind: member.kind,
370
374
  annotations: member.annotations,
371
375
  comment: member.comment,
372
376
  location: member.location,
@@ -102,7 +102,7 @@ module RBS
102
102
  end
103
103
  end
104
104
 
105
- path.each_child do |child|
105
+ path.children.sort.each do |child|
106
106
  each_file(child, immediate: false, skip_hidden: skip_hidden, &block)
107
107
  end
108
108
  end
@@ -53,11 +53,11 @@ module RBS
53
53
  definition = builder.build_interface(name)
54
54
  unless only_ancestors?
55
55
  definition.each_type do |type|
56
- each_type_name type, &block
56
+ each_type_node type, &block
57
57
  end
58
58
  end
59
59
  when name.alias?
60
- each_type_name builder.expand_alias(name), &block
60
+ each_type_node builder.expand_alias(name), &block
61
61
  else
62
62
  raise "Unexpected TypeNameNode with type_name=#{name}"
63
63
  end
@@ -77,7 +77,7 @@ module RBS
77
77
 
78
78
  unless only_ancestors?
79
79
  ancestor.args.each do |type|
80
- each_type_name type, &block
80
+ each_type_node type, &block
81
81
  end
82
82
  end
83
83
  when Definition::Ancestor::Singleton
@@ -88,13 +88,19 @@ module RBS
88
88
 
89
89
  unless only_ancestors?
90
90
  definition.each_type do |type|
91
- each_type_name type, &block
91
+ each_type_node type, &block
92
92
  end
93
93
  end
94
94
  end
95
95
  end
96
96
 
97
97
  def each_type_name(type, &block)
98
+ each_type_node(type) do |node|
99
+ yield node.type_name
100
+ end
101
+ end
102
+
103
+ def each_type_node(type, &block)
98
104
  case type
99
105
  when RBS::Types::Bases::Any
100
106
  when RBS::Types::Bases::Class
@@ -111,30 +117,30 @@ module RBS
111
117
  when RBS::Types::ClassInstance
112
118
  yield InstanceNode.new(type_name: type.name)
113
119
  type.args.each do |ty|
114
- each_type_name(ty, &block)
120
+ each_type_node(ty, &block)
115
121
  end
116
122
  when RBS::Types::Interface
117
123
  yield TypeNameNode.new(type_name: type.name)
118
124
  type.args.each do |ty|
119
- each_type_name(ty, &block)
125
+ each_type_node(ty, &block)
120
126
  end
121
127
  when RBS::Types::Alias
122
128
  yield TypeNameNode.new(type_name: type.name)
123
129
  when RBS::Types::Union, RBS::Types::Intersection, RBS::Types::Tuple
124
130
  type.types.each do |ty|
125
- each_type_name ty, &block
131
+ each_type_node ty, &block
126
132
  end
127
133
  when RBS::Types::Optional
128
- each_type_name type.type, &block
134
+ each_type_node type.type, &block
129
135
  when RBS::Types::Literal
130
136
  # nop
131
137
  when RBS::Types::Record
132
138
  type.fields.each_value do |ty|
133
- each_type_name ty, &block
139
+ each_type_node ty, &block
134
140
  end
135
141
  when RBS::Types::Proc
136
142
  type.each_type do |ty|
137
- each_type_name ty, &block
143
+ each_type_node ty, &block
138
144
  end
139
145
  else
140
146
  raise "Unexpected type given: #{type}"
@@ -68,18 +68,20 @@ module RBS
68
68
  attr_reader :location
69
69
 
70
70
  def initialize(ancestors:, location:)
71
- last = case last = ancestors.last
72
- when Definition::Ancestor::Singleton
73
- "singleton(#{last.name})"
74
- when Definition::Ancestor::Instance
75
- if last.args.empty?
76
- last.name.to_s
77
- else
78
- "#{last.name}[#{last.args.join(", ")}]"
79
- end
80
- end
81
-
82
- super "#{Location.to_string location}: Detected recursive ancestors: #{last}"
71
+ names = ancestors.map do |ancestor|
72
+ case ancestor
73
+ when Definition::Ancestor::Singleton
74
+ "singleton(#{ancestor.name})"
75
+ when Definition::Ancestor::Instance
76
+ if ancestor.args.empty?
77
+ ancestor.name.to_s
78
+ else
79
+ "#{ancestor.name}[#{ancestor.args.join(", ")}]"
80
+ end
81
+ end
82
+ end
83
+
84
+ super "#{Location.to_string location}: Detected recursive ancestors: #{names.join(" < ")}"
83
85
  end
84
86
 
85
87
  def self.check!(self_ancestor, ancestors:, location:)
@@ -194,44 +196,54 @@ module RBS
194
196
  end
195
197
 
196
198
  class DuplicatedMethodDefinitionError < StandardError
197
- attr_reader :decl
198
- attr_reader :location
199
+ attr_reader :type
200
+ attr_reader :method_name
201
+ attr_reader :members
199
202
 
200
- def initialize(decl:, name:, location:)
201
- decl_str = case decl
202
- when AST::Declarations::Interface, AST::Declarations::Class, AST::Declarations::Module
203
- decl.name.to_s
204
- when AST::Declarations::Extension
205
- "#{decl.name} (#{decl.extension_name})"
206
- end
203
+ def initialize(type:, method_name:, members:)
204
+ @type = type
205
+ @method_name = method_name
206
+ @members = members
207
207
 
208
- super "#{Location.to_string location}: #{decl_str} has duplicated method definition: #{name}"
208
+ super "#{Location.to_string location}: #{qualified_method_name} has duplicated definitions"
209
209
  end
210
210
 
211
- def self.check!(decl:, methods:, name:, location:)
212
- if methods.key?(name)
213
- raise new(decl: decl, name: name, location: location)
211
+ def qualified_method_name
212
+ case type
213
+ when Types::ClassSingleton
214
+ "#{type.name}.#{method_name}"
215
+ else
216
+ "#{type.name}##{method_name}"
214
217
  end
215
218
  end
219
+
220
+ def location
221
+ members[0].location
222
+ end
216
223
  end
217
224
 
218
- class MethodDefinitionConflictWithInterfaceMixinError < StandardError
225
+ class DuplicatedInterfaceMethodDefinitionError < StandardError
219
226
  include MethodNameHelper
220
227
 
221
- attr_reader :type_name
228
+ attr_reader :type
222
229
  attr_reader :method_name
223
- attr_reader :kind
224
- attr_reader :mixin_member
225
- attr_reader :entries
230
+ attr_reader :member
226
231
 
227
- def initialize(type_name:, method_name:, kind:, mixin_member:, entries:)
228
- @type_name = type_name
232
+ def initialize(type:, method_name:, member:)
233
+ @type = type
229
234
  @method_name = method_name
230
- @kind = kind
231
- @mixin_member = mixin_member
232
- @entries = entries
235
+ @member = member
233
236
 
234
- super "#{entries[0].decl.location}: Duplicated method with interface mixin: #{method_name_string}"
237
+ super "#{member.location}: Duplicated method definition: #{qualified_method_name}"
238
+ end
239
+
240
+ def qualified_method_name
241
+ case type
242
+ when Types::ClassSingleton
243
+ "#{type.name}.#{method_name}"
244
+ else
245
+ "#{type.name}##{method_name}"
246
+ end
235
247
  end
236
248
  end
237
249
 
@@ -247,12 +259,6 @@ module RBS
247
259
 
248
260
  super "#{Location.to_string location}: Unknown method alias name: #{original_name} => #{aliased_name}"
249
261
  end
250
-
251
- def self.check!(methods:, original_name:, aliased_name:, location:)
252
- unless methods.key?(original_name)
253
- raise new(original_name: original_name, aliased_name: aliased_name, location: location)
254
- end
255
- end
256
262
  end
257
263
 
258
264
  class SuperclassMismatchError < StandardError
@@ -336,33 +342,32 @@ module RBS
336
342
  end
337
343
 
338
344
  class InvalidVarianceAnnotationError < StandardError
339
- MethodTypeError = Struct.new(:method_name, :method_type, :param, keyword_init: true)
340
- InheritanceError = Struct.new(:super_class, :param, keyword_init: true)
341
- MixinError = Struct.new(:include_member, :param, keyword_init: true)
345
+ attr_reader :type_name
346
+ attr_reader :param
347
+ attr_reader :location
342
348
 
343
- attr_reader :decl
344
- attr_reader :errors
349
+ def initialize(type_name:, param:, location:)
350
+ @type_name = type_name
351
+ @param = param
352
+ @location = location
345
353
 
346
- def initialize(decl:, errors:)
347
- @decl = decl
348
- @errors = errors
349
-
350
- message = [
351
- "#{Location.to_string decl.location}: Invalid variance annotation: #{decl.name}"
352
- ]
353
-
354
- errors.each do |error|
355
- case error
356
- when MethodTypeError
357
- message << " MethodTypeError (#{error.param.name}): on `#{error.method_name}` #{error.method_type.to_s} (#{error.method_type.location&.start_line})"
358
- when InheritanceError
359
- message << " InheritanceError: #{error.super_class}"
360
- when MixinError
361
- message << " MixinError: #{error.include_member.name} (#{error.include_member.location&.start_line})"
362
- end
363
- end
354
+ super "#{Location.to_string location}: Type parameter variance error: #{param.name} is #{param.variance} but used as incompatible variance"
355
+ end
356
+ end
357
+
358
+ class RecursiveAliasDefinitionError < StandardError
359
+ attr_reader :type
360
+ attr_reader :defs
364
361
 
365
- super message.join("\n")
362
+ def initialize(type:, defs:)
363
+ @type = type
364
+ @defs = defs
365
+
366
+ super "#{Location.to_string location}: Recursive aliases in #{type}: #{defs.map(&:name).join(", ")}"
367
+ end
368
+
369
+ def location
370
+ defs[0].original.location
366
371
  end
367
372
  end
368
373
  end