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.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby-windows.yml +34 -0
  3. data/.github/workflows/ruby.yml +7 -2
  4. data/.gitignore +1 -0
  5. data/CHANGELOG.md +59 -0
  6. data/Gemfile +7 -4
  7. data/Gemfile.lock +17 -21
  8. data/Gemfile.steep +3 -0
  9. data/Gemfile.steep.lock +49 -0
  10. data/Rakefile +5 -0
  11. data/Steepfile +6 -1
  12. data/bin/setup +2 -0
  13. data/bin/steep +19 -0
  14. data/lib/steep/ast/builtin.rb +2 -2
  15. data/lib/steep/ast/types/factory.rb +7 -3
  16. data/lib/steep/ast/types/proc.rb +2 -0
  17. data/lib/steep/cli.rb +3 -1
  18. data/lib/steep/diagnostic/ruby.rb +50 -4
  19. data/lib/steep/diagnostic/signature.rb +18 -0
  20. data/lib/steep/drivers/check.rb +3 -3
  21. data/lib/steep/drivers/watch.rb +3 -1
  22. data/lib/steep/method_name.rb +9 -3
  23. data/lib/steep/node_helper.rb +49 -0
  24. data/lib/steep/path_helper.rb +22 -0
  25. data/lib/steep/project.rb +3 -15
  26. data/lib/steep/server/base_worker.rb +1 -0
  27. data/lib/steep/server/change_buffer.rb +1 -1
  28. data/lib/steep/server/interaction_worker.rb +3 -5
  29. data/lib/steep/server/master.rb +61 -45
  30. data/lib/steep/server/type_check_worker.rb +10 -25
  31. data/lib/steep/services/completion_provider.rb +25 -18
  32. data/lib/steep/services/goto_service.rb +2 -4
  33. data/lib/steep/services/hover_provider/rbs.rb +1 -1
  34. data/lib/steep/services/hover_provider/ruby.rb +30 -12
  35. data/lib/steep/services/stats_calculator.rb +0 -1
  36. data/lib/steep/services/type_check_service.rb +15 -12
  37. data/lib/steep/shims/symbol_start_with.rb +18 -0
  38. data/lib/steep/signature/validator.rb +25 -1
  39. data/lib/steep/source.rb +1 -1
  40. data/lib/steep/subtyping/check.rb +0 -3
  41. data/lib/steep/subtyping/constraints.rb +43 -14
  42. data/lib/steep/type_construction.rb +721 -764
  43. data/lib/steep/type_inference/constant_env.rb +0 -2
  44. data/lib/steep/type_inference/context.rb +23 -17
  45. data/lib/steep/type_inference/logic_type_interpreter.rb +210 -117
  46. data/lib/steep/type_inference/method_call.rb +80 -6
  47. data/lib/steep/type_inference/multiple_assignment.rb +189 -0
  48. data/lib/steep/type_inference/send_args.rb +1 -2
  49. data/lib/steep/type_inference/type_env.rb +273 -116
  50. data/lib/steep/type_inference/type_env_builder.rb +138 -0
  51. data/lib/steep/typing.rb +2 -0
  52. data/lib/steep/version.rb +1 -1
  53. data/lib/steep.rb +7 -5
  54. data/rbs_collection.steep.lock.yaml +112 -0
  55. data/rbs_collection.steep.yaml +19 -0
  56. data/sample/sig/conference.rbs +8 -0
  57. data/sig/shims/parser/source/map.rbs +146 -0
  58. data/sig/shims/parser/source/range.rbs +237 -0
  59. data/sig/shims/parser.rbs +17 -0
  60. data/sig/steep/ast/annotation/collection.rbs +75 -0
  61. data/sig/steep/ast/annotation.rbs +126 -0
  62. data/sig/steep/ast/builtin.rbs +69 -0
  63. data/sig/steep/ast/type_params.rbs +11 -0
  64. data/sig/steep/ast/types/any.rbs +29 -0
  65. data/sig/steep/ast/types/boolean.rbs +31 -0
  66. data/sig/steep/ast/types/bot.rbs +29 -0
  67. data/sig/steep/ast/types/class.rbs +29 -0
  68. data/sig/steep/ast/types/factory.rbs +76 -0
  69. data/sig/steep/ast/types/helper.rbs +19 -0
  70. data/sig/steep/ast/types/instance.rbs +29 -0
  71. data/sig/steep/ast/types/intersection.rbs +35 -0
  72. data/sig/steep/ast/types/literal.rbs +33 -0
  73. data/sig/steep/ast/types/logic.rbs +78 -0
  74. data/sig/steep/ast/types/name.rbs +71 -0
  75. data/sig/steep/ast/types/nil.rbs +31 -0
  76. data/sig/steep/ast/types/proc.rbs +46 -0
  77. data/sig/steep/ast/types/record.rbs +38 -0
  78. data/sig/steep/ast/types/self.rbs +29 -0
  79. data/sig/steep/ast/types/top.rbs +29 -0
  80. data/sig/steep/ast/types/tuple.rbs +34 -0
  81. data/sig/steep/ast/types/union.rbs +38 -0
  82. data/sig/steep/ast/types/var.rbs +37 -0
  83. data/sig/steep/ast/types/void.rbs +29 -0
  84. data/sig/steep/ast/types.rbs +37 -0
  85. data/sig/steep/diagnostic/deprecated/unknown_constant_assigned.rbs +15 -0
  86. data/sig/steep/diagnostic/helper.rbs +9 -0
  87. data/sig/steep/diagnostic/lsp_formatter.rbs +29 -0
  88. data/sig/steep/diagnostic/ruby.rbs +494 -0
  89. data/sig/steep/diagnostic/signature.rbs +215 -0
  90. data/sig/steep/interface/block.rbs +35 -0
  91. data/sig/steep/interface/function.rbs +253 -0
  92. data/sig/steep/interface/interface.rbs +23 -0
  93. data/sig/steep/interface/method_type.rbs +55 -0
  94. data/sig/steep/interface/substitution.rbs +53 -0
  95. data/sig/steep/interface/type_param.rbs +35 -0
  96. data/sig/steep/method_name.rbs +26 -0
  97. data/sig/steep/module_helper.rbs +7 -0
  98. data/sig/steep/node_helper.rbs +11 -0
  99. data/sig/steep/project/dsl.rbs +94 -0
  100. data/sig/steep/project/options.rbs +15 -0
  101. data/sig/steep/project/pattern.rbs +25 -0
  102. data/sig/steep/project/target.rbs +25 -0
  103. data/sig/steep/project.rbs +19 -0
  104. data/sig/steep/services/completion_provider.rbs +123 -0
  105. data/sig/steep/services/content_change.rbs +35 -0
  106. data/sig/steep/services/file_loader.rbs +13 -0
  107. data/sig/steep/services/goto_service.rbs +45 -0
  108. data/sig/steep/services/hover_provider/rbs.rbs +21 -0
  109. data/sig/steep/services/hover_provider/ruby.rbs +109 -0
  110. data/sig/steep/services/hover_provider/singleton_methods.rbs +11 -0
  111. data/sig/steep/services/path_assignment.rbs +21 -0
  112. data/sig/steep/services/signature_service.rbs +91 -0
  113. data/sig/steep/services/stats_calculator.rbs +17 -0
  114. data/sig/steep/services/type_check_service.rbs +93 -0
  115. data/sig/steep/source.rbs +55 -0
  116. data/sig/steep/subtyping/cache.rbs +17 -0
  117. data/sig/steep/subtyping/check.rbs +93 -0
  118. data/sig/steep/subtyping/constraints.rbs +111 -0
  119. data/sig/steep/subtyping/relation.rbs +51 -0
  120. data/sig/steep/subtyping/result.rbs +157 -0
  121. data/sig/steep/subtyping/variable_variance.rbs +23 -0
  122. data/sig/steep/type_construction.rbs +285 -0
  123. data/sig/steep/type_inference/block_params.rbs +52 -0
  124. data/sig/steep/type_inference/constant_env.rbs +27 -0
  125. data/sig/steep/type_inference/context.rbs +137 -0
  126. data/sig/steep/type_inference/logic_type_interpreter.rbs +72 -0
  127. data/sig/steep/type_inference/method_call.rbs +124 -0
  128. data/sig/steep/type_inference/method_params.rbs +104 -0
  129. data/sig/steep/type_inference/multiple_assignment.rbs +76 -0
  130. data/sig/steep/type_inference/type_env.rbs +158 -0
  131. data/sig/steep/type_inference/type_env_builder.rbs +77 -0
  132. data/sig/steep/typing.rbs +68 -0
  133. data/sig/steep.rbs +31 -0
  134. data/smoke/class/f.rb +1 -0
  135. data/smoke/class/test_expectations.yml +2 -2
  136. data/smoke/diagnostics/test_expectations.yml +4 -2
  137. data/smoke/regression/lambda.rb +3 -0
  138. data/smoke/regression/test_expectations.yml +12 -0
  139. data/steep.gemspec +1 -1
  140. metadata +95 -9
  141. data/lib/steep/subtyping/variable_occurrence.rb +0 -51
  142. data/lib/steep/type_inference/local_variable_type_env.rb +0 -249
  143. 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(orig_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)
