steep 1.5.2 → 1.6.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/.github/workflows/ruby-windows.yml +1 -2
- data/.github/workflows/ruby.yml +1 -2
- data/CHANGELOG.md +41 -0
- data/Gemfile +2 -4
- data/Gemfile.lock +37 -19
- data/gemfile_steep/Gemfile.lock +4 -4
- data/lib/steep/ast/types/logic.rb +6 -0
- data/lib/steep/cli.rb +39 -19
- data/lib/steep/interface/builder.rb +9 -0
- data/lib/steep/path_helper.rb +2 -0
- data/lib/steep/server/change_buffer.rb +9 -0
- data/lib/steep/server/delay_queue.rb +41 -0
- data/lib/steep/server/interaction_worker.rb +4 -2
- data/lib/steep/server/master.rb +106 -10
- data/lib/steep/server/type_check_worker.rb +10 -3
- data/lib/steep/services/completion_provider.rb +1 -1
- data/lib/steep/services/stats_calculator.rb +2 -2
- data/lib/steep/services/type_name_completion.rb +86 -15
- data/lib/steep/signature/validator.rb +9 -2
- data/lib/steep/subtyping/check.rb +24 -18
- data/lib/steep/type_construction.rb +60 -18
- data/lib/steep/type_inference/logic_type_interpreter.rb +26 -0
- data/lib/steep/type_inference/method_params.rb +1 -1
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +1 -3
- data/sig/shims/language-server_protocol.rbs +12 -0
- data/sig/steep/ast/types/logic.rbs +5 -0
- data/sig/steep/ast/types.rbs +1 -1
- data/sig/steep/cli.rbs +2 -0
- data/sig/steep/diagnostic/ruby.rbs +7 -7
- data/sig/steep/server/change_buffer.rbs +4 -0
- data/sig/steep/server/delay_queue.rbs +37 -0
- data/sig/steep/server/master.rbs +4 -0
- data/sig/steep/services/stats_calculator.rbs +30 -6
- data/sig/steep/services/type_name_completion.rbs +13 -0
- data/sig/steep/signature/validator.rbs +5 -0
- data/sig/steep/subtyping/check.rbs +1 -1
- data/sig/steep/subtyping/relation.rbs +11 -1
- data/sig/steep/subtyping/result.rbs +1 -1
- data/sig/steep/type_construction.rbs +1 -1
- data/smoke/block/test_expectations.yml +10 -14
- data/smoke/enumerator/test_expectations.yml +10 -10
- data/smoke/integer/test_expectations.yml +5 -16
- data/smoke/regression/hello world.rb +1 -0
- data/smoke/regression/test_expectations.yml +12 -0
- data/steep.gemspec +1 -1
- metadata +8 -7
- data/lib/steep/shims/filter_map.rb +0 -30
- data/lib/steep/shims/symbol_start_with.rb +0 -18
@@ -70,8 +70,15 @@ module Steep
|
|
70
70
|
when "initialize"
|
71
71
|
load_files(project: project, commandline_args: commandline_args)
|
72
72
|
writer.write({ id: request[:id], result: nil})
|
73
|
+
|
73
74
|
when "textDocument/didChange"
|
74
75
|
collect_changes(request)
|
76
|
+
|
77
|
+
when "$/file/reset"
|
78
|
+
uri = request[:params][:uri]
|
79
|
+
text = request[:params][:content]
|
80
|
+
reset_change(uri: uri, text: text)
|
81
|
+
|
75
82
|
when "workspace/symbol"
|
76
83
|
query = request[:params][:query]
|
77
84
|
queue << WorkspaceSymbolJob.new(id: request[:id], query: query)
|
@@ -165,7 +172,7 @@ module Steep
|
|
165
172
|
writer.write(
|
166
173
|
method: :"textDocument/publishDiagnostics",
|
167
174
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
168
|
-
uri: Steep::PathHelper.to_uri(job.path),
|
175
|
+
uri: Steep::PathHelper.to_uri(job.path).to_s,
|
169
176
|
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq
|
170
177
|
)
|
171
178
|
)
|
@@ -183,7 +190,7 @@ module Steep
|
|
183
190
|
writer.write(
|
184
191
|
method: :"textDocument/publishDiagnostics",
|
185
192
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
186
|
-
uri: Steep::PathHelper.to_uri(job.path),
|
193
|
+
uri: Steep::PathHelper.to_uri(job.path).to_s,
|
187
194
|
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
|
188
195
|
)
|
189
196
|
)
|
@@ -202,7 +209,7 @@ module Steep
|
|
202
209
|
writer.write(
|
203
210
|
method: :"textDocument/publishDiagnostics",
|
204
211
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
205
|
-
uri: Steep::PathHelper.to_uri(job.path),
|
212
|
+
uri: Steep::PathHelper.to_uri(job.path).to_s,
|
206
213
|
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
|
207
214
|
)
|
208
215
|
)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Steep
|
2
2
|
module Services
|
3
3
|
class StatsCalculator
|
4
|
-
SuccessStats
|
4
|
+
class SuccessStats < Struct.new(:target, :path, :typed_calls_count, :untyped_calls_count, :error_calls_count, keyword_init: true)
|
5
5
|
def as_json
|
6
6
|
{
|
7
7
|
type: "success",
|
@@ -14,7 +14,7 @@ module Steep
|
|
14
14
|
}
|
15
15
|
end
|
16
16
|
end
|
17
|
-
ErrorStats
|
17
|
+
class ErrorStats < Struct.new(:target, :path, keyword_init: true)
|
18
18
|
def as_json
|
19
19
|
{
|
20
20
|
type: "error",
|
@@ -31,15 +31,20 @@ module Steep
|
|
31
31
|
|
32
32
|
case prefix
|
33
33
|
when /\A((::\w+[A-Z])+(::)?)/
|
34
|
-
|
34
|
+
namespace = $1 or raise
|
35
|
+
NamespacePrefix.new(RBS::Namespace.parse(namespace.reverse), namespace.size)
|
35
36
|
when /\A::/
|
36
37
|
NamespacePrefix.new(RBS::Namespace.root, 2)
|
37
38
|
when /\A(\w*[A-Za-z_])((::\w+[A-Z])+(::)?)/
|
38
|
-
|
39
|
+
namespace = $1 or raise
|
40
|
+
identifier = $2 or raise
|
41
|
+
NamespacedIdentPrefix.new(RBS::Namespace.parse(identifier.reverse), namespace.reverse, namespace.size + identifier.size)
|
39
42
|
when /\A(\w*[A-Za-z_])::/
|
40
|
-
|
43
|
+
namespace = $1 or raise
|
44
|
+
NamespacedIdentPrefix.new(RBS::Namespace.root, namespace.reverse, namespace.size + 2)
|
41
45
|
when /\A(\w*[A-Za-z_])/
|
42
|
-
|
46
|
+
identifier = $1 or raise
|
47
|
+
RawIdentPrefix.new(identifier.reverse)
|
43
48
|
end
|
44
49
|
end
|
45
50
|
end
|
@@ -92,36 +97,97 @@ module Steep
|
|
92
97
|
if block
|
93
98
|
env = self.env
|
94
99
|
|
100
|
+
table = {} #: Hash[RBS::Namespace, Array[RBS::TypeName]]
|
101
|
+
env.class_decls.each_key do |type_name|
|
102
|
+
yield(type_name)
|
103
|
+
(table[type_name.namespace] ||= []) << type_name
|
104
|
+
end
|
105
|
+
env.type_alias_decls.each_key do |type_name|
|
106
|
+
yield(type_name)
|
107
|
+
(table[type_name.namespace] ||= []) << type_name
|
108
|
+
end
|
109
|
+
env.interface_decls.each_key do |type_name|
|
110
|
+
yield(type_name)
|
111
|
+
(table[type_name.namespace] ||= []) << type_name
|
112
|
+
end
|
113
|
+
env.class_alias_decls.each_key do |type_name|
|
114
|
+
yield(type_name)
|
115
|
+
(table[type_name.namespace] ||= []) << type_name
|
116
|
+
end
|
117
|
+
|
118
|
+
env.class_alias_decls.each_key do |alias_name|
|
119
|
+
normalized_name = env.normalize_module_name?(alias_name) or next
|
120
|
+
each_type_name_under(alias_name, normalized_name, table: table, &block)
|
121
|
+
end
|
122
|
+
|
123
|
+
resolve_pairs = [] #: Array[[RBS::TypeName, RBS::TypeName]]
|
124
|
+
|
95
125
|
map.instance_eval do
|
96
126
|
@map.each_key do |name|
|
97
127
|
relative_name = RBS::TypeName.new(name: name, namespace: RBS::Namespace.empty)
|
98
128
|
if absolute_name = resolve?(relative_name)
|
99
129
|
if env.type_name?(absolute_name)
|
100
130
|
# Yields only if the relative type name resolves to existing absolute type name
|
101
|
-
|
131
|
+
resolve_pairs << [relative_name, absolute_name]
|
102
132
|
end
|
103
133
|
end
|
104
134
|
end
|
105
135
|
end
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
136
|
+
|
137
|
+
resolve_pairs.each do |use_name, absolute_name|
|
138
|
+
yield use_name
|
139
|
+
each_type_name_under(use_name, absolute_name, table: table, &block)
|
140
|
+
end
|
110
141
|
else
|
111
142
|
enum_for :each_type_name
|
112
143
|
end
|
113
144
|
end
|
114
145
|
|
146
|
+
def each_type_name_under(module_name, normalized_name, table:, &block)
|
147
|
+
if children = table.fetch(normalized_name.to_namespace, nil)
|
148
|
+
module_namespace = module_name.to_namespace
|
149
|
+
|
150
|
+
children.each do |normalized_child_name|
|
151
|
+
child_name = RBS::TypeName.new(namespace: module_namespace, name: normalized_child_name.name)
|
152
|
+
|
153
|
+
yield child_name
|
154
|
+
|
155
|
+
if normalized_child_name.class?
|
156
|
+
each_type_name_under(child_name, env.normalize_module_name(normalized_child_name), table: table, &block)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def resolve_used_name(name)
|
163
|
+
return nil if name.absolute?
|
164
|
+
|
165
|
+
case
|
166
|
+
when resolved = map.resolve?(name)
|
167
|
+
resolved
|
168
|
+
when name.namespace.empty?
|
169
|
+
nil
|
170
|
+
else
|
171
|
+
if resolved_parent = resolve_used_name(name.namespace.to_type_name)
|
172
|
+
resolved_name = RBS::TypeName.new(namespace: resolved_parent.to_namespace, name: name.name)
|
173
|
+
if env.normalize_type_name?(resolved_name)
|
174
|
+
resolved_name
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
115
180
|
def resolve_name_in_context(name)
|
116
|
-
if resolved_name =
|
181
|
+
if resolved_name = resolve_used_name(name)
|
117
182
|
return [resolved_name, name]
|
118
183
|
end
|
119
184
|
|
120
185
|
name.absolute? or raise
|
186
|
+
normalized_name = env.normalize_type_name?(name) or raise "Cannot normalize given type name `#{name}`"
|
121
187
|
|
122
188
|
name.namespace.path.reverse_each.inject(RBS::TypeName.new(namespace: RBS::Namespace.empty, name: name.name)) do |relative_name, component|
|
123
189
|
if type_name_resolver.resolve(relative_name, context: context) == name
|
124
|
-
return [
|
190
|
+
return [normalized_name, relative_name]
|
125
191
|
end
|
126
192
|
|
127
193
|
RBS::TypeName.new(
|
@@ -130,10 +196,10 @@ module Steep
|
|
130
196
|
)
|
131
197
|
end
|
132
198
|
|
133
|
-
if type_name_resolver.resolve(name.relative!, context: context) == name && !
|
134
|
-
[
|
199
|
+
if type_name_resolver.resolve(name.relative!, context: context) == name && !resolve_used_name(name.relative!)
|
200
|
+
[normalized_name, name.relative!]
|
135
201
|
else
|
136
|
-
[
|
202
|
+
[normalized_name, name]
|
137
203
|
end
|
138
204
|
end
|
139
205
|
|
@@ -144,7 +210,12 @@ module Steep
|
|
144
210
|
type_name.split.any? {|sym| sym.to_s.downcase.include?(prefix.ident.downcase) }
|
145
211
|
end
|
146
212
|
when Prefix::NamespacedIdentPrefix
|
147
|
-
absolute_namespace =
|
213
|
+
absolute_namespace =
|
214
|
+
if prefix.namespace.empty?
|
215
|
+
RBS::Namespace.root
|
216
|
+
else
|
217
|
+
type_name_resolver.resolve(prefix.namespace.to_type_name, context: context)&.to_namespace || prefix.namespace
|
218
|
+
end
|
148
219
|
|
149
220
|
each_type_name.filter do|name|
|
150
221
|
name.namespace == absolute_namespace &&
|
@@ -112,10 +112,11 @@ module Steep
|
|
112
112
|
type.args
|
113
113
|
]
|
114
114
|
when RBS::Types::Alias
|
115
|
-
|
115
|
+
type_name = env.normalize_type_name?(type.name) or return
|
116
|
+
entry = env.type_alias_decls[type_name]
|
116
117
|
|
117
118
|
[
|
118
|
-
|
119
|
+
type_name,
|
119
120
|
entry.decl.type_params,
|
120
121
|
type.args
|
121
122
|
]
|
@@ -520,6 +521,12 @@ module Steep
|
|
520
521
|
def validate_one_alias(name, entry = env.type_alias_decls[name])
|
521
522
|
rescue_validation_errors(name) do
|
522
523
|
Steep.logger.debug "Validating alias `#{name}`..."
|
524
|
+
|
525
|
+
unless name.namespace.empty?
|
526
|
+
outer = name.namespace.to_type_name
|
527
|
+
builder.validate_type_name(outer, entry.decl.location&.aref(:name))
|
528
|
+
end
|
529
|
+
|
523
530
|
upper_bounds = entry.decl.type_params.each.with_object({}) do |param, bounds|
|
524
531
|
bounds[param.name] = factory.type_opt(param.upper_bound)
|
525
532
|
end
|
@@ -79,11 +79,11 @@ module Steep
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def instance_type
|
82
|
-
@instance_type
|
82
|
+
@instance_type || AST::Types::Instance.instance
|
83
83
|
end
|
84
84
|
|
85
85
|
def class_type
|
86
|
-
@class_type
|
86
|
+
@class_type || AST::Types::Class.instance
|
87
87
|
end
|
88
88
|
|
89
89
|
def constraints
|
@@ -193,7 +193,7 @@ module Steep
|
|
193
193
|
bounds = cache_bounds(relation)
|
194
194
|
fvs = relation.sub_type.free_variables + relation.super_type.free_variables
|
195
195
|
cached = cache[relation, @self_type, @instance_type, @class_type, bounds]
|
196
|
-
if cached && fvs.none? {|var| constraints.unknown?(var) }
|
196
|
+
if cached && fvs.none? {|var| var.is_a?(Symbol) && constraints.unknown?(var) }
|
197
197
|
cached
|
198
198
|
else
|
199
199
|
if assumptions.member?(relation)
|
@@ -212,7 +212,8 @@ module Steep
|
|
212
212
|
|
213
213
|
def cache_bounds(relation)
|
214
214
|
vars = relation.sub_type.free_variables + relation.super_type.free_variables
|
215
|
-
vars.each.with_object({}) do |var, hash|
|
215
|
+
vars.each.with_object({}) do |var, hash| #$ Hash[Symbol, AST::Types::t]
|
216
|
+
next unless var.is_a?(Symbol)
|
216
217
|
if upper_bound = variable_upper_bound(var)
|
217
218
|
hash[var] = upper_bound
|
218
219
|
end
|
@@ -232,7 +233,7 @@ module Steep
|
|
232
233
|
when AST::Types::Literal
|
233
234
|
type.value == true
|
234
235
|
else
|
235
|
-
AST::Builtin::TrueClass.instance_type?(type)
|
236
|
+
AST::Builtin::TrueClass.instance_type?(type) ? true : false
|
236
237
|
end
|
237
238
|
end
|
238
239
|
|
@@ -241,7 +242,7 @@ module Steep
|
|
241
242
|
when AST::Types::Literal
|
242
243
|
type.value == false
|
243
244
|
else
|
244
|
-
AST::Builtin::FalseClass.instance_type?(type)
|
245
|
+
AST::Builtin::FalseClass.instance_type?(type) ? true : false
|
245
246
|
end
|
246
247
|
end
|
247
248
|
|
@@ -410,7 +411,7 @@ module Steep
|
|
410
411
|
class_type: class_type,
|
411
412
|
variable_bounds: variable_upper_bounds
|
412
413
|
)
|
413
|
-
) or
|
414
|
+
) or return Failure(relation, Result::Failure::UnknownPairError.new(relation: relation))
|
414
415
|
}
|
415
416
|
)
|
416
417
|
end
|
@@ -492,7 +493,7 @@ module Steep
|
|
492
493
|
Failure(relation, Result::Failure::UnknownPairError.new(relation: relation))
|
493
494
|
end
|
494
495
|
|
495
|
-
when relation.sub_type.is_a?(AST::Types::Tuple) && AST::Builtin::Array.instance_type?(relation.super_type)
|
496
|
+
when relation.sub_type.is_a?(AST::Types::Tuple) && (super_type = AST::Builtin::Array.instance_type?(relation.super_type))
|
496
497
|
Expand(relation) do
|
497
498
|
tuple_element_type =
|
498
499
|
AST::Types::Union.build(
|
@@ -500,7 +501,7 @@ module Steep
|
|
500
501
|
location: relation.sub_type.location
|
501
502
|
)
|
502
503
|
|
503
|
-
check_type(Relation.new(sub_type: tuple_element_type, super_type:
|
504
|
+
check_type(Relation.new(sub_type: tuple_element_type, super_type: super_type.args[0]))
|
504
505
|
end
|
505
506
|
|
506
507
|
when relation.sub_type.is_a?(AST::Types::Record) && relation.super_type.is_a?(AST::Types::Record)
|
@@ -549,9 +550,7 @@ module Steep
|
|
549
550
|
end
|
550
551
|
|
551
552
|
when relation.super_type.is_a?(AST::Types::Nil) && AST::Builtin::NilClass.instance_type?(relation.sub_type)
|
552
|
-
|
553
|
-
|
554
|
-
when relation.sub_type.is_a?(AST::Types::Nil) && AST::Builtin::NilClass.instance_type?(relation.super_type)
|
553
|
+
# NilClass <: nil
|
555
554
|
Success(relation)
|
556
555
|
|
557
556
|
when relation.sub_type.is_a?(AST::Types::Literal)
|
@@ -742,10 +741,17 @@ module Steep
|
|
742
741
|
args = sub_type.type_params.map {|type_param| AST::Types::Var.fresh(type_param.name) }
|
743
742
|
args.each {|arg| constraints.unknown!(arg.name) }
|
744
743
|
|
745
|
-
upper_bounds = {}
|
746
|
-
relations = [] #: Array[Relation]
|
744
|
+
upper_bounds = {} #: Hash[Symbol, AST::Types::t]
|
745
|
+
relations = [] #: Array[Relation[AST::Types::t]]
|
747
746
|
|
748
747
|
args.zip(sub_type.type_params, super_type.type_params).each do |arg, sub_param, sup_param|
|
748
|
+
# @type var arg: AST::Types::Var
|
749
|
+
# @type var sub_param: Interface::TypeParam?
|
750
|
+
# @type var super_param: Interface::TypeParam?
|
751
|
+
|
752
|
+
sub_param or raise
|
753
|
+
sup_param or raise
|
754
|
+
|
749
755
|
sub_ub = sub_param.upper_bound
|
750
756
|
sup_ub = sup_param.upper_bound
|
751
757
|
|
@@ -927,7 +933,7 @@ module Steep
|
|
927
933
|
|
928
934
|
sub_params, super_params = relation
|
929
935
|
|
930
|
-
pairs = []
|
936
|
+
pairs = [] #: Array[[AST::Types::t, AST::Types::t]]
|
931
937
|
|
932
938
|
sub_flat = sub_params.flat_unnamed_params
|
933
939
|
sup_flat = super_params.flat_unnamed_params
|
@@ -939,7 +945,7 @@ module Steep
|
|
939
945
|
return failure unless sub_params.rest
|
940
946
|
|
941
947
|
while sub_flat.size > 0
|
942
|
-
sub_type = sub_flat.shift
|
948
|
+
sub_type = sub_flat.shift or raise
|
943
949
|
sup_type = sup_flat.shift
|
944
950
|
|
945
951
|
if sup_type
|
@@ -955,7 +961,7 @@ module Steep
|
|
955
961
|
|
956
962
|
when sub_params.rest
|
957
963
|
while sub_flat.size > 0
|
958
|
-
sub_type = sub_flat.shift
|
964
|
+
sub_type = sub_flat.shift or raise
|
959
965
|
sup_type = sup_flat.shift
|
960
966
|
|
961
967
|
if sup_type
|
@@ -972,7 +978,7 @@ module Steep
|
|
972
978
|
end
|
973
979
|
when sub_params.required.size + sub_params.optional.size >= super_params.required.size + super_params.optional.size
|
974
980
|
while sub_flat.size > 0
|
975
|
-
sub_type = sub_flat.shift
|
981
|
+
sub_type = sub_flat.shift or raise
|
976
982
|
sup_type = sup_flat.shift
|
977
983
|
|
978
984
|
if sup_type
|
@@ -710,7 +710,7 @@ module Steep
|
|
710
710
|
end
|
711
711
|
end
|
712
712
|
|
713
|
-
p = pair.constr.synthesize(last_node, hint: hint)
|
713
|
+
p = pair.constr.synthesize(last_node, hint: hint, condition: condition)
|
714
714
|
last_pair = pair + p
|
715
715
|
last_pair.constr.add_typing(node, type: last_pair.type, constr: last_pair.constr)
|
716
716
|
else
|
@@ -1305,29 +1305,39 @@ module Steep
|
|
1305
1305
|
var = node.children[0]
|
1306
1306
|
rhs = node.children[1]
|
1307
1307
|
|
1308
|
-
|
1308
|
+
if SPECIAL_LVAR_NAMES.include?(var)
|
1309
|
+
synthesize(rhs)
|
1310
|
+
add_typing(node, type: AST::Builtin.any_type)
|
1311
|
+
else
|
1312
|
+
var_type = context.type_env[var]
|
1309
1313
|
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
|
1317
|
-
|
1314
|
+
if var_type
|
1315
|
+
type, constr = check(rhs, var_type) do |expected_type, actual_type, result|
|
1316
|
+
typing.add_error(
|
1317
|
+
Diagnostic::Ruby::IncompatibleAssignment.new(
|
1318
|
+
node: node,
|
1319
|
+
lhs_type: expected_type,
|
1320
|
+
rhs_type: actual_type,
|
1321
|
+
result: result
|
1322
|
+
)
|
1318
1323
|
)
|
1319
|
-
|
1324
|
+
end
|
1325
|
+
else
|
1326
|
+
type, constr = synthesize(rhs)
|
1320
1327
|
end
|
1321
|
-
else
|
1322
|
-
type, constr = synthesize(rhs)
|
1323
|
-
end
|
1324
1328
|
|
1325
|
-
|
1329
|
+
constr.add_typing(node, type: type)
|
1330
|
+
end
|
1326
1331
|
end
|
1327
1332
|
|
1328
1333
|
when :restarg
|
1329
1334
|
yield_self do
|
1330
1335
|
var = node.children[0]
|
1336
|
+
|
1337
|
+
if SPECIAL_LVAR_NAMES.include?(var)
|
1338
|
+
return add_typing(node, type: AST::Builtin.any_type)
|
1339
|
+
end
|
1340
|
+
|
1331
1341
|
type = context.type_env[var]
|
1332
1342
|
|
1333
1343
|
unless type
|
@@ -1344,6 +1354,11 @@ module Steep
|
|
1344
1354
|
when :kwrestarg
|
1345
1355
|
yield_self do
|
1346
1356
|
var = node.children[0]
|
1357
|
+
|
1358
|
+
if SPECIAL_LVAR_NAMES.include?(var)
|
1359
|
+
return add_typing(node, type: AST::Builtin.any_type)
|
1360
|
+
end
|
1361
|
+
|
1347
1362
|
type = context.type_env[var]
|
1348
1363
|
unless type
|
1349
1364
|
if context.method_context&.method_type
|
@@ -3046,6 +3061,7 @@ module Steep
|
|
3046
3061
|
end
|
3047
3062
|
else
|
3048
3063
|
parent_type, constr = synthesize(parent_node).to_ary
|
3064
|
+
parent_type = expand_self(parent_type)
|
3049
3065
|
parent_type = deep_expand_alias(parent_type)
|
3050
3066
|
|
3051
3067
|
case parent_type
|
@@ -3284,7 +3300,14 @@ module Steep
|
|
3284
3300
|
|
3285
3301
|
if call && constr
|
3286
3302
|
case method_name.to_s
|
3287
|
-
when "[]="
|
3303
|
+
when "[]="
|
3304
|
+
if test_send_node(node) {|_, _, _, loc| !loc.dot }
|
3305
|
+
last_arg = arguments.last or raise
|
3306
|
+
if typing.has_type?(last_arg)
|
3307
|
+
call = call.with_return_type(typing.type_of(node: last_arg))
|
3308
|
+
end
|
3309
|
+
end
|
3310
|
+
when /\w=\Z/
|
3288
3311
|
last_arg = arguments.last or raise
|
3289
3312
|
if typing.has_type?(last_arg)
|
3290
3313
|
call = call.with_return_type(typing.type_of(node: last_arg))
|
@@ -3292,7 +3315,7 @@ module Steep
|
|
3292
3315
|
end
|
3293
3316
|
|
3294
3317
|
if call.is_a?(TypeInference::MethodCall::Typed)
|
3295
|
-
if (pure_call, type = constr.context.type_env.pure_method_calls
|
3318
|
+
if (pure_call, type = constr.context.type_env.pure_method_calls.fetch(node, nil))
|
3296
3319
|
if type
|
3297
3320
|
call = pure_call.update(node: node, return_type: type)
|
3298
3321
|
constr.add_typing(node, type: call.return_type)
|
@@ -3345,12 +3368,14 @@ module Steep
|
|
3345
3368
|
method_name: method_name,
|
3346
3369
|
method_types: method.method_types
|
3347
3370
|
)
|
3371
|
+
decls = method.method_types.each_with_object(Set[]) {|type, decls| decls.merge(type.method_decls) }
|
3348
3372
|
call = TypeInference::MethodCall::Error.new(
|
3349
3373
|
node: node,
|
3350
3374
|
context: context.call_context,
|
3351
3375
|
method_name: method_name,
|
3352
3376
|
receiver_type: receiver_type,
|
3353
|
-
errors: errors
|
3377
|
+
errors: errors,
|
3378
|
+
method_decls: decls
|
3354
3379
|
)
|
3355
3380
|
end
|
3356
3381
|
|
@@ -3665,6 +3690,23 @@ module Steep
|
|
3665
3690
|
end
|
3666
3691
|
end
|
3667
3692
|
|
3693
|
+
non_arity_errors = fails.reject do |call, _|
|
3694
|
+
if call.is_a?(TypeInference::MethodCall::Error)
|
3695
|
+
call.errors.any? do |error|
|
3696
|
+
error.is_a?(Diagnostic::Ruby::UnexpectedBlockGiven) ||
|
3697
|
+
error.is_a?(Diagnostic::Ruby::RequiredBlockMissing) ||
|
3698
|
+
error.is_a?(Diagnostic::Ruby::UnexpectedPositionalArgument) ||
|
3699
|
+
error.is_a?(Diagnostic::Ruby::InsufficientPositionalArguments) ||
|
3700
|
+
error.is_a?(Diagnostic::Ruby::UnexpectedKeywordArgument) ||
|
3701
|
+
error.is_a?(Diagnostic::Ruby::InsufficientKeywordArguments)
|
3702
|
+
end
|
3703
|
+
end
|
3704
|
+
end
|
3705
|
+
|
3706
|
+
unless non_arity_errors.empty?
|
3707
|
+
fails = non_arity_errors
|
3708
|
+
end
|
3709
|
+
|
3668
3710
|
if fails.one?
|
3669
3711
|
call, constr = fails[0]
|
3670
3712
|
|
@@ -367,6 +367,32 @@ module Steep
|
|
367
367
|
[truthy_result, falsy_result]
|
368
368
|
end
|
369
369
|
end
|
370
|
+
|
371
|
+
when AST::Types::Logic::ArgIsAncestor
|
372
|
+
if receiver && (arg = arguments[0])
|
373
|
+
receiver_type = typing.type_of(node: receiver)
|
374
|
+
arg_type = factory.deep_expand_alias(typing.type_of(node: arg))
|
375
|
+
|
376
|
+
if arg_type.is_a?(AST::Types::Name::Singleton)
|
377
|
+
truthy_type = arg_type
|
378
|
+
falsy_type = receiver_type
|
379
|
+
truthy_env, falsy_env = refine_node_type(
|
380
|
+
env: env,
|
381
|
+
node: receiver,
|
382
|
+
truthy_type: truthy_type,
|
383
|
+
falsy_type: falsy_type
|
384
|
+
)
|
385
|
+
|
386
|
+
truthy_result = Result.new(type: TRUE, env: truthy_env, unreachable: false)
|
387
|
+
truthy_result.unreachable! unless truthy_type
|
388
|
+
|
389
|
+
falsy_result = Result.new(type: FALSE, env: falsy_env, unreachable: false)
|
390
|
+
falsy_result.unreachable! unless falsy_type
|
391
|
+
|
392
|
+
[truthy_result, falsy_result]
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
370
396
|
when AST::Types::Logic::Not
|
371
397
|
if receiver
|
372
398
|
truthy_result, falsy_result = evaluate_node(env: env, node: receiver)
|
@@ -453,7 +453,7 @@ module Steep
|
|
453
453
|
has_error = false
|
454
454
|
|
455
455
|
keywords.each do |keyword|
|
456
|
-
rest_types << keyword_params.requireds[keyword] || keyword_params.optionals[keyword]
|
456
|
+
rest_types << (keyword_params.requireds[keyword] || keyword_params.optionals[keyword])
|
457
457
|
has_error = true
|
458
458
|
end
|
459
459
|
keywords.clear
|
data/lib/steep/version.rb
CHANGED
data/lib/steep.rb
CHANGED
@@ -23,9 +23,6 @@ require "rbs"
|
|
23
23
|
|
24
24
|
require "steep/path_helper"
|
25
25
|
|
26
|
-
require "steep/shims/filter_map"
|
27
|
-
require "steep/shims/symbol_start_with"
|
28
|
-
|
29
26
|
require "steep/thread_waiter"
|
30
27
|
require "steep/equatable"
|
31
28
|
require "steep/method_name"
|
@@ -113,6 +110,7 @@ require "steep/services/stats_calculator"
|
|
113
110
|
require "steep/services/file_loader"
|
114
111
|
require "steep/services/goto_service"
|
115
112
|
|
113
|
+
require "steep/server/delay_queue"
|
116
114
|
require "steep/server/lsp_formatter"
|
117
115
|
require "steep/server/change_buffer"
|
118
116
|
require "steep/server/base_worker"
|
@@ -52,6 +52,11 @@ module Steep
|
|
52
52
|
def initialize: (?location: untyped?) -> void
|
53
53
|
end
|
54
54
|
|
55
|
+
# A type for `Class#<` or `Class#<=` call results.
|
56
|
+
class ArgIsAncestor < Base
|
57
|
+
def initialize: (?location: untyped?) -> void
|
58
|
+
end
|
59
|
+
|
55
60
|
# A type with truthy/falsy type environment.
|
56
61
|
class Env < Base
|
57
62
|
attr_reader truthy: TypeInference::TypeEnv
|
data/sig/steep/ast/types.rbs
CHANGED
@@ -6,7 +6,7 @@ module Steep
|
|
6
6
|
| Intersection | Record | Tuple | Union
|
7
7
|
| Name::Alias | Name::Instance | Name::Interface | Name::Singleton
|
8
8
|
| Proc | Var
|
9
|
-
| Logic::Not | Logic::ReceiverIsNil | Logic::ReceiverIsNotNil | Logic::ReceiverIsArg | Logic::ArgIsReceiver | Logic::ArgEqualsReceiver | Logic::Env
|
9
|
+
| Logic::Not | Logic::ReceiverIsNil | Logic::ReceiverIsNotNil | Logic::ReceiverIsArg | Logic::ArgIsReceiver | Logic::ArgEqualsReceiver | Logic::ArgIsAncestor | Logic::Env
|
10
10
|
|
11
11
|
# Variables and special types that is subject for substitution
|
12
12
|
#
|
data/sig/steep/cli.rbs
CHANGED