steep 1.4.0 → 1.5.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.vscode/steep-shared.code-snippets +41 -0
- data/CHANGELOG.md +37 -0
- data/Gemfile +2 -5
- data/Gemfile.lock +20 -17
- data/Gemfile.steep +1 -1
- data/Gemfile.steep.lock +6 -6
- data/Rakefile +198 -0
- data/Steepfile +3 -1
- data/lib/steep/ast/builtin.rb +9 -7
- data/lib/steep/ast/node/type_application.rb +13 -5
- data/lib/steep/ast/node/type_assertion.rb +28 -9
- data/lib/steep/ast/types/factory.rb +39 -7
- data/lib/steep/cli.rb +2 -1
- data/lib/steep/diagnostic/deprecated/else_on_exhaustive_case.rb +20 -0
- data/lib/steep/diagnostic/lsp_formatter.rb +3 -3
- data/lib/steep/diagnostic/ruby.rb +73 -12
- data/lib/steep/drivers/annotations.rb +1 -0
- data/lib/steep/drivers/check.rb +18 -13
- data/lib/steep/drivers/checkfile.rb +1 -1
- data/lib/steep/drivers/diagnostic_printer.rb +6 -4
- data/lib/steep/drivers/init.rb +2 -1
- data/lib/steep/drivers/print_project.rb +3 -1
- data/lib/steep/drivers/stats.rb +1 -1
- data/lib/steep/drivers/utils/driver_helper.rb +10 -8
- data/lib/steep/drivers/utils/jobs_option.rb +6 -1
- data/lib/steep/drivers/validate.rb +9 -5
- data/lib/steep/drivers/watch.rb +8 -3
- data/lib/steep/expectations.rb +144 -75
- data/lib/steep/index/signature_symbol_provider.rb +22 -13
- data/lib/steep/node_helper.rb +172 -0
- data/lib/steep/server/base_worker.rb +2 -1
- data/lib/steep/server/change_buffer.rb +17 -15
- data/lib/steep/server/interaction_worker.rb +20 -0
- data/lib/steep/server/lsp_formatter.rb +20 -1
- data/lib/steep/server/master.rb +51 -36
- data/lib/steep/server/type_check_worker.rb +18 -2
- data/lib/steep/server/worker_process.rb +19 -2
- data/lib/steep/services/completion_provider.rb +189 -3
- data/lib/steep/services/file_loader.rb +1 -1
- data/lib/steep/services/goto_service.rb +123 -27
- data/lib/steep/services/signature_help_provider.rb +1 -6
- data/lib/steep/signature/validator.rb +6 -1
- data/lib/steep/source.rb +165 -108
- data/lib/steep/subtyping/check.rb +5 -3
- data/lib/steep/subtyping/variable_variance.rb +11 -0
- data/lib/steep/thread_waiter.rb +35 -0
- data/lib/steep/type_construction.rb +416 -171
- data/lib/steep/type_inference/block_params.rb +50 -9
- data/lib/steep/type_inference/context.rb +4 -0
- data/lib/steep/type_inference/context_array.rb +6 -6
- data/lib/steep/type_inference/logic_type_interpreter.rb +202 -68
- data/lib/steep/typing.rb +5 -4
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +21 -14
- data/sample/Steepfile +1 -0
- data/sig/shims/bundler.rbs +3 -0
- data/sig/shims/language-server_protocol.rbs +151 -10
- data/sig/shims/parser/nodes.rbs +210 -0
- data/sig/shims/parser.rbs +10 -0
- data/sig/steep/ast/builtin.rbs +2 -2
- data/sig/steep/ast/node/type_application.rbs +2 -2
- data/sig/steep/ast/node/type_assertion.rbs +8 -2
- data/sig/steep/ast/types/factory.rbs +28 -1
- data/sig/steep/diagnostic/deprecated/else_on_exhaustive_case.rbs +13 -0
- data/sig/steep/diagnostic/lsp_formatter.rbs +5 -2
- data/sig/steep/diagnostic/ruby.rbs +76 -6
- data/sig/steep/drivers/annotations.rbs +5 -5
- data/sig/steep/drivers/check.rbs +11 -11
- data/sig/steep/drivers/diagnostic_printer.rbs +9 -9
- data/sig/steep/drivers/init.rbs +6 -6
- data/sig/steep/drivers/print_project.rbs +4 -4
- data/sig/steep/drivers/utils/driver_helper.rbs +8 -6
- data/sig/steep/drivers/validate.rbs +4 -4
- data/sig/steep/drivers/watch.rbs +1 -1
- data/sig/steep/expectations.rbs +72 -0
- data/sig/steep/index/signature_symbol_provider.rbs +22 -10
- data/sig/steep/interface/block.rbs +2 -0
- data/sig/steep/interface/function.rbs +2 -2
- data/sig/steep/node_helper.rbs +56 -0
- data/sig/steep/path_helper.rbs +1 -1
- data/sig/steep/project/options.rbs +1 -1
- data/sig/steep/range_extension.rbs +2 -2
- data/sig/steep/server/master.rbs +16 -2
- data/sig/steep/server/type_check_worker.rbs +5 -1
- data/sig/steep/server/worker_process.rbs +5 -1
- data/sig/steep/services/completion_provider.rbs +31 -1
- data/sig/steep/services/goto_service.rbs +80 -19
- data/sig/steep/source.rbs +27 -4
- data/sig/steep/subtyping/variable_variance.rbs +9 -9
- data/sig/steep/thread_waiter.rbs +13 -0
- data/sig/steep/type_construction.rbs +26 -9
- data/sig/steep/type_inference/block_params.rbs +13 -1
- data/sig/steep/type_inference/context.rbs +5 -1
- data/sig/steep/type_inference/context_array.rbs +16 -15
- data/sig/steep/type_inference/logic_type_interpreter.rbs +36 -6
- data/sig/steep/type_inference/type_env_builder.rbs +4 -0
- data/sig/steep/typing.rbs +22 -20
- data/sig/steep.rbs +14 -13
- data/smoke/and/a.rb +1 -1
- data/smoke/and/test_expectations.yml +5 -7
- data/smoke/diagnostics/incompatible_annotation.rb +1 -1
- data/smoke/diagnostics/test_expectations.yml +2 -2
- data/smoke/enumerator/a.rb +0 -7
- data/smoke/enumerator/b.rb +0 -2
- data/smoke/enumerator/test_expectations.yml +17 -105
- data/smoke/lambda/a.rb +0 -5
- data/smoke/lambda/test_expectations.yml +0 -22
- data/smoke/type_case/test_expectations.yml +10 -0
- data/steep.gemspec +2 -2
- metadata +16 -9
@@ -76,6 +76,14 @@ module Steep
|
|
76
76
|
enum_for :each_param
|
77
77
|
end
|
78
78
|
end
|
79
|
+
|
80
|
+
def type
|
81
|
+
types = params.map do |param|
|
82
|
+
param.type or return
|
83
|
+
end
|
84
|
+
|
85
|
+
AST::Types::Tuple.new(types: types)
|
86
|
+
end
|
79
87
|
end
|
80
88
|
|
81
89
|
attr_reader :leading_params
|
@@ -191,15 +199,30 @@ module Steep
|
|
191
199
|
return nil
|
192
200
|
end
|
193
201
|
|
194
|
-
if rest_param
|
195
|
-
|
196
|
-
|
197
|
-
|
202
|
+
if rest_param
|
203
|
+
if hint.rest
|
204
|
+
if rest_type = rest_param.type
|
205
|
+
if AST::Builtin::Array.instance_type?(rest_type)
|
206
|
+
rest_type.is_a?(AST::Types::Name::Instance) or raise
|
207
|
+
rest = rest_type.args.first or raise
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
rest ||= hint.rest
|
212
|
+
end
|
198
213
|
end
|
199
214
|
else
|
200
215
|
leadings = leading_params.map {|param| param.type || AST::Types::Any.new }
|
201
216
|
optionals = optional_params.map {|param| param.type || AST::Types::Any.new }
|
202
|
-
|
217
|
+
|
218
|
+
if rest_param
|
219
|
+
if rest_type = rest_param.type
|
220
|
+
if array = AST::Builtin::Array.instance_type?(rest_type)
|
221
|
+
rest = array.args.first or raise
|
222
|
+
end
|
223
|
+
end
|
224
|
+
rest ||= AST::Types::Any.new
|
225
|
+
end
|
203
226
|
end
|
204
227
|
|
205
228
|
Interface::Function::Params.build(
|
@@ -217,6 +240,17 @@ module Steep
|
|
217
240
|
# @type var zip: Array[[Param | MultipleParam, AST::Types::t]]
|
218
241
|
zip = []
|
219
242
|
|
243
|
+
if untyped_args?(params_type)
|
244
|
+
params.each do |param|
|
245
|
+
if param == rest_param
|
246
|
+
zip << [param, AST::Builtin::Array.instance_type(fill_untyped: true)]
|
247
|
+
else
|
248
|
+
zip << [param, AST::Builtin.any_type]
|
249
|
+
end
|
250
|
+
end
|
251
|
+
return zip
|
252
|
+
end
|
253
|
+
|
220
254
|
if expandable? && (type = expandable_params?(params_type, factory))
|
221
255
|
case
|
222
256
|
when AST::Builtin::Array.instance_type?(type)
|
@@ -254,10 +288,10 @@ module Steep
|
|
254
288
|
types = params_type.flat_unnamed_params
|
255
289
|
|
256
290
|
(leading_params + optional_params).each do |param|
|
257
|
-
|
291
|
+
typ = types.shift&.last || params_type.rest
|
258
292
|
|
259
|
-
if
|
260
|
-
zip << [param,
|
293
|
+
if typ
|
294
|
+
zip << [param, typ]
|
261
295
|
else
|
262
296
|
zip << [param, AST::Builtin.nil_type]
|
263
297
|
end
|
@@ -268,7 +302,9 @@ module Steep
|
|
268
302
|
array = AST::Builtin::Array.instance_type(params_type.rest || AST::Builtin.any_type)
|
269
303
|
zip << [rest_param, array]
|
270
304
|
else
|
271
|
-
|
305
|
+
union_members = types.map(&:last)
|
306
|
+
union_members << params_type.rest if params_type.rest
|
307
|
+
union = AST::Types::Union.build(types: union_members)
|
272
308
|
array = AST::Builtin::Array.instance_type(union)
|
273
309
|
zip << [rest_param, array]
|
274
310
|
end
|
@@ -360,6 +396,11 @@ module Steep
|
|
360
396
|
|
361
397
|
MultipleParam.new(node: node, params: params)
|
362
398
|
end
|
399
|
+
|
400
|
+
def untyped_args?(params)
|
401
|
+
flat = params.flat_unnamed_params
|
402
|
+
flat.size == 1 && flat[0][1].is_a?(AST::Types::Any)
|
403
|
+
end
|
363
404
|
end
|
364
405
|
end
|
365
406
|
end
|
@@ -23,14 +23,15 @@ module Steep
|
|
23
23
|
root.range
|
24
24
|
end
|
25
25
|
|
26
|
-
def self.from_source(source:, range: nil, context:
|
26
|
+
def self.from_source(source:, range: nil, context:)
|
27
27
|
content = if source.node
|
28
28
|
source.node.location.expression.source_buffer.source
|
29
29
|
else
|
30
30
|
""
|
31
31
|
end
|
32
32
|
buffer = RBS::Buffer.new(name: source.path, content: content)
|
33
|
-
|
33
|
+
range ||= 0..buffer.content.size
|
34
|
+
new(buffer: buffer, context: context, range: range)
|
34
35
|
end
|
35
36
|
|
36
37
|
def insert_context(range, context:, entry: self.root)
|
@@ -62,12 +63,11 @@ module Steep
|
|
62
63
|
end
|
63
64
|
end
|
64
65
|
|
65
|
-
def each_entry
|
66
|
-
if
|
66
|
+
def each_entry(&block)
|
67
|
+
if block
|
67
68
|
es = [root]
|
68
69
|
|
69
|
-
|
70
|
-
e = es.pop
|
70
|
+
while e = es.pop
|
71
71
|
es.push(*e.sub_entries.to_a)
|
72
72
|
|
73
73
|
yield e
|
@@ -1,6 +1,22 @@
|
|
1
1
|
module Steep
|
2
2
|
module TypeInference
|
3
3
|
class LogicTypeInterpreter
|
4
|
+
class Result < Struct.new(:env, :type, :unreachable, keyword_init: true)
|
5
|
+
def update_env
|
6
|
+
env = yield()
|
7
|
+
Result.new(type: type, env: env, unreachable: unreachable)
|
8
|
+
end
|
9
|
+
|
10
|
+
def update_type
|
11
|
+
Result.new(type: yield, env: env, unreachable: unreachable)
|
12
|
+
end
|
13
|
+
|
14
|
+
def unreachable!
|
15
|
+
self.unreachable = true
|
16
|
+
self
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
4
20
|
attr_reader :subtyping
|
5
21
|
attr_reader :typing
|
6
22
|
attr_reader :config
|
@@ -31,55 +47,112 @@ module Steep
|
|
31
47
|
end
|
32
48
|
end
|
33
49
|
|
34
|
-
|
35
|
-
|
36
|
-
|
50
|
+
TRUE = AST::Types::Literal.new(value: true)
|
51
|
+
FALSE = AST::Types::Literal.new(value: false)
|
52
|
+
BOOL = AST::Types::Boolean.new
|
53
|
+
BOT = AST::Types::Bot.new
|
54
|
+
UNTYPED = AST::Types::Any.new
|
37
55
|
|
38
|
-
|
56
|
+
def eval(env:, node:)
|
57
|
+
evaluate_node(env: env, node: node)
|
39
58
|
end
|
40
59
|
|
41
|
-
def evaluate_node(env:, node:,
|
42
|
-
type = typing.type_of(node: node)
|
43
|
-
|
60
|
+
def evaluate_node(env:, node:, type: typing.type_of(node: node))
|
44
61
|
if type.is_a?(AST::Types::Logic::Env)
|
45
62
|
truthy_env = type.truthy
|
46
63
|
falsy_env = type.falsy
|
47
64
|
|
48
|
-
|
65
|
+
truthy_type, falsy_type = factory.partition_union(type.type)
|
66
|
+
|
67
|
+
return [
|
68
|
+
Result.new(env: truthy_env, type: truthy_type || TRUE, unreachable: !truthy_type),
|
69
|
+
Result.new(env: falsy_env, type: falsy_type || FALSE, unreachable: !falsy_type)
|
70
|
+
]
|
71
|
+
end
|
72
|
+
|
73
|
+
if type.is_a?(AST::Types::Bot)
|
74
|
+
return [
|
75
|
+
Result.new(env: env, type: type, unreachable: true),
|
76
|
+
Result.new(env: env, type: type, unreachable: true),
|
77
|
+
]
|
49
78
|
end
|
50
79
|
|
51
80
|
case node.type
|
52
81
|
when :lvar
|
53
82
|
name = node.children[0]
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
truthy_type
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
83
|
+
truthy_type, falsy_type = factory.partition_union(type)
|
84
|
+
|
85
|
+
truthy_result =
|
86
|
+
if truthy_type
|
87
|
+
Result.new(type: truthy_type, env: env.refine_types(local_variable_types: { name => truthy_type }), unreachable: false)
|
88
|
+
else
|
89
|
+
Result.new(type: type, env: env, unreachable: true)
|
90
|
+
end
|
91
|
+
|
92
|
+
falsy_result =
|
93
|
+
if falsy_type
|
94
|
+
Result.new(type: falsy_type, env: env.refine_types(local_variable_types: { name => falsy_type }), unreachable: false)
|
95
|
+
else
|
96
|
+
Result.new(type: type, env: env, unreachable: true)
|
97
|
+
end
|
98
|
+
|
99
|
+
return [truthy_result, falsy_result]
|
100
|
+
|
62
101
|
when :lvasgn
|
63
102
|
name, rhs = node.children
|
64
|
-
|
103
|
+
if TypeConstruction::SPECIAL_LVAR_NAMES.include?(name)
|
104
|
+
return [
|
105
|
+
Result.new(type: type, env: env, unreachable: false),
|
106
|
+
Result.new(type: type, env: env, unreachable: false)
|
107
|
+
]
|
108
|
+
end
|
109
|
+
|
110
|
+
truthy_result, falsy_result = evaluate_node(env: env, node: rhs)
|
111
|
+
|
65
112
|
return [
|
66
|
-
|
67
|
-
|
68
|
-
evaluate_assignment(node, truthy_env, truthy_type, refined_objects: refined_objects),
|
69
|
-
evaluate_assignment(node, falsy_env, falsy_type, refined_objects: refined_objects)
|
113
|
+
truthy_result.update_env { evaluate_assignment(node, truthy_result.env, truthy_result.type) },
|
114
|
+
falsy_result.update_env { evaluate_assignment(node, falsy_result.env, falsy_result.type) }
|
70
115
|
]
|
116
|
+
|
71
117
|
when :masgn
|
72
|
-
|
73
|
-
|
118
|
+
_, rhs = node.children
|
119
|
+
truthy_result, falsy_result = evaluate_node(env: env, node: rhs)
|
120
|
+
|
74
121
|
return [
|
75
|
-
|
76
|
-
|
77
|
-
evaluate_assignment(node, truthy_env, truthy_type, refined_objects: refined_objects),
|
78
|
-
evaluate_assignment(node, falsy_env, falsy_type, refined_objects: refined_objects)
|
122
|
+
truthy_result.update_env { evaluate_assignment(node, truthy_result.env, truthy_result.type) },
|
123
|
+
falsy_result.update_env { evaluate_assignment(node, falsy_result.env, falsy_result.type) }
|
79
124
|
]
|
125
|
+
|
80
126
|
when :begin
|
81
127
|
last_node = node.children.last or raise
|
82
|
-
return evaluate_node(env: env, node: last_node
|
128
|
+
return evaluate_node(env: env, node: last_node)
|
129
|
+
|
130
|
+
when :csend
|
131
|
+
if type.is_a?(AST::Types::Any)
|
132
|
+
type = guess_type_from_method(node) || type
|
133
|
+
end
|
134
|
+
|
135
|
+
receiver, _, *arguments = node.children
|
136
|
+
receiver_type = typing.type_of(node: receiver)
|
137
|
+
|
138
|
+
truthy_receiver, falsy_receiver = evaluate_node(env: env, node: receiver)
|
139
|
+
truthy_type, _ = factory.partition_union(type)
|
140
|
+
|
141
|
+
truthy_result, falsy_result = evaluate_node(
|
142
|
+
env: truthy_receiver.env,
|
143
|
+
node: node.updated(:send),
|
144
|
+
type: truthy_type || type
|
145
|
+
)
|
146
|
+
truthy_result.unreachable! if truthy_receiver.unreachable
|
147
|
+
|
148
|
+
falsy_result = Result.new(
|
149
|
+
env: env.join(falsy_receiver.env, falsy_result.env),
|
150
|
+
unreachable: falsy_result.unreachable && falsy_receiver.unreachable,
|
151
|
+
type: falsy_result.type
|
152
|
+
)
|
153
|
+
|
154
|
+
return [truthy_result, falsy_result]
|
155
|
+
|
83
156
|
when :send
|
84
157
|
if type.is_a?(AST::Types::Any)
|
85
158
|
type = guess_type_from_method(node) || type
|
@@ -88,38 +161,46 @@ module Steep
|
|
88
161
|
case type
|
89
162
|
when AST::Types::Logic::Base
|
90
163
|
receiver, _, *arguments = node.children
|
91
|
-
|
92
|
-
|
93
|
-
if truthy_env && falsy_env
|
94
|
-
return [AST::Builtin.true_type, AST::Builtin.false_type, truthy_env, falsy_env]
|
164
|
+
if (truthy_result, falsy_result = evaluate_method_call(env: env, type: type, receiver: receiver, arguments: arguments))
|
165
|
+
return [truthy_result, falsy_result]
|
95
166
|
end
|
96
167
|
else
|
97
168
|
if env[node]
|
98
|
-
truthy_type, falsy_type = factory.
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
169
|
+
truthy_type, falsy_type = factory.partition_union(type)
|
170
|
+
|
171
|
+
truthy_result =
|
172
|
+
if truthy_type
|
173
|
+
Result.new(type: truthy_type, env: env.refine_types(pure_call_types: { node => truthy_type }), unreachable: false)
|
174
|
+
else
|
175
|
+
Result.new(type: type, env: env, unreachable: true)
|
176
|
+
end
|
177
|
+
|
178
|
+
falsy_result =
|
179
|
+
if falsy_type
|
180
|
+
Result.new(type: falsy_type, env: env.refine_types(pure_call_types: { node => falsy_type }), unreachable: false)
|
181
|
+
else
|
182
|
+
Result.new(type: type, env: env, unreachable: true)
|
183
|
+
end
|
184
|
+
|
185
|
+
return [truthy_result, falsy_result]
|
107
186
|
end
|
108
187
|
end
|
109
188
|
end
|
110
189
|
|
111
|
-
truthy_type, falsy_type = factory.
|
112
|
-
return [
|
190
|
+
truthy_type, falsy_type = factory.partition_union(type)
|
191
|
+
return [
|
192
|
+
Result.new(type: truthy_type || BOT, env: env, unreachable: truthy_type.nil?),
|
193
|
+
Result.new(type: falsy_type || BOT, env: env, unreachable: falsy_type.nil?)
|
194
|
+
]
|
113
195
|
end
|
114
196
|
|
115
|
-
def evaluate_assignment(assignment_node, env, rhs_type
|
197
|
+
def evaluate_assignment(assignment_node, env, rhs_type)
|
116
198
|
case assignment_node.type
|
117
199
|
when :lvasgn
|
118
200
|
name, _ = assignment_node.children
|
119
201
|
if TypeConstruction::SPECIAL_LVAR_NAMES.include?(name)
|
120
202
|
env
|
121
203
|
else
|
122
|
-
refined_objects << name
|
123
204
|
env.refine_types(local_variable_types: { name => rhs_type })
|
124
205
|
end
|
125
206
|
when :masgn
|
@@ -140,7 +221,7 @@ module Steep
|
|
140
221
|
|
141
222
|
assignments.each do |pair|
|
142
223
|
node, type = pair
|
143
|
-
env = evaluate_assignment(node, env, type
|
224
|
+
env = evaluate_assignment(node, env, type)
|
144
225
|
end
|
145
226
|
|
146
227
|
env
|
@@ -149,7 +230,7 @@ module Steep
|
|
149
230
|
end
|
150
231
|
end
|
151
232
|
|
152
|
-
def refine_node_type(env:, node:, truthy_type:, falsy_type
|
233
|
+
def refine_node_type(env:, node:, truthy_type:, falsy_type:)
|
153
234
|
case node.type
|
154
235
|
when :lvar
|
155
236
|
name = node.children[0]
|
@@ -157,7 +238,6 @@ module Steep
|
|
157
238
|
if TypeConstruction::SPECIAL_LVAR_NAMES.include?(name)
|
158
239
|
[env, env]
|
159
240
|
else
|
160
|
-
refined_objects << name
|
161
241
|
[
|
162
242
|
env.refine_types(local_variable_types: { name => truthy_type }),
|
163
243
|
env.refine_types(local_variable_types: { name => falsy_type })
|
@@ -167,12 +247,11 @@ module Steep
|
|
167
247
|
when :lvasgn
|
168
248
|
name, rhs = node.children
|
169
249
|
|
170
|
-
truthy_env, falsy_env = refine_node_type(env: env, node: rhs, truthy_type: truthy_type, falsy_type: falsy_type
|
250
|
+
truthy_env, falsy_env = refine_node_type(env: env, node: rhs, truthy_type: truthy_type, falsy_type: falsy_type)
|
171
251
|
|
172
252
|
if TypeConstruction::SPECIAL_LVAR_NAMES.include?(name)
|
173
253
|
[truthy_env, falsy_env]
|
174
254
|
else
|
175
|
-
refined_objects << name
|
176
255
|
[
|
177
256
|
truthy_env.refine_types(local_variable_types: { name => truthy_type }),
|
178
257
|
falsy_env.refine_types(local_variable_types: { name => falsy_type })
|
@@ -181,7 +260,6 @@ module Steep
|
|
181
260
|
|
182
261
|
when :send
|
183
262
|
if env[node]
|
184
|
-
refined_objects << node
|
185
263
|
[
|
186
264
|
env.refine_types(pure_call_types: { node => truthy_type }),
|
187
265
|
env.refine_types(pure_call_types: { node => falsy_type })
|
@@ -191,20 +269,35 @@ module Steep
|
|
191
269
|
end
|
192
270
|
when :begin
|
193
271
|
last_node = node.children.last or raise
|
194
|
-
refine_node_type(env: env, node: last_node, truthy_type: truthy_type, falsy_type: falsy_type
|
272
|
+
refine_node_type(env: env, node: last_node, truthy_type: truthy_type, falsy_type: falsy_type)
|
195
273
|
else
|
196
274
|
[env, env]
|
197
275
|
end
|
198
276
|
end
|
199
277
|
|
200
|
-
def evaluate_method_call(env:, type:, receiver:, arguments
|
278
|
+
def evaluate_method_call(env:, type:, receiver:, arguments:)
|
201
279
|
case type
|
202
280
|
when AST::Types::Logic::ReceiverIsNil
|
203
281
|
if receiver && arguments.size.zero?
|
204
282
|
receiver_type = typing.type_of(node: receiver)
|
205
|
-
truthy_receiver, falsy_receiver = factory.
|
206
|
-
|
283
|
+
truthy_receiver, falsy_receiver = factory.partition_union(receiver_type)
|
284
|
+
|
285
|
+
truthy_env, falsy_env = refine_node_type(
|
286
|
+
env: env,
|
287
|
+
node: receiver,
|
288
|
+
truthy_type: falsy_receiver || BOT,
|
289
|
+
falsy_type: truthy_receiver || BOT
|
290
|
+
)
|
291
|
+
|
292
|
+
truthy_result = Result.new(type: TRUE, env: truthy_env, unreachable: false)
|
293
|
+
truthy_result.unreachable! unless truthy_receiver
|
294
|
+
|
295
|
+
falsy_result = Result.new(type: FALSE, env: falsy_env, unreachable: false)
|
296
|
+
falsy_result.unreachable! unless falsy_receiver
|
297
|
+
|
298
|
+
[truthy_result, falsy_result]
|
207
299
|
end
|
300
|
+
|
208
301
|
when AST::Types::Logic::ReceiverIsArg
|
209
302
|
if receiver && (arg = arguments[0])
|
210
303
|
receiver_type = typing.type_of(node: receiver)
|
@@ -212,9 +305,23 @@ module Steep
|
|
212
305
|
|
213
306
|
if arg_type.is_a?(AST::Types::Name::Singleton)
|
214
307
|
truthy_type, falsy_type = type_case_select(receiver_type, arg_type.name)
|
215
|
-
|
308
|
+
truthy_env, falsy_env = refine_node_type(
|
309
|
+
env: env,
|
310
|
+
node: receiver,
|
311
|
+
truthy_type: truthy_type || factory.instance_type(arg_type.name),
|
312
|
+
falsy_type: falsy_type || UNTYPED
|
313
|
+
)
|
314
|
+
|
315
|
+
truthy_result = Result.new(type: TRUE, env: truthy_env, unreachable: false)
|
316
|
+
truthy_result.unreachable! unless truthy_type
|
317
|
+
|
318
|
+
falsy_result = Result.new(type: FALSE, env: falsy_env, unreachable: false)
|
319
|
+
falsy_result.unreachable! unless falsy_type
|
320
|
+
|
321
|
+
[truthy_result, falsy_result]
|
216
322
|
end
|
217
323
|
end
|
324
|
+
|
218
325
|
when AST::Types::Logic::ArgIsReceiver
|
219
326
|
if receiver && (arg = arguments[0])
|
220
327
|
receiver_type = factory.deep_expand_alias(typing.type_of(node: receiver))
|
@@ -222,26 +329,49 @@ module Steep
|
|
222
329
|
|
223
330
|
if receiver_type.is_a?(AST::Types::Name::Singleton)
|
224
331
|
truthy_type, falsy_type = type_case_select(arg_type, receiver_type.name)
|
225
|
-
|
332
|
+
truthy_env, falsy_env = refine_node_type(
|
333
|
+
env: env,
|
334
|
+
node: arg,
|
335
|
+
truthy_type: truthy_type || factory.instance_type(receiver_type.name),
|
336
|
+
falsy_type: falsy_type || UNTYPED
|
337
|
+
)
|
338
|
+
|
339
|
+
truthy_result = Result.new(type: TRUE, env: truthy_env, unreachable: false)
|
340
|
+
truthy_result.unreachable! unless truthy_type
|
341
|
+
|
342
|
+
falsy_result = Result.new(type: FALSE, env: falsy_env, unreachable: false)
|
343
|
+
falsy_result.unreachable! unless falsy_type
|
344
|
+
|
345
|
+
[truthy_result, falsy_result]
|
226
346
|
end
|
227
347
|
end
|
228
348
|
when AST::Types::Logic::ArgEqualsReceiver
|
229
349
|
if receiver && (arg = arguments[0])
|
230
350
|
arg_type = factory.expand_alias(typing.type_of(node: arg))
|
231
351
|
if (truthy_types, falsy_types = literal_var_type_case_select(receiver, arg_type))
|
232
|
-
refine_node_type(
|
352
|
+
truthy_env, falsy_env = refine_node_type(
|
233
353
|
env: env,
|
234
354
|
node: arg,
|
235
|
-
truthy_type: AST::Types::Union.build(types: truthy_types),
|
236
|
-
falsy_type: AST::Types::Union.build(types: falsy_types)
|
237
|
-
refined_objects: refined_objects
|
355
|
+
truthy_type: truthy_types.empty? ? BOT : AST::Types::Union.build(types: truthy_types),
|
356
|
+
falsy_type: falsy_types.empty? ? BOT : AST::Types::Union.build(types: falsy_types)
|
238
357
|
)
|
358
|
+
|
359
|
+
truthy_result = Result.new(type: TRUE, env: truthy_env, unreachable: false)
|
360
|
+
truthy_result.unreachable! if truthy_types.empty?
|
361
|
+
|
362
|
+
falsy_result = Result.new(type: FALSE, env: falsy_env, unreachable: false)
|
363
|
+
falsy_result.unreachable! if falsy_types.empty?
|
364
|
+
|
365
|
+
[truthy_result, falsy_result]
|
239
366
|
end
|
240
367
|
end
|
241
368
|
when AST::Types::Logic::Not
|
242
369
|
if receiver
|
243
|
-
|
244
|
-
[
|
370
|
+
truthy_result, falsy_result = evaluate_node(env: env, node: receiver)
|
371
|
+
[
|
372
|
+
falsy_result.update_type { TRUE },
|
373
|
+
truthy_result.update_type { FALSE }
|
374
|
+
]
|
245
375
|
end
|
246
376
|
end
|
247
377
|
end
|
@@ -332,8 +462,8 @@ module Steep
|
|
332
462
|
truth_types, false_types = type_case_select0(type, klass)
|
333
463
|
|
334
464
|
[
|
335
|
-
AST::Types::Union.build(types: truth_types),
|
336
|
-
AST::Types::Union.build(types: false_types)
|
465
|
+
truth_types.empty? ? nil : AST::Types::Union.build(types: truth_types),
|
466
|
+
false_types.empty? ? nil : AST::Types::Union.build(types: false_types)
|
337
467
|
]
|
338
468
|
end
|
339
469
|
|
@@ -342,8 +472,8 @@ module Steep
|
|
342
472
|
|
343
473
|
case type
|
344
474
|
when AST::Types::Union
|
345
|
-
truthy_types = []
|
346
|
-
falsy_types = []
|
475
|
+
truthy_types = [] # :Array[AST::Types::t]
|
476
|
+
falsy_types = [] #: Array[AST::Types::t]
|
347
477
|
|
348
478
|
type.types.each do |ty|
|
349
479
|
truths, falses = type_case_select0(ty, klass)
|
@@ -360,7 +490,11 @@ module Steep
|
|
360
490
|
|
361
491
|
when AST::Types::Name::Alias
|
362
492
|
ty = factory.expand_alias(type)
|
363
|
-
|
493
|
+
if ty == type
|
494
|
+
[[type], [type]]
|
495
|
+
else
|
496
|
+
type_case_select0(ty, klass)
|
497
|
+
end
|
364
498
|
|
365
499
|
when AST::Types::Any, AST::Types::Top
|
366
500
|
[
|
data/lib/steep/typing.rb
CHANGED
@@ -32,10 +32,10 @@ module Steep
|
|
32
32
|
@should_update = false
|
33
33
|
|
34
34
|
@errors = []
|
35
|
-
@typing = {}.compare_by_identity
|
35
|
+
(@typing = {}).compare_by_identity
|
36
36
|
@root_context = root_context
|
37
|
-
@contexts = contexts || TypeInference::ContextArray.from_source(source: source)
|
38
|
-
@method_calls = {}.compare_by_identity
|
37
|
+
@contexts = contexts || TypeInference::ContextArray.from_source(source: source, context: root_context)
|
38
|
+
(@method_calls = {}).compare_by_identity
|
39
39
|
|
40
40
|
@source_index = source_index || Index::SourceIndex.new(source: source)
|
41
41
|
end
|
@@ -222,10 +222,11 @@ module Steep
|
|
222
222
|
end
|
223
223
|
|
224
224
|
def new_child(range)
|
225
|
+
context = contexts[range.begin] || contexts.root.context
|
225
226
|
child = self.class.new(source: source,
|
226
227
|
parent: self,
|
227
228
|
root_context: root_context,
|
228
|
-
contexts: TypeInference::ContextArray.new(buffer: contexts.buffer, range: range, context:
|
229
|
+
contexts: TypeInference::ContextArray.new(buffer: contexts.buffer, range: range, context: context),
|
229
230
|
source_index: source_index.new_child)
|
230
231
|
@should_update = true
|
231
232
|
|
data/lib/steep/version.rb
CHANGED