steep 0.43.0 → 0.45.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.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +8 -0
- data/.github/workflows/ruby.yml +3 -2
- data/.gitignore +0 -1
- data/CHANGELOG.md +30 -0
- data/Gemfile +0 -1
- data/Gemfile.lock +77 -0
- data/bin/output_test.rb +8 -2
- data/lib/steep.rb +4 -1
- data/lib/steep/ast/builtin.rb +7 -1
- data/lib/steep/ast/types/factory.rb +19 -25
- data/lib/steep/diagnostic/ruby.rb +137 -60
- data/lib/steep/diagnostic/signature.rb +34 -0
- data/lib/steep/equatable.rb +21 -0
- data/lib/steep/index/source_index.rb +55 -5
- data/lib/steep/interface/block.rb +4 -0
- data/lib/steep/interface/function.rb +798 -579
- data/lib/steep/server/interaction_worker.rb +239 -20
- data/lib/steep/server/master.rb +40 -19
- data/lib/steep/server/type_check_worker.rb +68 -0
- data/lib/steep/services/file_loader.rb +26 -19
- data/lib/steep/services/goto_service.rb +322 -0
- data/lib/steep/services/hover_content.rb +131 -79
- data/lib/steep/services/type_check_service.rb +25 -0
- data/lib/steep/source.rb +7 -10
- data/lib/steep/type_construction.rb +496 -518
- data/lib/steep/type_inference/block_params.rb +2 -5
- data/lib/steep/type_inference/method_params.rb +483 -0
- data/lib/steep/type_inference/send_args.rb +610 -128
- data/lib/steep/typing.rb +46 -21
- data/lib/steep/version.rb +1 -1
- data/sig/steep/type_inference/send_args.rbs +42 -0
- data/smoke/array/test_expectations.yml +3 -3
- data/smoke/block/c.rb +0 -1
- data/smoke/class/test_expectations.yml +12 -15
- data/smoke/const/test_expectations.yml +0 -10
- data/smoke/diagnostics-rbs/mixin-class-error.rbs +6 -0
- data/smoke/diagnostics-rbs/test_expectations.yml +12 -0
- data/smoke/diagnostics-ruby-unsat/Steepfile +5 -0
- data/smoke/diagnostics-ruby-unsat/a.rbs +3 -0
- data/smoke/diagnostics-ruby-unsat/test_expectations.yml +27 -0
- data/smoke/{diagnostics → diagnostics-ruby-unsat}/unsatisfiable_constraint.rb +0 -1
- data/smoke/diagnostics/a.rbs +0 -4
- data/smoke/diagnostics/different_method_parameter_kind.rb +9 -0
- data/smoke/diagnostics/method_arity_mismatch.rb +2 -2
- data/smoke/diagnostics/method_parameter_mismatch.rb +10 -0
- data/smoke/diagnostics/test_expectations.yml +108 -57
- data/smoke/ensure/test_expectations.yml +3 -3
- data/smoke/enumerator/test_expectations.yml +1 -1
- data/smoke/literal/test_expectations.yml +2 -2
- data/smoke/method/test_expectations.yml +11 -10
- data/smoke/regression/issue_372.rb +8 -0
- data/smoke/regression/issue_372.rbs +4 -0
- data/smoke/regression/test_expectations.yml +0 -12
- data/smoke/rescue/test_expectations.yml +3 -3
- data/smoke/toplevel/test_expectations.yml +3 -3
- data/smoke/tsort/test_expectations.yml +2 -2
- data/steep.gemspec +2 -2
- metadata +24 -10
data/lib/steep/typing.rb
CHANGED
@@ -102,13 +102,20 @@ module Steep
|
|
102
102
|
end
|
103
103
|
|
104
104
|
def block_range(node)
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
105
|
+
case node.type
|
106
|
+
when :block
|
107
|
+
send_node, args_node, _ = node.children
|
108
|
+
begin_pos = if send_node.type != :lambda && args_node.loc.expression
|
109
|
+
args_node.loc.expression.end_pos
|
110
|
+
else
|
111
|
+
node.loc.begin.end_pos
|
112
|
+
end
|
113
|
+
end_pos = node.loc.end.begin_pos
|
114
|
+
when :numblock
|
115
|
+
send_node, _ = node.children
|
116
|
+
begin_pos = node.loc.begin.end_pos
|
117
|
+
end_pos = node.loc.end.begin_pos
|
118
|
+
end
|
112
119
|
|
113
120
|
begin_pos..end_pos
|
114
121
|
end
|
@@ -139,21 +146,39 @@ module Steep
|
|
139
146
|
add_context(begin_pos..end_pos, context: context)
|
140
147
|
|
141
148
|
when :def, :defs
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
149
|
+
if node.children.last
|
150
|
+
args_node =
|
151
|
+
case node.type
|
152
|
+
when :def
|
153
|
+
node.children[1]
|
154
|
+
when :defs
|
155
|
+
node.children[2]
|
156
|
+
end
|
157
|
+
|
158
|
+
body_begin_pos =
|
159
|
+
case
|
160
|
+
when node.loc.assignment
|
161
|
+
# endless def
|
162
|
+
node.loc.assignment.end_pos
|
163
|
+
when args_node.loc.expression
|
164
|
+
# with args
|
165
|
+
args_node.loc.expression.end_pos
|
166
|
+
else
|
167
|
+
# without args
|
168
|
+
node.loc.name.end_pos
|
169
|
+
end
|
170
|
+
|
171
|
+
body_end_pos =
|
172
|
+
if node.loc.end
|
173
|
+
node.loc.end.begin_pos
|
174
|
+
else
|
175
|
+
node.loc.expression.end_pos
|
176
|
+
end
|
177
|
+
|
178
|
+
add_context(body_begin_pos..body_end_pos, context: context)
|
179
|
+
end
|
155
180
|
|
156
|
-
when :block
|
181
|
+
when :block, :numblock
|
157
182
|
range = block_range(node)
|
158
183
|
add_context(range, context: context)
|
159
184
|
|
data/lib/steep/version.rb
CHANGED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Steep
|
2
|
+
type node = untyped
|
3
|
+
|
4
|
+
module TypeInference
|
5
|
+
class SendArgs
|
6
|
+
class PositionalArgs
|
7
|
+
end
|
8
|
+
|
9
|
+
class KeywordArgs
|
10
|
+
type value = ArgTypePairs | UnexpectedKeyword | MissingKeyword
|
11
|
+
|
12
|
+
class ArgTypePairs
|
13
|
+
end
|
14
|
+
|
15
|
+
class UnexpectedKeyword
|
16
|
+
end
|
17
|
+
|
18
|
+
class MissingKeyword
|
19
|
+
end
|
20
|
+
|
21
|
+
def consume: () -> [value, self]?
|
22
|
+
|
23
|
+
def consume_keys: (Array[Symbol], node: node) -> [AST::Types::t | UnexpectedKeyword, self]
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
type error = Diagnostics::Ruby::IncompatibleArguments
|
28
|
+
| Diagnostics::Ruby::UnexpectedBlockGiven
|
29
|
+
| Diagnostics::Ruby::RequiredBlockMissing
|
30
|
+
|
31
|
+
type arg = PositionalArgs::NodeParamPair
|
32
|
+
| PositionalArgs::NodeTypePair
|
33
|
+
| PositionalArgs::SplatArg
|
34
|
+
| PositionalArgs::UnexpectedArg
|
35
|
+
| KeywordArgs::ArgTypePairs
|
36
|
+
| KeywordArgs::SplatArg
|
37
|
+
| KeywordArgs::UnexpectedKeyword
|
38
|
+
|
39
|
+
def each_arg: (TypeConstruction) { (arg, TypeConstruction) -> TypeConstruction } -> Array[error]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -16,9 +16,9 @@
|
|
16
16
|
| (::int, ::int, ::Integer) -> ::Integer
|
17
17
|
| (::int, ::int, ::Array[::Integer]) -> ::Array[::Integer]
|
18
18
|
| (::int, ::int, nil) -> nil
|
19
|
-
| (::Range[::Integer], ::Integer) -> ::Integer
|
20
|
-
| (::Range[::Integer], ::Array[::Integer]) -> ::Array[::Integer]
|
21
|
-
| (::Range[::Integer], nil) -> nil
|
19
|
+
| (::Range[(::Integer | nil)], ::Integer) -> ::Integer
|
20
|
+
| (::Range[(::Integer | nil)], ::Array[::Integer]) -> ::Array[::Integer]
|
21
|
+
| (::Range[(::Integer | nil)], nil) -> nil
|
22
22
|
code: Ruby::UnresolvedOverloading
|
23
23
|
- range:
|
24
24
|
start:
|
data/smoke/block/c.rb
CHANGED
@@ -4,20 +4,20 @@
|
|
4
4
|
- range:
|
5
5
|
start:
|
6
6
|
line: 8
|
7
|
-
character:
|
7
|
+
character: 10
|
8
8
|
end:
|
9
9
|
line: 8
|
10
|
-
character:
|
10
|
+
character: 11
|
11
11
|
severity: ERROR
|
12
|
-
message:
|
13
|
-
code: Ruby::
|
12
|
+
message: The method parameter is incompatible with the declaration `() -> ::String`
|
13
|
+
code: Ruby::MethodParameterMismatch
|
14
14
|
- range:
|
15
15
|
start:
|
16
16
|
line: 13
|
17
|
-
character:
|
17
|
+
character: 6
|
18
18
|
end:
|
19
|
-
line:
|
20
|
-
character:
|
19
|
+
line: 13
|
20
|
+
character: 10
|
21
21
|
severity: ERROR
|
22
22
|
message: |-
|
23
23
|
Cannot allow method body have type `::Integer` because declared as type `::String`
|
@@ -29,10 +29,10 @@
|
|
29
29
|
- range:
|
30
30
|
start:
|
31
31
|
line: 22
|
32
|
-
character:
|
32
|
+
character: 11
|
33
33
|
end:
|
34
|
-
line:
|
35
|
-
character:
|
34
|
+
line: 22
|
35
|
+
character: 14
|
36
36
|
severity: ERROR
|
37
37
|
message: |-
|
38
38
|
Cannot allow method body have type `::String` because declared as type `::Integer`
|
@@ -113,8 +113,5 @@
|
|
113
113
|
line: 10
|
114
114
|
character: 11
|
115
115
|
severity: ERROR
|
116
|
-
message:
|
117
|
-
|
118
|
-
Method types:
|
119
|
-
def initialize: (name: ::String) -> untyped
|
120
|
-
code: Ruby::IncompatibleArguments
|
116
|
+
message: 'More keyword arguments are required: name'
|
117
|
+
code: Ruby::InsufficientKeywordArguments
|
@@ -26,16 +26,6 @@
|
|
26
26
|
severity: ERROR
|
27
27
|
message: Cannot detect the type of the expression
|
28
28
|
code: Ruby::FallbackAny
|
29
|
-
- range:
|
30
|
-
start:
|
31
|
-
line: 8
|
32
|
-
character: 7
|
33
|
-
end:
|
34
|
-
line: 8
|
35
|
-
character: 8
|
36
|
-
severity: ERROR
|
37
|
-
message: Cannot detect the type of the expression
|
38
|
-
code: Ruby::FallbackAny
|
39
29
|
- range:
|
40
30
|
start:
|
41
31
|
line: 14
|
@@ -229,3 +229,15 @@
|
|
229
229
|
severity: ERROR
|
230
230
|
message: Cannot find type `ZZZ`
|
231
231
|
code: RBS::UnknownTypeName
|
232
|
+
- file: mixin-class-error.rbs
|
233
|
+
diagnostics:
|
234
|
+
- range:
|
235
|
+
start:
|
236
|
+
line: 5
|
237
|
+
character: 2
|
238
|
+
end:
|
239
|
+
line: 5
|
240
|
+
character: 13
|
241
|
+
severity: ERROR
|
242
|
+
message: Cannot include a class `::Foo` in the definition of `::Bar`
|
243
|
+
code: RBS::MixinClassError
|
@@ -0,0 +1,27 @@
|
|
1
|
+
---
|
2
|
+
- file: unsatisfiable_constraint.rb
|
3
|
+
diagnostics:
|
4
|
+
- range:
|
5
|
+
start:
|
6
|
+
line: 3
|
7
|
+
character: 0
|
8
|
+
end:
|
9
|
+
line: 6
|
10
|
+
character: 3
|
11
|
+
severity: ERROR
|
12
|
+
message: |-
|
13
|
+
Unsatisfiable constraint `::Array[untyped] <: A(2) <: ::String` is generated through (A(2)) { (A(2)) -> void } -> B(3)
|
14
|
+
::Array[untyped] <: ::String
|
15
|
+
::Object <: ::String
|
16
|
+
::BasicObject <: ::String
|
17
|
+
code: Ruby::UnsatisfiableConstraint
|
18
|
+
- range:
|
19
|
+
start:
|
20
|
+
line: 5
|
21
|
+
character: 4
|
22
|
+
end:
|
23
|
+
line: 5
|
24
|
+
character: 7
|
25
|
+
severity: ERROR
|
26
|
+
message: Type `::String` does not have method `foo`
|
27
|
+
code: Ruby::NoMethod
|
data/smoke/diagnostics/a.rbs
CHANGED
@@ -63,6 +63,52 @@
|
|
63
63
|
::Object <: ::Integer
|
64
64
|
::BasicObject <: ::Integer
|
65
65
|
code: Ruby::BreakTypeMismatch
|
66
|
+
- file: different_method_parameter_kind.rb
|
67
|
+
diagnostics:
|
68
|
+
- range:
|
69
|
+
start:
|
70
|
+
line: 3
|
71
|
+
character: 10
|
72
|
+
end:
|
73
|
+
line: 3
|
74
|
+
character: 15
|
75
|
+
severity: ERROR
|
76
|
+
message: The method parameter has different kind from the declaration `(::Integer,
|
77
|
+
::String) -> void`
|
78
|
+
code: Ruby::DifferentMethodParameterKind
|
79
|
+
- range:
|
80
|
+
start:
|
81
|
+
line: 3
|
82
|
+
character: 17
|
83
|
+
end:
|
84
|
+
line: 3
|
85
|
+
character: 19
|
86
|
+
severity: ERROR
|
87
|
+
message: The method parameter has different kind from the declaration `(::Integer,
|
88
|
+
::String) -> void`
|
89
|
+
code: Ruby::DifferentMethodParameterKind
|
90
|
+
- range:
|
91
|
+
start:
|
92
|
+
line: 7
|
93
|
+
character: 10
|
94
|
+
end:
|
95
|
+
line: 7
|
96
|
+
character: 21
|
97
|
+
severity: ERROR
|
98
|
+
message: 'The method parameter has different kind from the declaration `(size:
|
99
|
+
::Integer, name: ::String) -> void`'
|
100
|
+
code: Ruby::DifferentMethodParameterKind
|
101
|
+
- range:
|
102
|
+
start:
|
103
|
+
line: 7
|
104
|
+
character: 23
|
105
|
+
end:
|
106
|
+
line: 7
|
107
|
+
character: 29
|
108
|
+
severity: ERROR
|
109
|
+
message: 'The method parameter has different kind from the declaration `(size:
|
110
|
+
::Integer, name: ::String) -> void`'
|
111
|
+
code: Ruby::DifferentMethodParameterKind
|
66
112
|
- file: else_on_exhaustive_case.rb
|
67
113
|
diagnostics:
|
68
114
|
- range:
|
@@ -96,16 +142,23 @@
|
|
96
142
|
- range:
|
97
143
|
start:
|
98
144
|
line: 1
|
99
|
-
character:
|
145
|
+
character: 11
|
100
146
|
end:
|
101
147
|
line: 1
|
102
|
-
character:
|
148
|
+
character: 12
|
103
149
|
severity: ERROR
|
104
|
-
message:
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
150
|
+
message: Unexpected positional argument
|
151
|
+
code: Ruby::UnexpectedPositionalArgument
|
152
|
+
- range:
|
153
|
+
start:
|
154
|
+
line: 1
|
155
|
+
character: 13
|
156
|
+
end:
|
157
|
+
line: 1
|
158
|
+
character: 14
|
159
|
+
severity: ERROR
|
160
|
+
message: Unexpected positional argument
|
161
|
+
code: Ruby::UnexpectedPositionalArgument
|
109
162
|
- file: incompatible_assignment.rb
|
110
163
|
diagnostics:
|
111
164
|
- range:
|
@@ -160,9 +213,10 @@
|
|
160
213
|
character: 9
|
161
214
|
end:
|
162
215
|
line: 3
|
163
|
-
character:
|
216
|
+
character: 11
|
164
217
|
severity: ERROR
|
165
|
-
message: Method parameters are incompatible with declaration `()
|
218
|
+
message: 'Method parameters are incompatible with declaration `(name: ::String)
|
219
|
+
-> void`'
|
166
220
|
code: Ruby::MethodArityMismatch
|
167
221
|
- range:
|
168
222
|
start:
|
@@ -179,10 +233,10 @@
|
|
179
233
|
- range:
|
180
234
|
start:
|
181
235
|
line: 3
|
182
|
-
character:
|
236
|
+
character: 6
|
183
237
|
end:
|
184
|
-
line:
|
185
|
-
character:
|
238
|
+
line: 3
|
239
|
+
character: 9
|
186
240
|
severity: ERROR
|
187
241
|
message: |-
|
188
242
|
Cannot allow method body have type `::String` because declared as type `::Integer`
|
@@ -202,6 +256,41 @@
|
|
202
256
|
severity: ERROR
|
203
257
|
message: Cannot find implementation of method `::MethodDefinitionMissing#foo`
|
204
258
|
code: Ruby::MethodDefinitionMissing
|
259
|
+
- file: method_parameter_mismatch.rb
|
260
|
+
diagnostics:
|
261
|
+
- range:
|
262
|
+
start:
|
263
|
+
line: 3
|
264
|
+
character: 10
|
265
|
+
end:
|
266
|
+
line: 3
|
267
|
+
character: 11
|
268
|
+
severity: ERROR
|
269
|
+
message: The method parameter is incompatible with the declaration `(?::String,
|
270
|
+
*::Integer) -> void`
|
271
|
+
code: Ruby::MethodParameterMismatch
|
272
|
+
- range:
|
273
|
+
start:
|
274
|
+
line: 3
|
275
|
+
character: 13
|
276
|
+
end:
|
277
|
+
line: 3
|
278
|
+
character: 14
|
279
|
+
severity: ERROR
|
280
|
+
message: The method parameter is incompatible with the declaration `(?::String,
|
281
|
+
*::Integer) -> void`
|
282
|
+
code: Ruby::MethodParameterMismatch
|
283
|
+
- range:
|
284
|
+
start:
|
285
|
+
line: 7
|
286
|
+
character: 15
|
287
|
+
end:
|
288
|
+
line: 7
|
289
|
+
character: 20
|
290
|
+
severity: ERROR
|
291
|
+
message: 'The method parameter is incompatible with the declaration `(?name: ::String)
|
292
|
+
-> void`'
|
293
|
+
code: Ruby::MethodParameterMismatch
|
205
294
|
- file: method_return_type_annotation_mismatch.rb
|
206
295
|
diagnostics:
|
207
296
|
- range:
|
@@ -224,13 +313,13 @@
|
|
224
313
|
- range:
|
225
314
|
start:
|
226
315
|
line: 1
|
227
|
-
character:
|
316
|
+
character: 19
|
228
317
|
end:
|
229
318
|
line: 1
|
230
319
|
character: 32
|
231
320
|
severity: ERROR
|
232
|
-
message: '
|
233
|
-
code: Ruby::
|
321
|
+
message: 'More keyword arguments are required: foo'
|
322
|
+
code: Ruby::InsufficientKeywordArguments
|
234
323
|
- file: no_method.rb
|
235
324
|
diagnostics:
|
236
325
|
- range:
|
@@ -335,25 +424,13 @@
|
|
335
424
|
- range:
|
336
425
|
start:
|
337
426
|
line: 1
|
338
|
-
character:
|
339
|
-
end:
|
340
|
-
line: 1
|
341
|
-
character: 45
|
342
|
-
severity: ERROR
|
343
|
-
message: 'Cannot specify unexpected keyword arguments: `bar`'
|
344
|
-
code: Ruby::UnexpectedKeyword
|
345
|
-
- file: unexpected_splat.rb
|
346
|
-
diagnostics:
|
347
|
-
- range:
|
348
|
-
start:
|
349
|
-
line: 1
|
350
|
-
character: 13
|
427
|
+
character: 36
|
351
428
|
end:
|
352
429
|
line: 1
|
353
|
-
character:
|
430
|
+
character: 39
|
354
431
|
severity: ERROR
|
355
|
-
message:
|
356
|
-
code: Ruby::
|
432
|
+
message: Unexpected keyword argument
|
433
|
+
code: Ruby::UnexpectedKeywordArgument
|
357
434
|
- file: unexpected_yield.rb
|
358
435
|
diagnostics:
|
359
436
|
- range:
|
@@ -436,32 +513,6 @@
|
|
436
513
|
| (::Rational) -> ::Rational
|
437
514
|
| (::Complex) -> ::Complex
|
438
515
|
code: Ruby::UnresolvedOverloading
|
439
|
-
- file: unsatisfiable_constraint.rb
|
440
|
-
diagnostics:
|
441
|
-
- range:
|
442
|
-
start:
|
443
|
-
line: 4
|
444
|
-
character: 0
|
445
|
-
end:
|
446
|
-
line: 7
|
447
|
-
character: 3
|
448
|
-
severity: ERROR
|
449
|
-
message: |-
|
450
|
-
Unsatisfiable constraint `::Array[untyped] <: A(1) <: ::String` is generated through (A(1)) { (A(1)) -> void } -> B(2)
|
451
|
-
::Array[untyped] <: ::String
|
452
|
-
::Object <: ::String
|
453
|
-
::BasicObject <: ::String
|
454
|
-
code: Ruby::UnsatisfiableConstraint
|
455
|
-
- range:
|
456
|
-
start:
|
457
|
-
line: 6
|
458
|
-
character: 4
|
459
|
-
end:
|
460
|
-
line: 6
|
461
|
-
character: 7
|
462
|
-
severity: ERROR
|
463
|
-
message: Type `::String` does not have method `foo`
|
464
|
-
code: Ruby::NoMethod
|
465
516
|
- file: unsupported_syntax.rb
|
466
517
|
diagnostics:
|
467
518
|
- range:
|