steep 1.10.0 → 2.0.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.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +84 -1
  3. data/CLAUDE.md +114 -0
  4. data/README.md +1 -1
  5. data/Rakefile +15 -3
  6. data/Steepfile +13 -13
  7. data/lib/steep/annotation_parser.rb +5 -1
  8. data/lib/steep/annotations_helper.rb +12 -2
  9. data/lib/steep/ast/node/type_application.rb +22 -16
  10. data/lib/steep/ast/node/type_assertion.rb +7 -4
  11. data/lib/steep/ast/types/factory.rb +3 -2
  12. data/lib/steep/cli.rb +246 -2
  13. data/lib/steep/daemon/configuration.rb +19 -0
  14. data/lib/steep/daemon/server.rb +476 -0
  15. data/lib/steep/daemon.rb +201 -0
  16. data/lib/steep/diagnostic/ruby.rb +50 -8
  17. data/lib/steep/diagnostic/signature.rb +31 -8
  18. data/lib/steep/drivers/check.rb +301 -140
  19. data/lib/steep/drivers/print_project.rb +9 -10
  20. data/lib/steep/drivers/query.rb +102 -0
  21. data/lib/steep/drivers/start_server.rb +19 -0
  22. data/lib/steep/drivers/stop_server.rb +20 -0
  23. data/lib/steep/drivers/watch.rb +2 -2
  24. data/lib/steep/index/rbs_index.rb +38 -13
  25. data/lib/steep/index/signature_symbol_provider.rb +24 -3
  26. data/lib/steep/interface/builder.rb +48 -15
  27. data/lib/steep/interface/shape.rb +13 -5
  28. data/lib/steep/locator.rb +377 -0
  29. data/lib/steep/project/dsl.rb +26 -5
  30. data/lib/steep/project/group.rb +8 -2
  31. data/lib/steep/project/target.rb +16 -2
  32. data/lib/steep/project.rb +21 -2
  33. data/lib/steep/server/base_worker.rb +2 -2
  34. data/lib/steep/server/change_buffer.rb +2 -1
  35. data/lib/steep/server/custom_methods.rb +12 -0
  36. data/lib/steep/server/inline_source_change_detector.rb +94 -0
  37. data/lib/steep/server/interaction_worker.rb +51 -74
  38. data/lib/steep/server/lsp_formatter.rb +48 -12
  39. data/lib/steep/server/master.rb +100 -18
  40. data/lib/steep/server/target_group_files.rb +124 -151
  41. data/lib/steep/server/type_check_controller.rb +276 -123
  42. data/lib/steep/server/type_check_worker.rb +104 -3
  43. data/lib/steep/services/completion_provider/rbs.rb +74 -0
  44. data/lib/steep/services/completion_provider/ruby.rb +652 -0
  45. data/lib/steep/services/completion_provider/type_name.rb +243 -0
  46. data/lib/steep/services/completion_provider.rb +39 -662
  47. data/lib/steep/services/content_change.rb +14 -1
  48. data/lib/steep/services/file_loader.rb +4 -2
  49. data/lib/steep/services/goto_service.rb +271 -68
  50. data/lib/steep/services/hover_provider/content.rb +67 -0
  51. data/lib/steep/services/hover_provider/rbs.rb +8 -9
  52. data/lib/steep/services/hover_provider/ruby.rb +123 -64
  53. data/lib/steep/services/hover_provider/singleton_methods.rb +4 -0
  54. data/lib/steep/services/signature_service.rb +129 -54
  55. data/lib/steep/services/type_check_service.rb +72 -27
  56. data/lib/steep/signature/validator.rb +30 -18
  57. data/lib/steep/source/ignore_ranges.rb +14 -4
  58. data/lib/steep/source.rb +16 -2
  59. data/lib/steep/tagged_logging.rb +39 -0
  60. data/lib/steep/type_construction.rb +94 -21
  61. data/lib/steep/type_inference/block_params.rb +7 -7
  62. data/lib/steep/type_inference/context.rb +4 -2
  63. data/lib/steep/type_inference/logic_type_interpreter.rb +21 -3
  64. data/lib/steep/type_inference/method_call.rb +4 -0
  65. data/lib/steep/type_inference/type_env.rb +1 -1
  66. data/lib/steep/typing.rb +0 -2
  67. data/lib/steep/version.rb +1 -1
  68. data/lib/steep.rb +42 -32
  69. data/manual/ruby-diagnostics.md +67 -0
  70. data/sample/Steepfile +1 -0
  71. data/sample/lib/conference.rb +1 -0
  72. data/sample/lib/deprecated.rb +6 -0
  73. data/sample/lib/inline.rb +43 -0
  74. data/sample/sig/generics.rbs +3 -0
  75. data/steep.gemspec +4 -5
  76. metadata +26 -26
  77. data/lib/steep/services/type_name_completion.rb +0 -236
