steep 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/README.md +95 -0
- data/Rakefile +23 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bin/smoke_runner.rb +106 -0
- data/exe/steep +18 -0
- data/lib/steep.rb +33 -0
- data/lib/steep/annotation.rb +223 -0
- data/lib/steep/cli.rb +79 -0
- data/lib/steep/drivers/check.rb +141 -0
- data/lib/steep/errors.rb +207 -0
- data/lib/steep/interface.rb +280 -0
- data/lib/steep/parser.y +311 -0
- data/lib/steep/signature/class.rb +358 -0
- data/lib/steep/signature/errors.rb +78 -0
- data/lib/steep/signature/extension.rb +51 -0
- data/lib/steep/signature/interface.rb +48 -0
- data/lib/steep/source.rb +98 -0
- data/lib/steep/type_assignability.rb +362 -0
- data/lib/steep/type_construction.rb +993 -0
- data/lib/steep/type_name.rb +37 -0
- data/lib/steep/types.rb +4 -0
- data/lib/steep/types/any.rb +31 -0
- data/lib/steep/types/class.rb +27 -0
- data/lib/steep/types/instance.rb +27 -0
- data/lib/steep/types/merge.rb +32 -0
- data/lib/steep/types/name.rb +57 -0
- data/lib/steep/types/union.rb +42 -0
- data/lib/steep/types/var.rb +38 -0
- data/lib/steep/typing.rb +70 -0
- data/lib/steep/version.rb +3 -0
- data/manual/annotations.md +144 -0
- data/sig/signature.rbi +54 -0
- data/sig/types.rbi +43 -0
- data/smoke/and/a.rb +9 -0
- data/smoke/array/a.rb +22 -0
- data/smoke/block/a.rb +12 -0
- data/smoke/block/a.rbi +4 -0
- data/smoke/case/a.rb +20 -0
- data/smoke/class/a.rb +31 -0
- data/smoke/class/a.rbi +9 -0
- data/smoke/class/b.rb +7 -0
- data/smoke/class/c.rb +10 -0
- data/smoke/const/a.rb +30 -0
- data/smoke/dstr/a.rb +6 -0
- data/smoke/extension/a.rb +11 -0
- data/smoke/extension/a.rbi +8 -0
- data/smoke/extension/b.rb +12 -0
- data/smoke/extension/c.rb +9 -0
- data/smoke/hello/hello.rb +13 -0
- data/smoke/hello/hello.rbi +7 -0
- data/smoke/if/a.rb +20 -0
- data/smoke/implements/a.rb +14 -0
- data/smoke/implements/a.rbi +6 -0
- data/smoke/literal/a.rb +16 -0
- data/smoke/map/a.rb +5 -0
- data/smoke/method/a.rb +26 -0
- data/smoke/method/a.rbi +0 -0
- data/smoke/module/a.rb +21 -0
- data/smoke/module/a.rbi +7 -0
- data/smoke/module/b.rb +8 -0
- data/smoke/self/a.rb +23 -0
- data/smoke/self/a.rbi +4 -0
- data/smoke/super/a.rb +34 -0
- data/smoke/super/a.rbi +10 -0
- data/smoke/yield/a.rb +18 -0
- data/stdlib/builtin.rbi +89 -0
- data/steep.gemspec +32 -0
- metadata +214 -0
data/lib/steep/parser.y
ADDED
@@ -0,0 +1,311 @@
|
|
1
|
+
class Steep::Parser
|
2
|
+
|
3
|
+
rule
|
4
|
+
|
5
|
+
target: type_METHOD method_type { result = val[1] }
|
6
|
+
| type_SIGNATURE signatures { result = val[1] }
|
7
|
+
| type_ANNOTATION annotation { result = val[1] }
|
8
|
+
|
9
|
+
method_type: type_params params block_opt ARROW return_type
|
10
|
+
{ result = Interface::MethodType.new(type_params: val[0], params: val[1], block: val[2], return_type: val[4]) }
|
11
|
+
|
12
|
+
return_type: simple_type
|
13
|
+
| LPAREN union_seq RPAREN { result = Types::Union.new(types: val[1]) }
|
14
|
+
|
15
|
+
params: { result = Interface::Params.empty }
|
16
|
+
| LPAREN params0 RPAREN { result = val[1] }
|
17
|
+
| type { result = Interface::Params.empty.with(required: [val[0]]) }
|
18
|
+
|
19
|
+
params0: required_param { result = Interface::Params.empty.with(required: [val[0]]) }
|
20
|
+
| required_param COMMA params0 { result = val[2].with(required: [val[0]] + val[2].required) }
|
21
|
+
| params1 { result = val[0] }
|
22
|
+
|
23
|
+
params1: optional_param { result = Interface::Params.empty.with(optional: [val[0]]) }
|
24
|
+
| optional_param COMMA params1 { result = val[2].with(optional: [val[0]] + val[2].optional) }
|
25
|
+
| params2 { result = val[0] }
|
26
|
+
|
27
|
+
params2: rest_param { result = Interface::Params.empty.with(rest: val[0]) }
|
28
|
+
| rest_param COMMA params3 { result = val[2].with(rest: val[0]) }
|
29
|
+
| params3 { result = val[0] }
|
30
|
+
|
31
|
+
params3: required_keyword { result = Interface::Params.empty.with(required_keywords: val[0]) }
|
32
|
+
| optional_keyword { result = Interface::Params.empty.with(optional_keywords: val[0]) }
|
33
|
+
| required_keyword COMMA params3 { result = val[2].with(required_keywords: val[2].required_keywords.merge(val[0])) }
|
34
|
+
| optional_keyword COMMA params3 { result = val[2].with(optional_keywords: val[2].optional_keywords.merge(val[0])) }
|
35
|
+
| params4 { result = val[0] }
|
36
|
+
|
37
|
+
params4: { result = Interface::Params.empty }
|
38
|
+
| STAR2 type { result = Interface::Params.empty.with(rest_keywords: val[1]) }
|
39
|
+
|
40
|
+
required_param: type { result = val[0] }
|
41
|
+
optional_param: QUESTION type { result = val[1] }
|
42
|
+
rest_param: STAR type { result = val[1] }
|
43
|
+
required_keyword: keyword COLON type { result = { val[0] => val[2] } }
|
44
|
+
optional_keyword: QUESTION keyword COLON type { result = { val[1] => val[3] } }
|
45
|
+
|
46
|
+
block_opt: { result = nil }
|
47
|
+
| LBRACE RBRACE { result = Interface::Block.new(params: Interface::Params.empty.with(rest: Types::Any.new),
|
48
|
+
return_type: Types::Any.new) }
|
49
|
+
| LBRACE block_params ARROW type RBRACE { result = Interface::Block.new(params: val[1], return_type: val[3]) }
|
50
|
+
|
51
|
+
block_params: LPAREN block_params0 RPAREN { result = val[1] }
|
52
|
+
| { result = Interface::Params.empty.with(rest: Types::Any.new) }
|
53
|
+
|
54
|
+
block_params0: required_param { result = Interface::Params.empty.with(required: [val[0]]) }
|
55
|
+
| required_param COMMA block_params0 { result = val[2].with(required: [val[0]] + val[2].required) }
|
56
|
+
| block_params1 { result = val[0] }
|
57
|
+
|
58
|
+
block_params1: optional_param { result = Interface::Params.empty.with(optional: [val[0]]) }
|
59
|
+
| optional_param COMMA block_params1 { result = val[2].with(optional: [val[0]] + val[2].optional) }
|
60
|
+
| block_params2 { result = val[0] }
|
61
|
+
|
62
|
+
block_params2: { result = Interface::Params.empty }
|
63
|
+
| rest_param { result = Interface::Params.empty.with(rest: val[0]) }
|
64
|
+
|
65
|
+
simple_type: INTERFACE_NAME { result = Types::Name.interface(name: val[0]) }
|
66
|
+
| INTERFACE_NAME LT type_seq GT { result = Types::Name.interface(name: val[0], params: val[2]) }
|
67
|
+
| MODULE_NAME { result = Types::Name.instance(name: val[0])}
|
68
|
+
| MODULE_NAME LT type_seq GT { result = Types::Name.instance(name: val[0], params: val[2]) }
|
69
|
+
| CLASS_IDENT { result = Types::Name.module(name: val[0]) }
|
70
|
+
| ANY { result = Types::Any.new }
|
71
|
+
| TVAR { result = Types::Var.new(name: val[0]) }
|
72
|
+
| CLASS { result = Types::Class.new }
|
73
|
+
| MODULE { result = Types::Class.new }
|
74
|
+
| INSTANCE { result = Types::Instance.new }
|
75
|
+
|
76
|
+
type: simple_type
|
77
|
+
| union_seq { result = Types::Union.new(types: val[0]) }
|
78
|
+
|
79
|
+
type_seq: type { result = [val[0]] }
|
80
|
+
| type COMMA type_seq { result = [val[0]] + val[2] }
|
81
|
+
|
82
|
+
union_seq: simple_type BAR simple_type { result = [val[0], val[2]] }
|
83
|
+
| simple_type BAR union_seq { result = [val[0]] + val[2] }
|
84
|
+
|
85
|
+
keyword: IDENT
|
86
|
+
| MODULE_NAME
|
87
|
+
| INTERFACE_NAME
|
88
|
+
| ANY { result = :any }
|
89
|
+
| CLASS { result = :class }
|
90
|
+
| MODULE { result = :module }
|
91
|
+
| INSTANCE { result = :instance }
|
92
|
+
|
93
|
+
signatures: { result = [] }
|
94
|
+
| interface signatures { result = [val[0]] + val[1] }
|
95
|
+
| class_decl signatures { result = [val[0]] + val[1] }
|
96
|
+
| module_decl signatures { result = [val[0]] + val[1] }
|
97
|
+
| extension_decl signatures { result = [val[0]] + val[1] }
|
98
|
+
|
99
|
+
interface: INTERFACE interface_name type_params method_decls END { result = Signature::Interface.new(name: val[1], params: val[2], methods: val[3]) }
|
100
|
+
class_decl: CLASS class_name type_params super_opt class_members END { result = Signature::Class.new(name: val[1], params: val[2], super_class: val[3], members: val[4] )}
|
101
|
+
module_decl: MODULE class_name type_params self_type_opt class_members END { result = Signature::Module.new(name: val[1], params: val[2], self_type: val[3], members: val[4]) }
|
102
|
+
extension_decl: EXTENSION class_name LPAREN class_name RPAREN class_members END { result = Signature::Extension.new(module_name: val[1], extension_name: val[3], members: val[5]) }
|
103
|
+
|
104
|
+
self_type_opt: { result = nil }
|
105
|
+
| COLON type { result = val[1] }
|
106
|
+
|
107
|
+
interface_name: INTERFACE_NAME { result = val[0] }
|
108
|
+
|
109
|
+
class_name: MODULE_NAME { result = val[0] }
|
110
|
+
|
111
|
+
class_members: { result = [] }
|
112
|
+
| class_member class_members { result = [val[0]] + val[1] }
|
113
|
+
|
114
|
+
class_member: instance_method_member { result = val[0] }
|
115
|
+
| class_method_member { result = val[0] }
|
116
|
+
| class_instance_method_member { result = val[0] }
|
117
|
+
| include_member { result = val[0] }
|
118
|
+
| extend_member { result = val[0] }
|
119
|
+
|
120
|
+
instance_method_member: DEF method_name COLON method_type_union { result = Signature::Members::InstanceMethod.new(name: val[1], types: val[3]) }
|
121
|
+
class_method_member: DEF SELF DOT method_name COLON method_type_union { result = Signature::Members::ModuleMethod.new(name: val[3], types: val[5]) }
|
122
|
+
class_instance_method_member: DEF SELFQ DOT method_name COLON method_type_union { result = Signature::Members::ModuleInstanceMethod.new(name: val[3], types: val[5]) }
|
123
|
+
include_member: INCLUDE type { result = Signature::Members::Include.new(name: val[1]) }
|
124
|
+
extend_member: EXTEND type { result = Signature::Members::Extend.new(name: val[1]) }
|
125
|
+
|
126
|
+
super_opt: { result = nil }
|
127
|
+
| LTCOLON type { result = val[1] }
|
128
|
+
|
129
|
+
type_params: { result = [] }
|
130
|
+
| LT type_param_seq GT { result = val[1] }
|
131
|
+
|
132
|
+
type_param_seq: TVAR { result = [val[0]] }
|
133
|
+
| TVAR COMMA type_param_seq { result = [val[0]] + val[2] }
|
134
|
+
|
135
|
+
method_decls: { result = {} }
|
136
|
+
| method_decl method_decls { result = val[1].merge(val[0]) }
|
137
|
+
|
138
|
+
method_decl: DEF method_name COLON method_type_union { result = { val[1] => val[3] }}
|
139
|
+
|
140
|
+
method_type_union: method_type { result = [val[0]] }
|
141
|
+
| method_type BAR method_type_union { result = [val[0]] + val[2] }
|
142
|
+
|
143
|
+
method_name: IDENT
|
144
|
+
| MODULE_NAME
|
145
|
+
| INTERFACE_NAME
|
146
|
+
| ANY { result = :any }
|
147
|
+
| INTERFACE { result = :interface }
|
148
|
+
| END { result = :end }
|
149
|
+
| PLUS { result = :+ }
|
150
|
+
| CLASS { result = :class }
|
151
|
+
| MODULE { result = :module }
|
152
|
+
| INSTANCE { result = :instance }
|
153
|
+
| OPERATOR
|
154
|
+
| METHOD_NAME
|
155
|
+
|
156
|
+
annotation: AT_TYPE VAR subject COLON type { result = Annotation::VarType.new(var: val[2], type: val[4]) }
|
157
|
+
| AT_TYPE METHOD subject COLON method_type { result = Annotation::MethodType.new(method: val[2], type: val[4]) }
|
158
|
+
| AT_TYPE RETURN COLON type { result = Annotation::ReturnType.new(type: val[3]) }
|
159
|
+
| AT_TYPE BLOCK COLON type { result = Annotation::BlockType.new(type: val[3]) }
|
160
|
+
| AT_TYPE SELF COLON type { result = Annotation::SelfType.new(type: val[3]) }
|
161
|
+
| AT_TYPE CONST CONST_PATH COLON type { result = Annotation::ConstType.new(name: val[2], type: val[4]) }
|
162
|
+
| AT_TYPE CONST MODULE_NAME COLON type { result = Annotation::ConstType.new(name: val[2], type: val[4]) }
|
163
|
+
| AT_TYPE INSTANCE COLON type { result = Annotation::InstanceType.new(type: val[3]) }
|
164
|
+
| AT_TYPE MODULE COLON type { result = Annotation::ModuleType.new(type: val[3]) }
|
165
|
+
| AT_TYPE IVAR IVAR_NAME COLON type { result = Annotation::IvarType.new(name: val[2], type: val[4]) }
|
166
|
+
| AT_TYPE { raise "Invalid type annotation" }
|
167
|
+
| AT_IMPLEMENTS MODULE_NAME { result = Annotation::Implements.new(module_name: val[1]) }
|
168
|
+
| AT_DYNAMIC method_name { result = Annotation::Dynamic.new(name: val[1]) }
|
169
|
+
|
170
|
+
subject: IDENT { result = val[0] }
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
---- inner
|
175
|
+
|
176
|
+
require "strscan"
|
177
|
+
|
178
|
+
attr_reader :input
|
179
|
+
|
180
|
+
def initialize(type, input)
|
181
|
+
super()
|
182
|
+
@type = type
|
183
|
+
@input = StringScanner.new(input)
|
184
|
+
end
|
185
|
+
|
186
|
+
def self.parse_method(input)
|
187
|
+
new(:METHOD, input).do_parse
|
188
|
+
end
|
189
|
+
|
190
|
+
def self.parse_signature(input)
|
191
|
+
new(:SIGNATURE, input).do_parse
|
192
|
+
end
|
193
|
+
|
194
|
+
def self.parse_annotation_opt(input)
|
195
|
+
new(:ANNOTATION, input).do_parse
|
196
|
+
rescue
|
197
|
+
nil
|
198
|
+
end
|
199
|
+
|
200
|
+
def next_token
|
201
|
+
if @type
|
202
|
+
type = @type
|
203
|
+
@type = nil
|
204
|
+
return [:"type_#{type}", nil]
|
205
|
+
end
|
206
|
+
|
207
|
+
case
|
208
|
+
when input.scan(/\s+/)
|
209
|
+
next_token
|
210
|
+
when input.scan(/#.*/)
|
211
|
+
next_token
|
212
|
+
when input.eos?
|
213
|
+
[false, false]
|
214
|
+
when input.scan(/->/)
|
215
|
+
[:ARROW, nil]
|
216
|
+
when input.scan(/\?/)
|
217
|
+
[:QUESTION, nil]
|
218
|
+
when input.scan(/\(/)
|
219
|
+
[:LPAREN, nil]
|
220
|
+
when input.scan(/\)/)
|
221
|
+
[:RPAREN, nil]
|
222
|
+
when input.scan(/{/)
|
223
|
+
[:LBRACE, nil]
|
224
|
+
when input.scan(/}/)
|
225
|
+
[:RBRACE, nil]
|
226
|
+
when input.scan(/,/)
|
227
|
+
[:COMMA, nil]
|
228
|
+
when input.scan(/[A-Z]\w*(::[A-Z]\w*)+/)
|
229
|
+
[:CONST_PATH, input.matched.to_sym]
|
230
|
+
when input.scan(/::[A-Z]\w*(::[A-Z]\w*)*/)
|
231
|
+
[:CONST_PATH, input.matched.to_sym]
|
232
|
+
when input.scan(/:/)
|
233
|
+
[:COLON, nil]
|
234
|
+
when input.scan(/\*\*/)
|
235
|
+
[:STAR2, nil]
|
236
|
+
when input.scan(/\*/)
|
237
|
+
[:STAR, nil]
|
238
|
+
when input.scan(/\+/)
|
239
|
+
[:PLUS, nil]
|
240
|
+
when input.scan(/\./)
|
241
|
+
[:DOT, nil]
|
242
|
+
when input.scan(/<:/)
|
243
|
+
[:LTCOLON, nil]
|
244
|
+
when input.scan(/(\[\]=)|(\[\])|===|==|\^|!=|<<|>>/)
|
245
|
+
[:OPERATOR, input.matched.to_sym]
|
246
|
+
when input.scan(/</)
|
247
|
+
[:LT, nil]
|
248
|
+
when input.scan(/>/)
|
249
|
+
[:GT, nil]
|
250
|
+
when input.scan(/any\b/)
|
251
|
+
[:ANY, nil]
|
252
|
+
when input.scan(/interface\b/)
|
253
|
+
[:INTERFACE, nil]
|
254
|
+
when input.scan(/end\b/)
|
255
|
+
[:END, nil]
|
256
|
+
when input.scan(/\|/)
|
257
|
+
[:BAR, nil]
|
258
|
+
when input.scan(/def\b/)
|
259
|
+
[:DEF, nil]
|
260
|
+
when input.scan(/@type\b/)
|
261
|
+
[:AT_TYPE, nil]
|
262
|
+
when input.scan(/@implements\b/)
|
263
|
+
[:AT_IMPLEMENTS, nil]
|
264
|
+
when input.scan(/@dynamic\b/)
|
265
|
+
[:AT_DYNAMIC, nil]
|
266
|
+
when input.scan(/const\b/)
|
267
|
+
[:CONST, nil]
|
268
|
+
when input.scan(/var\b/)
|
269
|
+
[:VAR, nil]
|
270
|
+
when input.scan(/return\b/)
|
271
|
+
[:RETURN, nil]
|
272
|
+
when input.scan(/block\b/)
|
273
|
+
[:BLOCK, nil]
|
274
|
+
when input.scan(/method\b/)
|
275
|
+
[:METHOD, nil]
|
276
|
+
when input.scan(/self\?/)
|
277
|
+
[:SELFQ, nil]
|
278
|
+
when input.scan(/self\b/)
|
279
|
+
[:SELF, nil]
|
280
|
+
when input.scan(/'\w+/)
|
281
|
+
[:TVAR, input.matched.gsub(/\A'/, '').to_sym]
|
282
|
+
when input.scan(/instance\b/)
|
283
|
+
[:INSTANCE, nil]
|
284
|
+
when input.scan(/class\b/)
|
285
|
+
[:CLASS, nil]
|
286
|
+
when input.scan(/module\b/)
|
287
|
+
[:MODULE, nil]
|
288
|
+
when input.scan(/include\b/)
|
289
|
+
[:INCLUDE, nil]
|
290
|
+
when input.scan(/extend\b/)
|
291
|
+
[:EXTEND, nil]
|
292
|
+
when input.scan(/instance\b/)
|
293
|
+
[:INSTANCE, nil]
|
294
|
+
when input.scan(/ivar\b/)
|
295
|
+
[:IVAR, nil]
|
296
|
+
when input.scan(/extension\b/)
|
297
|
+
[:EXTENSION, nil]
|
298
|
+
when input.scan(/[A-Z]\w*\.(class|module)\b/)
|
299
|
+
[:CLASS_IDENT, input.matched.gsub(/\.(class|module)$/, '').to_sym]
|
300
|
+
when input.scan(/\w+(\!|\?)/)
|
301
|
+
[:METHOD_NAME, input.matched.to_sym]
|
302
|
+
when input.scan(/[A-Z]\w*/)
|
303
|
+
[:MODULE_NAME, input.matched.to_sym]
|
304
|
+
when input.scan(/_\w+/)
|
305
|
+
[:INTERFACE_NAME, input.matched.to_sym]
|
306
|
+
when input.scan(/@[\w_]+/)
|
307
|
+
[:IVAR_NAME, input.matched.to_sym]
|
308
|
+
when input.scan(/\w+/)
|
309
|
+
[:IDENT, input.matched.to_sym]
|
310
|
+
end
|
311
|
+
end
|
@@ -0,0 +1,358 @@
|
|
1
|
+
module Steep
|
2
|
+
module Signature
|
3
|
+
module Members
|
4
|
+
class InstanceMethod
|
5
|
+
attr_reader :name
|
6
|
+
attr_reader :types
|
7
|
+
|
8
|
+
def initialize(name:, types:)
|
9
|
+
@name = name
|
10
|
+
@types = types
|
11
|
+
end
|
12
|
+
|
13
|
+
def ==(other)
|
14
|
+
other.is_a?(InstanceMethod) && other.name == name && other.types == types
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class ModuleMethod
|
19
|
+
attr_reader :name
|
20
|
+
attr_reader :types
|
21
|
+
|
22
|
+
def initialize(name:, types:)
|
23
|
+
@name = name
|
24
|
+
@types = types
|
25
|
+
end
|
26
|
+
|
27
|
+
def ==(other)
|
28
|
+
other.is_a?(ModuleMethod) && other.name == name && other.types == types
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class ModuleInstanceMethod
|
33
|
+
attr_reader :name
|
34
|
+
attr_reader :types
|
35
|
+
|
36
|
+
def initialize(name:, types:)
|
37
|
+
@name = name
|
38
|
+
@types = types
|
39
|
+
end
|
40
|
+
|
41
|
+
def ==(other)
|
42
|
+
other.is_a?(ModuleInstanceMethod) && other.name == name && other.types == types
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class Include
|
47
|
+
attr_reader :name
|
48
|
+
|
49
|
+
def initialize(name:)
|
50
|
+
@name = name
|
51
|
+
end
|
52
|
+
|
53
|
+
def ==(other)
|
54
|
+
other.is_a?(Include) && other.name == name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class Extend
|
59
|
+
attr_reader :name
|
60
|
+
|
61
|
+
def initialize(name:)
|
62
|
+
@name = name
|
63
|
+
end
|
64
|
+
|
65
|
+
def ==(other)
|
66
|
+
other.is_a?(Extend) && other.name == name
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
module WithMethods
|
72
|
+
def instance_methods(assignability:, klass:, instance:, params:)
|
73
|
+
methods = super
|
74
|
+
|
75
|
+
hash = type_application_hash(params)
|
76
|
+
|
77
|
+
members.each do |member|
|
78
|
+
case member
|
79
|
+
when Members::Include
|
80
|
+
module_signature = assignability.lookup_included_signature(member.name)
|
81
|
+
merge_methods(methods, module_signature.instance_methods(assignability: assignability,
|
82
|
+
klass: klass,
|
83
|
+
instance: instance,
|
84
|
+
params: module_signature.type_application_hash(member.name.params)))
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
members.each do |member|
|
89
|
+
case member
|
90
|
+
when Members::InstanceMethod, Members::ModuleInstanceMethod
|
91
|
+
method_types = member.types.map {|type| type.substitute(klass: klass, instance: instance, params: hash) }
|
92
|
+
merge_methods(methods, member.name => Steep::Interface::Method.new(types: method_types, super_method: nil))
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
extensions = assignability.lookup_extensions(name)
|
97
|
+
extensions.each do |extension|
|
98
|
+
extension_methods = extension.instance_methods(assignability: assignability, klass: klass, instance: instance, params: [])
|
99
|
+
merge_methods(methods, extension_methods)
|
100
|
+
end
|
101
|
+
|
102
|
+
methods
|
103
|
+
end
|
104
|
+
|
105
|
+
def module_methods(assignability:, klass:, instance:, params:)
|
106
|
+
methods = super
|
107
|
+
|
108
|
+
members.each do |member|
|
109
|
+
case member
|
110
|
+
when Members::Include
|
111
|
+
module_signature = assignability.lookup_included_signature(member.name)
|
112
|
+
merge_methods(methods, module_signature.module_methods(assignability: assignability,
|
113
|
+
klass: klass,
|
114
|
+
instance: instance,
|
115
|
+
params: module_signature.type_application_hash(member.name.params)))
|
116
|
+
when Members::Extend
|
117
|
+
module_signature = assignability.lookup_included_signature(member.name)
|
118
|
+
merge_methods(methods, module_signature.instance_methods(assignability: assignability,
|
119
|
+
klass: klass,
|
120
|
+
instance: instance,
|
121
|
+
params: module_signature.type_application_hash(member.name.params)))
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
members.each do |member|
|
126
|
+
case member
|
127
|
+
when Members::ModuleInstanceMethod, Members::ModuleMethod
|
128
|
+
method_types = member.types.map {|type| type.substitute(klass: klass, instance: instance, params: {}) }
|
129
|
+
merge_methods(methods, member.name => Steep::Interface::Method.new(types: method_types, super_method: nil))
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
if self.is_a?(Class)
|
134
|
+
instance_methods = instance_methods(assignability: assignability, klass: klass, instance: instance, params: params)
|
135
|
+
new_method = if instance_methods[:initialize]
|
136
|
+
types = instance_methods[:initialize].types.map do |method_type|
|
137
|
+
method_type.updated(return_type: instance)
|
138
|
+
end
|
139
|
+
Steep::Interface::Method.new(types: types, super_method: nil)
|
140
|
+
else
|
141
|
+
Steep::Interface::Method.new(types: [Steep::Interface::MethodType.new(type_params: [],
|
142
|
+
params: Steep::Interface::Params.empty,
|
143
|
+
block: nil,
|
144
|
+
return_type: instance)],
|
145
|
+
super_method: nil)
|
146
|
+
end
|
147
|
+
methods[:new] = new_method
|
148
|
+
end
|
149
|
+
|
150
|
+
methods
|
151
|
+
end
|
152
|
+
|
153
|
+
def merge_methods(methods, hash)
|
154
|
+
hash.each_key do |name|
|
155
|
+
method = hash[name]
|
156
|
+
|
157
|
+
methods[name] = Steep::Interface::Method.new(types: method.types,
|
158
|
+
super_method: methods[name])
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
module WithMembers
|
164
|
+
def each_type
|
165
|
+
if block_given?
|
166
|
+
members.each do |member|
|
167
|
+
case member
|
168
|
+
when Members::InstanceMethod, Members::ModuleMethod, Members::ModuleInstanceMethod
|
169
|
+
member.types.each do |method_type|
|
170
|
+
method_type.params.each_type do |type|
|
171
|
+
yield type
|
172
|
+
end
|
173
|
+
yield method_type.return_type
|
174
|
+
if method_type.block
|
175
|
+
method_type.block.params.each_type do |type|
|
176
|
+
yield type
|
177
|
+
end
|
178
|
+
yield method_type.block.return_type
|
179
|
+
end
|
180
|
+
end
|
181
|
+
when Members::Include, Members::Extend
|
182
|
+
yield member.name
|
183
|
+
else
|
184
|
+
raise "Unknown member: #{member.class.inspect}"
|
185
|
+
end
|
186
|
+
end
|
187
|
+
else
|
188
|
+
enum_for :each_type
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def validate_mixins(assignability, interface)
|
193
|
+
members.each do |member|
|
194
|
+
if member.is_a?(Members::Include)
|
195
|
+
module_signature = assignability.lookup_included_signature(member.name)
|
196
|
+
|
197
|
+
if module_signature.self_type
|
198
|
+
self_type = module_signature.self_type.substitute(klass: Types::Name.module(name: name),
|
199
|
+
instance: Types::Name.instance(name: name),
|
200
|
+
params: {})
|
201
|
+
self_interface = assignability.resolve_interface(self_type.name, member.name.params)
|
202
|
+
|
203
|
+
unless assignability.test_interface(interface, self_interface, [])
|
204
|
+
assignability.errors << Errors::InvalidSelfType.new(signature: self, member: member)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
module WithParams
|
213
|
+
def type_application_hash(args)
|
214
|
+
Hash[params.zip(args)]
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
class Module
|
219
|
+
attr_reader :name
|
220
|
+
attr_reader :params
|
221
|
+
attr_reader :members
|
222
|
+
attr_reader :self_type
|
223
|
+
|
224
|
+
prepend WithMethods
|
225
|
+
include WithMembers
|
226
|
+
include WithParams
|
227
|
+
|
228
|
+
def initialize(name:, params:, members:, self_type:)
|
229
|
+
@name = name
|
230
|
+
@members = members
|
231
|
+
@params = params
|
232
|
+
@self_type = self_type
|
233
|
+
end
|
234
|
+
|
235
|
+
def ==(other)
|
236
|
+
other.is_a?(Module) && other.name == name && other.params == params && other.members == members && other.self_type == self_type
|
237
|
+
end
|
238
|
+
|
239
|
+
def instance_methods(assignability:, klass:, instance:, params:)
|
240
|
+
{}
|
241
|
+
end
|
242
|
+
|
243
|
+
def module_methods(assignability:, klass:, instance:, params:)
|
244
|
+
{}
|
245
|
+
end
|
246
|
+
|
247
|
+
def each_type
|
248
|
+
if block_given?
|
249
|
+
yield self_type if self_type
|
250
|
+
super do |type|
|
251
|
+
yield type
|
252
|
+
end
|
253
|
+
else
|
254
|
+
enum_for :each_type
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
def validate(assignability)
|
259
|
+
each_type do |type|
|
260
|
+
assignability.validate_type_presence self, type
|
261
|
+
end
|
262
|
+
|
263
|
+
interface = assignability.resolve_interface(TypeName::Instance.new(name: name),
|
264
|
+
params.map {|x| Types::Var.new(name: x) })
|
265
|
+
|
266
|
+
validate_mixins(assignability, interface)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
class Class
|
271
|
+
attr_reader :name
|
272
|
+
attr_reader :params
|
273
|
+
attr_reader :members
|
274
|
+
attr_reader :super_class
|
275
|
+
|
276
|
+
prepend WithMethods
|
277
|
+
include WithMembers
|
278
|
+
include WithParams
|
279
|
+
|
280
|
+
def initialize(name:, params:, members:, super_class:)
|
281
|
+
@name = name
|
282
|
+
@members = members
|
283
|
+
@params = params
|
284
|
+
@super_class = super_class
|
285
|
+
end
|
286
|
+
|
287
|
+
def ==(other)
|
288
|
+
other.is_a?(Class) && other.name == name && other.params == params && other.members == members && other.super_class == super_class
|
289
|
+
end
|
290
|
+
|
291
|
+
def instance_methods(assignability:, klass:, instance:, params:)
|
292
|
+
if self.name == :BasicObject
|
293
|
+
{}
|
294
|
+
else
|
295
|
+
super_class = self.super_class || Types::Name.instance(name: :Object)
|
296
|
+
signature = assignability.lookup_super_class_signature(super_class)
|
297
|
+
|
298
|
+
hash = type_application_hash(params)
|
299
|
+
super_class_params = super_class.params.map do |type|
|
300
|
+
type.substitute(klass: klass, instance: instance, params: hash)
|
301
|
+
end
|
302
|
+
|
303
|
+
signature.instance_methods(assignability: assignability, klass: klass, instance: instance, params: super_class_params)
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
def module_methods(assignability:, klass:, instance:, params:)
|
308
|
+
signature = assignability.lookup_class_signature(Types::Name.instance(name: :Class))
|
309
|
+
class_methods = signature.instance_methods(assignability: assignability,
|
310
|
+
klass: klass,
|
311
|
+
instance: instance,
|
312
|
+
params: [instance])
|
313
|
+
if self.name == :BasicObject
|
314
|
+
class_methods
|
315
|
+
else
|
316
|
+
super_class = self.super_class || Types::Name.instance(name: :Object)
|
317
|
+
signature = assignability.lookup_super_class_signature(super_class)
|
318
|
+
|
319
|
+
hash = type_application_hash(params)
|
320
|
+
super_class_params = super_class.params.map do |type|
|
321
|
+
type.substitute(klass: klass, instance: instance, params: hash)
|
322
|
+
end
|
323
|
+
|
324
|
+
class_methods.merge!(signature.module_methods(assignability: assignability, klass: klass, instance: instance, params: super_class_params))
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
def each_type
|
329
|
+
if block_given?
|
330
|
+
yield super_class if super_class
|
331
|
+
super do |type|
|
332
|
+
yield type
|
333
|
+
end
|
334
|
+
else
|
335
|
+
enum_for :each_type
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def validate(assignability)
|
340
|
+
each_type do |type|
|
341
|
+
assignability.validate_type_presence self, type
|
342
|
+
end
|
343
|
+
|
344
|
+
interface = assignability.resolve_interface(TypeName::Instance.new(name: name),
|
345
|
+
params.map {|x| Types::Var.new(name: x) })
|
346
|
+
|
347
|
+
interface.methods.each_key do |method_name|
|
348
|
+
method = interface.methods[method_name]
|
349
|
+
if method.super_method
|
350
|
+
assignability.validate_method_compatibility(self, method_name, method)
|
351
|
+
end
|
352
|
+
end
|
353
|
+
|
354
|
+
validate_mixins(assignability, interface)
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|