steep 1.2.1 → 1.3.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 +16 -0
- data/Gemfile.lock +4 -4
- data/Gemfile.steep +1 -1
- data/Gemfile.steep.lock +13 -3
- data/Steepfile +0 -1
- data/lib/steep/annotation_parser.rb +34 -28
- data/lib/steep/ast/annotation.rb +16 -5
- data/lib/steep/ast/node/type_application.rb +74 -0
- data/lib/steep/ast/node/type_assertion.rb +56 -0
- data/lib/steep/ast/types/factory.rb +5 -1
- data/lib/steep/diagnostic/helper.rb +2 -1
- data/lib/steep/diagnostic/lsp_formatter.rb +3 -1
- data/lib/steep/diagnostic/ruby.rb +70 -5
- data/lib/steep/diagnostic/signature.rb +21 -8
- data/lib/steep/drivers/check.rb +1 -1
- data/lib/steep/drivers/checkfile.rb +1 -1
- data/lib/steep/drivers/langserver.rb +2 -2
- data/lib/steep/drivers/stats.rb +1 -1
- data/lib/steep/drivers/watch.rb +1 -1
- data/lib/steep/drivers/worker.rb +0 -1
- data/lib/steep/server/lsp_formatter.rb +13 -3
- data/lib/steep/server/master.rb +4 -1
- data/lib/steep/server/worker_process.rb +86 -14
- data/lib/steep/services/hover_provider/rbs.rb +7 -7
- data/lib/steep/services/hover_provider/ruby.rb +19 -4
- data/lib/steep/services/signature_service.rb +7 -4
- data/lib/steep/signature/validator.rb +36 -13
- data/lib/steep/source.rb +189 -71
- data/lib/steep/type_construction.rb +232 -126
- data/lib/steep/type_inference/logic_type_interpreter.rb +3 -1
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +2 -0
- data/rbs_collection.steep.lock.yaml +27 -10
- data/rbs_collection.steep.yaml +0 -1
- data/sig/shims/exception.rbs +4 -0
- data/sig/shims/parser/comment.rbs +33 -0
- data/sig/shims/parser.rbs +30 -2
- data/sig/steep/annotation_parser.rbs +59 -0
- data/sig/steep/ast/annotation.rbs +21 -26
- data/sig/steep/ast/node/type_application.rbs +31 -0
- data/sig/steep/ast/node/type_assertion.rbs +26 -0
- data/sig/steep/ast/types/factory.rbs +0 -2
- data/sig/steep/diagnostic/helper.rbs +9 -3
- data/sig/steep/diagnostic/lsp_formatter.rbs +12 -8
- data/sig/steep/diagnostic/ruby.rbs +62 -8
- data/sig/steep/diagnostic/signature.rbs +118 -85
- data/sig/steep/drivers/worker.rbs +11 -13
- data/sig/steep/range_extension.rbs +7 -0
- data/sig/steep/server/lsp_formatter.rbs +14 -7
- data/sig/steep/server/worker_process.rbs +74 -12
- data/sig/steep/services/hover_provider/rbs.rbs +27 -7
- data/sig/steep/services/hover_provider/ruby.rbs +18 -4
- data/sig/steep/services/hover_provider/singleton_methods.rbs +1 -1
- data/sig/steep/signature/validator.rbs +76 -0
- data/sig/steep/source.rbs +54 -30
- data/sig/steep/type_construction.rbs +85 -27
- data/sig/steep/type_inference/method_call.rbs +1 -1
- data/smoke/diagnostics-rbs/inherit-module.rbs +2 -0
- data/smoke/diagnostics-rbs/test_expectations.yml +12 -0
- data/steep.gemspec +1 -1
- metadata +16 -6
data/lib/steep/source.rb
CHANGED
@@ -1,27 +1,11 @@
|
|
1
1
|
module Steep
|
2
2
|
class Source
|
3
|
-
class LocatedAnnotation
|
4
|
-
attr_reader :line
|
5
|
-
attr_reader :annotation
|
6
|
-
attr_reader :source
|
7
|
-
|
8
|
-
def initialize(line:, source:, annotation:)
|
9
|
-
@line = line
|
10
|
-
@source = source
|
11
|
-
@annotation = annotation
|
12
|
-
end
|
13
|
-
|
14
|
-
def ==(other)
|
15
|
-
other.is_a?(LocatedAnnotation) &&
|
16
|
-
other.line == line &&
|
17
|
-
other.annotation == annotation
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
3
|
attr_reader :path
|
22
4
|
attr_reader :node
|
23
5
|
attr_reader :mapping
|
24
6
|
|
7
|
+
extend NodeHelper
|
8
|
+
|
25
9
|
def initialize(path:, node:, mapping:)
|
26
10
|
@path = path
|
27
11
|
@node = node
|
@@ -47,46 +31,61 @@ module Steep
|
|
47
31
|
|
48
32
|
def self.parse(source_code, path:, factory:)
|
49
33
|
buffer = ::Parser::Source::Buffer.new(path.to_s, 1, source: source_code)
|
50
|
-
node = new_parser().
|
34
|
+
node, comments = new_parser().parse_with_comments(buffer)
|
51
35
|
|
36
|
+
# @type var annotations: Array[AST::Annotation::t]
|
52
37
|
annotations = []
|
53
|
-
|
54
|
-
|
55
|
-
buffer = ::Parser::Source::Buffer.new(path.to_s, 1, source: source_code)
|
56
|
-
new_parser().tokenize(buffer)
|
57
|
-
end
|
38
|
+
# @type var type_comments: Hash[Integer, type_comment]
|
39
|
+
type_comments = {}
|
58
40
|
|
59
41
|
buffer = RBS::Buffer.new(name: path, content: source_code)
|
42
|
+
annotation_parser = AnnotationParser.new(factory: factory)
|
60
43
|
|
61
44
|
comments.each do |comment|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
45
|
+
if comment.inline?
|
46
|
+
content = comment.text.delete_prefix('#')
|
47
|
+
content.lstrip!
|
48
|
+
prefix = comment.text.size - content.size
|
49
|
+
content.rstrip!
|
50
|
+
suffix = comment.text.size - content.size - prefix
|
51
|
+
|
52
|
+
location = RBS::Location.new(
|
53
|
+
buffer: buffer,
|
54
|
+
start_pos: comment.location.expression.begin_pos + prefix,
|
55
|
+
end_pos: comment.location.expression.end_pos - suffix
|
56
|
+
)
|
57
|
+
|
58
|
+
case
|
59
|
+
when annotation = annotation_parser.parse(content, location: location)
|
60
|
+
annotations << annotation
|
61
|
+
when assertion = AST::Node::TypeAssertion.parse(location)
|
62
|
+
type_comments[assertion.line] = assertion
|
63
|
+
when tapp = AST::Node::TypeApplication.parse(location)
|
64
|
+
type_comments[tapp.line] = tapp
|
65
|
+
end
|
69
66
|
end
|
70
67
|
end
|
71
68
|
|
72
|
-
|
69
|
+
map = {}
|
70
|
+
map.compare_by_identity
|
73
71
|
|
74
72
|
if node
|
75
|
-
|
73
|
+
node = insert_type_node(node, type_comments)
|
74
|
+
construct_mapping(node: node, annotations: annotations, mapping: map)
|
76
75
|
end
|
77
76
|
|
78
77
|
annotations.each do |annot|
|
79
|
-
|
80
|
-
|
78
|
+
map[node] ||= []
|
79
|
+
map[node] << annot
|
81
80
|
end
|
82
81
|
|
83
|
-
new(path: path, node: node, mapping:
|
82
|
+
new(path: path, node: node, mapping: map)
|
84
83
|
end
|
85
84
|
|
86
85
|
def self.construct_mapping(node:, annotations:, mapping:, line_range: nil)
|
87
86
|
case node.type
|
88
87
|
when :if
|
89
|
-
if node.loc.
|
88
|
+
if node.loc.respond_to?(:question)
|
90
89
|
# Skip ternary operator
|
91
90
|
each_child_node node do |child|
|
92
91
|
construct_mapping(node: child, annotations: annotations, mapping: mapping, line_range: nil)
|
@@ -200,7 +199,7 @@ module Steep
|
|
200
199
|
last_cond = node.children[-2]
|
201
200
|
body = node.children.last
|
202
201
|
|
203
|
-
node.children.take(node.children.size-1) do |child|
|
202
|
+
node.children.take(node.children.size-1).each do |child|
|
204
203
|
construct_mapping(node: child, annotations: annotations, mapping: mapping, line_range: nil)
|
205
204
|
end
|
206
205
|
|
@@ -235,7 +234,7 @@ module Steep
|
|
235
234
|
end
|
236
235
|
end
|
237
236
|
|
238
|
-
associated_annotations = annotations.
|
237
|
+
associated_annotations, other_annotations = annotations.partition do |annot|
|
239
238
|
case node.type
|
240
239
|
when :def, :module, :class, :block, :ensure, :defs
|
241
240
|
loc = node.loc
|
@@ -257,33 +256,34 @@ module Steep
|
|
257
256
|
associated_annotations.each do |annot|
|
258
257
|
mapping[node] ||= []
|
259
258
|
mapping[node] << annot
|
260
|
-
annotations.delete annot
|
261
259
|
end
|
262
|
-
end
|
263
260
|
|
264
|
-
|
265
|
-
node.children.each do |child|
|
266
|
-
if child.is_a?(::AST::Node)
|
267
|
-
yield child
|
268
|
-
end
|
269
|
-
end
|
261
|
+
annotations.replace(other_annotations)
|
270
262
|
end
|
271
263
|
|
272
|
-
def self.
|
264
|
+
def self.map_child_node(node, type = nil, skip: nil)
|
273
265
|
children = node.children.map do |child|
|
274
|
-
if child.is_a?(::AST::Node)
|
275
|
-
|
266
|
+
if child.is_a?(Parser::AST::Node)
|
267
|
+
if skip
|
268
|
+
if skip.member?(child)
|
269
|
+
child
|
270
|
+
else
|
271
|
+
yield child
|
272
|
+
end
|
273
|
+
else
|
274
|
+
yield child
|
275
|
+
end
|
276
276
|
else
|
277
277
|
child
|
278
278
|
end
|
279
279
|
end
|
280
280
|
|
281
|
-
node.updated(
|
281
|
+
node.updated(type, children)
|
282
282
|
end
|
283
283
|
|
284
284
|
def annotations(block:, factory:, context:)
|
285
285
|
AST::Annotation::Collection.new(
|
286
|
-
annotations: (mapping[block] || [])
|
286
|
+
annotations: (mapping[block] || []),
|
287
287
|
factory: factory,
|
288
288
|
context: context
|
289
289
|
)
|
@@ -292,7 +292,7 @@ module Steep
|
|
292
292
|
def each_annotation(&block)
|
293
293
|
if block_given?
|
294
294
|
mapping.each do |node, annots|
|
295
|
-
yield node, annots
|
295
|
+
yield [node, annots]
|
296
296
|
end
|
297
297
|
else
|
298
298
|
enum_for :each_annotation
|
@@ -301,9 +301,11 @@ module Steep
|
|
301
301
|
|
302
302
|
def each_heredoc_node(node = self.node, parents = [], &block)
|
303
303
|
if block
|
304
|
+
return unless node
|
305
|
+
|
304
306
|
case node.type
|
305
307
|
when :dstr, :str
|
306
|
-
if node.location.
|
308
|
+
if node.location.respond_to?(:heredoc_body)
|
307
309
|
yield [node, *parents]
|
308
310
|
end
|
309
311
|
end
|
@@ -344,7 +346,9 @@ module Steep
|
|
344
346
|
parents.unshift node
|
345
347
|
|
346
348
|
Source.each_child_node(node) do |child|
|
347
|
-
ns = find_nodes_loc(child, position, parents)
|
349
|
+
if ns = find_nodes_loc(child, position, parents)
|
350
|
+
return ns
|
351
|
+
end
|
348
352
|
end
|
349
353
|
|
350
354
|
parents
|
@@ -359,12 +363,14 @@ module Steep
|
|
359
363
|
node.location.expression.source_buffer.source_line(i+1).size + 1
|
360
364
|
end + column
|
361
365
|
|
362
|
-
if
|
363
|
-
Source.each_child_node(
|
364
|
-
find_nodes_loc(child, position,
|
366
|
+
if heredoc_nodes = find_heredoc_nodes(line, column, position)
|
367
|
+
Source.each_child_node(heredoc_nodes[0]) do |child|
|
368
|
+
if nodes = find_nodes_loc(child, position, heredoc_nodes)
|
369
|
+
return nodes
|
370
|
+
end
|
365
371
|
end
|
366
372
|
|
367
|
-
|
373
|
+
return heredoc_nodes
|
368
374
|
else
|
369
375
|
find_nodes_loc(node, position, [])
|
370
376
|
end
|
@@ -385,7 +391,7 @@ module Steep
|
|
385
391
|
delete_defs(node.children[0], allow_list)
|
386
392
|
end
|
387
393
|
else
|
388
|
-
|
394
|
+
map_child_node(node) do |child|
|
389
395
|
delete_defs(child, allow_list)
|
390
396
|
end
|
391
397
|
end
|
@@ -398,7 +404,9 @@ module Steep
|
|
398
404
|
|
399
405
|
node_ = Source.delete_defs(node, defs)
|
400
406
|
|
401
|
-
mapping
|
407
|
+
# @type var mapping: Hash[Parser::AST::Node, Array[AST::Annotation::t]]
|
408
|
+
mapping = {}
|
409
|
+
mapping.compare_by_identity
|
402
410
|
|
403
411
|
annotations = self.mapping.values.flatten
|
404
412
|
Source.construct_mapping(node: node_, annotations: annotations, mapping: mapping)
|
@@ -414,19 +422,129 @@ module Steep
|
|
414
422
|
end
|
415
423
|
end
|
416
424
|
|
417
|
-
def
|
418
|
-
|
419
|
-
|
420
|
-
node.
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
425
|
+
def self.insert_type_node(node, comments)
|
426
|
+
if node.location.expression
|
427
|
+
first_line = node.location.expression.first_line
|
428
|
+
last_line = node.location.expression.last_line
|
429
|
+
last_comment = comments[last_line]
|
430
|
+
|
431
|
+
if (first_line..last_line).none? {|l| comments.key?(l) }
|
432
|
+
return node
|
433
|
+
end
|
434
|
+
|
435
|
+
case
|
436
|
+
when last_comment.is_a?(AST::Node::TypeAssertion)
|
437
|
+
case node.type
|
438
|
+
when :lvasgn, :ivasgn, :gvasgn, :cvasgn, :casgn
|
439
|
+
# Skip
|
440
|
+
when :masgn
|
441
|
+
lhs, rhs = node.children
|
442
|
+
node = node.updated(nil, [lhs, insert_type_node(rhs, comments)])
|
443
|
+
return adjust_location(node)
|
444
|
+
when :return, :break, :next
|
445
|
+
# Skip
|
446
|
+
when :begin
|
447
|
+
if node.loc.begin
|
448
|
+
# paren
|
449
|
+
child_assertions = comments.except(last_line)
|
450
|
+
node = map_child_node(node) {|child| insert_type_node(child, child_assertions) }
|
451
|
+
node = adjust_location(node)
|
452
|
+
return assertion_node(node, last_comment)
|
453
|
+
end
|
454
|
+
else
|
455
|
+
child_assertions = comments.except(last_line)
|
456
|
+
node = map_child_node(node) {|child| insert_type_node(child, child_assertions) }
|
457
|
+
node = adjust_location(node)
|
458
|
+
return assertion_node(node, last_comment)
|
459
|
+
end
|
460
|
+
when selector_line = sendish_node?(node)
|
461
|
+
if (comment = comments[selector_line]).is_a?(AST::Node::TypeApplication)
|
462
|
+
child_assertions = comments.except(selector_line)
|
463
|
+
case node.type
|
464
|
+
when :block
|
465
|
+
send, *children = node.children
|
466
|
+
node = node.updated(
|
467
|
+
nil,
|
468
|
+
[
|
469
|
+
map_child_node(send) {|child| insert_type_node(child, child_assertions) },
|
470
|
+
*children.map {|child| insert_type_node(child, child_assertions) }
|
471
|
+
]
|
472
|
+
)
|
473
|
+
when :numblock
|
474
|
+
send, size, body = node.children
|
475
|
+
node = node.updated(
|
476
|
+
nil,
|
477
|
+
[
|
478
|
+
map_child_node(send) {|child| insert_type_node(child, child_assertions) },
|
479
|
+
size,
|
480
|
+
insert_type_node(body, child_assertions)
|
481
|
+
]
|
482
|
+
)
|
483
|
+
else
|
484
|
+
node = map_child_node(node) {|child| insert_type_node(child, child_assertions) }
|
485
|
+
end
|
486
|
+
node = adjust_location(node)
|
487
|
+
return type_application_node(node, comment)
|
488
|
+
end
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
adjust_location(
|
493
|
+
map_child_node(node, nil) {|child| insert_type_node(child, comments) }
|
494
|
+
)
|
495
|
+
end
|
496
|
+
|
497
|
+
def self.sendish_node?(node)
|
498
|
+
send_node =
|
499
|
+
case node.type
|
500
|
+
when :send, :csend
|
501
|
+
node
|
502
|
+
when :block, :numblock
|
503
|
+
send = node.children[0]
|
504
|
+
case send.type
|
505
|
+
when :send, :csend
|
506
|
+
send
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
if send_node
|
511
|
+
if send_node.location.dot
|
512
|
+
send_node.location.selector.line
|
513
|
+
end
|
514
|
+
end
|
515
|
+
end
|
516
|
+
|
517
|
+
def self.adjust_location(node)
|
518
|
+
if end_pos = node.location.expression&.end_pos
|
519
|
+
if last_pos = each_child_node(node).map {|node| node.location.expression&.end_pos }.compact.max
|
520
|
+
if last_pos > end_pos
|
521
|
+
props = { location: node.location.with_expression(node.location.expression.with(end_pos: last_pos)) }
|
522
|
+
end
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
if props
|
527
|
+
node.updated(nil, nil, props)
|
427
528
|
else
|
428
529
|
node
|
429
530
|
end
|
430
531
|
end
|
532
|
+
|
533
|
+
def self.assertion_node(node, type)
|
534
|
+
map = Parser::Source::Map.new(node.location.expression.with(end_pos: type.location.end_pos))
|
535
|
+
Parser::AST::Node.new(:assertion, [node, type], { location: map })
|
536
|
+
end
|
537
|
+
|
538
|
+
def self.type_application_node(node, tapp)
|
539
|
+
if node.location.expression.end_pos > tapp.location.end_pos
|
540
|
+
map = Parser::Source::Map.new(node.location.expression)
|
541
|
+
else
|
542
|
+
map = Parser::Source::Map.new(node.location.expression.with(end_pos: tapp.location.end_pos))
|
543
|
+
end
|
544
|
+
|
545
|
+
node = Parser::AST::Node.new(:tapp, [node, tapp], { location: map })
|
546
|
+
tapp.set_node(node)
|
547
|
+
node
|
548
|
+
end
|
431
549
|
end
|
432
550
|
end
|