steep 1.9.4 → 1.10.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/CHANGELOG.md +34 -3
- data/Steepfile +5 -2
- data/lib/steep/annotations_helper.rb +43 -0
- data/lib/steep/ast/ignore.rb +3 -4
- data/lib/steep/cli.rb +102 -23
- data/lib/steep/diagnostic/lsp_formatter.rb +17 -3
- data/lib/steep/diagnostic/ruby.rb +75 -0
- data/lib/steep/diagnostic/signature.rb +20 -0
- data/lib/steep/drivers/check.rb +3 -1
- data/lib/steep/drivers/diagnostic_printer/base_formatter.rb +19 -0
- data/lib/steep/drivers/diagnostic_printer/code_formatter.rb +95 -0
- data/lib/steep/drivers/diagnostic_printer/github_actions_formatter.rb +44 -0
- data/lib/steep/drivers/diagnostic_printer.rb +9 -86
- data/lib/steep/drivers/langserver.rb +4 -1
- data/lib/steep/drivers/worker.rb +2 -0
- data/lib/steep/interface/builder.rb +2 -2
- data/lib/steep/server/custom_methods.rb +12 -0
- data/lib/steep/server/interaction_worker.rb +33 -6
- data/lib/steep/server/master.rb +103 -7
- data/lib/steep/server/type_check_worker.rb +48 -2
- data/lib/steep/server/worker_process.rb +31 -20
- data/lib/steep/services/completion_provider.rb +12 -2
- data/lib/steep/services/signature_service.rb +2 -2
- data/lib/steep/services/type_check_service.rb +22 -7
- data/lib/steep/signature/validator.rb +56 -4
- data/lib/steep/source.rb +3 -1
- data/lib/steep/subtyping/check.rb +22 -16
- data/lib/steep/type_construction.rb +153 -34
- data/lib/steep/type_inference/case_when.rb +2 -0
- data/lib/steep/type_inference/logic_type_interpreter.rb +77 -15
- data/lib/steep/type_inference/method_call.rb +5 -3
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +10 -0
- data/manual/ruby-diagnostics.md +114 -1
- data/sample/Steepfile +0 -2
- data/sample/lib/conference.rb +14 -0
- data/sample/lib/deprecated.rb +7 -0
- data/sample/sig/deprecated.rbs +16 -0
- data/steep.gemspec +4 -3
- metadata +28 -8
@@ -8,32 +8,30 @@ module Steep
|
|
8
8
|
attr_reader :name
|
9
9
|
attr_reader :wait_thread
|
10
10
|
attr_reader :index
|
11
|
+
attr_reader :io_socket
|
11
12
|
|
12
|
-
def initialize(reader:, writer:, stderr:, wait_thread:, name:, index: nil)
|
13
|
+
def initialize(reader:, writer:, io_socket: nil, stderr:, wait_thread:, name:, index: nil)
|
13
14
|
@reader = reader
|
14
15
|
@writer = writer
|
15
16
|
@stderr = stderr
|
17
|
+
@io_socket = io_socket
|
16
18
|
@wait_thread = wait_thread
|
17
19
|
@name = name
|
18
20
|
@index = index
|
19
21
|
end
|
20
22
|
|
21
23
|
def self.start_worker(type, name:, steepfile:, steep_command:, index: nil, delay_shutdown: false, patterns: [])
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
# Use `#spawn_worker`
|
34
|
-
raise NotImplementedError
|
35
|
-
end
|
36
|
-
rescue NotImplementedError
|
24
|
+
if Steep.can_fork? && !steep_command
|
25
|
+
fork_worker(
|
26
|
+
type,
|
27
|
+
name: name,
|
28
|
+
steepfile: steepfile,
|
29
|
+
index: index,
|
30
|
+
is_primary: index && (index[1] == 0 && index[0] >= 2),
|
31
|
+
delay_shutdown: delay_shutdown,
|
32
|
+
patterns: patterns
|
33
|
+
)
|
34
|
+
else
|
37
35
|
spawn_worker(
|
38
36
|
type,
|
39
37
|
name: name,
|
@@ -46,9 +44,10 @@ module Steep
|
|
46
44
|
end
|
47
45
|
end
|
48
46
|
|
49
|
-
def self.fork_worker(type, name:, steepfile:, index:, delay_shutdown:, patterns:)
|
47
|
+
def self.fork_worker(type, name:, steepfile:, index:, delay_shutdown:, patterns:, is_primary:)
|
50
48
|
stdin_in, stdin_out = IO.pipe
|
51
49
|
stdout_in, stdout_out = IO.pipe
|
50
|
+
sock_master, sock_worker = UNIXSocket.socketpair if is_primary
|
52
51
|
|
53
52
|
worker = Drivers::Worker.new(stdout: stdout_out, stdin: stdin_in, stderr: STDERR)
|
54
53
|
|
@@ -61,12 +60,14 @@ module Steep
|
|
61
60
|
worker.index = this
|
62
61
|
end
|
63
62
|
worker.commandline_args = patterns
|
63
|
+
worker.io_socket = sock_worker
|
64
64
|
|
65
65
|
pid = fork do
|
66
66
|
Process.setpgid(0, 0)
|
67
67
|
Steep.ui_logger.level = :fatal
|
68
68
|
stdin_out.close
|
69
69
|
stdout_in.close
|
70
|
+
sock_master&.close
|
70
71
|
worker.run()
|
71
72
|
end
|
72
73
|
|
@@ -81,6 +82,7 @@ module Steep
|
|
81
82
|
|
82
83
|
stdin_in.close
|
83
84
|
stdout_out.close
|
85
|
+
sock_worker&.close
|
84
86
|
|
85
87
|
new(
|
86
88
|
reader: reader,
|
@@ -88,7 +90,8 @@ module Steep
|
|
88
90
|
stderr: STDERR,
|
89
91
|
wait_thread: wait_thread,
|
90
92
|
name: name,
|
91
|
-
index: index&.[](1)
|
93
|
+
index: index&.[](1),
|
94
|
+
io_socket: sock_master,
|
92
95
|
)
|
93
96
|
end
|
94
97
|
|
@@ -146,6 +149,10 @@ module Steep
|
|
146
149
|
end
|
147
150
|
end
|
148
151
|
|
152
|
+
def redirect_to(worker)
|
153
|
+
@writer = worker.writer
|
154
|
+
end
|
155
|
+
|
149
156
|
def <<(message)
|
150
157
|
writer.write(message)
|
151
158
|
end
|
@@ -155,11 +162,11 @@ module Steep
|
|
155
162
|
end
|
156
163
|
|
157
164
|
def kill(force: false)
|
158
|
-
Steep.logger.tagged("WorkerProcess#kill@#{name}(#{
|
165
|
+
Steep.logger.tagged("WorkerProcess#kill@#{name}(#{pid})") do
|
159
166
|
begin
|
160
167
|
signal = force ? :KILL : :TERM
|
161
168
|
Steep.logger.debug("Sending signal SIG#{signal}...")
|
162
|
-
Process.kill(signal,
|
169
|
+
Process.kill(signal, pid)
|
163
170
|
Steep.logger.debug("Successfully sent the signal.")
|
164
171
|
rescue Errno::ESRCH => error
|
165
172
|
Steep.logger.debug("Failed #{error.inspect}")
|
@@ -171,6 +178,10 @@ module Steep
|
|
171
178
|
end
|
172
179
|
end
|
173
180
|
end
|
181
|
+
|
182
|
+
def pid
|
183
|
+
wait_thread.pid
|
184
|
+
end
|
174
185
|
end
|
175
186
|
end
|
176
187
|
end
|
@@ -51,9 +51,17 @@ module Steep
|
|
51
51
|
raise
|
52
52
|
end
|
53
53
|
end
|
54
|
+
|
55
|
+
def deprecated?
|
56
|
+
if AnnotationsHelper.deprecated_type_name?(full_name, env)
|
57
|
+
true
|
58
|
+
else
|
59
|
+
false
|
60
|
+
end
|
61
|
+
end
|
54
62
|
end
|
55
63
|
|
56
|
-
SimpleMethodNameItem = _ = Struct.new(:identifier, :range, :receiver_type, :method_types, :method_member, :method_name, keyword_init: true) do
|
64
|
+
SimpleMethodNameItem = _ = Struct.new(:identifier, :range, :receiver_type, :method_types, :method_member, :method_name, :deprecated, keyword_init: true) do
|
57
65
|
# @implements SimpleMethodNameItem
|
58
66
|
|
59
67
|
def comment
|
@@ -640,13 +648,15 @@ module Steep
|
|
640
648
|
all_members.each do |member|
|
641
649
|
associated_decl = all_decls.find {|decl| decl.method_def.member == member } or next
|
642
650
|
overloads = method_entry.overloads.select {|overload| overload.method_defs.any? {|defn| defn.member == member }}
|
651
|
+
annotations = associated_decl.method_def.member_annotations
|
643
652
|
items << SimpleMethodNameItem.new(
|
644
653
|
identifier: name,
|
645
654
|
range: range,
|
646
655
|
receiver_type: type,
|
647
656
|
method_name: associated_decl.method_name,
|
648
657
|
method_types: overloads.map {|overload| subtyping.factory.method_type_1(overload.method_type) },
|
649
|
-
method_member: member
|
658
|
+
method_member: member,
|
659
|
+
deprecated: AnnotationsHelper.deprecated_annotation?(annotations) ? true : false
|
650
660
|
)
|
651
661
|
end
|
652
662
|
else
|
@@ -294,8 +294,8 @@ module Steep
|
|
294
294
|
end
|
295
295
|
|
296
296
|
unless errors.empty?
|
297
|
-
|
298
|
-
factory = AST::Types::Factory.new(builder:
|
297
|
+
errors.uniq! { |e| [e.class, e.message] }
|
298
|
+
factory = AST::Types::Factory.new(builder: RBS::DefinitionBuilder.new(env: env, ancestor_builder: builder))
|
299
299
|
return errors.map {|error| Diagnostic::Signature.from_rbs_error(error, factory: factory) }
|
300
300
|
end
|
301
301
|
|
@@ -302,7 +302,22 @@ module Steep
|
|
302
302
|
def self.type_check(source:, subtyping:, constant_resolver:, cursor:)
|
303
303
|
annotations = source.annotations(block: source.node, factory: subtyping.factory, context: nil)
|
304
304
|
|
305
|
-
|
305
|
+
case annotations.self_type
|
306
|
+
when AST::Types::Name::Instance
|
307
|
+
module_name = annotations.self_type.name
|
308
|
+
module_type = AST::Types::Name::Singleton.new(name: module_name)
|
309
|
+
instance_type = annotations.self_type
|
310
|
+
when AST::Types::Name::Singleton
|
311
|
+
module_name = annotations.self_type.name
|
312
|
+
module_type = annotations.self_type
|
313
|
+
instance_type = annotations.self_type
|
314
|
+
else
|
315
|
+
module_name = AST::Builtin::Object.module_name
|
316
|
+
module_type = AST::Builtin::Object.module_type
|
317
|
+
instance_type = AST::Builtin::Object.instance_type
|
318
|
+
end
|
319
|
+
|
320
|
+
definition = subtyping.factory.definition_builder.build_instance(module_name)
|
306
321
|
|
307
322
|
const_env = TypeInference::ConstantEnv.new(
|
308
323
|
factory: subtyping.factory,
|
@@ -321,17 +336,17 @@ module Steep
|
|
321
336
|
context = TypeInference::Context.new(
|
322
337
|
block_context: nil,
|
323
338
|
module_context: TypeInference::Context::ModuleContext.new(
|
324
|
-
instance_type:
|
325
|
-
module_type:
|
339
|
+
instance_type: instance_type,
|
340
|
+
module_type: module_type,
|
326
341
|
implement_name: nil,
|
327
342
|
nesting: nil,
|
328
|
-
class_name:
|
329
|
-
instance_definition: subtyping.factory.definition_builder.build_instance(
|
330
|
-
module_definition: subtyping.factory.definition_builder.build_singleton(
|
343
|
+
class_name: module_name,
|
344
|
+
instance_definition: subtyping.factory.definition_builder.build_instance(module_name),
|
345
|
+
module_definition: subtyping.factory.definition_builder.build_singleton(module_name)
|
331
346
|
),
|
332
347
|
method_context: nil,
|
333
348
|
break_context: nil,
|
334
|
-
self_type:
|
349
|
+
self_type: instance_type,
|
335
350
|
type_env: type_env,
|
336
351
|
call_context: TypeInference::MethodCall::TopLevelContext.new,
|
337
352
|
variable_context: TypeInference::Context::TypeVariableContext.empty
|
@@ -144,17 +144,39 @@ module Steep
|
|
144
144
|
validate_type_application_constraints(name, type_params, type_args, location: type.location)
|
145
145
|
end
|
146
146
|
end
|
147
|
-
|
148
|
-
type.each_type do |child|
|
149
|
-
validate_type_application(child)
|
150
|
-
end
|
151
147
|
end
|
152
148
|
|
153
149
|
def validate_type(type)
|
154
150
|
Steep.logger.debug { "#{Location.to_string type.location}: Validating #{type}..." }
|
155
151
|
|
156
152
|
validator.validate_type(type, context: nil)
|
153
|
+
validate_type_0(type)
|
154
|
+
end
|
155
|
+
|
156
|
+
def validate_type_0(type)
|
157
157
|
validate_type_application(type)
|
158
|
+
|
159
|
+
case type
|
160
|
+
when RBS::Types::ClassInstance, RBS::Types::Interface, RBS::Types::ClassSingleton, RBS::Types::Alias
|
161
|
+
type_name = type.name
|
162
|
+
if type.location
|
163
|
+
location = type.location[:name]
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
if type_name && location
|
168
|
+
validate_type_name_deprecation(type_name, location)
|
169
|
+
end
|
170
|
+
|
171
|
+
type.each_type do |child|
|
172
|
+
validate_type_0(child)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def validate_type_name_deprecation(type_name, location)
|
177
|
+
if (_, message = AnnotationsHelper.deprecated_type_name?(type_name, env))
|
178
|
+
@errors << Diagnostic::Signature::DeprecatedTypeName.new(type_name, message, location: location)
|
179
|
+
end
|
158
180
|
end
|
159
181
|
|
160
182
|
def ancestor_to_type(ancestor)
|
@@ -269,6 +291,9 @@ module Steep
|
|
269
291
|
type_params.each do |type_param|
|
270
292
|
param = checker.factory.type_param(type_param)
|
271
293
|
|
294
|
+
validate_type(type_param.upper_bound_type) if type_param.upper_bound_type
|
295
|
+
validate_type(type_param.default_type) if type_param.default_type
|
296
|
+
|
272
297
|
default_type = param.default_type or next
|
273
298
|
upper_bound = param.upper_bound or next
|
274
299
|
|
@@ -296,6 +321,16 @@ module Steep
|
|
296
321
|
args: entry.type_params.map { AST::Types::Any.instance() }
|
297
322
|
)
|
298
323
|
|
324
|
+
entry.decls.each do |decl|
|
325
|
+
ast = decl.decl
|
326
|
+
|
327
|
+
unless AnnotationsHelper.deprecated_annotation?(ast.annotations)
|
328
|
+
if location = ast.location
|
329
|
+
validate_type_name_deprecation(name, location[:name])
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
299
334
|
Steep.logger.tagged "#{name}" do
|
300
335
|
builder.build_instance(name).tap do |definition|
|
301
336
|
upper_bounds = definition.type_params_decl.each.with_object({}) do |param, bounds| #$ Hash[Symbol, AST::Types::t?]
|
@@ -353,6 +388,20 @@ module Steep
|
|
353
388
|
case ancestor
|
354
389
|
when RBS::Definition::Ancestor::Instance
|
355
390
|
validate_ancestor_application(name, ancestor)
|
391
|
+
location =
|
392
|
+
case ancestor.source
|
393
|
+
when :super
|
394
|
+
if (primary_decl = entry.primary.decl).is_a?(RBS::AST::Declarations::Class)
|
395
|
+
primary_decl.super_class&.location
|
396
|
+
end
|
397
|
+
when nil
|
398
|
+
# skip
|
399
|
+
else
|
400
|
+
ancestor.source.location
|
401
|
+
end
|
402
|
+
if location
|
403
|
+
validate_type_name_deprecation(ancestor.name, location)
|
404
|
+
end
|
356
405
|
end
|
357
406
|
end
|
358
407
|
|
@@ -632,6 +681,9 @@ module Steep
|
|
632
681
|
rescue_validation_errors(name) do
|
633
682
|
Steep.logger.debug "Validating class/module alias `#{name}`..."
|
634
683
|
validator.validate_class_alias(entry: entry)
|
684
|
+
if location = entry.decl.location
|
685
|
+
validate_type_name_deprecation(entry.decl.old_name, location[:old_name])
|
686
|
+
end
|
635
687
|
end
|
636
688
|
end
|
637
689
|
|
data/lib/steep/source.rb
CHANGED
@@ -498,6 +498,8 @@ module Steep
|
|
498
498
|
# Skip
|
499
499
|
when :kwargs
|
500
500
|
# skip
|
501
|
+
when :when
|
502
|
+
# skip
|
501
503
|
when :pair
|
502
504
|
key, value = node.children
|
503
505
|
key = insert_type_node(key, comments.except(last_line))
|
@@ -644,7 +646,7 @@ module Steep
|
|
644
646
|
receiver_node, name, _, location = deconstruct_send_node!(send_node)
|
645
647
|
|
646
648
|
if receiver_node
|
647
|
-
if location.dot
|
649
|
+
if location.dot && location.selector
|
648
650
|
location.selector.line
|
649
651
|
end
|
650
652
|
else
|
@@ -285,11 +285,6 @@ module Steep
|
|
285
285
|
)
|
286
286
|
end
|
287
287
|
|
288
|
-
when relation.sub_type.is_a?(AST::Types::Self) && !self_type.is_a?(AST::Types::Self)
|
289
|
-
Expand(relation) do
|
290
|
-
check_type(Relation.new(sub_type: self_type, super_type: relation.super_type))
|
291
|
-
end
|
292
|
-
|
293
288
|
when relation.sub_type.is_a?(AST::Types::Instance) && !instance_type.is_a?(AST::Types::Instance)
|
294
289
|
Expand(relation) do
|
295
290
|
check_type(Relation.new(sub_type: instance_type, super_type: relation.super_type))
|
@@ -419,6 +414,11 @@ module Steep
|
|
419
414
|
end
|
420
415
|
end
|
421
416
|
|
417
|
+
when relation.sub_type.is_a?(AST::Types::Self) && !self_type.is_a?(AST::Types::Self)
|
418
|
+
Expand(relation) do
|
419
|
+
check_type(Relation.new(sub_type: self_type, super_type: relation.super_type))
|
420
|
+
end
|
421
|
+
|
422
422
|
when relation.super_type.is_a?(AST::Types::Name::Interface)
|
423
423
|
Expand(relation) do
|
424
424
|
check_interface(
|
@@ -493,7 +493,7 @@ module Steep
|
|
493
493
|
end
|
494
494
|
|
495
495
|
when relation.sub_type.is_a?(AST::Types::Tuple) && relation.super_type.is_a?(AST::Types::Tuple)
|
496
|
-
if relation.sub_type.types.size
|
496
|
+
if relation.sub_type.types.size == relation.super_type.types.size
|
497
497
|
pairs = relation.sub_type.types.take(relation.super_type.types.size).zip(relation.super_type.types)
|
498
498
|
|
499
499
|
All(relation) do |result|
|
@@ -541,21 +541,28 @@ module Steep
|
|
541
541
|
|
542
542
|
when relation.sub_type.is_a?(AST::Types::Record) && relation.super_type.is_a?(AST::Types::Record)
|
543
543
|
All(relation) do |result|
|
544
|
+
unchecked_keys = Set.new(relation.sub_type.elements.each_key)
|
545
|
+
|
544
546
|
relation.super_type.elements.each_key do |key|
|
545
|
-
super_element_type = relation.super_type.elements
|
547
|
+
super_element_type = relation.super_type.elements.fetch(key) #: AST::Types::t
|
548
|
+
sub_element_type = relation.sub_type.elements.fetch(key, nil) #: AST::Types::t?
|
546
549
|
|
547
|
-
if relation.
|
548
|
-
|
550
|
+
if relation.super_type.required?(key)
|
551
|
+
rel = Relation.new(sub_type: sub_element_type || AST::Builtin.nil_type, super_type: super_element_type)
|
552
|
+
result.add(rel) { check_type(rel) }
|
549
553
|
else
|
550
|
-
|
551
|
-
|
554
|
+
# If the key is optional, it's okay to not have the key
|
555
|
+
if sub_element_type
|
556
|
+
rel = Relation.new(sub_type: sub_element_type, super_type: super_element_type)
|
557
|
+
result.add(rel) { check_type(rel) }
|
552
558
|
end
|
553
559
|
end
|
554
560
|
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
561
|
+
unchecked_keys.delete(key)
|
562
|
+
end
|
563
|
+
|
564
|
+
unless unchecked_keys.empty?
|
565
|
+
return Failure(relation, Result::Failure::UnknownPairError.new(relation: relation))
|
559
566
|
end
|
560
567
|
end
|
561
568
|
|
@@ -601,7 +608,6 @@ module Steep
|
|
601
608
|
Expand(relation) do
|
602
609
|
check_type(Relation.new(sub_type: relation.sub_type.back_type, super_type: relation.super_type))
|
603
610
|
end
|
604
|
-
|
605
611
|
else
|
606
612
|
Failure(relation, Result::Failure::UnknownPairError.new(relation: relation))
|
607
613
|
end
|