rbs 0.4.0 → 0.5.0

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +7 -1
  3. data/.gitignore +1 -1
  4. data/CHANGELOG.md +7 -0
  5. data/Gemfile +12 -0
  6. data/README.md +86 -47
  7. data/Rakefile +54 -21
  8. data/bin/rbs-prof +9 -0
  9. data/bin/run_in_md.rb +49 -0
  10. data/lib/rbs.rb +2 -0
  11. data/lib/rbs/ast/declarations.rb +62 -7
  12. data/lib/rbs/ast/members.rb +41 -17
  13. data/lib/rbs/cli.rb +299 -121
  14. data/lib/rbs/constant.rb +4 -4
  15. data/lib/rbs/constant_table.rb +50 -44
  16. data/lib/rbs/definition.rb +175 -59
  17. data/lib/rbs/definition_builder.rb +647 -603
  18. data/lib/rbs/environment.rb +338 -209
  19. data/lib/rbs/environment_walker.rb +14 -23
  20. data/lib/rbs/errors.rb +141 -3
  21. data/lib/rbs/parser.y +14 -9
  22. data/lib/rbs/prototype/rb.rb +100 -112
  23. data/lib/rbs/prototype/rbi.rb +4 -2
  24. data/lib/rbs/prototype/runtime.rb +10 -6
  25. data/lib/rbs/substitution.rb +8 -1
  26. data/lib/rbs/test/hook.rb +2 -2
  27. data/lib/rbs/test/setup.rb +3 -1
  28. data/lib/rbs/test/test_helper.rb +2 -5
  29. data/lib/rbs/test/type_check.rb +1 -2
  30. data/lib/rbs/type_name_resolver.rb +58 -0
  31. data/lib/rbs/types.rb +94 -2
  32. data/lib/rbs/validator.rb +51 -0
  33. data/lib/rbs/variance_calculator.rb +12 -2
  34. data/lib/rbs/version.rb +1 -1
  35. data/lib/rbs/writer.rb +125 -89
  36. data/rbs.gemspec +0 -10
  37. data/schema/decls.json +15 -0
  38. data/schema/members.json +3 -0
  39. data/stdlib/benchmark/benchmark.rbs +151 -151
  40. data/stdlib/builtin/enumerable.rbs +1 -1
  41. data/stdlib/builtin/file.rbs +0 -3
  42. data/stdlib/builtin/io.rbs +4 -4
  43. data/stdlib/builtin/thread.rbs +2 -2
  44. data/stdlib/csv/csv.rbs +4 -6
  45. data/stdlib/fiber/fiber.rbs +1 -1
  46. data/stdlib/json/json.rbs +1 -1
  47. data/stdlib/mutex_m/mutex_m.rbs +77 -0
  48. data/stdlib/pathname/pathname.rbs +6 -6
  49. data/stdlib/prime/integer-extension.rbs +1 -1
  50. data/stdlib/prime/prime.rbs +44 -44
  51. data/stdlib/tmpdir/tmpdir.rbs +1 -1
  52. metadata +8 -129
@@ -4,23 +4,23 @@ module RBS
4
4
  attr_reader :type
5
5
  attr_reader :declaration
6
6
 
7
- def initialize(name:, type:, declaration:)
7
+ def initialize(name:, type:, entry:)
8
8
  @name = name
9
9
  @type = type
10
- @declaration = declaration
10
+ @entry = entry
11
11
  end
12
12
 
13
13
  def ==(other)
14
14
  other.is_a?(Constant) &&
15
15
  other.name == name &&
16
16
  other.type == type &&
17
- other.declaration == declaration
17
+ other.entry == entry
18
18
  end
19
19
 
20
20
  alias eql? ==
21
21
 
22
22
  def hash
23
- self.class.hash ^ name.hash ^ type.hash ^ declaration.hash
23
+ self.class.hash ^ name.hash ^ type.hash ^ entry.hash
24
24
  end
25
25
  end
26
26
  end
@@ -7,21 +7,34 @@ module RBS
7
7
  definition_builder.env
8
8
  end
9
9
 
