steep 0.18.0 → 0.23.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 +28 -1
- data/Gemfile +7 -0
- data/bin/steep-prof +16 -0
- data/lib/steep/ast/types/factory.rb +16 -13
- data/lib/steep/ast/types/literal.rb +4 -0
- data/lib/steep/project/completion_provider.rb +24 -8
- data/lib/steep/project/dsl.rb +7 -1
- data/lib/steep/project/file.rb +7 -0
- 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 +5 -5
- 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 +214 -43
- data/lib/steep/type_construction.rb +184 -75
- 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 +8 -97
@@ -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,7 +190,7 @@ HOVER
|
|
190
190
|
new_text: "#{item.identifier}#{method_type_snippet}",
|
191
191
|
range: range
|
192
192
|
),
|
193
|
-
documentation: item.
|
193
|
+
documentation: item.comment&.string,
|
194
194
|
insert_text_format: LanguageServer::Protocol::Constant::InsertTextFormat::SNIPPET,
|
195
195
|
sort_text: item.inherited_method ? 'z' : 'a' # Ensure language server puts non-inherited methods before inherited methods
|
196
196
|
)
|
@@ -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
|
@@ -102,15 +180,6 @@ module Steep
|
|
102
180
|
constraints: constraints
|
103
181
|
)
|
104
182
|
|
105
|
-
when relation.sub_type.is_a?(AST::Types::Literal)
|
106
|
-
check(
|
107
|
-
Relation.new(sub_type: relation.sub_type.back_type, super_type: relation.super_type),
|
108
|
-
self_type: self_type,
|
109
|
-
assumption: assumption,
|
110
|
-
trace: trace,
|
111
|
-
constraints: constraints
|
112
|
-
)
|
113
|
-
|
114
183
|
when relation.sub_type.is_a?(AST::Types::Union)
|
115
184
|
results = relation.sub_type.types.map do |sub_type|
|
116
185
|
check(Relation.new(sub_type: sub_type, super_type: relation.super_type),
|
@@ -175,30 +244,45 @@ module Steep
|
|
175
244
|
failure(error: Result::Failure::UnknownPairError.new(relation: relation),
|
176
245
|
trace: trace)
|
177
246
|
|
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
|
247
|
+
when relation.super_type.is_a?(AST::Types::Name::Interface)
|
248
|
+
sub_interface = factory.interface(relation.sub_type, private: false)
|
249
|
+
super_interface = factory.interface(relation.super_type, private: false)
|
191
250
|
|
192
|
-
|
193
|
-
|
251
|
+
check_interface(sub_interface,
|
252
|
+
super_interface,
|
253
|
+
self_type: self_type,
|
254
|
+
assumption: assumption,
|
255
|
+
trace: trace,
|
256
|
+
constraints: constraints)
|
257
|
+
|
258
|
+
when relation.sub_type.is_a?(AST::Types::Name::Base) && relation.super_type.is_a?(AST::Types::Name::Base)
|
259
|
+
if relation.sub_type.name == relation.super_type.name && relation.sub_type.class == relation.super_type.class
|
260
|
+
if arg_type?(relation.sub_type) && arg_type?(relation.super_type)
|
261
|
+
check_type_arg(relation, self_type: self_type, assumption: assumption, trace: trace, constraints: constraints)
|
194
262
|
else
|
195
|
-
|
263
|
+
success(constraints: constraints)
|
196
264
|
end
|
197
265
|
else
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
266
|
+
possible_sub_types = case relation.sub_type
|
267
|
+
when AST::Types::Name::Instance
|
268
|
+
instance_super_types(relation.sub_type.name, args: relation.sub_type.args)
|
269
|
+
when AST::Types::Name::Class
|
270
|
+
singleton_super_types(relation.sub_type.name)
|
271
|
+
else
|
272
|
+
[]
|
273
|
+
end
|
274
|
+
|
275
|
+
unless possible_sub_types.empty?
|
276
|
+
success_any?(possible_sub_types) do |sub_type|
|
277
|
+
check(Relation.new(sub_type: sub_type, super_type: relation.super_type),
|
278
|
+
self_type: self_type,
|
279
|
+
assumption: assumption,
|
280
|
+
trace: trace,
|
281
|
+
constraints: constraints)
|
282
|
+
end
|
283
|
+
else
|
284
|
+
failure(error: Result::Failure::UnknownPairError.new(relation: relation), trace: trace)
|
285
|
+
end
|
202
286
|
end
|
203
287
|
|
204
288
|
when relation.sub_type.is_a?(AST::Types::Proc) && relation.super_type.is_a?(AST::Types::Proc)
|
@@ -276,6 +360,32 @@ module Steep
|
|
276
360
|
trace: trace,
|
277
361
|
constraints: constraints)
|
278
362
|
|
363
|
+
when relation.super_type.is_a?(AST::Types::Literal)
|
364
|
+
case
|
365
|
+
when relation.super_type.value == true && AST::Builtin::TrueClass.instance_type?(relation.sub_type)
|
366
|
+
success(constraints: constraints)
|
367
|
+
when relation.super_type.value == false && AST::Builtin::FalseClass.instance_type?(relation.sub_type)
|
368
|
+
success(constraints: constraints)
|
369
|
+
else
|
370
|
+
failure(error: Result::Failure::UnknownPairError.new(relation: relation),
|
371
|
+
trace: trace)
|
372
|
+
end
|
373
|
+
|
374
|
+
when relation.super_type.is_a?(AST::Types::Nil) && AST::Builtin::NilClass.instance_type?(relation.sub_type)
|
375
|
+
success(constraints: constraints)
|
376
|
+
|
377
|
+
when relation.sub_type.is_a?(AST::Types::Nil) && AST::Builtin::NilClass.instance_type?(relation.super_type)
|
378
|
+
success(constraints: constraints)
|
379
|
+
|
380
|
+
when relation.sub_type.is_a?(AST::Types::Literal)
|
381
|
+
check(
|
382
|
+
Relation.new(sub_type: relation.sub_type.back_type, super_type: relation.super_type),
|
383
|
+
self_type: self_type,
|
384
|
+
assumption: assumption,
|
385
|
+
trace: trace,
|
386
|
+
constraints: constraints
|
387
|
+
)
|
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:)
|