steep 1.5.2 → 1.6.0.pre.1
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/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