10
+ def resolver
11
+ @resolver ||= TypeNameResolver.from_env(env)
12
+ end
13
+
10
14
  def initialize(builder:)
11
15
  @definition_builder = builder
12
16
  @constant_scopes_cache = {}
13
17
  end
14
18
 
19
+ def absolute_type(type, context:)
20
+ type.map_type_name do |type_name, location|
21
+ absolute_type_name(type_name, context: context, location: location)
22
+ end
23
+ end
24
+
25
+ def absolute_type_name(type_name, context:, location:)
26
+ resolver.resolve(type_name, context: context) or
27
+ raise NoTypeFoundError.new(type_name: type_name, location: location)
28
+ end
29
+
15
30
  def name_to_constant(name)
16
31
  case
17
- when env.name_to_constant.key?(name)
18
- decl = env.name_to_constant[name]
19
- type = env.absolute_type(decl.type, namespace: name.namespace) {|type| type.name.absolute! }
20
- Constant.new(name: name, type: type, declaration: decl)
21
- when env.class?(name)
22
- decl = env.name_to_decl[name]
32
+ when entry = env.constant_decls[name]
33
+ type = absolute_type(entry.decl.type, context: entry.context)
34
+ Constant.new(name: name, type: type, entry: entry)
35
+ when entry = env.class_decls[name]
23
36
  type = Types::ClassSingleton.new(name: name, location: nil)
24
- Constant.new(name: name, type: type, declaration: decl)
37
+ Constant.new(name: name, type: type, entry: entry)
25
38
  end
26
39
  end
27
40
 
@@ -88,14 +101,18 @@ module RBS
88
101
  end
89
102
 
90
103
  def constant_scopes_module(name, scopes:)
91
- decl = env.find_class(name)
104
+ entry = env.class_decls[name]
92
105
  namespace = name.to_namespace
93
106
 
94
- decl.members.each do |member|
95
- case member
96
- when AST::Members::Include
97
- constant_scopes_module absolute_type_name(member.name, namespace: namespace),
98
- scopes: scopes
107
+ entry.decls.each do |d|
108
+ d.decl.members.each do |member|
109
+ case member
110
+ when AST::Members::Include
111
+ if member.name.class?
112
+ constant_scopes_module absolute_type_name(member.name, context: d.context, location: member.location),
113
+ scopes: scopes
114
+ end
115
+ end
99
116
  end
100
117
  end
101
118
 
@@ -103,53 +120,42 @@ module RBS
103
120
  end
104
121
 
105
122
  def constant_scopes0(name, scopes: [])
106
- decl = env.find_class(name)
123
+ entry = env.class_decls[name]
107
124
  namespace = name.to_namespace
108
125
 
109
- case decl
110
- when AST::Declarations::Module
111
- constant_scopes0 BuiltinNames::Module.name, scopes: scopes
112
- constant_scopes_module name, scopes: scopes
113
-
114
- when AST::Declarations::Class
126
+ case entry
127
+ when Environment::ClassEntry
115
128
  unless name == BuiltinNames::BasicObject.name
116
- super_name = decl.super_class&.yield_self {|super_class|
117
- absolute_type_name(super_class.name, namespace: namespace)
118
- } || BuiltinNames::Object.name
129
+ super_name = entry.primary.decl.super_class&.yield_self do |super_class|
130
+ absolute_type_name(super_class.name, context: entry.primary.context, location: entry.primary.decl.location)
131
+ end || BuiltinNames::Object.name
119
132
 
120
133
  constant_scopes0 super_name, scopes: scopes
121
134
  end
122
135
 
123
- decl.members.each do |member|
124
- case member
125
- when AST::Members::Include
126
- constant_scopes_module absolute_type_name(member.name, namespace: namespace),
127
- scopes: scopes
136
+ entry.decls.each do |d|
137
+ d.decl.members.each do |member|
138
+ case member
139
+ when AST::Members::Include
140
+ if member.name.class?
141
+ constant_scopes_module absolute_type_name(member.name, context: d.context, location: member.location),
142
+ scopes: scopes
143
+ end
144
+ end
128
145
  end
129
146
  end