@@ -0,0 +1,94 @@
1
+ module Steep
2
+ module Server
3
+ class InlineSourceChangeDetector
4
+ class Source
5
+ attr_reader :content
6
+ attr_reader :changes
7
+ attr_reader :last_fingerprint
8
+
9
+ def initialize(content)
10
+ @content = content
11
+ @changes = []
12
+ update_fingerprint!
13
+ end
14
+
15
+ def <<(changes)
16
+ @changes << changes
17
+ end
18
+
19
+ def updated?
20
+ if changes.empty?
21
+ return false
22
+ end
23
+
24
+ updated_content = changes.inject(content) do |current_content, change|
25
+ change.apply_to(current_content)
26
+ end
27
+ changes.clear
28
+
29
+ if updated_content == content
30
+ return false
31
+ end
32
+
33
+ @content = updated_content
34
+
35
+ update_fingerprint!
36
+ end
37
+
38
+ def update_fingerprint!
39
+ buffer = RBS::Buffer.new(name: Pathname("test.rb"), content: content)
40
+ prism = Prism.parse(content)
41
+ result = RBS::InlineParser.parse(buffer, prism)
42
+
43
+ new_fingerprint = result.type_fingerprint
44
+
45
+ (new_fingerprint != last_fingerprint).tap do
46
+ @last_fingerprint = new_fingerprint
47
+ end
48
+ end
49
+
50
+ def clear
51
+ @changes.clear
52
+ end
53
+ end
54
+
55
+ attr_reader :sources
56
+
57
+ def initialize
58
+ @sources = {}
59
+ end
60
+
61
+ def add_source(path, content)
62
+ sources.key?(path) and raise "Source already exists for #{path}"
63
+ sources[path] = Source.new(content)
64
+ end
65
+
66
+ def replace_source(path, content)
67
+ source = sources.fetch(path)
68
+ if source.content == content
69
+ source.clear
70
+ else
71
+ source << Services::ContentChange.string(content)
72
+ end
73
+ end
74
+
75
+ def accumulate_change(file_path, changes)
76
+ changes.each do |change|
77
+ sources.fetch(file_path) << change
78
+ end
79
+ end
80
+
81
+ def type_updated_paths(paths)
82
+ paths.select { sources[_1]&.updated? }.to_set
83
+ end
84
+
85
+ def has_source?(path)
86
+ sources.key?(path)
87
+ end
88
+
89
+ def reset
90
+ sources.each_value { _1.updated? }
91
+ end
92
+ end
93
+ end
94
+ end
@@ -154,19 +154,25 @@ module Steep
154
154
  Steep.logger.info "path: #{job.path}, line: #{job.line}, column: #{job.column}, trigger: #{job.trigger}"
155
155
 
156
156
  case
157
- when target = project.target_for_source_path(job.path)
157
+ when target = project.target_for_inline_source_path(job.path) || project.target_for_source_path(job.path)
158
158
  file = service.source_files[job.path] or return
