steep 1.7.0.dev.3 → 1.7.0.dev.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +12 -12
- data/doc/narrowing.md +1 -1
- data/doc/shape.md +176 -0
- data/gemfile_steep/Gemfile.lock +5 -5
- data/lib/steep/ast/types/factory.rb +27 -18
- data/lib/steep/ast/types/proc.rb +14 -9
- data/lib/steep/interface/block.rb +1 -1
- data/lib/steep/interface/builder.rb +1 -0
- data/lib/steep/interface/function.rb +14 -6
- data/lib/steep/interface/method_type.rb +15 -7
- data/lib/steep/project/pattern.rb +1 -2
- data/lib/steep/server/interaction_worker.rb +6 -0
- data/lib/steep/server/lsp_formatter.rb +2 -0
- data/lib/steep/services/completion_provider.rb +1 -1
- data/lib/steep/services/file_loader.rb +15 -20
- data/lib/steep/services/signature_help_provider.rb +11 -9
- data/lib/steep/signature/validator.rb +1 -1
- data/lib/steep/subtyping/check.rb +15 -6
- data/lib/steep/subtyping/variable_variance.rb +3 -3
- data/lib/steep/type_construction.rb +185 -149
- data/lib/steep/type_inference/block_params.rb +1 -1
- data/lib/steep/type_inference/logic_type_interpreter.rb +2 -1
- data/lib/steep/type_inference/method_params.rb +16 -0
- data/lib/steep/type_inference/send_args.rb +5 -2
- data/lib/steep/version.rb +1 -1
- data/sig/steep/ast/types/factory.rbs +2 -2
- data/sig/steep/interface/builder.rbs +12 -53
- data/sig/steep/interface/function.rbs +5 -4
- data/sig/steep/services/signature_help_provider.rbs +1 -1
- data/sig/steep/subtyping/variable_variance.rbs +1 -1
- data/sig/steep/type_inference/block_params.rbs +1 -1
- data/sig/steep/type_inference/method_params.rbs +3 -3
- data/steep.gemspec +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17795ed14e183d6e8858e6ea8f57f71dbd3cdced0e4d9cf7e43c646188e486cd
|
4
|
+
data.tar.gz: 7005e9d96f44f23a47f1844597b86fd3d774f000b1de5cf100d235e68c56a0b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e178baa7a185edaafb359032266bfa7f29d082c9da30ca418e5ef4030b5723423f3f36ba4165a640d996e252bb91883dcfe55b1f750f51c3153452b368e5a9ee
|
7
|
+
data.tar.gz: 8919d4c047097e7e7fd63ecba71ae96f412a56588c7b6ff1d381838d2d935d2ba7dc382ca83fe5b679f35ebbe298460e80e87047c88b6ebcc5e3e6ef258e2535
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
steep (1.7.0.dev.
|
4
|
+
steep (1.7.0.dev.4)
|
5
5
|
activesupport (>= 5.1)
|
6
6
|
concurrent-ruby (>= 1.1.10)
|
7
7
|
csv (>= 3.0.9)
|
@@ -12,7 +12,7 @@ PATH
|
|
12
12
|
logger (>= 1.3.0)
|
13
13
|
parser (>= 3.1)
|
14
14
|
rainbow (>= 2.2.2, < 4.0)
|
15
|
-
rbs (>= 3.
|
15
|
+
rbs (>= 3.5.0.pre)
|
16
16
|
securerandom (>= 0.1)
|
17
17
|
strscan (>= 1.0.0)
|
18
18
|
terminal-table (>= 2, < 4)
|
@@ -33,23 +33,23 @@ GEM
|
|
33
33
|
tzinfo (~> 2.0)
|
34
34
|
ast (2.4.2)
|
35
35
|
base64 (0.2.0)
|
36
|
-
bigdecimal (3.1.
|
36
|
+
bigdecimal (3.1.8)
|
37
37
|
concurrent-ruby (1.2.3)
|
38
38
|
connection_pool (2.4.1)
|
39
39
|
csv (3.3.0)
|
40
|
-
debug (1.9.
|
40
|
+
debug (1.9.2)
|
41
41
|
irb (~> 1.10)
|
42
42
|
reline (>= 0.3.8)
|
43
43
|
drb (2.2.1)
|
44
44
|
ffi (1.16.3)
|
45
45
|
fileutils (1.7.2)
|
46
|
-
i18n (1.14.
|
46
|
+
i18n (1.14.5)
|
47
47
|
concurrent-ruby (~> 1.0)
|
48
48
|
io-console (0.7.2)
|
49
|
-
irb (1.
|
50
|
-
rdoc
|
49
|
+
irb (1.13.1)
|
50
|
+
rdoc (>= 4.0.0)
|
51
51
|
reline (>= 0.4.2)
|
52
|
-
json (2.7.
|
52
|
+
json (2.7.2)
|
53
53
|
language_server-protocol (3.17.0.3)
|
54
54
|
listen (3.9.0)
|
55
55
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
@@ -61,22 +61,22 @@ GEM
|
|
61
61
|
minitest-slow_test (0.2.0)
|
62
62
|
minitest (>= 5.0)
|
63
63
|
mutex_m (0.2.0)
|
64
|
-
parser (3.3.0
|
64
|
+
parser (3.3.1.0)
|
65
65
|
ast (~> 2.4.1)
|
66
66
|
racc
|
67
67
|
psych (5.1.2)
|
68
68
|
stringio
|
69
69
|
racc (1.7.3)
|
70
70
|
rainbow (3.1.1)
|
71
|
-
rake (13.1
|
71
|
+
rake (13.2.1)
|
72
72
|
rb-fsevent (0.11.2)
|
73
73
|
rb-inotify (0.10.1)
|
74
74
|
ffi (~> 1.0)
|
75
|
-
rbs (3.
|
75
|
+
rbs (3.5.0.pre.2)
|
76
76
|
abbrev
|
77
77
|
rdoc (6.6.3.1)
|
78
78
|
psych (>= 4.0.0)
|
79
|
-
reline (0.
|
79
|
+
reline (0.5.6)
|
80
80
|
io-console (~> 0.5)
|
81
81
|
securerandom (0.3.1)
|
82
82
|
stackprof (0.2.26)
|
data/doc/narrowing.md
CHANGED
@@ -65,7 +65,7 @@ It immediately type checks the left hand side, but with *conditional mode*. Cond
|
|
65
65
|
x && y
|
66
66
|
```
|
67
67
|
|
68
|
-
Going down again, it gets a typing `x: String?` and `y: String
|
68
|
+
Going down again, it gets a typing `x: String?` and `y: String?`. It runs a type narrowing, to obtain a result both of `x` and `y` are `String` for truthy result, both of `x` and `y` are `String?` for falsy result. The two environments should be propagated to the upper node, because the parent node is also `&&` which is a subject of type narrowing. So, it returns an `ENV` type, `String?` for original type, `{ x: String, y: String }` for truthy result, and `{ x: String?, y: String? }` for falsy result.
|
69
69
|
|
70
70
|
Going up to the outer `&&` expression. The left hand side has `ENV` type, and then the right hand side is type checked based on the truthy environment (because of the semantics of `&&` expression.) Both `x` and `y` are `String` and it type checks. The type of the whole expression union of `String` and the falsy part of the original type -- `nil`.
|
71
71
|
## Union type partition
|
data/doc/shape.md
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
# Shapes
|
2
|
+
|
3
|
+
A *shape* is a data structure, which contains the set of available methods and their types, which is associated with a type. Steep uses shapes to type check method calls -- it calculates the shape of the type of the receiver, checks if the called method is defined on the shape and the arguments are compatible with the method, and calculates the return type.
|
4
|
+
|
5
|
+
Assume an interface `_Foo` is defined as follows:
|
6
|
+
|
7
|
+
```rbs
|
8
|
+
interface _Foo
|
9
|
+
def foo: () -> String
|
10
|
+
|
11
|
+
def bar: () -> self
|
12
|
+
end
|
13
|
+
```
|
14
|
+
|
15
|
+
The shape of `_Foo` will be the following:
|
16
|
+
|
17
|
+
```
|
18
|
+
Shape (_Foo) {
|
19
|
+
foo: () -> String,
|
20
|
+
bar: () -> _Foo
|
21
|
+
}
|
22
|
+
```
|
23
|
+
|
24
|
+
Note that the `self` type in the example is resolved to `_Foo` during shape calculation.
|
25
|
+
|
26
|
+
The shape calculation of an object is straightforward. Calculate a `RBS::Definition` of a class singleton/instance, or an interface, and translate the data structure to a `Shape` object. But there are a few things to consider.
|
27
|
+
## Tuple, record, and proc types
|
28
|
+
The shape of tuple, record, or proc types are based on their base types -- Array, Hash, or Proc classes --, but with specialized method types.
|
29
|
+
|
30
|
+
```
|
31
|
+
Shape ([Integer, String]) {
|
32
|
+
[]: (0) -> Integer
|
33
|
+
| (1) -> String
|
34
|
+
| (Integer) -> (Integer | String)
|
35
|
+
...
|
36
|
+
}
|
37
|
+
```
|
38
|
+
|
39
|
+
The specialization is implemented as a part of shape calculation.
|
40
|
+
## Special methods
|
41
|
+
Steep recognizes some special methods for type narrowing, including `#is_a?`, `#===`, `#nil?`, ... These methods are defined with normal RBS syntax, but the method types in shapes are transformed to types using logic types.
|
42
|
+
|
43
|
+
The shape calculation inserts the specialized methods with these special methods.
|
44
|
+
## `self` types
|
45
|
+
There are two cases of `self` types to consider during shape calculation.
|
46
|
+
|
47
|
+
1. `self` types included in the shape of a type
|
48
|
+
2. `self` types included in given types
|
49
|
+
### 1. `self` types included in the shape of a type
|
50
|
+
`self` types may be included in a class or interface definition.
|
51
|
+
|
52
|
+
```rbs
|
53
|
+
interface _Foo
|
54
|
+
def itself: () -> self
|
55
|
+
end
|
56
|
+
```
|
57
|
+
|
58
|
+
The `self` types included in the shape of `_Foo` type should be resolved to `_Foo` type.
|
59
|
+
|
60
|
+
```
|
61
|
+
Shape (_Foo) {
|
62
|
+
itself: () -> _Foo
|
63
|
+
}
|
64
|
+
```
|
65
|
+
### 2. `self` types included in given types
|
66
|
+
Unlike `self` types included in definitions, `self` types in given types should be preserved.
|
67
|
+
|
68
|
+
```rbs
|
69
|
+
interface _Foo[A]
|
70
|
+
def get: () -> A
|
71
|
+
end
|
72
|
+
```
|
73
|
+
|
74
|
+
The shape of `_Foo[self]` has `self` type as its type argument, and we want the `self` type preserved after the shape calculation.
|
75
|
+
|
76
|
+
```
|
77
|
+
Shape (_Foo[self]) {
|
78
|
+
get: () -> self
|
79
|
+
}
|
80
|
+
```
|
81
|
+
|
82
|
+
We often use `self` types as the return type of a method.
|
83
|
+
|
84
|
+
```rbs
|
85
|
+
class Foo
|
86
|
+
def foo: () -> self
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
So, the implementation of `foo` might use `self` node to return `self` type.
|
91
|
+
|
92
|
+
```rb
|
93
|
+
class Foo
|
94
|
+
def foo
|
95
|
+
# @type var foo: _Foo[self]
|
96
|
+
foo = ...
|
97
|
+
foo.get
|
98
|
+
end
|
99
|
+
end
|
100
|
+
```
|
101
|
+
|
102
|
+
We want the type of `foo.get` to be `self`, not `Foo`, to avoid a type error being detected.
|
103
|
+
## Shape of `self` types
|
104
|
+
We also want `self` type if `self` is the type of the shape.
|
105
|
+
|
106
|
+
```rb
|
107
|
+
class Foo
|
108
|
+
def foo
|
109
|
+
self.itself
|
110
|
+
end
|
111
|
+
end
|
112
|
+
```
|
113
|
+
|
114
|
+
This is a straightforward case, because the type of `self` is `self` itself. Calculate the shape of it, but keep the `self` types in the shape.
|
115
|
+
|
116
|
+
```
|
117
|
+
Shape (self) {
|
118
|
+
itself: () -> self
|
119
|
+
}
|
120
|
+
```
|
121
|
+
|
122
|
+
If `self` is a union type, or something built with a type constructor, the shape calculation gets complicated.
|
123
|
+
|
124
|
+
```rbs
|
125
|
+
class Foo
|
126
|
+
def foo: () -> Integer
|
127
|
+
end
|
128
|
+
|
129
|
+
class Bar
|
130
|
+
def foo: () -> self
|
131
|
+
end
|
132
|
+
```
|
133
|
+
|
134
|
+
What is the expected shape of `self` where the type of `self` is `Foo | Bar`?
|
135
|
+
|
136
|
+
The shape of a union type is straightforward. It calculates the shape of each type, and then it calculates a union of the shape.
|
137
|
+
|
138
|
+
We do the same for the case with `self` types, but it results in slightly incorrect shapes.
|
139
|
+
|
140
|
+
```
|
141
|
+
Shape (Foo) {
|
142
|
+
foo: () -> Integer
|
143
|
+
}
|
144
|
+
|
145
|
+
Shape (Bar) {
|
146
|
+
foo: () -> self # self is preserved, because the shape of `self` is being calculated
|
147
|
+
}
|
148
|
+
|
149
|
+
Shape (Foo | Bar) {
|
150
|
+
foo: () -> (Integer | self)
|
151
|
+
}
|
152
|
+
```
|
153
|
+
|
154
|
+
So, the resulting type of `self.foo` where the type of `self` is `Foo | Bar`, would be `Integer | Foo | Bar`. But, actually, it won't be `Foo` because the `self` comes from `Bar`.
|
155
|
+
|
156
|
+
This is an incorrect result, but Steep is doing this right now.
|
157
|
+
## `class` and `instance` types
|
158
|
+
The shape calculation provides limited support for `class` and `instance` types.
|
159
|
+
|
160
|
+
1. `class`/`instance` types from the definition are resolved
|
161
|
+
2. `class`/`instance` types in generics type arguments of interfaces/instances are preserved
|
162
|
+
3. Shape of `class`/`instance` types are resolved to configuration's `class_type` and `instance_type`, and the translated types are used to calculate the shape
|
163
|
+
|
164
|
+
It's different from `self` types except case #2. The relationship between `self`/`class`/`instance` is not trivial in Ruby. All of them might be resolved to any type, which means calculating one from another of them is simply impossible.
|
165
|
+
## Public methods, private methods
|
166
|
+
`Shape` objects have a flag of if the shape is for *public* method calls or *private* method calls. Private method call is a form of `foo()` or `self.foo()` -- when the receiver is omitted or `self`. Public method calls are anything else.
|
167
|
+
|
168
|
+
The shape calculation starts with *private methods*, and the `Shape#public_shape` method returns another shape that only has *public* methods.
|
169
|
+
|
170
|
+
> Note that the private shape calculation is required even on public method calls. This means a possible chance of future optimizations.
|
171
|
+
## Lazy method type calculation
|
172
|
+
We rarely need all of the methods available for an object. If we want to type check a method call, we only need the method type of that method. All other methods can be just ignored.
|
173
|
+
|
174
|
+
*Lazy method type calculation* is introduced for that case. Instead of calculating the types of all of the methods, it registers a block that computes the method type.
|
175
|
+
|
176
|
+
It is implemented in `Steep::Interface::Shape::Entry` and used to make the shape calculation of a union type faster.
|
data/gemfile_steep/Gemfile.lock
CHANGED
@@ -14,16 +14,16 @@ GEM
|
|
14
14
|
tzinfo (~> 2.0)
|
15
15
|
ast (2.4.2)
|
16
16
|
base64 (0.2.0)
|
17
|
-
bigdecimal (3.1.
|
17
|
+
bigdecimal (3.1.8)
|
18
18
|
concurrent-ruby (1.2.3)
|
19
19
|
connection_pool (2.4.1)
|
20
20
|
csv (3.3.0)
|
21
21
|
drb (2.2.1)
|
22
22
|
ffi (1.16.3)
|
23
23
|
fileutils (1.7.2)
|
24
|
-
i18n (1.14.
|
24
|
+
i18n (1.14.5)
|
25
25
|
concurrent-ruby (~> 1.0)
|
26
|
-
json (2.7.
|
26
|
+
json (2.7.2)
|
27
27
|
language_server-protocol (3.17.0.3)
|
28
28
|
listen (3.9.0)
|
29
29
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
@@ -31,7 +31,7 @@ GEM
|
|
31
31
|
logger (1.6.0)
|
32
32
|
minitest (5.22.3)
|
33
33
|
mutex_m (0.2.0)
|
34
|
-
parser (3.3.0
|
34
|
+
parser (3.3.1.0)
|
35
35
|
ast (~> 2.4.1)
|
36
36
|
racc
|
37
37
|
racc (1.7.3)
|
@@ -42,7 +42,7 @@ GEM
|
|
42
42
|
rbs (3.4.4)
|
43
43
|
abbrev
|
44
44
|
securerandom (0.3.1)
|
45
|
-
steep (1.7.0.dev.
|
45
|
+
steep (1.7.0.dev.3)
|
46
46
|
activesupport (>= 5.1)
|
47
47
|
concurrent-ruby (>= 1.1.10)
|
48
48
|
csv (>= 3.0.9)
|
@@ -212,27 +212,36 @@ module Steep
|
|
212
212
|
params = func.params
|
213
213
|
return_type = func.return_type
|
214
214
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
215
|
+
if params
|
216
|
+
RBS::Types::Function.new(
|
217
|
+
required_positionals: params.required.map {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
|
218
|
+
optional_positionals: params.optional.map {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
|
219
|
+
rest_positionals: params.rest&.yield_self {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
|
220
|
+
trailing_positionals: [],
|
221
|
+
required_keywords: params.required_keywords.transform_values {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
|
222
|
+
optional_keywords: params.optional_keywords.transform_values {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
|
223
|
+
rest_keywords: params.rest_keywords&.yield_self {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
|
224
|
+
return_type: type_1(return_type)
|
225
|
+
)
|
226
|
+
else
|
227
|
+
RBS::Types::UntypedFunction.new(return_type: type_1(return_type))
|
228
|
+
end
|
225
229
|
end
|
226
230
|
|
227
231
|
def params(type)
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
232
|
+
case type
|
233
|
+
when RBS::Types::Function
|
234
|
+
Interface::Function::Params.build(
|
235
|
+
required: type.required_positionals.map {|param| type(param.type) },
|
236
|
+
optional: type.optional_positionals.map {|param| type(param.type) },
|
237
|
+
rest: type.rest_positionals&.yield_self {|param| type(param.type) },
|
238
|
+
required_keywords: type.required_keywords.transform_values {|param| type(param.type) },
|
239
|
+
optional_keywords: type.optional_keywords.transform_values {|param| type(param.type) },
|
240
|
+
rest_keywords: type.rest_keywords&.yield_self {|param| type(param.type) }
|
241
|
+
)
|
242
|
+
when RBS::Types::UntypedFunction
|
243
|
+
nil
|
244
|
+
end
|
236
245
|
end
|
237
246
|
|
238
247
|
def type_param(type_param)
|
data/lib/steep/ast/types/proc.rb
CHANGED
@@ -57,9 +57,11 @@ module Steep
|
|
57
57
|
include Helper::ChildrenLevel
|
58
58
|
|
59
59
|
def level
|
60
|
-
children = type.params
|
60
|
+
children = type.params&.each_type.to_a + [type.return_type]
|
61
61
|
if block
|
62
|
-
|
62
|
+
if block.type.params
|
63
|
+
children.push(*block.type.params.each_type.to_a)
|
64
|
+
end
|
63
65
|
children.push(block.type.return_type)
|
64
66
|
end
|
65
67
|
if self_type
|
@@ -83,13 +85,16 @@ module Steep
|
|
83
85
|
|
84
86
|
def one_arg?
|
85
87
|
params = type.params
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
88
|
+
if params
|
89
|
+
params.required.size == 1 &&
|
90
|
+
params.optional.empty? &&
|
91
|
+
!params.rest &&
|
92
|
+
params.required_keywords.empty? &&
|
93
|
+
params.optional_keywords.empty? &&
|
94
|
+
!params.rest_keywords
|
95
|
+
else
|
96
|
+
true
|
97
|
+
end
|
93
98
|
end
|
94
99
|
|
95
100
|
def back_type
|
@@ -82,7 +82,7 @@ module Steep
|
|
82
82
|
def +(other)
|
83
83
|
optional = self.optional? || other.optional?
|
84
84
|
type = Function.new(
|
85
|
-
params: self.type.params + other.type.params,
|
85
|
+
params: self.type.params && other.type.params ? self.type.params + other.type.params : nil,
|
86
86
|
return_type: AST::Types::Union.build(types: [self.type.return_type, other.type.return_type]),
|
87
87
|
location: nil
|
88
88
|
)
|
@@ -1008,7 +1008,7 @@ module Steep
|
|
1008
1008
|
def free_variables
|
1009
1009
|
@fvs ||= Set[].tap do |fvs|
|
1010
1010
|
# @type var fvs: Set[AST::Types::variable]
|
1011
|
-
fvs.merge(params.free_variables)
|
1011
|
+
fvs.merge(params.free_variables) if params
|
1012
1012
|
fvs.merge(return_type.free_variables)
|
1013
1013
|
end
|
1014
1014
|
end
|
@@ -1016,7 +1016,7 @@ module Steep
|
|
1016
1016
|
def subst(s)
|
1017
1017
|
return self if s.empty?
|
1018
1018
|
|
1019
|
-
ps = params.subst(s)
|
1019
|
+
ps = params.subst(s) if params
|
1020
1020
|
ret = return_type.subst(s)
|
1021
1021
|
|
1022
1022
|
if ps == params && ret == return_type
|
@@ -1032,7 +1032,7 @@ module Steep
|
|
1032
1032
|
|
1033
1033
|
def each_type(&block)
|
1034
1034
|
if block
|
1035
|
-
params
|
1035
|
+
params&.each_type(&block)
|
1036
1036
|
yield return_type
|
1037
1037
|
else
|
1038
1038
|
enum_for :each_type
|
@@ -1043,7 +1043,7 @@ module Steep
|
|
1043
1043
|
|
1044
1044
|
def map_type(&block)
|
1045
1045
|
Function.new(
|
1046
|
-
params: params
|
1046
|
+
params: params&.map_type(&block),
|
1047
1047
|
return_type: yield(return_type),
|
1048
1048
|
location: location
|
1049
1049
|
)
|
@@ -1058,11 +1058,19 @@ module Steep
|
|
1058
1058
|
end
|
1059
1059
|
|
1060
1060
|
def to_s
|
1061
|
-
|
1061
|
+
if params
|
1062
|
+
"#{params} -> #{return_type}"
|
1063
|
+
else
|
1064
|
+
"(?) -> #{return_type}"
|
1065
|
+
end
|
1062
1066
|
end
|
1063
1067
|
|
1064
1068
|
def closed?
|
1065
|
-
params
|
1069
|
+
if params
|
1070
|
+
params.closed? && return_type.free_variables.empty?
|
1071
|
+
else
|
1072
|
+
return_type.free_variables.empty?
|
1073
|
+
end
|
1066
1074
|
end
|
1067
1075
|
end
|
1068
1076
|
end
|
@@ -61,7 +61,7 @@ module Steep
|
|
61
61
|
type.each_type(&block)
|
62
62
|
if block()
|
63
63
|
yield(block().self_type) if block().self_type
|
64
|
-
block().type.params
|
64
|
+
block().type.params&.each_type(&block)
|
65
65
|
yield(block().type.return_type)
|
66
66
|
end
|
67
67
|
else
|
@@ -119,7 +119,7 @@ module Steep
|
|
119
119
|
self.class.new(
|
120
120
|
type_params: type_params,
|
121
121
|
type: Function.new(
|
122
|
-
params: type.params.subst(s1) + other.type.params.subst(s2),
|
122
|
+
params: type.params && other.type.params ? type.params.subst(s1) + other.type.params.subst(s2) : nil,
|
123
123
|
return_type: AST::Types::Union.build(
|
124
124
|
types: [type.return_type.subst(s1), other.type.return_type.subst(s2)]
|
125
125
|
),
|
@@ -250,10 +250,13 @@ module Steep
|
|
250
250
|
nil
|
251
251
|
end
|
252
252
|
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
253
|
+
if b.type.params && ob.type.params
|
254
|
+
# Return when the two block parameters are imcompatible.
|
255
|
+
return unless b.type.params & ob.type.params
|
256
|
+
block_params = b.type.params | ob.type.params or return
|
257
|
+
else
|
258
|
+
block_params = b.type.params || ob.type.params
|
259
|
+
end
|
257
260
|
|
258
261
|
block_return_type = AST::Types::Intersection.build(types: [b.type.return_type, ob.type.return_type])
|
259
262
|
block_type = Function.new(params: block_params, return_type: block_return_type, location: nil)
|
@@ -285,7 +288,12 @@ module Steep
|
|
285
288
|
def &(other)
|
286
289
|
return self if self == other
|
287
290
|
|
288
|
-
|
291
|
+
if self.type.params && other.type.params
|
292
|
+
params = self.type.params | other.type.params or return
|
293
|
+
else
|
294
|
+
params = self.type.params || other.type.params
|
295
|
+
end
|
296
|
+
|
289
297
|
block =
|
290
298
|
case
|
291
299
|
when (b = self.block) && (ob = other.block)
|
@@ -46,10 +46,9 @@ module Steep
|
|
46
46
|
|
47
47
|
def test_string(path, patterns, prefixes)
|
48
48
|
string = path.to_s
|
49
|
-
extension = path.extname
|
50
49
|
|
51
50
|
patterns.any? {|pat| File.fnmatch(pat, string, File::FNM_PATHNAME) } ||
|
52
|
-
prefixes.any? {|prefix|
|
51
|
+
prefixes.any? {|prefix| File.fnmatch("#{prefix}**/*#{ext}", string, File::FNM_PATHNAME) }
|
53
52
|
end
|
54
53
|
end
|
55
54
|
end
|
@@ -90,6 +90,12 @@ module Steep
|
|
90
90
|
collect_changes(request)
|
91
91
|
queue_job ApplyChangeJob.new
|
92
92
|
|
93
|
+
when "$/file/reset"
|
94
|
+
uri = request[:params][:uri]
|
95
|
+
text = request[:params][:content]
|
96
|
+
reset_change(uri: uri, text: text)
|
97
|
+
queue_job ApplyChangeJob.new
|
98
|
+
|
93
99
|
when "textDocument/hover"
|
94
100
|
id = request[:id]
|
95
101
|
|
@@ -740,7 +740,7 @@ module Steep
|
|
740
740
|
if method = shape.methods[call.method_name]
|
741
741
|
method.method_types.each.with_index do |method_type, i|
|
742
742
|
defn = method_type.method_decls.to_a[0]&.method_def
|
743
|
-
if defn
|
743
|
+
if defn && defn.type.type
|
744
744
|
range = range_for(position, prefix: prefix)
|
745
745
|
kwargs = argument_nodes.find { |arg| arg.type == :kwargs }&.children || []
|
746
746
|
used_kwargs = kwargs.filter_map { |arg| arg.type == :pair && arg.children.first.children.first }
|
@@ -12,30 +12,25 @@ module Steep
|
|
12
12
|
pats = commandline_patterns.empty? ? pattern.patterns : commandline_patterns
|
13
13
|
|
14
14
|
pats.each do |path|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
if source_path.file?
|
31
|
-
relative_path = source_path.relative_path_from(base_dir)
|
32
|
-
unless pattern.ignore?(relative_path)
|
33
|
-
yield relative_path
|
15
|
+
Pathname.glob((base_dir + path).to_s).each do |absolute_path|
|
16
|
+
if absolute_path.file?
|
17
|
+
relative_path = absolute_path.relative_path_from(base_dir)
|
18
|
+
if pattern =~ relative_path
|
19
|
+
yield relative_path
|
20
|
+
end
|
21
|
+
else
|
22
|
+
files = Pathname.glob("#{absolute_path}/**/*#{pattern.ext}")
|
23
|
+
|
24
|
+
files.sort.each do |source_path|
|
25
|
+
if source_path.file?
|
26
|
+
relative_path = source_path.relative_path_from(base_dir)
|
27
|
+
unless pattern.ignore?(relative_path)
|
28
|
+
yield relative_path
|
29
|
+
end
|
34
30
|
end
|
35
31
|
end
|
36
32
|
end
|
37
33
|
end
|
38
|
-
|
39
34
|
end
|
40
35
|
else
|
41
36
|
enum_for :each_path_in_patterns, pattern, commandline_patterns
|
@@ -7,15 +7,17 @@ module Steep
|
|
7
7
|
# @implements Item
|
8
8
|
|
9
9
|
def parameters
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
10
|
+
if method_type.type.is_a?(RBS::Types::Function)
|
11
|
+
arguments = [] #: Array[String]
|
12
|
+
arguments.push(*method_type.type.required_positionals.map(&:to_s))
|
13
|
+
arguments.push(*method_type.type.optional_positionals.map {|p| "?#{p}"})
|
14
|
+
arguments.push("*#{self.method_type.type.rest_positionals}") if method_type.type.rest_positionals
|
15
|
+
arguments.push(*method_type.type.trailing_positionals.map(&:to_s))
|
16
|
+
arguments.push(*method_type.type.required_keywords.map {|name, param| "#{name}: #{param}" })
|
17
|
+
arguments.push(*method_type.type.optional_keywords.map {|name, param| "?#{name}: #{param}" })
|
18
|
+
arguments.push("**#{method_type.type.rest_keywords}") if method_type.type.rest_keywords
|
19
|
+
arguments
|
20
|
+
end
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
@@ -134,7 +134,7 @@ module Steep
|
|
134
134
|
end
|
135
135
|
|
136
136
|
def validate_type(type)
|
137
|
-
Steep.logger.debug "#{Location.to_string type.location}: Validating #{type}..."
|
137
|
+
Steep.logger.debug { "#{Location.to_string type.location}: Validating #{type}..." }
|
138
138
|
|
139
139
|
validator.validate_type(type, context: nil)
|
140
140
|
validate_type_application(type)
|