130
147
 
131
148
  scopes.unshift namespace
149
+
150
+ when Environment::ModuleEntry
151
+ constant_scopes0 BuiltinNames::Module.name, scopes: scopes
152
+ constant_scopes_module name, scopes: scopes
153
+
132
154
  else
133
155
  raise "Unexpected declaration: #{name} (#{decl.class})"
134
156
  end
135
157
 
136
- env.each_extension(name).sort_by {|e| e.extension_name.to_s }.each do |extension|
137
- extension.members.each do |member|
138
- case member
139
- when AST::Members::Include
140
- constant_scopes_module absolute_type_name(member.name, namespace: namespace),
141
- scopes: []
142
- end
143
- end
144
- end
145
-
146
158
  scopes
147
159
  end
148
-
149
- def absolute_type_name(name, namespace:)
150
- env.absolute_type_name(name, namespace: namespace) do
151
- raise
152
- end
153
- end
154
160
  end
155
161
  end
@@ -10,27 +10,76 @@ module RBS
10
10
  @type = type
11
11
  @declared_in = declared_in
12
12
  end
13
+
14
+ def sub(s)
15
+ self.class.new(
16
+ parent_variable: parent_variable,
17
+ type: type.sub(s),
18
+ declared_in: declared_in
19
+ )
20
+ end
13
21
  end
14
22
 
15
23
  class Method
24
+ class TypeDef
25
+ attr_reader :type
26
+ attr_reader :member
27
+ attr_reader :defined_in
28
+ attr_reader :implemented_in
29
+
30
+ def initialize(type:, member:, defined_in:, implemented_in:)
31
+ @type = type
32
+ @member = member
33
+ @defined_in = defined_in
34
+ @implemented_in = implemented_in
35
+ end
36
+
37
+ def comment
38
+ member.comment
39
+ end
40
+
41
+ def annotations
42
+ member.annotations
43
+ end
44
+
45
+ def update(type: self.type, member: self.member, defined_in: self.defined_in, implemented_in: self.implemented_in)
46
+ TypeDef.new(type: type, member: member, defined_in: defined_in, implemented_in: implemented_in)
47
+ end
48
+ end
49
+
16
50
  attr_reader :super_method
17
- attr_reader :method_types
18
- attr_reader :defined_in
19
- attr_reader :implemented_in
51
+ attr_reader :defs
20
52
  attr_reader :accessibility
21
- attr_reader :attributes
22
- attr_reader :annotations
23
- attr_reader :comment
24
53
 
25
- def initialize(super_method:, method_types:, defined_in:, implemented_in:, accessibility:, attributes:, annotations:, comment:)
54
+ def initialize(super_method:, defs:, accessibility:)
26
55
  @super_method = super_method
27
- @method_types = method_types
28
- @defined_in = defined_in
29
- @implemented_in = implemented_in
56
+ @defs = defs
30
57
  @accessibility = accessibility
31
- @attributes = attributes
32
- @annotations = annotations
33
- @comment = comment
58
+ end
59
+
60
+ def defined_in
61
+ @defined_in ||= defs.last.defined_in
62
+ end
63
+
64
+ def implemented_in
65
+ @implemented_in ||= defs.last.implemented_in
66
+ end
67
+
68
+ def method_types
69
+ @method_types ||= defs.map(&:type)
70
+ end
71
+
72
+ def comments
73
+ @comments ||= defs.map(&:comment).compact
74
+ end
75
+
76
+ def annotations
77
+ @annotations ||= defs.flat_map(&:annotations)
78
+ end
79
+
80
+ # @deprecated
81
+ def attributes
82
+ []
34
83
  end
35
84
 
36
85
  def public?
@@ -44,28 +93,24 @@ module RBS
44
93
  def sub(s)
45
94
  self.class.new(
46
95
  super_method: super_method&.sub(s),
47
- method_types: method_types.map {|ty| ty.sub(s) },
48
- defined_in: defined_in,
49
- implemented_in: implemented_in,
50
- accessibility: @accessibility,
51
- attributes: attributes,
52
- annotations: annotations,
53
- comment: comment
96
+ defs: defs.map {|defn| defn.update(type: defn.type.sub(s)) },
97
+ accessibility: @accessibility
54
98
  )