159
159
  subtyping = service.signature_services.fetch(target.name).current_subtyping or return
160
160
 
161
- provider = Services::CompletionProvider.new(source_text: file.content, path: job.path, subtyping: subtyping)
162
- items = begin
163
- provider.run(line: job.line, column: job.column)
164
- rescue Parser::SyntaxError
165
- [] #: Array[Services::CompletionProvider::item]
166
- end
161
+ provider = Services::CompletionProvider::Ruby.new(source_text: file.content, path: job.path, subtyping: subtyping)
167
162
 
168
- completion_items = items.map do |item|
169
- format_completion_item(item)
163
+ if (prefix_size, items = provider.run_at_comment(line: job.line, column: job.column))
164
+ completion_items = items.map { format_completion_item(_1) }
165
+ completion_items.concat builtin_types(prefix_size, job.line, job.column)
166
+ else
167
+ items = begin
168
+ provider.run(line: job.line, column: job.column)
169
+ rescue Parser::SyntaxError
170
+ [] #: Array[Services::CompletionProvider::item]
171
+ end
172
+
173
+ completion_items = items.map do |item|
174
+ format_completion_item(item)
175
+ end
170
176
  end
171
177
 
172
178
  Steep.logger.debug "items = #{completion_items.inspect}"
@@ -179,71 +185,14 @@ module Steep
179
185
  sig_service = service.signature_services[target.name] or raise
180
186
  relative_path = job.path
181
187
 
182
- context = nil #: RBS::Resolver::context
188
+ completion = Services::CompletionProvider::RBS.new(relative_path, sig_service)
189
+ prefix_size, type_names = completion.run(job.line, job.column)
183
190
 
184
- case sig_service.status
185
- when Services::SignatureService::SyntaxErrorStatus, Services::SignatureService::AncestorErrorStatus
186
- if buffer = sig_service.latest_env.buffers.find {|buf| Pathname(buf.name) == Pathname(relative_path) }
187
- dirs = sig_service.latest_env.signatures.fetch(buffer)[0]
188
- else
189
- dirs = [] #: Array[RBS::AST::Directives::t]
190
- end
191
- else
192
- signature = sig_service.files.fetch(relative_path).signature
193
- signature.is_a?(Array) or raise
194
- buffer, dirs, decls = signature
195
-
196
- locator = RBS::Locator.new(buffer: buffer, dirs: dirs, decls: decls)
197
-
198
- _hd, tail = locator.find2(line: job.line, column: job.column)
199
- tail ||= [] #: Array[RBS::Locator::component]
200
-
201
- tail.reverse_each do |t|
202
- case t
203
- when RBS::AST::Declarations::Module, RBS::AST::Declarations::Class
204
- if (last_type_name = context&.[](1)).is_a?(RBS::TypeName)
205
- context = [context, last_type_name + t.name]
206
- else
207
- context = [context, t.name.absolute!]
208
- end
209
- end
210
- end
211
- end
212
-
213
- buffer = RBS::Buffer.new(name: relative_path, content: sig_service.files.fetch(relative_path).content)
214
- prefix = Services::TypeNameCompletion::Prefix.parse(buffer, line: job.line, column: job.column)
215
-
216
- completion = Services::TypeNameCompletion.new(env: sig_service.latest_env, context: context, dirs: dirs)
217
- type_names = completion.find_type_names(prefix)
218
- prefix_size = prefix ? prefix.size : 0
219
-
220
- completion_items = type_names.map do |type_name|
221
- absolute_name, relative_name = completion.resolve_name_in_context(type_name)
191
+ completion_items = type_names.map do |absolute_name, relative_name|
222
192
  format_completion_item_for_rbs(sig_service, absolute_name, job, relative_name.to_s, prefix_size)
223
193
  end
224
194
 
