steep 0.17.1 → 0.22.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/workflows/ruby.yml +5 -1
- data/CHANGELOG.md +27 -0
- data/Gemfile +7 -0
- data/bin/steep-prof +16 -0
- data/lib/steep.rb +1 -0
- data/lib/steep/ast/types/factory.rb +15 -12
- data/lib/steep/ast/types/literal.rb +4 -0
- data/lib/steep/project/completion_provider.rb +26 -5
- data/lib/steep/project/dsl.rb +7 -1
- data/lib/steep/project/file.rb +7 -0
- data/lib/steep/project/file_loader.rb +1 -1
- data/lib/steep/project/hover_content.rb +9 -3
- data/lib/steep/project/options.rb +7 -0
- data/lib/steep/project/target.rb +43 -23
- data/lib/steep/server/interaction_worker.rb +7 -6
- data/lib/steep/server/signature_worker.rb +4 -0
- data/lib/steep/signature/errors.rb +28 -0
- data/lib/steep/signature/validator.rb +57 -27
- data/lib/steep/subtyping/check.rb +205 -34
- data/lib/steep/type_construction.rb +170 -63
- data/lib/steep/type_inference/type_env.rb +2 -2
- data/lib/steep/typing.rb +6 -0
- data/lib/steep/version.rb +1 -1
- data/smoke/class/a.rbs +1 -2
- data/smoke/class/f.rb +3 -1
- data/smoke/extension/a.rbs +3 -2
- data/smoke/extension/e.rbs +2 -3
- data/smoke/interface/a.rbs +6 -6
- data/steep.gemspec +1 -8
- metadata +7 -96
@@ -95,8 +95,8 @@ module Steep
|
|
95
95
|
```
|
96
96
|
HOVER
|
97
97
|
if content.definition
|
98
|
-
if content.definition.
|
99
|
-
string << "\n----\n\n#{content.definition.
|
98
|
+
if content.definition.comments
|
99
|
+
string << "\n----\n\n#{content.definition.comments.map(&:string).join("\n\n")}"
|
100
100
|
end
|
101
101
|
|
102
102
|
string << "\n----\n\n#{content.definition.method_types.map {|x| "- `#{x}`\n" }.join()}"
|
@@ -110,8 +110,8 @@ HOVER
|
|
110
110
|
def #{content.method_name}: #{content.method_type}
|
111
111
|
```
|
112
112
|
HOVER
|
113
|
-
if (comment = content.
|
114
|
-
string << "\n----\n\n#{comment
|
113
|
+
if (comment = content.comment_string)
|
114
|
+
string << "\n----\n\n#{comment}\n"
|
115
115
|
end
|
116
116
|
|
117
117
|
if content.definition.method_types.size > 1
|
@@ -190,8 +190,9 @@ HOVER
|
|
190
190
|
new_text: "#{item.identifier}#{method_type_snippet}",
|
191
191
|
range: range
|
192
192
|
),
|
193
|
-
documentation: item.
|
194
|
-
insert_text_format: LanguageServer::Protocol::Constant::InsertTextFormat::SNIPPET
|
193
|
+
documentation: item.comment&.string,
|
194
|
+
insert_text_format: LanguageServer::Protocol::Constant::InsertTextFormat::SNIPPET,
|
195
|
+
sort_text: item.inherited_method ? 'z' : 'a' # Ensure language server puts non-inherited methods before inherited methods
|
195
196
|
)
|
196
197
|
when Project::CompletionProvider::InstanceVariableItem
|
197
198
|
label = "#{item.identifier}: #{item.type}"
|
@@ -112,8 +112,12 @@ module Steep
|
|
112
112
|
target.signature_files.each_key.with_object({}) do |path, hash|
|
113
113
|
hash[path] = []
|
114
114
|
end
|
115
|
+
when Project::Target::SignatureOtherErrorStatus
|
116
|
+
Steep.log_error status.error
|
117
|
+
{}
|
115
118
|
else
|
116
119
|
Steep.logger.info "Unexpected target status: #{status.class}"
|
120
|
+
{}
|
117
121
|
end
|
118
122
|
|
119
123
|
diagnostics.each do |path, diags|
|
@@ -19,6 +19,19 @@ module Steep
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
class DuplicatedDefinitionError < Base
|
23
|
+
attr_reader :name
|
24
|
+
|
25
|
+
def initialize(name:, location:)
|
26
|
+
@name = name
|
27
|
+
@location = location
|
28
|
+
end
|
29
|
+
|
30
|
+
def puts(io)
|
31
|
+
io.puts "#{loc_to_s}\sDuplicatedDefinitionError: name=#{name}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
22
35
|
class UnknownTypeNameError < Base
|
23
36
|
attr_reader :name
|
24
37
|
|
@@ -48,6 +61,21 @@ module Steep
|
|
48
61
|
io.puts "#{loc_to_s}\tInvalidTypeApplicationError: name=#{name}, expected=[#{params.join(", ")}], actual=[#{args.join(", ")}]"
|
49
62
|
end
|
50
63
|
end
|
64
|
+
|
65
|
+
class InvalidMethodOverloadError < Base
|
66
|
+
attr_reader :class_name
|
67
|
+
attr_reader :method_name
|
68
|
+
|
69
|
+
def initialize(class_name:, method_name:, location:)
|
70
|
+
@class_name = class_name
|
71
|
+
@method_name = method_name
|
72
|
+
@location = location
|
73
|
+
end
|
74
|
+
|
75
|
+
def puts(io)
|
76
|
+
io.puts "#{loc_to_s}\tInvalidMethodOverloadError: class_name=#{class_name}, method_name=#{method_name}"
|
77
|
+
end
|
78
|
+
end
|
51
79
|
end
|
52
80
|
end
|
53
81
|
end
|
@@ -35,6 +35,14 @@ module Steep
|
|
35
35
|
checker.factory.definition_builder
|
36
36
|
end
|
37
37
|
|
38
|
+
def type_name_resolver
|
39
|
+
@type_name_resolver ||= RBS::TypeNameResolver.from_env(env)
|
40
|
+
end
|
41
|
+
|
42
|
+
def validator
|
43
|
+
@validator ||= RBS::Validator.new(env: env, resolver: type_name_resolver)
|
44
|
+
end
|
45
|
+
|
38
46
|
def factory
|
39
47
|
checker.factory
|
40
48
|
end
|
@@ -45,59 +53,75 @@ module Steep
|
|
45
53
|
validate_decl
|
46
54
|
validate_const
|
47
55
|
validate_global
|
56
|
+
validate_alias
|
48
57
|
end
|
49
58
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
59
|
+
def validate_type(type)
|
60
|
+
Steep.logger.debug "#{Location.to_string type.location}: Validating #{type}..."
|
61
|
+
validator.validate_type type, context: [RBS::Namespace.root]
|
62
|
+
end
|
63
|
+
|
64
|
+
def validate_one_class(name)
|
65
|
+
rescue_validation_errors do
|
66
|
+
Steep.logger.debug "Validating class definition `#{name}`..."
|
67
|
+
Steep.logger.tagged "#{name}" do
|
68
|
+
builder.build_instance(name).each_type do |type|
|
69
|
+
validate_type type
|
57
70
|
end
|
58
|
-
builder.build_singleton(
|
59
|
-
|
71
|
+
builder.build_singleton(name).each_type do |type|
|
72
|
+
validate_type type
|
60
73
|
end
|
61
74
|
end
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def validate_one_interface(name)
|
79
|
+
rescue_validation_errors do
|
80
|
+
Steep.logger.debug "Validating interface `#{name}`..."
|
81
|
+
Steep.logger.tagged "#{name}" do
|
82
|
+
builder.build_interface(name).each_type do |type|
|
83
|
+
validate_type type
|
67
84
|
end
|
68
85
|
end
|
69
86
|
end
|
70
87
|
end
|
71
88
|
|
72
89
|
def validate_decl
|
73
|
-
env.
|
74
|
-
|
90
|
+
env.class_decls.each_key do |name|
|
91
|
+
validate_one_class(name)
|
92
|
+
end
|
93
|
+
|
94
|
+
env.interface_decls.each_key do |name|
|
95
|
+
validate_one_interface(name)
|
75
96
|
end
|
76
97
|
end
|
77
98
|
|
78
99
|
def validate_const
|
79
|
-
env.
|
100
|
+
env.constant_decls.each do |name, entry|
|
80
101
|
rescue_validation_errors do
|
81
|
-
Steep.logger.debug "
|
82
|
-
|
102
|
+
Steep.logger.debug "Validating constant `#{name}`..."
|
103
|
+
builder.ensure_namespace!(name.namespace, location: entry.decl.location)
|
104
|
+
validate_type entry.decl.type
|
83
105
|
end
|
84
106
|
end
|
85
107
|
end
|
86
108
|
|
87
109
|
def validate_global
|
88
|
-
env.
|
110
|
+
env.global_decls.each do |name, entry|
|
89
111
|
rescue_validation_errors do
|
90
|
-
Steep.logger.debug "
|
91
|
-
|
112
|
+
Steep.logger.debug "Validating global `#{name}`..."
|
113
|
+
validate_type entry.decl.type
|
92
114
|
end
|
93
115
|
end
|
94
116
|
end
|
95
117
|
|
96
118
|
def validate_alias
|
97
|
-
env.
|
119
|
+
env.alias_decls.each do |name, entry|
|
98
120
|
rescue_validation_errors do
|
99
|
-
Steep.logger.debug "
|
100
|
-
|
121
|
+
Steep.logger.debug "Validating alias `#{name}`..."
|
122
|
+
builder.expand_alias(name).tap do |type|
|
123
|
+
validate_type(type)
|
124
|
+
end
|
101
125
|
end
|
102
126
|
end
|
103
127
|
end
|
@@ -108,14 +132,20 @@ module Steep
|
|
108
132
|
@errors << Errors::InvalidTypeApplicationError.new(
|
109
133
|
name: factory.type_name(exn.type_name),
|
110
134
|
args: exn.args.map {|ty| factory.type(ty) },
|
111
|
-
params: exn.params
|
135
|
+
params: exn.params,
|
112
136
|
location: exn.location
|
113
137
|
)
|
114
|
-
rescue RBS::NoTypeFoundError => exn
|
138
|
+
rescue RBS::NoTypeFoundError, RBS::NoSuperclassFoundError, RBS::NoMixinFoundError => exn
|
115
139
|
@errors << Errors::UnknownTypeNameError.new(
|
116
140
|
name: factory.type_name(exn.type_name),
|
117
141
|
location: exn.location
|
118
142
|
)
|
143
|
+
rescue RBS::InvalidOverloadMethodError => exn
|
144
|
+
@errors << Errors::InvalidMethodOverloadError.new(
|
145
|
+
class_name: factory.type_name(exn.type_name),
|
146
|
+
method_name: exn.method_name,
|
147
|
+
location: exn.members[0].location
|
148
|
+
)
|
119
149
|
end
|
120
150
|
end
|
121
151
|
end
|
@@ -9,6 +9,84 @@ module Steep
|
|
9
9
|
@cache = {}
|
10
10
|
end
|
11
11
|
|
12
|
+
def instance_super_types(type_name, args:)
|
13
|
+
type_name_1 = factory.type_name_1(type_name)
|
14
|
+
ancestors = factory.definition_builder.one_instance_ancestors(type_name_1)
|
15
|
+
|
16
|
+
subst = unless args.empty?
|
17
|
+
args_ = args.map {|type| factory.type_1(type) }
|
18
|
+
RBS::Substitution.build(ancestors.params, args_)
|
19
|
+
end
|
20
|
+
|
21
|
+
ancestors.each_ancestor.map do |ancestor|
|
22
|
+
name = factory.type_name(ancestor.name)
|
23
|
+
|
24
|
+
case ancestor
|
25
|
+
when RBS::Definition::Ancestor::Instance
|
26
|
+
args = ancestor.args.map do |type|
|
27
|
+
type = type.sub(subst) if subst
|
28
|
+
factory.type(type)
|
29
|
+
end
|
30
|
+
|
31
|
+
if ancestor.name.class?
|
32
|
+
AST::Types::Name::Instance.new(
|
33
|
+
name: name,
|
34
|
+
args: args,
|
35
|
+
location: nil
|
36
|
+
)
|
37
|
+
else
|
38
|
+
AST::Types::Name::Interface.new(
|
39
|
+
name: name,
|
40
|
+
args: args,
|
41
|
+
location: nil
|
42
|
+
)
|
43
|
+
end
|
44
|
+
when RBS::Definition::Ancestor::Singleton
|
45
|
+
AST::Types::Name::Class.new(
|
46
|
+
name: name,
|
47
|
+
constructor: nil,
|
48
|
+
location: nil
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def singleton_super_types(type_name)
|
55
|
+
type_name_1 = factory.type_name_1(type_name)
|
56
|
+
ancestors = factory.definition_builder.one_singleton_ancestors(type_name_1)
|
57
|
+
|
58
|
+
ancestors.each_ancestor.map do |ancestor|
|
59
|
+
name = factory.type_name(ancestor.name)
|
60
|
+
|
61
|
+
case ancestor
|
62
|
+
when RBS::Definition::Ancestor::Instance
|
63
|
+
args = ancestor.args.map do |type|
|
64
|
+
factory.type(type)
|
65
|
+
end
|
66
|
+
|
67
|
+
if ancestor.name.class?
|
68
|
+
AST::Types::Name::Instance.new(
|
69
|
+
name: name,
|
70
|
+
args: args,
|
71
|
+
location: nil
|
72
|
+
)
|
73
|
+
else
|
74
|
+
AST::Types::Name::Interface.new(
|
75
|
+
name: name,
|
76
|
+
args: args,
|
77
|
+
location: nil
|
78
|
+
)
|
79
|
+
end
|
80
|
+
when RBS::Definition::Ancestor::Singleton
|
81
|
+
AST::Types::Name::Class.new(
|
82
|
+
name: name,
|
83
|
+
constructor: nil,
|
84
|
+
location: nil
|
85
|
+
)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
12
90
|
def check(relation, constraints:, self_type:, assumption: Set.new, trace: Trace.new)
|
13
91
|
Steep.logger.tagged "#{relation.sub_type} <: #{relation.super_type}" do
|
14
92
|
prefix = trace.size
|
@@ -175,30 +253,45 @@ module Steep
|
|
175
253
|
failure(error: Result::Failure::UnknownPairError.new(relation: relation),
|
176
254
|
trace: trace)
|
177
255
|
|
178
|
-
when relation.
|
179
|
-
|
180
|
-
|
181
|
-
Relation.new(sub_type: sub, super_type: sup).yield_self do |rel|
|
182
|
-
[rel, rel.flip]
|
183
|
-
end
|
184
|
-
end.map do |relation|
|
185
|
-
check(relation,
|
186
|
-
self_type: self_type,
|
187
|
-
assumption: assumption,
|
188
|
-
trace: trace,
|
189
|
-
constraints: constraints)
|
190
|
-
end
|
256
|
+
when relation.super_type.is_a?(AST::Types::Name::Interface)
|
257
|
+
sub_interface = factory.interface(relation.sub_type, private: false)
|
258
|
+
super_interface = factory.interface(relation.super_type, private: false)
|
191
259
|
|
192
|
-
|
193
|
-
|
260
|
+
check_interface(sub_interface,
|
261
|
+
super_interface,
|
262
|
+
self_type: self_type,
|
263
|
+
assumption: assumption,
|
264
|
+
trace: trace,
|
265
|
+
constraints: constraints)
|
266
|
+
|
267
|
+
when relation.sub_type.is_a?(AST::Types::Name::Base) && relation.super_type.is_a?(AST::Types::Name::Base)
|
268
|
+
if relation.sub_type.name == relation.super_type.name && relation.sub_type.class == relation.super_type.class
|
269
|
+
if arg_type?(relation.sub_type) && arg_type?(relation.super_type)
|
270
|
+
check_type_arg(relation, self_type: self_type, assumption: assumption, trace: trace, constraints: constraints)
|
194
271
|
else
|
195
|
-
|
272
|
+
success(constraints: constraints)
|
196
273
|
end
|
197
274
|
else
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
275
|
+
possible_sub_types = case relation.sub_type
|
276
|
+
when AST::Types::Name::Instance
|
277
|
+
instance_super_types(relation.sub_type.name, args: relation.sub_type.args)
|
278
|
+
when AST::Types::Name::Class
|
279
|
+
singleton_super_types(relation.sub_type.name)
|
280
|
+
else
|
281
|
+
[]
|
282
|
+
end
|
283
|
+
|
284
|
+
unless possible_sub_types.empty?
|
285
|
+
success_any?(possible_sub_types) do |sub_type|
|
286
|
+
check(Relation.new(sub_type: sub_type, super_type: relation.super_type),
|
287
|
+
self_type: self_type,
|
288
|
+
assumption: assumption,
|
289
|
+
trace: trace,
|
290
|
+
constraints: constraints)
|
291
|
+
end
|
292
|
+
else
|
293
|
+
failure(error: Result::Failure::UnknownPairError.new(relation: relation), trace: trace)
|
294
|
+
end
|
202
295
|
end
|
203
296
|
|
204
297
|
when relation.sub_type.is_a?(AST::Types::Proc) && relation.super_type.is_a?(AST::Types::Proc)
|
@@ -276,6 +369,23 @@ module Steep
|
|
276
369
|
trace: trace,
|
277
370
|
constraints: constraints)
|
278
371
|
|
372
|
+
when relation.super_type.is_a?(AST::Types::Literal)
|
373
|
+
case
|
374
|
+
when relation.super_type.value == true && AST::Builtin::TrueClass.instance_type?(relation.sub_type)
|
375
|
+
success(constraints: constraints)
|
376
|
+
when relation.super_type.value == false && AST::Builtin::FalseClass.instance_type?(relation.sub_type)
|
377
|
+
success(constraints: constraints)
|
378
|
+
else
|
379
|
+
failure(error: Result::Failure::UnknownPairError.new(relation: relation),
|
380
|
+
trace: trace)
|
381
|
+
end
|
382
|
+
|
383
|
+
when relation.super_type.is_a?(AST::Types::Nil) && AST::Builtin::NilClass.instance_type?(relation.sub_type)
|
384
|
+
success(constraints: constraints)
|
385
|
+
|
386
|
+
when relation.sub_type.is_a?(AST::Types::Nil) && AST::Builtin::NilClass.instance_type?(relation.super_type)
|
387
|
+
success(constraints: constraints)
|
388
|
+
|
279
389
|
else
|
280
390
|
failure(error: Result::Failure::UnknownPairError.new(relation: relation),
|
281
391
|
trace: trace)
|
@@ -283,6 +393,80 @@ module Steep
|
|
283
393
|
end
|
284
394
|
end
|
285
395
|
|
396
|
+
def definition_for_type(type)
|
397
|
+
type_name = factory.type_name_1(type.name)
|
398
|
+
|
399
|
+
case type
|
400
|
+
when AST::Types::Name::Instance
|
401
|
+
factory.definition_builder.build_instance(type_name)
|
402
|
+
when AST::Types::Name::Class
|
403
|
+
factory.definition_builder.build_singleton(type_name)
|
404
|
+
when AST::Types::Name::Interface
|
405
|
+
factory.definition_builder.build_interface(type_name)
|
406
|
+
else
|
407
|
+
raise
|
408
|
+
end
|
409
|
+
end
|
410
|
+
|
411
|
+
def arg_type?(type)
|
412
|
+
case type
|
413
|
+
when AST::Types::Name::Instance, AST::Types::Name::Interface
|
414
|
+
type.args.size > 0
|
415
|
+
else
|
416
|
+
false
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
def check_type_arg(relation, self_type:, assumption:, trace:, constraints:)
|
421
|
+
sub_args = relation.sub_type.args
|
422
|
+
sup_args = relation.super_type.args
|
423
|
+
|
424
|
+
sup_def = definition_for_type(relation.super_type)
|
425
|
+
sup_params = sup_def.type_params_decl
|
426
|
+
|
427
|
+
success_all?(sub_args.zip(sup_args, sup_params.each)) do |sub_arg, sup_arg, sup_param|
|
428
|
+
case sup_param.variance
|
429
|
+
when :covariant
|
430
|
+
check(Relation.new(sub_type: sub_arg, super_type: sup_arg), self_type: self_type, assumption: assumption, trace: trace, constraints: constraints)
|
431
|
+
when :contravariant
|
432
|
+
check(Relation.new(sub_type: sup_arg, super_type: sub_arg), self_type: self_type, assumption: assumption, trace: trace, constraints: constraints)
|
433
|
+
when :invariant
|
434
|
+
rel = Relation.new(sub_type: sub_arg, super_type: sup_arg)
|
435
|
+
success_all?([rel, rel.flip]) do |r|
|
436
|
+
check(r, self_type: self_type, assumption: assumption, trace: trace, constraints: constraints)
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
end
|
441
|
+
|
442
|
+
def success_all?(collection, &block)
|
443
|
+
results = collection.map do |obj|
|
444
|
+
result = yield(obj)
|
445
|
+
|
446
|
+
if result.failure?
|
447
|
+
return result
|
448
|
+
end
|
449
|
+
|
450
|
+
result
|
451
|
+
end
|
452
|
+
|
453
|
+
results[0]
|
454
|
+
end
|
455
|
+
|
456
|
+
def success_any?(collection, &block)
|
457
|
+
results = collection.map do |obj|
|
458
|
+
result = yield(obj)
|
459
|
+
|
460
|
+
if result.success?
|
461
|
+
return result
|
462
|
+
end
|
463
|
+
|
464
|
+
result
|
465
|
+
end
|
466
|
+
|
467
|
+
results[0]
|
468
|
+
end
|
469
|
+
|
286
470
|
def extract_nominal_pairs(relation)
|
287
471
|
sub_type = relation.sub_type
|
288
472
|
super_type = relation.super_type
|
@@ -316,20 +500,7 @@ module Steep
|
|
316
500
|
return true
|
317
501
|
end
|
318
502
|
|
319
|
-
|
320
|
-
when relation.sub_type == relation.super_type
|
321
|
-
true
|
322
|
-
when relation.sub_type.is_a?(AST::Types::Name::Base) && relation.super_type.is_a?(AST::Types::Name::Base)
|
323
|
-
if (pairs = extract_nominal_pairs(relation))
|
324
|
-
pairs.all? do |(s, t)|
|
325
|
-
same_type?(Relation.new(sub_type: s, super_type: t), assumption: assumption)
|
326
|
-
end
|
327
|
-
else
|
328
|
-
false
|
329
|
-
end
|
330
|
-
else
|
331
|
-
false
|
332
|
-
end
|
503
|
+
relation.sub_type == relation.super_type
|
333
504
|
end
|
334
505
|
|
335
506
|
def check_interface(sub_interface, super_interface, self_type:, assumption:, trace:, constraints:)
|