55
99
  end
56
100
 
57
101
  def map_type(&block)
58
102
  self.class.new(
59
103
  super_method: super_method&.map_type(&block),
60
- method_types: method_types.map do |ty|
61
- ty.map_type(&block)
62
- end,
63
- defined_in: defined_in,
64
- implemented_in: implemented_in,
65
- accessibility: @accessibility,
66
- attributes: attributes,
67
- annotations: annotations,
68
- comment: comment
104
+ defs: defs.map {|defn| defn.update(type: defn.type.map_type(&block)) },
105
+ accessibility: @accessibility
106
+ )
107
+ end
108
+
109
+ def map_method_type(&block)
110
+ self.class.new(
111
+ super_method: super_method,
112
+ defs: defs.map {|defn| defn.update(type: yield(defn.type)) },
113
+ accessibility: @accessibility
69
114
  )
70
115
  end
71
116
  end
@@ -73,78 +118,149 @@ module RBS
73
118
  module Ancestor
74
119
  Instance = Struct.new(:name, :args, keyword_init: true)
75
120
  Singleton = Struct.new(:name, keyword_init: true)
76
- ExtensionInstance = Struct.new(:name, :extension_name, :args, keyword_init: true)
77
- ExtensionSingleton = Struct.new(:name, :extension_name, keyword_init: true)
78
121
  end
79
122
 
80
- attr_reader :declaration
123
+ class InstanceAncestors
124
+ attr_reader :type_name
125
+ attr_reader :params
126
+ attr_reader :ancestors
127
+
128
+ def initialize(type_name:, params:, ancestors:)
129
+ @type_name = type_name
130
+ @params = params
131
+ @ancestors = ancestors
132
+ end
133
+
134
+ def apply(args, location:)
135
+ InvalidTypeApplicationError.check!(
136
+ type_name: type_name,
137
+ args: args,
138
+ params: params,
139
+ location: location
140
+ )
141
+
142
+ subst = Substitution.build(params, args)
143
+
144
+ ancestors.map do |ancestor|
145
+ case ancestor
146
+ when Ancestor::Instance
147
+ if ancestor.args.empty?
148
+ ancestor
149
+ else
150
+ Ancestor::Instance.new(
151
+ name: ancestor.name,
152
+ args: ancestor.args.map {|type| type.sub(subst) }
153
+ )
154
+ end
155
+ when Ancestor::Singleton
156
+ ancestor
157
+ end
158
+ end
159
+ end
160
+ end
161
+
162
+ class SingletonAncestors
163
+ attr_reader :type_name
164
+ attr_reader :ancestors
165
+
166
+ def initialize(type_name:, ancestors:)
167
+ @type_name = type_name
168
+ @ancestors = ancestors
169
+ end
170
+ end
171
+
172
+ attr_reader :type_name
173
+ attr_reader :entry
174
+ attr_reader :ancestors
81
175
  attr_reader :self_type
82
176
  attr_reader :methods
83
177
  attr_reader :instance_variables
84
178
  attr_reader :class_variables
85
- attr_reader :ancestors
86
179
 
87
- def initialize(declaration:, self_type:, ancestors:)
88
- unless declaration.is_a?(AST::Declarations::Class) ||
89
- declaration.is_a?(AST::Declarations::Module) ||
90
- declaration.is_a?(AST::Declarations::Interface) ||
91
- declaration.is_a?(AST::Declarations::Extension)
92
- raise "Declaration should be a class, module, or interface: #{declaration.name}"
180
+ def initialize(type_name:, entry:, self_type:, ancestors:)
181
+ case entry
182
+ when Environment::ClassEntry, Environment::ModuleEntry
183
+ # ok
184
+ else
185
+ unless entry.decl.is_a?(AST::Declarations::Interface)
186
+ raise "Declaration should be a class, module, or interface: #{type_name}"
187
+ end
93
188
  end
94
189
 