225
- ["untyped", "void", "bool", "class", "module", "instance", "nil"].each do |name|
226
- completion_items << LSP::Interface::CompletionItem.new(
227
- label: name,
228
- detail: "(builtin type)",
229
- text_edit: LSP::Interface::TextEdit.new(
230
- range: LSP::Interface::Range.new(
231
- start: LSP::Interface::Position.new(
232
- line: job.line - 1,
233
- character: job.column - prefix_size
234
- ),
235
- end: LSP::Interface::Position.new(
236
- line: job.line - 1,
237
- character: job.column
238
- )
239
- ),
240
- new_text: name
241
- ),
242
- kind: LSP::Constant::CompletionItemKind::KEYWORD,
243
- filter_text: name,
244
- sort_text: "zz__#{name}"
245
- )
246
- end
195
+ completion_items.concat(builtin_types(prefix_size, job.line, job.column))
247
196
 
248
197
  LSP::Interface::CompletionList.new(
249
198
  is_incomplete: !sig_service.status.is_a?(Services::SignatureService::LoadedStatus),
@@ -280,10 +229,13 @@ module Steep
280
229
 
281
230
  case class_entry
282
231
  when RBS::Environment::ClassEntry, RBS::Environment::ModuleEntry
283
- comments = class_entry.decls.map {|decl| decl.decl.comment }.compact
284
- decl = class_entry.primary.decl
232
+ comments = class_entry.each_decl.map {|decl| decl.is_a?(RBS::AST::Declarations::Base) ? decl.comment : nil }.compact
233
+ decl = class_entry.primary_decl
285
234
  when RBS::Environment::ClassAliasEntry, RBS::Environment::ModuleAliasEntry
286
- comments = [class_entry.decl.comment].compact
235
+ comments = [] #: Array[RBS::AST::Comment]
236
+ if comment = class_entry.decl.comment
237
+ comments << comment
238
+ end
287
239
  decl = class_entry.decl
288
240
  end
289
241
 
@@ -476,7 +428,7 @@ module Steep
476
428
 
477
429
  def process_signature_help(job)
478
430
  Steep.logger.tagged("##{__method__}") do
479
- if target = project.target_for_source_path(job.path)
431
+ if target = project.target_for_inline_source_path(job.path) || project.target_for_source_path(job.path)
480
432
  file = service.source_files[job.path] or return
481
433
  subtyping = service.signature_services.fetch(target.name).current_subtyping or return
482
434
  source =
@@ -514,6 +466,31 @@ module Steep
514
466
  # Reuse the latest result to keep SignatureHelp opened while typing
515
467
  @last_signature_help_result if @last_signature_help_line == job.line
516
468
  end
469
+
470
+ def builtin_types(prefix_size, line, column)
471
+ ["untyped", "void", "bool", "class", "module", "instance", "nil", "top", "bot"].map do |name|
472
+ LSP::Interface::CompletionItem.new(
473
+ label: name,
474
+ detail: "(builtin type)",
475
+ text_edit: LSP::Interface::TextEdit.new(
476
+ range: LSP::Interface::Range.new(
477
+ start: LSP::Interface::Position.new(
478
+ line: line - 1,
479
+ character: column - prefix_size
480
+ ),
481
+ end: LSP::Interface::Position.new(
482
+ line: line - 1,
483
+ character: column
484
+ )
485
+ ),
486
+ new_text: name
487
+ ),
488
+ kind: LSP::Constant::CompletionItemKind::KEYWORD,
489
+ filter_text: name,
490
+ sort_text: "zz__#{name}"
491
+ )
492
+ end
493
+ end
517
494
  end
518
495
  end
519
496
  end
@@ -19,10 +19,10 @@ module Steep
19
19
 
20
20
  def format_hover_content(content)
21
21
  case content
22
- when HoverProvider::Ruby::VariableContent
22
+ when HoverProvider::VariableContent
23
23
  local_variable(content.name, content.type)
24
24
 
25
- when HoverProvider::Ruby::MethodCallContent
25
+ when HoverProvider::MethodCallContent
26
26
  io = StringIO.new
27
27
  call = content.method_call
28
28
 
@@ -76,7 +76,7 @@ module Steep
76
76
 
77
77
  io.string
78
78
 
79
- when HoverProvider::Ruby::DefinitionContent
79
+ when HoverProvider::DefinitionContent
80
80
  io = StringIO.new
81
81
 
82
82
  method_name =
@@ -115,13 +115,13 @@ module Steep
115
115
  )
