steep 1.0.0 → 1.1.0.pre.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby-windows.yml +34 -0
- data/.github/workflows/ruby.yml +7 -2
- data/.gitignore +1 -0
- data/CHANGELOG.md +59 -0
- data/Gemfile +7 -4
- data/Gemfile.lock +17 -21
- data/Gemfile.steep +3 -0
- data/Gemfile.steep.lock +49 -0
- data/Rakefile +5 -0
- data/Steepfile +6 -1
- data/bin/setup +2 -0
- data/bin/steep +19 -0
- data/lib/steep/ast/builtin.rb +2 -2
- data/lib/steep/ast/types/factory.rb +7 -3
- data/lib/steep/ast/types/proc.rb +2 -0
- data/lib/steep/cli.rb +3 -1
- data/lib/steep/diagnostic/ruby.rb +50 -4
- data/lib/steep/diagnostic/signature.rb +18 -0
- data/lib/steep/drivers/check.rb +3 -3
- data/lib/steep/drivers/watch.rb +3 -1
- data/lib/steep/method_name.rb +9 -3
- data/lib/steep/node_helper.rb +49 -0
- data/lib/steep/path_helper.rb +22 -0
- data/lib/steep/project.rb +3 -15
- data/lib/steep/server/base_worker.rb +1 -0
- data/lib/steep/server/change_buffer.rb +1 -1
- data/lib/steep/server/interaction_worker.rb +3 -5
- data/lib/steep/server/master.rb +61 -45
- data/lib/steep/server/type_check_worker.rb +10 -25
- data/lib/steep/services/completion_provider.rb +25 -18
- data/lib/steep/services/goto_service.rb +2 -4
- data/lib/steep/services/hover_provider/rbs.rb +1 -1
- data/lib/steep/services/hover_provider/ruby.rb +30 -12
- data/lib/steep/services/stats_calculator.rb +0 -1
- data/lib/steep/services/type_check_service.rb +15 -12
- data/lib/steep/shims/symbol_start_with.rb +18 -0
- data/lib/steep/signature/validator.rb +25 -1
- data/lib/steep/source.rb +1 -1
- data/lib/steep/subtyping/check.rb +0 -3
- data/lib/steep/subtyping/constraints.rb +43 -14
- data/lib/steep/type_construction.rb +721 -764
- data/lib/steep/type_inference/constant_env.rb +0 -2
- data/lib/steep/type_inference/context.rb +23 -17
- data/lib/steep/type_inference/logic_type_interpreter.rb +210 -117
- data/lib/steep/type_inference/method_call.rb +80 -6
- data/lib/steep/type_inference/multiple_assignment.rb +189 -0
- data/lib/steep/type_inference/send_args.rb +1 -2
- data/lib/steep/type_inference/type_env.rb +273 -116
- data/lib/steep/type_inference/type_env_builder.rb +138 -0
- data/lib/steep/typing.rb +2 -0
- data/lib/steep/version.rb +1 -1
- data/lib/steep.rb +7 -5
- data/rbs_collection.steep.lock.yaml +112 -0
- data/rbs_collection.steep.yaml +19 -0
- data/sample/sig/conference.rbs +8 -0
- data/sig/shims/parser/source/map.rbs +146 -0
- data/sig/shims/parser/source/range.rbs +237 -0
- data/sig/shims/parser.rbs +17 -0
- data/sig/steep/ast/annotation/collection.rbs +75 -0
- data/sig/steep/ast/annotation.rbs +126 -0
- data/sig/steep/ast/builtin.rbs +69 -0
- data/sig/steep/ast/type_params.rbs +11 -0
- data/sig/steep/ast/types/any.rbs +29 -0
- data/sig/steep/ast/types/boolean.rbs +31 -0
- data/sig/steep/ast/types/bot.rbs +29 -0
- data/sig/steep/ast/types/class.rbs +29 -0
- data/sig/steep/ast/types/factory.rbs +76 -0
- data/sig/steep/ast/types/helper.rbs +19 -0
- data/sig/steep/ast/types/instance.rbs +29 -0
- data/sig/steep/ast/types/intersection.rbs +35 -0
- data/sig/steep/ast/types/literal.rbs +33 -0
- data/sig/steep/ast/types/logic.rbs +78 -0
- data/sig/steep/ast/types/name.rbs +71 -0
- data/sig/steep/ast/types/nil.rbs +31 -0
- data/sig/steep/ast/types/proc.rbs +46 -0
- data/sig/steep/ast/types/record.rbs +38 -0
- data/sig/steep/ast/types/self.rbs +29 -0
- data/sig/steep/ast/types/top.rbs +29 -0
- data/sig/steep/ast/types/tuple.rbs +34 -0
- data/sig/steep/ast/types/union.rbs +38 -0
- data/sig/steep/ast/types/var.rbs +37 -0
- data/sig/steep/ast/types/void.rbs +29 -0
- data/sig/steep/ast/types.rbs +37 -0
- data/sig/steep/diagnostic/deprecated/unknown_constant_assigned.rbs +15 -0
- data/sig/steep/diagnostic/helper.rbs +9 -0
- data/sig/steep/diagnostic/lsp_formatter.rbs +29 -0
- data/sig/steep/diagnostic/ruby.rbs +494 -0
- data/sig/steep/diagnostic/signature.rbs +215 -0
- data/sig/steep/interface/block.rbs +35 -0
- data/sig/steep/interface/function.rbs +253 -0
- data/sig/steep/interface/interface.rbs +23 -0
- data/sig/steep/interface/method_type.rbs +55 -0
- data/sig/steep/interface/substitution.rbs +53 -0
- data/sig/steep/interface/type_param.rbs +35 -0
- data/sig/steep/method_name.rbs +26 -0
- data/sig/steep/module_helper.rbs +7 -0
- data/sig/steep/node_helper.rbs +11 -0
- data/sig/steep/project/dsl.rbs +94 -0
- data/sig/steep/project/options.rbs +15 -0
- data/sig/steep/project/pattern.rbs +25 -0
- data/sig/steep/project/target.rbs +25 -0
- data/sig/steep/project.rbs +19 -0
- data/sig/steep/services/completion_provider.rbs +123 -0
- data/sig/steep/services/content_change.rbs +35 -0
- data/sig/steep/services/file_loader.rbs +13 -0
- data/sig/steep/services/goto_service.rbs +45 -0
- data/sig/steep/services/hover_provider/rbs.rbs +21 -0
- data/sig/steep/services/hover_provider/ruby.rbs +109 -0
- data/sig/steep/services/hover_provider/singleton_methods.rbs +11 -0
- data/sig/steep/services/path_assignment.rbs +21 -0
- data/sig/steep/services/signature_service.rbs +91 -0
- data/sig/steep/services/stats_calculator.rbs +17 -0
- data/sig/steep/services/type_check_service.rbs +93 -0
- data/sig/steep/source.rbs +55 -0
- data/sig/steep/subtyping/cache.rbs +17 -0
- data/sig/steep/subtyping/check.rbs +93 -0
- data/sig/steep/subtyping/constraints.rbs +111 -0
- data/sig/steep/subtyping/relation.rbs +51 -0
- data/sig/steep/subtyping/result.rbs +157 -0
- data/sig/steep/subtyping/variable_variance.rbs +23 -0
- data/sig/steep/type_construction.rbs +285 -0
- data/sig/steep/type_inference/block_params.rbs +52 -0
- data/sig/steep/type_inference/constant_env.rbs +27 -0
- data/sig/steep/type_inference/context.rbs +137 -0
- data/sig/steep/type_inference/logic_type_interpreter.rbs +72 -0
- data/sig/steep/type_inference/method_call.rbs +124 -0
- data/sig/steep/type_inference/method_params.rbs +104 -0
- data/sig/steep/type_inference/multiple_assignment.rbs +76 -0
- data/sig/steep/type_inference/type_env.rbs +158 -0
- data/sig/steep/type_inference/type_env_builder.rbs +77 -0
- data/sig/steep/typing.rbs +68 -0
- data/sig/steep.rbs +31 -0
- data/smoke/class/f.rb +1 -0
- data/smoke/class/test_expectations.yml +2 -2
- data/smoke/diagnostics/test_expectations.yml +4 -2
- data/smoke/regression/lambda.rb +3 -0
- data/smoke/regression/test_expectations.yml +12 -0
- data/steep.gemspec +1 -1
- metadata +95 -9
- data/lib/steep/subtyping/variable_occurrence.rb +0 -51
- data/lib/steep/type_inference/local_variable_type_env.rb +0 -249
- data/lib/steep/type_inference/logic.rb +0 -161
@@ -0,0 +1,49 @@
|
|
1
|
+
module Steep
|
2
|
+
module NodeHelper
|
3
|
+
def each_child_node(node, &block)
|
4
|
+
if block
|
5
|
+
node.children.each do |child|
|
6
|
+
if child.is_a?(Parser::AST::Node)
|
7
|
+
yield child
|
8
|
+
end
|
9
|
+
end
|
10
|
+
else
|
11
|
+
enum_for :each_child_node, node
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def each_descendant_node(node, &block)
|
16
|
+
if block
|
17
|
+
each_child_node(node) do |child|
|
18
|
+
yield child
|
19
|
+
each_descendant_node(child, &block)
|
20
|
+
end
|
21
|
+
else
|
22
|
+
enum_for :each_descendant_node, node
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def value_node?(node)
|
27
|
+
case node.type
|
28
|
+
when :true, :false, :str, :sym, :int, :float, :nil
|
29
|
+
true
|
30
|
+
when :lvar
|
31
|
+
true
|
32
|
+
when :const
|
33
|
+
each_child_node(node).all? {|child| child.type == :cbase || value_node?(child) }
|
34
|
+
when :array
|
35
|
+
each_child_node(node).all? {|child| value_node?(child) }
|
36
|
+
when :hash
|
37
|
+
each_child_node(node).all? do |pair|
|
38
|
+
each_child_node(pair).all? {|child| value_node?(child) }
|
39
|
+
end
|
40
|
+
when :dstr
|
41
|
+
each_child_node(node).all? {|child| value_node?(child)}
|
42
|
+
when :begin
|
43
|
+
each_child_node(node).all? {|child| value_node?(node) }
|
44
|
+
else
|
45
|
+
false
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Steep
|
2
|
+
module PathHelper
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def to_pathname(uri, dosish: Gem.win_platform?)
|
6
|
+
uri = URI.parse(uri)
|
7
|
+
if uri.scheme == "file"
|
8
|
+
path = uri.path
|
9
|
+
path.sub!(%r{^/([a-zA-Z])(:|%3A)//?}i, '\1:/') if dosish
|
10
|
+
Pathname(path)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_uri(path, dosish: Gem.win_platform?)
|
15
|
+
str_path = path.to_s
|
16
|
+
if dosish
|
17
|
+
str_path.insert(0, "/") if str_path[0] != "/"
|
18
|
+
end
|
19
|
+
URI::File.build(path: str_path)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/steep/project.rb
CHANGED
@@ -16,22 +16,10 @@ module Steep
|
|
16
16
|
steepfile_path.parent
|
17
17
|
end
|
18
18
|
|
19
|
-
def relative_path(
|
20
|
-
path = if Gem.win_platform?
|
21
|
-
path_str = URI.decode_www_form_component(
|
22
|
-
orig_path.to_s.delete_prefix("/")
|
23
|
-
)
|
24
|
-
unless path_str.start_with?(%r{[a-z]:/}i)
|
25
|
-
# FIXME: Sometimes drive letter is missing, taking from base_dir
|
26
|
-
path_str = base_dir.to_s.split("/")[0] + "/" + path_str
|
27
|
-
end
|
28
|
-
Pathname.new(
|
29
|
-
path_str
|
30
|
-
)
|
31
|
-
else
|
32
|
-
orig_path
|
33
|
-
end
|
19
|
+
def relative_path(path)
|
34
20
|
path.relative_path_from(base_dir)
|
21
|
+
rescue ArgumentError
|
22
|
+
path
|
35
23
|
end
|
36
24
|
|
37
25
|
def absolute_path(path)
|
@@ -40,7 +40,7 @@ module Steep
|
|
40
40
|
|
41
41
|
def collect_changes(request)
|
42
42
|
push_buffer do |changes|
|
43
|
-
path = project.relative_path(
|
43
|
+
path = project.relative_path(Steep::PathHelper.to_pathname(request[:params][:textDocument][:uri]))
|
44
44
|
version = request[:params][:textDocument][:version]
|
45
45
|
Steep.logger.info { "Updating source: path=#{path}, version=#{version}..." }
|
46
46
|
|
@@ -53,8 +53,7 @@ module Steep
|
|
53
53
|
when "textDocument/hover"
|
54
54
|
id = request[:id]
|
55
55
|
|
56
|
-
|
57
|
-
path = project.relative_path(Pathname(uri.path))
|
56
|
+
path = project.relative_path(Steep::PathHelper.to_pathname(request[:params][:textDocument][:uri]))
|
58
57
|
line = request[:params][:position][:line]+1
|
59
58
|
column = request[:params][:position][:character]
|
60
59
|
|
@@ -64,8 +63,7 @@ module Steep
|
|
64
63
|
id = request[:id]
|
65
64
|
|
66
65
|
params = request[:params]
|
67
|
-
|
68
|
-
path = project.relative_path(Pathname(uri.path))
|
66
|
+
path = project.relative_path(Steep::PathHelper.to_pathname(params[:textDocument][:uri]))
|
69
67
|
line, column = params[:position].yield_self {|hash| [hash[:line]+1, hash[:character]] }
|
70
68
|
trigger = params.dig(:context, :triggerCharacter)
|
71
69
|
|
@@ -144,7 +142,7 @@ module Steep
|
|
144
142
|
decls = sig_service.files[relative_path].decls
|
145
143
|
locator = RBS::Locator.new(decls: decls)
|
146
144
|
|
147
|
-
|
145
|
+
_hd, tail = locator.find2(line: job.line, column: job.column)
|
148
146
|
|
149
147
|
namespace = []
|
150
148
|
tail.each do |t|
|
data/lib/steep/server/master.rb
CHANGED
@@ -21,9 +21,7 @@ module Steep
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def uri(path)
|
24
|
-
|
25
|
-
uri.scheme = "file"
|
26
|
-
end
|
24
|
+
Steep::PathHelper.to_uri(path)
|
27
25
|
end
|
28
26
|
|
29
27
|
def as_json(assignment:)
|
@@ -41,7 +39,7 @@ module Steep
|
|
41
39
|
end
|
42
40
|
|
43
41
|
def percentage
|
44
|
-
checked_paths.size * 100 /
|
42
|
+
checked_paths.size * 100 / all_paths.size
|
45
43
|
end
|
46
44
|
|
47
45
|
def all_paths
|
@@ -50,12 +48,7 @@ module Steep
|
|
50
48
|
|
51
49
|
def checking_path?(path)
|
52
50
|
[library_paths, signature_paths, code_paths].any? do |paths|
|
53
|
-
|
54
|
-
# FIXME: Sometimes drive letter is missing, so comparing without drive letter.
|
55
|
-
paths.any? {|p| p.to_s.split("/", 2)[1] == path.to_s.split("/", 2)[1]}
|
56
|
-
else
|
57
|
-
paths.include?(path)
|
58
|
-
end
|
51
|
+
paths.include?(path)
|
59
52
|
end
|
60
53
|
end
|
61
54
|
|
@@ -463,7 +456,7 @@ module Steep
|
|
463
456
|
end
|
464
457
|
|
465
458
|
def pathname(uri)
|
466
|
-
|
459
|
+
Steep::PathHelper.to_pathname(uri)
|
467
460
|
end
|
468
461
|
|
469
462
|
def work_done_progress_supported?
|
@@ -524,40 +517,54 @@ module Steep
|
|
524
517
|
end
|
525
518
|
|
526
519
|
when "textDocument/didChange"
|
527
|
-
|
528
|
-
|
529
|
-
|
520
|
+
if path = pathname(message[:params][:textDocument][:uri])
|
521
|
+
broadcast_notification(message)
|
522
|
+
controller.push_changes(path)
|
523
|
+
end
|
530
524
|
|
531
525
|
when "textDocument/didSave"
|
532
|
-
if
|
533
|
-
if
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
526
|
+
if path = pathname(message[:params][:textDocument][:uri])
|
527
|
+
if typecheck_automatically
|
528
|
+
if request = controller.make_request(last_request: current_type_check_request)
|
529
|
+
start_type_check(
|
530
|
+
request,
|
531
|
+
last_request: current_type_check_request,
|
532
|
+
start_progress: request.total > 10
|
533
|
+
)
|
534
|
+
end
|
539
535
|
end
|
540
536
|
end
|
541
537
|
|
542
538
|
when "textDocument/didOpen"
|
543
|
-
path = pathname(message[:params][:textDocument][:uri])
|
544
|
-
|
539
|
+
if path = pathname(message[:params][:textDocument][:uri])
|
540
|
+
controller.update_priority(open: path)
|
541
|
+
end
|
545
542
|
|
546
543
|
when "textDocument/didClose"
|
547
|
-
path = pathname(message[:params][:textDocument][:uri])
|
548
|
-
|
544
|
+
if path = pathname(message[:params][:textDocument][:uri])
|
545
|
+
controller.update_priority(close: path)
|
546
|
+
end
|
549
547
|
|
550
548
|
when "textDocument/hover", "textDocument/completion"
|
551
549
|
if interaction_worker
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
550
|
+
if path = pathname(message[:params][:textDocument][:uri])
|
551
|
+
result_controller << send_request(method: message[:method], params: message[:params], worker: interaction_worker) do |handler|
|
552
|
+
handler.on_completion do |response|
|
553
|
+
job_queue << SendMessageJob.to_client(
|
554
|
+
message: {
|
555
|
+
id: message[:id],
|
556
|
+
result: response[:result]
|
557
|
+
}
|
558
|
+
)
|
559
|
+
end
|
560
560
|
end
|
561
|
+
else
|
562
|
+
job_queue << SendMessageJob.to_client(
|
563
|
+
message: {
|
564
|
+
id: message[:id],
|
565
|
+
result: nil
|
566
|
+
}
|
567
|
+
)
|
561
568
|
end
|
562
569
|
end
|
563
570
|
|
@@ -594,20 +601,29 @@ module Steep
|
|
594
601
|
end
|
595
602
|
|
596
603
|
when "textDocument/definition", "textDocument/implementation"
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
604
|
+
if path = pathname(message[:params][:textDocument][:uri])
|
605
|
+
result_controller << group_request do |group|
|
606
|
+
typecheck_workers.each do |worker|
|
607
|
+
group << send_request(method: message[:method], params: message[:params], worker: worker)
|
608
|
+
end
|
601
609
|
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
+
group.on_completion do |handlers|
|
611
|
+
links = handlers.flat_map(&:result)
|
612
|
+
job_queue << SendMessageJob.to_client(
|
613
|
+
message: {
|
614
|
+
id: message[:id],
|
615
|
+
result: links
|
616
|
+
}
|
617
|
+
)
|
618
|
+
end
|
610
619
|
end
|
620
|
+
else
|
621
|
+
job_queue << SendMessageJob.to_client(
|
622
|
+
message: {
|
623
|
+
id: message[:id],
|
624
|
+
result: []
|
625
|
+
}
|
626
|
+
)
|
611
627
|
end
|
612
628
|
|
613
629
|
when "$/typecheck"
|
@@ -86,10 +86,10 @@ module Steep
|
|
86
86
|
queue << StartTypeCheckJob.new(guid: guid, changes: changes)
|
87
87
|
end
|
88
88
|
|
89
|
-
priority_paths = Set.new(params[:priority_uris].map {|uri|
|
90
|
-
library_paths = params[:library_uris].map {|uri|
|
91
|
-
signature_paths = params[:signature_uris].map {|uri|
|
92
|
-
code_paths = params[:code_uris].map {|uri|
|
89
|
+
priority_paths = Set.new(params[:priority_uris].map {|uri| Steep::PathHelper.to_pathname(uri) })
|
90
|
+
library_paths = params[:library_uris].map {|uri| Steep::PathHelper.to_pathname(uri) }
|
91
|
+
signature_paths = params[:signature_uris].map {|uri| Steep::PathHelper.to_pathname(uri) }
|
92
|
+
code_paths = params[:code_uris].map {|uri| Steep::PathHelper.to_pathname(uri) }
|
93
93
|
|
94
94
|
library_paths.each do |path|
|
95
95
|
if priority_paths.include?(path)
|
@@ -135,21 +135,6 @@ module Steep
|
|
135
135
|
end
|
136
136
|
|
137
137
|
def handle_job(job)
|
138
|
-
job_path = if job.respond_to?(:path)
|
139
|
-
if Gem.win_platform?
|
140
|
-
# FIXME: Sometimes drive letter is missing, using base_dir
|
141
|
-
if job.path.to_s.start_with?(%r{/[a-z](:|%3A)/}i)
|
142
|
-
job.path.to_s
|
143
|
-
else
|
144
|
-
"/#{project.base_dir.to_s.split("/").first}/#{job.path}"
|
145
|
-
end
|
146
|
-
else
|
147
|
-
job.path.to_s
|
148
|
-
end
|
149
|
-
else
|
150
|
-
nil
|
151
|
-
end
|
152
|
-
|
153
138
|
case job
|
154
139
|
when StartTypeCheckJob
|
155
140
|
Steep.logger.info { "Processing StartTypeCheckJob for guid=#{job.guid}" }
|
@@ -164,7 +149,7 @@ module Steep
|
|
164
149
|
writer.write(
|
165
150
|
method: :"textDocument/publishDiagnostics",
|
166
151
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
167
|
-
uri:
|
152
|
+
uri: Steep::PathHelper.to_uri(job.path),
|
168
153
|
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq
|
169
154
|
)
|
170
155
|
)
|
@@ -182,7 +167,7 @@ module Steep
|
|
182
167
|
writer.write(
|
183
168
|
method: :"textDocument/publishDiagnostics",
|
184
169
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
185
|
-
uri:
|
170
|
+
uri: Steep::PathHelper.to_uri(job.path),
|
186
171
|
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
|
187
172
|
)
|
188
173
|
)
|
@@ -201,7 +186,7 @@ module Steep
|
|
201
186
|
writer.write(
|
202
187
|
method: :"textDocument/publishDiagnostics",
|
203
188
|
params: LSP::Interface::PublishDiagnosticsParams.new(
|
204
|
-
uri:
|
189
|
+
uri: Steep::PathHelper.to_uri(job.path),
|
205
190
|
diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
|
206
191
|
)
|
207
192
|
)
|
@@ -251,7 +236,7 @@ module Steep
|
|
251
236
|
location: symbol.location.yield_self do |location|
|
252
237
|
path = Pathname(location.buffer.name)
|
253
238
|
{
|
254
|
-
uri:
|
239
|
+
uri: Steep::PathHelper.to_uri(project.absolute_path(path)),
|
255
240
|
range: {
|
256
241
|
start: { line: location.start_line - 1, character: location.start_column },
|
257
242
|
end: { line: location.end_line - 1, character: location.end_column }
|
@@ -279,7 +264,7 @@ module Steep
|
|
279
264
|
end
|
280
265
|
|
281
266
|
def goto(job)
|
282
|
-
path =
|
267
|
+
path = Steep::PathHelper.to_pathname(job.params[:textDocument][:uri])
|
283
268
|
line = job.params[:position][:line] + 1
|
284
269
|
column = job.params[:position][:character]
|
285
270
|
|
@@ -306,7 +291,7 @@ module Steep
|
|
306
291
|
path = project.absolute_path(path)
|
307
292
|
|
308
293
|
{
|
309
|
-
uri:
|
294
|
+
uri: Steep::PathHelper.to_uri(path.to_s).to_s,
|
310
295
|
range: loc.as_lsp_range
|
311
296
|
}
|
312
297
|
end
|
@@ -1,16 +1,20 @@
|
|
1
1
|
module Steep
|
2
2
|
module Services
|
3
3
|
class CompletionProvider
|
4
|
-
Position = Struct.new(:line, :column, keyword_init: true) do
|
4
|
+
Position = _ = Struct.new(:line, :column, keyword_init: true) do
|
5
|
+
# @implements Position
|
5
6
|
def -(size)
|
6
7
|
Position.new(line: line, column: column - size)
|
7
8
|
end
|
8
9
|
end
|
9
|
-
Range = Struct.new(:start, :end, keyword_init: true)
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
Range = _ = Struct.new(:start, :end, keyword_init: true)
|
12
|
+
|
13
|
+
InstanceVariableItem = _ = Struct.new(:identifier, :range, :type, keyword_init: true)
|
14
|
+
LocalVariableItem = _ = Struct.new(:identifier, :range, :type, keyword_init: true)
|
15
|
+
ConstantItem = _ = Struct.new(:env, :identifier, :range, :type, :full_name, keyword_init: true) do
|
16
|
+
# @implements ConstantItem
|
17
|
+
|
14
18
|
def class?
|
15
19
|
if decl = env.class_decls[full_name]
|
16
20
|
decl.primary.decl.is_a?(RBS::AST::Declarations::Class)
|
@@ -34,20 +38,23 @@ module Steep
|
|
34
38
|
end
|
35
39
|
end
|
36
40
|
end
|
37
|
-
MethodNameItem = Struct.new(:identifier, :range, :receiver_type, :method_type, :method_decls, keyword_init: true) do
|
41
|
+
MethodNameItem = _ = Struct.new(:identifier, :range, :receiver_type, :method_type, :method_decls, keyword_init: true) do
|
42
|
+
# @implements MethodNameItem
|
43
|
+
|
38
44
|
def comment
|
39
45
|
case method_decls.size
|
40
46
|
when 0
|
41
47
|
nil
|
42
48
|
when 1
|
43
|
-
method_decls.to_a.first
|
49
|
+
method = method_decls.to_a.first or raise
|
50
|
+
method.method_def&.comment
|
44
51
|
else
|
45
52
|
nil
|
46
53
|
end
|
47
54
|
end
|
48
55
|
|
49
56
|
def inherited?
|
50
|
-
case receiver_type
|
57
|
+
case receiver_type = receiver_type()
|
51
58
|
when AST::Types::Name::Instance, AST::Types::Name::Singleton, AST::Types::Name::Interface
|
52
59
|
method_decls.any? do |decl|
|
53
60
|
decl.method_name.type_name != receiver_type.name
|
@@ -157,7 +164,7 @@ module Steep
|
|
157
164
|
end
|
158
165
|
|
159
166
|
def items_for_trigger(position:)
|
160
|
-
node, *
|
167
|
+
node, *_parents = source.find_nodes(line: position.line, column: position.column)
|
161
168
|
node ||= source.node
|
162
169
|
|
163
170
|
return [] unless node
|
@@ -265,7 +272,7 @@ module Steep
|
|
265
272
|
def items_for_dot(position:)
|
266
273
|
# foo. ←
|
267
274
|
shift_pos = position-1
|
268
|
-
node, *
|
275
|
+
node, *_parents = source.find_nodes(line: shift_pos.line, column: shift_pos.column)
|
269
276
|
node ||= source.node
|
270
277
|
|
271
278
|
return [] unless node
|
@@ -355,7 +362,7 @@ module Steep
|
|
355
362
|
end
|
356
363
|
end
|
357
364
|
end
|
358
|
-
rescue RuntimeError =>
|
365
|
+
rescue RuntimeError => _exn
|
359
366
|
# nop
|
360
367
|
end
|
361
368
|
|
@@ -365,11 +372,11 @@ module Steep
|
|
365
372
|
|
366
373
|
def local_variable_items_for_context(context, position:, prefix:, items:)
|
367
374
|
range = range_for(position, prefix: prefix)
|
368
|
-
context.
|
375
|
+
context.type_env.local_variable_types.each do |name, pair|
|
376
|
+
type, _ = pair
|
377
|
+
|
369
378
|
if name.to_s.start_with?(prefix)
|
370
|
-
items << LocalVariableItem.new(identifier: name,
|
371
|
-
range: range,
|
372
|
-
type: type)
|
379
|
+
items << LocalVariableItem.new(identifier: name, range: range, type: type)
|
373
380
|
end
|
374
381
|
end
|
375
382
|
end
|
@@ -381,10 +388,10 @@ module Steep
|
|
381
388
|
case parent.type
|
382
389
|
when :const
|
383
390
|
const_name = typing.source_index.reference(constant_node: parent)
|
384
|
-
consts = context.
|
391
|
+
consts = context.type_env.constant_env.children(const_name)
|
385
392
|
end
|
386
393
|
else
|
387
|
-
consts = context.
|
394
|
+
consts = context.type_env.constant_env.constants
|
388
395
|
end
|
389
396
|
|
390
397
|
if consts
|
@@ -400,7 +407,7 @@ module Steep
|
|
400
407
|
|
401
408
|
def instance_variable_items_for_context(context, position:, prefix:, items:)
|
402
409
|
range = range_for(position, prefix: prefix)
|
403
|
-
context.type_env.
|
410
|
+
context.type_env.instance_variable_types.each do |name, type|
|
404
411
|
if name.to_s.start_with?(prefix)
|
405
412
|
items << InstanceVariableItem.new(identifier: name,
|
406
413
|
range: range,
|
@@ -35,7 +35,7 @@ module Steep
|
|
35
35
|
def implementation(path:, line:, column:)
|
36
36
|
locations = []
|
37
37
|
|
38
|
-
relative_path = project.relative_path(path)
|
38
|
+
# relative_path = project.relative_path(path)
|
39
39
|
|
40
40
|
queries = query_at(path: path, line: line, column: column)
|
41
41
|
queries.uniq!
|
@@ -57,8 +57,6 @@ module Steep
|
|
57
57
|
def definition(path:, line:, column:)
|
58
58
|
locations = []
|
59
59
|
|
60
|
-
relative_path = project.relative_path(path)
|
61
|
-
|
62
60
|
queries = query_at(path: path, line: line, column: column)
|
63
61
|
queries.uniq!
|
64
62
|
|
@@ -108,7 +106,7 @@ module Steep
|
|
108
106
|
case
|
109
107
|
when target = type_check.source_file?(relative_path)
|
110
108
|
source = type_check.source_files[relative_path]
|
111
|
-
typing,
|
109
|
+
typing, _signature = type_check_path(target: target, path: relative_path, content: source.content, line: line, column: column)
|
112
110
|
if typing
|
113
111
|
node, *parents = typing.source.find_nodes(line: line, column: column)
|
114
112
|
|
@@ -2,22 +2,36 @@ module Steep
|
|
2
2
|
module Services
|
3
3
|
module HoverProvider
|
4
4
|
class Ruby
|
5
|
-
TypeContent = Struct.new(:node, :type, :location, keyword_init: true)
|
6
|
-
VariableContent = Struct.new(:node, :name, :type, :location, keyword_init: true)
|
7
|
-
MethodCallContent = Struct.new(:node, :method_call, :location, keyword_init: true)
|
8
|
-
DefinitionContent = Struct.new(:node, :method_name, :method_type, :definition, :location, keyword_init: true)
|
9
|
-
ConstantContent = Struct.new(:location, :full_name, :type, :decl, keyword_init: true) do
|
5
|
+
TypeContent = _ = Struct.new(:node, :type, :location, keyword_init: true)
|
6
|
+
VariableContent = _ = Struct.new(:node, :name, :type, :location, keyword_init: true)
|
7
|
+
MethodCallContent = _ = Struct.new(:node, :method_call, :location, keyword_init: true)
|
8
|
+
DefinitionContent = _ = Struct.new(:node, :method_name, :method_type, :definition, :location, keyword_init: true)
|
9
|
+
ConstantContent = _ = Struct.new(:location, :full_name, :type, :decl, keyword_init: true) do
|
10
|
+
# @implements ConstantContent
|
11
|
+
|
10
12
|
def comments
|
11
13
|
case
|
12
|
-
when
|
13
|
-
decl.decls.
|
14
|
-
when
|
14
|
+
when decl = class_decl
|
15
|
+
decl.decls.map {|d| d.decl.comment }
|
16
|
+
when decl = constant_decl
|
15
17
|
[decl.decl.comment]
|
16
18
|
else
|
17
|
-
|
19
|
+
raise
|
18
20
|
end.compact
|
19
21
|
end
|
20
22
|
|
23
|
+
def class_decl
|
24
|
+
if (decl = decl()).is_a?(::RBS::Environment::MultiEntry)
|
25
|
+
decl
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def constant_decl
|
30
|
+
if (decl = decl()).is_a?(::RBS::Environment::SingleEntry)
|
31
|
+
decl
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
21
35
|
def constant?
|
22
36
|
decl.is_a?(::RBS::Environment::SingleEntry)
|
23
37
|
end
|
@@ -49,6 +63,8 @@ module Steep
|
|
49
63
|
else
|
50
64
|
methods[singleton_method]
|
51
65
|
end
|
66
|
+
else
|
67
|
+
raise "One of the instance_method or singleton_method is required"
|
52
68
|
end
|
53
69
|
end
|
54
70
|
|
@@ -72,6 +88,8 @@ module Steep
|
|
72
88
|
InstanceMethodName.new(type_name: defined_in, method_name: method_name)
|
73
89
|
when builder.build_singleton(defined_in).methods.key?(method_name)
|
74
90
|
SingletonMethodName.new(type_name: defined_in, method_name: method_name)
|
91
|
+
else
|
92
|
+
raise
|
75
93
|
end
|
76
94
|
else
|
77
95
|
InstanceMethodName.new(type_name: defined_in, method_name: method_name)
|
@@ -83,19 +101,19 @@ module Steep
|
|
83
101
|
typing = typecheck(target, path: path, content: file.content, line: line, column: column) or return
|
84
102
|
node, *parents = typing.source.find_nodes(line: line, column: column)
|
85
103
|
|
86
|
-
if node
|
104
|
+
if node && parents
|
87
105
|
case node.type
|
88
106
|
when :lvar
|
89
107
|
var_name = node.children[0]
|
90
108
|
context = typing.context_at(line: line, column: column)
|
91
|
-
var_type = context.
|
109
|
+
var_type = context.type_env[var_name] || AST::Types::Any.new(location: nil)
|
92
110
|
|
93
111
|
return VariableContent.new(node: node, name: var_name, type: var_type, location: node.location.name)
|
94
112
|
|
95
113
|
when :lvasgn
|
96
114
|
var_name, rhs = node.children
|
97
115
|
context = typing.context_at(line: line, column: column)
|
98
|
-
type = context.
|
116
|
+
type = context.type_env[var_name] || typing.type_of(node: node)
|
99
117
|
|
100
118
|
return VariableContent.new(node: node, name: var_name, type: type, location: node.location.name)
|
101
119
|
|