rbs 0.18.0 → 1.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/Rakefile +4 -0
- data/core/builtin.rbs +4 -0
- data/core/file.rbs +0 -4
- data/core/hash.rbs +1 -3
- data/core/io.rbs +159 -6
- data/core/kernel.rbs +1 -1
- data/core/time.rbs +0 -12
- data/goodcheck.yml +20 -0
- data/lib/rbs.rb +2 -0
- data/lib/rbs/ast/declarations.rb +7 -2
- data/lib/rbs/ast/members.rb +10 -4
- data/lib/rbs/cli.rb +10 -10
- data/lib/rbs/definition.rb +70 -3
- data/lib/rbs/definition_builder.rb +544 -989
- data/lib/rbs/definition_builder/ancestor_builder.rb +476 -0
- data/lib/rbs/definition_builder/method_builder.rb +217 -0
- data/lib/rbs/environment.rb +5 -1
- data/lib/rbs/environment_loader.rb +1 -1
- data/lib/rbs/environment_walker.rb +16 -10
- data/lib/rbs/errors.rb +71 -66
- data/lib/rbs/method_type.rb +1 -31
- data/lib/rbs/parser.rb +1000 -894
- data/lib/rbs/parser.y +108 -57
- data/lib/rbs/prototype/rb.rb +14 -3
- data/lib/rbs/prototype/rbi.rb +6 -6
- data/lib/rbs/prototype/runtime.rb +53 -33
- data/lib/rbs/substitution.rb +4 -0
- data/lib/rbs/test.rb +3 -1
- data/lib/rbs/test/hook.rb +24 -7
- data/lib/rbs/types.rb +63 -6
- data/lib/rbs/validator.rb +4 -2
- data/lib/rbs/variance_calculator.rb +5 -1
- data/lib/rbs/version.rb +1 -1
- data/lib/rbs/writer.rb +9 -1
- data/schema/members.json +5 -1
- data/sig/definition.rbs +6 -1
- data/sig/definition_builder.rbs +3 -0
- data/sig/errors.rbs +20 -0
- data/sig/members.rbs +4 -1
- data/sig/method_types.rbs +3 -16
- data/sig/type_name_resolver.rbs +4 -2
- data/sig/types.rbs +17 -1
- data/sig/validator.rbs +12 -0
- data/stdlib/dbm/0/dbm.rbs +0 -2
- data/stdlib/logger/0/log_device.rbs +1 -2
- data/stdlib/monitor/0/monitor.rbs +119 -0
- data/stdlib/time/0/time.rbs +327 -0
- data/stdlib/tsort/0/tsort.rbs +8 -0
- data/stdlib/uri/0/common.rbs +401 -0
- data/stdlib/uri/0/rfc2396_parser.rbs +9 -0
- data/stdlib/uri/0/rfc3986_parser.rbs +2 -0
- data/steep/Gemfile.lock +13 -14
- 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
|
data/lib/rbs/environment.rb
CHANGED
@@ -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,
|
@@ -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
|
-
|
56
|
+
each_type_node type, &block
|
57
57
|
end
|
58
58
|
end
|
59
59
|
when name.alias?
|
60
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
131
|
+
each_type_node ty, &block
|
126
132
|
end
|
127
133
|
when RBS::Types::Optional
|
128
|
-
|
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
|
-
|
139
|
+
each_type_node ty, &block
|
134
140
|
end
|
135
141
|
when RBS::Types::Proc
|
136
142
|
type.each_type do |ty|
|
137
|
-
|
143
|
+
each_type_node ty, &block
|
138
144
|
end
|
139
145
|
else
|
140
146
|
raise "Unexpected type given: #{type}"
|
data/lib/rbs/errors.rb
CHANGED
@@ -68,18 +68,20 @@ module RBS
|
|
68
68
|
attr_reader :location
|
69
69
|
|
70
70
|
def initialize(ancestors:, location:)
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
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 :
|
198
|
-
attr_reader :
|
199
|
+
attr_reader :type
|
200
|
+
attr_reader :method_name
|
201
|
+
attr_reader :members
|
199
202
|
|
200
|
-
def initialize(
|
201
|
-
|
202
|
-
|
203
|
-
|
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}: #{
|
208
|
+
super "#{Location.to_string location}: #{qualified_method_name} has duplicated definitions"
|
209
209
|
end
|
210
210
|
|
211
|
-
def
|
212
|
-
|
213
|
-
|
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
|
225
|
+
class DuplicatedInterfaceMethodDefinitionError < StandardError
|
219
226
|
include MethodNameHelper
|
220
227
|
|
221
|
-
attr_reader :
|
228
|
+
attr_reader :type
|
222
229
|
attr_reader :method_name
|
223
|
-
attr_reader :
|
224
|
-
attr_reader :mixin_member
|
225
|
-
attr_reader :entries
|
230
|
+
attr_reader :member
|
226
231
|
|
227
|
-
def initialize(
|
228
|
-
@
|
232
|
+
def initialize(type:, method_name:, member:)
|
233
|
+
@type = type
|
229
234
|
@method_name = method_name
|
230
|
-
@
|
231
|
-
@mixin_member = mixin_member
|
232
|
-
@entries = entries
|
235
|
+
@member = member
|
233
236
|
|
234
|
-
super "#{
|
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
|
-
|
340
|
-
|
341
|
-
|
345
|
+
attr_reader :type_name
|
346
|
+
attr_reader :param
|
347
|
+
attr_reader :location
|
342
348
|
|
343
|
-
|
344
|
-
|
349
|
+
def initialize(type_name:, param:, location:)
|
350
|
+
@type_name = type_name
|
351
|
+
@param = param
|
352
|
+
@location = location
|
345
353
|
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
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
|
-
|
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
|