116
116
 
117
117
  io.string
118
- when HoverProvider::Ruby::ConstantContent
118
+ when HoverProvider::ConstantContent
119
119
  io = StringIO.new
120
120
 
121
121
  decl_summary =
122
122
  case
123
123
  when decl = content.class_decl
124
- declaration_summary(decl.primary.decl)
124
+ declaration_summary(decl.primary_decl)
125
125
  when decl = content.constant_decl
126
126
  declaration_summary(decl.decl)
127
127
  when decl = content.class_alias
@@ -144,14 +144,14 @@ module Steep
144
144
  end
145
145
 
146
146
  io.string
147
- when HoverProvider::Ruby::TypeContent
147
+ when HoverProvider::TypeContent
148
148
  <<~MD
149
149
  ```rbs
150
150
  #{content.type}
151
151
  ```
152
152
  MD
153
153
 
154
- when HoverProvider::Ruby::TypeAssertionContent
154
+ when HoverProvider::TypeAssertionContent
155
155
  <<~MD
156
156
  ```rbs
157
157
  #{content.asserted_type}
@@ -160,7 +160,7 @@ module Steep
160
160
  ↑ Converted from `#{content.original_type.to_s}`
161
161
  MD
162
162
 
163
- when HoverProvider::RBS::TypeAliasContent, HoverProvider::RBS::InterfaceContent
163
+ when HoverProvider::TypeAliasContent, HoverProvider::InterfaceTypeContent
164
164
  io = StringIO.new()
165
165
 
166
166
  io.puts <<~MD
@@ -178,7 +178,7 @@ module Steep
178
178
 
179
179
  io.string
180
180
 
181
- when HoverProvider::RBS::ClassContent
181
+ when HoverProvider::ClassTypeContent
182
182
  io = StringIO.new
183
183
 
184
184
  io << <<~MD