@@ -69,6 +69,7 @@ module Steep
69
69
  end
70
70
  end
71
71
  end
72
+ thread.abort_on_exception = true
72
73
 
73
74
  Steep.logger.tagged "frontend" do
74
75
  begin
@@ -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(Pathname(URI.parse(request[:params][:textDocument][:uri]).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
- uri = URI.parse(request[:params][:textDocument][:uri])
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
- uri = URI.parse(params[:textDocument][:uri])
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
- hd, tail = locator.find2(line: job.line, column: job.column)
145
+ _hd, tail = locator.find2(line: job.line, column: job.column)
148
146
 
149
147
  namespace = []
150
148
  tail.each do |t|
@@ -21,9 +21,7 @@ module Steep
21
21
  end
22
22
 
23
23
  def uri(path)
24
- URI.parse(path.to_s).tap do |uri|
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 / total
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
- if Gem.win_platform?
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
- Pathname(URI.parse(uri).path)
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
- broadcast_notification(message)
528
- path = pathname(message[:params][:textDocument][:uri])
529
- controller.push_changes(path)
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 typecheck_automatically
533
- if request = controller.make_request(last_request: current_type_check_request)
534
- start_type_check(
535
- request,
536
- last_request: current_type_check_request,
537
- start_progress: request.total > 10
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
- controller.update_priority(open: path)
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
- controller.update_priority(close: path)
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
- result_controller << send_request(method: message[:method], params: message[:params], worker: interaction_worker) do |handler|
553
- handler.on_completion do |response|
554
- job_queue << SendMessageJob.to_client(
555
- message: {
556
- id: message[:id],
557
- result: response[:result]
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
- result_controller << group_request do |group|
598
- typecheck_workers.each do |worker|
599
- group << send_request(method: message[:method], params: message[:params], worker: worker)
600
- end
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
- group.on_completion do |handlers|
603
- links = handlers.flat_map(&:result)
604
- job_queue << SendMessageJob.to_client(
605
- message: {
606
- id: message[:id],
607
- result: links
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| Pathname(URI.parse(uri).path) })
90
- library_paths = params[:library_uris].map {|uri| Pathname(URI.parse(uri).path) }
91
- signature_paths = params[:signature_uris].map {|uri| Pathname(URI.parse(uri).path) }
92
- code_paths = params[:code_uris].map {|uri| Pathname(URI.parse(uri).path) }
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: URI.parse(job_path).tap {|uri| uri.scheme = "file"},
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: URI.parse(job_path).tap {|uri| uri.scheme = "file"},
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: URI.parse(job_path).tap {|uri| uri.scheme = "file"},
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: URI.parse(project.absolute_path(path).to_s).tap {|uri| uri.scheme = "file" },
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 = Pathname(URI.parse(job.params[:textDocument][:uri]).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: URI.parse(path.to_s).tap {|uri| uri.scheme = "file" }.to_s,
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
- InstanceVariableItem = Struct.new(:identifier, :range, :type, keyword_init: true)
12
- LocalVariableItem = Struct.new(:identifier, :range, :type, keyword_init: true)
13
- ConstantItem = Struct.new(:env, :identifier, :range, :type, :full_name, keyword_init: true) do
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.method_def&.comment
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, *parents = source.find_nodes(line: position.line, column: position.column)
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, *parents = source.find_nodes(line: shift_pos.line, column: shift_pos.column)
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 => exn
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.lvar_env.each do |name, type|
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.module_context.const_env.children(const_name)
391
+ consts = context.type_env.constant_env.children(const_name)
385
392
  end
386
393
  else
387
- consts = context.module_context.const_env.constants
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.ivar_types.map do |name, type|
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, signature = type_check_path(target: target, path: relative_path, content: source.content, line: line, column: column)
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
 
@@ -26,7 +26,7 @@ module Steep
26
26
  return if decls.nil?
27
27
 
28
28
  loc_key, path = ::RBS::Locator.new(decls: decls).find2(line: line, column: column) || return
29
- head, *tail = path
29
+ head, *_tail = path
30
30
 
31
31
  case head
32
32
  when ::RBS::Types::Alias
@@ -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 class_or_module?
13
- decl.decls.filter_map {|d| d.decl.comment }
14
- when constant?
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.lvar_env[var_name] || AST::Types::Any.new(location: nil)
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.lvar_env[var_name] || typing.type_of(node: rhs)
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
 
@@ -39,7 +39,6 @@ module Steep
39
39
  typed = 0
40
40
  untyped = 0
41
41
  errors = 0
42
- total = 0
43
42
  typing.method_calls.each_value do |call|
44
43
  case call
45
44
  when TypeInference::MethodCall::Typed