95
- unless (self_type.is_a?(Types::ClassSingleton) || self_type.is_a?(Types::Interface) || self_type.is_a?(Types::ClassInstance)) && self_type.name == declaration.name.absolute!
190
+ unless self_type.is_a?(Types::ClassSingleton) || self_type.is_a?(Types::Interface) || self_type.is_a?(Types::ClassInstance)
96
191
  raise "self_type should be the type of declaration: #{self_type}"
97
192
  end
98
193
 
194
+ @type_name = type_name
99
195
  @self_type = self_type
100
- @declaration = declaration
196
+ @entry = entry
101
197
  @methods = {}
102
198
  @instance_variables = {}
103
199
  @class_variables = {}
104
200
  @ancestors = ancestors
105
201
  end
106
202
 
107
- def name
108
- declaration.name
109
- end
110
-
111
203
  def class?
112
- declaration.is_a?(AST::Declarations::Class)
204
+ entry.is_a?(Environment::ClassEntry)
113
205
  end
114
206
 
115
207
  def module?
116
- declaration.is_a?(AST::Declarations::Module)
208
+ entry.is_a?(Environment::ModuleEntry)
209
+ end
210
+
211
+ def interface?
212
+ entry.is_a?(Environment::SingleEntry) && entry.decl.is_a?(AST::Declarations::Interface)
117
213
  end
118
214
 
119
215
  def class_type?
120
- @self_type.is_a?(Types::ClassSingleton)
216
+ self_type.is_a?(Types::ClassSingleton)
121
217
  end
122
218
 
123
219
  def instance_type?
124
- @self_type.is_a?(Types::ClassInstance)
220
+ self_type.is_a?(Types::ClassInstance)
125
221
  end
126
222
 
127
223
  def interface_type?
128
- @self_type.is_a?(Types::Interface)
224
+ self_type.is_a?(Types::Interface)
129
225
  end
130
226
 
131
227
  def type_params
132
- @self_type.args.map(&:name)
228
+ type_params_decl.each.map(&:name)
133
229
  end
134
230
 
135
231
  def type_params_decl
136
- case declaration
137
- when AST::Declarations::Extension
138
- nil
139
- else
140
- declaration.type_params
232
+ case entry
233
+ when Environment::ClassEntry, Environment::ModuleEntry
234
+ entry.type_params
235
+ when Environment::SingleEntry
236
+ entry.decl.type_params
141
237
  end
142
238
  end
143
239
 
240
+ def sub(s)
241
+ definition = self.class.new(type_name: type_name, self_type: self_type.sub(s), ancestors: ancestors, entry: entry)
242
+
243
+ definition.methods.merge!(methods.transform_values {|method| method.sub(s) })
244
+ definition.instance_variables.merge!(instance_variables.transform_values {|v| v.sub(s) })
245
+ definition.class_variables.merge!(class_variables.transform_values {|v| v.sub(s) })
246
+
247
+ definition
248
+ end
249
+
250
+ def map_method_type(&block)
251
+ definition = self.class.new(type_name: type_name, self_type: self_type, ancestors: ancestors, entry: entry)
252
+
253
+ definition.methods.merge!(methods.transform_values {|method| method.map_method_type(&block) })
254
+ definition.instance_variables.merge!(instance_variables)
255
+ definition.class_variables.merge!(class_variables)
256
+
257
+ definition
258
+ end
259
+
144
260
  def each_type(&block)
145
261
  if block_given?
146
262
  methods.each_value do |method|
147
- if method.defined_in == self.declaration
263
+ if method.defined_in == type_name
148
264
  method.method_types.each do |method_type|
149
265
  method_type.each_type(&block)
150
266
  end
@@ -152,13 +268,13 @@ module RBS
152
268
  end
153
269
 
154
270
  instance_variables.each_value do |var|
155
- if var.declared_in == self.declaration
271
+ if var.declared_in == type_name
156
272
  yield var.type
157
273
  end
158
274
  end
159
275
 
160
276
  class_variables.each_value do |var|
161
- if var.declared_in == self.declaration
277
+ if var.declared_in == type_name
162
278
  yield var.type
163
279
  end
164
280
  end