@@ -187,7 +187,15 @@ module Steep
187
187
  ```
188
188
  MD
189
189
 
190
- if content.decl.comment
190
+ comment =
191
+ case content.decl
192
+ when RBS::AST::Declarations::Base
193
+ content.decl.comment
194
+ when RBS::AST::Ruby::Declarations::Base
195
+ nil
196
+ end
197
+
198
+ if comment
191
199
  io.puts "----"
192
200
 
193
201
  class_name =
@@ -235,10 +243,24 @@ module Steep
235
243
  when Services::CompletionProvider::InstanceVariableItem
236
244
  instance_variable(item.identifier, item.type)
237
245
  when Services::CompletionProvider::SimpleMethodNameItem
238
- format_method_item_doc(item.method_types, [], { item.method_name => item.method_member.comment })
246
+ item_comment =
247
+ case item.method_member
248
+ when RBS::AST::Members::Base
249
+ item.method_member.comment
250
+ when RBS::AST::Ruby::Members::Base
251
+ nil
252
+ end
253
+ format_method_item_doc(item.method_types, [], { item.method_name => item_comment })
239
254
  when Services::CompletionProvider::ComplexMethodNameItem
240
255
  method_names = item.method_names.map(&:relative).uniq
241
- comments = item.method_definitions.transform_values {|member| member.comment }
256
+ comments = item.method_definitions.transform_values do |member|
257
+ case member
258
+ when RBS::AST::Members::Base
259
+ member.comment
260
+ when RBS::AST::Ruby::Members::Base
261
+ nil
262
+ end
263
+ end
242
264
  format_method_item_doc(item.method_types, method_names, comments)
243
265
  when Services::CompletionProvider::GeneratedMethodNameItem
244
266
  format_method_item_doc(item.method_types, [], {}, "🤖 Generated method for receiver type")
@@ -419,6 +441,20 @@ module Steep
419
441
  "#{decl.name}: #{decl.type}"
420
442
  when RBS::AST::Declarations::Constant
421
443
  "#{decl.name.relative!}: #{decl.type}"
444
+ when RBS::AST::Ruby::Declarations::ClassDecl
445
+ "class #{decl.class_name.relative!}"
446
+ when RBS::AST::Ruby::Declarations::ModuleDecl
447
+ "module #{decl.module_name.relative!}"
448
+ when RBS::AST::Ruby::Declarations::ConstantDecl
449
+ "#{decl.constant_name.relative!}: #{decl.type}"
450
+ when RBS::AST::Ruby::Declarations::ClassModuleAliasDecl
451
+ keyword =
452
+ if decl.annotation.is_a?(RBS::AST::Ruby::Annotations::ClassAliasAnnotation)
453
+ "class"
454
+ else
455
+ "module"
456
+ end
457
+ "#{keyword} #{decl.new_name} = #{decl.old_name}"
422
458
  end
423
459
  end
424
460
 
@@ -207,14 +207,14 @@ module Steep
207
207
 
208
208
  def start
209
209
  Steep.logger.tagged "master" do
210
- tags = Steep.logger.formatter.current_tags.dup
210
+ tags = Steep.logger.current_tags.dup
211
211
 
212
212
  # @type var worker_threads: Array[Thread]
213
213
  worker_threads = []
214
214
 
215
215
  if interaction_worker
216
216
  worker_threads << Thread.new do
217
- Steep.logger.formatter.push_tags(*tags, "from-worker@interaction")
217
+ Steep.logger.push_tags(*tags, "from-worker@interaction")
218
218
  interaction_worker.reader.read do |message|
219
219
  job_queue << ReceiveMessageJob.new(source: interaction_worker, message: message)
220
220
  end
@@ -223,7 +223,7 @@ module Steep
223
223
 
224
224
  typecheck_workers.each do |worker|
225
225
  worker_threads << Thread.new do
226
- Steep.logger.formatter.push_tags(*tags, "from-worker@#{worker.name}")
226
+ Steep.logger.push_tags(*tags, "from-worker@#{worker.name}")
227
227
  worker.reader.read do |message|
228
228
  job_queue << ReceiveMessageJob.new(source: worker, message: message)
229
229
  end
@@ -238,7 +238,7 @@ module Steep
238
238
  end
239
239
 
240
240
  write_thread = Thread.new do
241
- Steep.logger.formatter.push_tags(*tags)
241
+ Steep.logger.push_tags(*tags)
242
242
  Steep.logger.tagged "write" do
243
243
  while job = write_queue.deq
244
244
  # @type var job: SendMessageJob
@@ -257,7 +257,7 @@ module Steep
257
257
  end
258
258
 
259
259
  loop_thread = Thread.new do
260
- Steep.logger.formatter.push_tags(*tags)
260
+ Steep.logger.push_tags(*tags)
261
261
  Steep.logger.tagged "main" do
262
262
  while job = job_queue.deq
263
263
  case job
@@ -408,7 +408,8 @@ module Steep
408
408
  if content.valid_encoding?
409
409
  content
410
410
  else
411
- { text: Base64.encode64(content), binary: true }
411
+ base64_encoded = [content].pack("m")
412
+ { text: base64_encoded, binary: true }
412
413
  end
413
414
  end
414
415
  broadcast_notification(CustomMethods::FileLoad.notification({ content: input }))
@@ -423,7 +424,7 @@ module Steep
423
424
  setup_file_system_watcher()
424
425
  end
425
426
 
426
- controller.changed_paths.clear()
427
+ # controller.changed_paths.clear()
427
428
 
428
429
  # if typecheck_automatically
429
430
  # if request = controller.make_request(guid: progress.guid, include_unchanged: true, progress: progress)
@@ -442,11 +443,9 @@ module Steep
442
443
 
443
444
  path = PathHelper.to_pathname!(uri)
444
445
 
445
- unless controller.priority_paths.include?(path)
446
+ unless controller.open_paths.include?(path)
446
447
  updated_watched_files << path
447
448
 
448
- controller.push_changes(path)
449
-
450
449
  case type
451
450
  when LSP::Constant::FileChangeType::CREATED, LSP::Constant::FileChangeType::CHANGED
452
451
  content = path.read
@@ -456,6 +455,15 @@ module Steep
456
455
 
457
456
  content or raise
458
457
 
458
+ case
459
+ when controller.code_path?(path)
460
+ controller.add_dirty_code_path(path)
461
+ when controller.signature_path?(path)
462
+ controller.add_dirty_signature_path(path)
463
+ when controller.inline_path?(path)
464
+ controller.add_dirty_inline_path(path, content)
465
+ end
466
+
459
467
  broadcast_notification(CustomMethods::FileReset.notification({ uri: uri, content: content }))
460
468
  end
461
469
  end
@@ -485,7 +493,21 @@ module Steep
485
493
  when "textDocument/didChange"
486
494
  if path = pathname(message[:params][:textDocument][:uri])
487
495
  broadcast_notification(message)
488
- controller.push_changes(path)
496
+
497
+ Steep.logger.debug { path.to_s }
498
+
499
+ case
500
+ when controller.code_path?(path)
501
+ Steep.logger.debug { "code_path?" }
502
+ controller.add_dirty_code_path(path)
503
+ when controller.signature_path?(path)
504
+ Steep.logger.debug { "signature_path?" }
505
+ controller.add_dirty_signature_path(path)
506
+ when controller.inline_path?(path)
507
+ Steep.logger.debug { "inline_path?" }
508
+ changes = Services::ContentChange.from_lsp(message[:params][:contentChanges])
509
+ controller.add_dirty_inline_path(path, changes)
510
+ end
489
511
 
490
512
  if typecheck_automatically
491
513
  start_type_checking_queue.execute do
@@ -513,7 +535,12 @@ module Steep
513
535
 
514
536
  if path = pathname(uri)
515
537
  if target = project.group_for_path(path)
516
- controller.update_priority(open: path)
538
+ if controller.inline_path?(path)
539
+ controller.open_inline_path(path, text)
540
+ else
541
+ controller.open_path(path)
542
+ end
543
+
517
544
  # broadcast_notification(CustomMethods::FileReset.notification({ uri: uri, content: text }))
518
545
 
519
546
  start_type_checking_queue.execute do
@@ -525,7 +552,7 @@ module Steep
525
552
 
526
553
  when "textDocument/didClose"
527
554
  if path = pathname(message[:params][:textDocument][:uri])
528
- controller.update_priority(close: path)
555
+ controller.close_path(path)
529
556
  end
530
557
 
531
558
  when "textDocument/hover", "textDocument/completion", "textDocument/signatureHelp"
@@ -605,6 +632,38 @@ module Steep
605
632
  )
606
633
  end
607
634
 
635
+ when CustomMethods::Query__Definition::METHOD
636
+ params = message[:params] #: CustomMethods::Query__Definition::params
637
+ result_controller << group_request do |group|
638
+ typecheck_workers.each do |worker|
639
+ group << send_request(method: CustomMethods::Query__Definition::METHOD, params: params, worker: worker)
640
+ end
641
+
642
+ group.on_completion do |handlers|
643
+ kind = "unknown" #: CustomMethods::Query__Definition::kind
644
+ locations = [] #: Array[CustomMethods::Query__Definition::location]
645
+
646
+ handlers.each do |handler|
647
+ result = handler.result #: CustomMethods::Query__Definition::result
648
+ next unless result
649
+
650
+ if kind == "unknown"
651
+ kind = result[:kind]
652
+ end
653
+ locations.concat(result[:locations])
654
+ end
655
+
656
+ locations.uniq!
657
+
658
+ enqueue_write_job SendMessageJob.to_client(
659
+ message: CustomMethods::Query__Definition.response(
660
+ message[:id],
661
+ { name: params[:name], kind: kind, locations: locations }
662
+ )
663
+ )
664
+ end
665
+ end
666
+
608
667
  when CustomMethods::TypeCheck::METHOD
609
668
  id = message[:id]
610
669
  params = message[:params] #: CustomMethods::TypeCheck::params
@@ -621,6 +680,9 @@ module Steep
621
680
  params[:library_paths].each do |target_name, path|
622
681
  request.library_paths << [target_name.to_sym, Pathname(path)]
623
682
  end
683
+ params[:inline_paths].each do |target_name, path|
684
+ request.inline_paths << [target_name.to_sym, Pathname(path)]
685
+ end
624
686
 
625
687
  start_type_check(request: request, last_request: nil)
626
688
 
@@ -632,7 +694,12 @@ module Steep
632
694
  progress = work_done_progress(SecureRandom.uuid)
633
695
  progress.begin("Type checking #{groups.empty? ? "project" : groups.join(", ")}", request_id: fresh_request_id)
634
696
 
635
- request = controller.make_group_request(groups, progress: progress)
697
+ if groups.empty?
698
+ request = controller.make_all_request(progress: progress)
699
+ else
700
+ request = controller.make_group_request(groups, progress: progress)
701
+ end
702
+
636
703
  request.needs_response = false
637
704
  start_type_check(request: request, last_request: current_type_check_request, report_progress_threshold: 0)
638
705
 
@@ -744,7 +811,14 @@ module Steep
744
811
 
745
812
  unless request
746
813
  progress or raise
747
- request = controller.make_request(guid: progress.guid, include_unchanged: include_unchanged, progress: progress) or return
814
+ request =
815
+ if include_unchanged
816
+ controller.make_all_request(guid: progress.guid, progress: progress)
817
+ else
818
+ controller.make_request(guid: progress.guid, progress: progress)
819
+ end
820
+ return unless request
821
+
748
822
  request.needs_response = needs_response ? true : false
749
823
  end
750
824
 
@@ -752,6 +826,14 @@ module Steep
752
826
  request.merge!(last_request)
753
827
  end
754
828
 
829
+ Steep.logger.debug {
830
+ {
831
+ code_paths: request.code_paths.map { _1[1].to_s },
832
+ signature_paths: request.signature_paths.map { _1[1].to_s },
833
+ inline_paths: request.inline_paths.map { _1[1].to_s }
834
+ }.inspect
835
+ }
836
+
755
837
  if request.total > report_progress_threshold
756
838
  request.report_progress!
757
839
  end
@@ -854,8 +936,8 @@ module Steep
854
936
  end
855
937
 
856
938
  Thread.new do
857
- tags = Steep.logger.formatter.current_tags.dup
858
- Steep.logger.formatter.push_tags(*tags, "from-worker@#{new_worker.name}")
939
+ tags = Steep.logger.current_tags.dup
940
+ Steep.logger.push_tags(*tags, "from-worker@#{new_worker.name}")
859
941
  new_worker.reader.read do |message|
860
942
  job_queue << ReceiveMessageJob.new(source: new_worker, message: message)
861
943
  end
@@ -936,7 +1018,7 @@ module Steep
936
1018
 
937
1019
  def enqueue_write_job(job)
938
1020
  Steep.logger.info { "Write_queue has #{write_queue.size} items"}
939
- write_queue.push(job) # steep:ignore InsufficientKeywordArguments
1021
+ write_queue.push(job)
940
1022
  end
941
1023
 
942
1024
  def work_done_progress(guid)