steep 1.8.2 → 1.9.0.dev.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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +0 -12
  3. data/Steepfile +0 -14
  4. data/lib/steep/cli.rb +47 -5
  5. data/lib/steep/diagnostic/ruby.rb +1 -58
  6. data/lib/steep/drivers/annotations.rb +1 -1
  7. data/lib/steep/drivers/check.rb +107 -1
  8. data/lib/steep/drivers/checkfile.rb +10 -8
  9. data/lib/steep/drivers/print_project.rb +83 -40
  10. data/lib/steep/drivers/utils/driver_helper.rb +5 -3
  11. data/lib/steep/drivers/watch.rb +24 -2
  12. data/lib/steep/index/signature_symbol_provider.rb +8 -8
  13. data/lib/steep/interface/builder.rb +14 -1
  14. data/lib/steep/interface/function.rb +2 -2
  15. data/lib/steep/path_helper.rb +4 -2
  16. data/lib/steep/project/dsl.rb +176 -151
  17. data/lib/steep/project/group.rb +31 -0
  18. data/lib/steep/project/target.rb +32 -6
  19. data/lib/steep/project.rb +38 -10
  20. data/lib/steep/server/delay_queue.rb +0 -3
  21. data/lib/steep/server/interaction_worker.rb +2 -11
  22. data/lib/steep/server/master.rb +95 -281
  23. data/lib/steep/server/target_group_files.rb +205 -0
  24. data/lib/steep/server/type_check_controller.rb +322 -0
  25. data/lib/steep/server/type_check_worker.rb +60 -86
  26. data/lib/steep/services/file_loader.rb +23 -0
  27. data/lib/steep/services/goto_service.rb +40 -31
  28. data/lib/steep/services/hover_provider/singleton_methods.rb +4 -4
  29. data/lib/steep/services/path_assignment.rb +23 -4
  30. data/lib/steep/services/type_check_service.rb +76 -159
  31. data/lib/steep/signature/validator.rb +4 -4
  32. data/lib/steep/subtyping/check.rb +2 -2
  33. data/lib/steep/thread_waiter.rb +24 -16
  34. data/lib/steep/type_construction.rb +5 -5
  35. data/lib/steep/type_inference/block_params.rb +1 -2
  36. data/lib/steep/type_inference/context.rb +1 -1
  37. data/lib/steep/type_inference/type_env.rb +4 -4
  38. data/lib/steep/type_inference/type_env_builder.rb +1 -1
  39. data/lib/steep/version.rb +1 -1
  40. data/lib/steep.rb +6 -4
  41. data/sample/Steepfile +6 -0
  42. data/sample/lib/conference.rb +1 -5
  43. data/steep.gemspec +7 -1
  44. metadata +8 -6
  45. data/lib/steep/drivers/validate.rb +0 -65
@@ -8,9 +8,9 @@ module Steep
8
8
  WorkspaceSymbolJob = _ = Struct.new(:query, :id, keyword_init: true)
9
9
  StatsJob = _ = Struct.new(:id, keyword_init: true)
10
10
  StartTypeCheckJob = _ = Struct.new(:guid, :changes, keyword_init: true)
11
- TypeCheckCodeJob = _ = Struct.new(:guid, :path, keyword_init: true)
12
- ValidateAppSignatureJob = _ = Struct.new(:guid, :path, keyword_init: true)
13
- ValidateLibrarySignatureJob = _ = Struct.new(:guid, :path, keyword_init: true)
11
+ TypeCheckCodeJob = _ = Struct.new(:guid, :path, :target, keyword_init: true)
12
+ ValidateAppSignatureJob = _ = Struct.new(:guid, :path, :target, keyword_init: true)
13
+ ValidateLibrarySignatureJob = _ = Struct.new(:guid, :path, :target, keyword_init: true)
14
14
  class GotoJob < Struct.new(:id, :kind, :params, keyword_init: true)
15
15
  def self.implementation(id:, params:)
16
16
  new(
@@ -111,51 +111,47 @@ module Steep
111
111
  queue << StartTypeCheckJob.new(guid: guid, changes: changes)
112
112
  end
113
113
 
114
- priority_paths = Set.new(params[:priority_uris].map {|uri| Steep::PathHelper.to_pathname(uri) || raise })
115
- library_paths = params[:library_uris].map {|uri| Steep::PathHelper.to_pathname(uri) || raise }
116
- signature_paths = params[:signature_uris].map {|uri| Steep::PathHelper.to_pathname(uri) || raise }
117
- code_paths = params[:code_uris].map {|uri| Steep::PathHelper.to_pathname(uri) || raise }
114
+ targets = project.targets.each.with_object({}) do |target, hash| #$ Hash[String, Project::Target]
115
+ hash[target.name.to_s] = target
116
+ end
118
117
 
119
- library_paths.each do |path|
120
- if priority_paths.include?(path)
121
- Steep.logger.info { "Enqueueing ValidateLibrarySignatureJob for guid=#{guid}, path=#{path}" }
122
- queue << ValidateLibrarySignatureJob.new(guid: guid, path: path)
123
- end
118
+ priority_paths = Set.new(params[:priority_uris].map {|uri| Steep::PathHelper.to_pathname!(uri) })
119
+ libraries = params[:library_uris].map {|target_name, uri| [targets.fetch(target_name), Steep::PathHelper.to_pathname!(uri)] } #: Array[[Project::Target, Pathname]]
120
+ signatures = params[:signature_uris].map {|target_name, uri| [targets.fetch(target_name), Steep::PathHelper.to_pathname!(uri)] } #: Array[[Project::Target, Pathname]]
121
+ codes = params[:code_uris].map {|target_name, uri| [targets.fetch(target_name), Steep::PathHelper.to_pathname!(uri)] } #: Array[[Project::Target, Pathname]]
122
+
123
+ priority_libs, non_priority_libs = libraries.partition {|_, path| priority_paths.include?(path) }
124
+ priority_sigs, non_priority_sigs = signatures.partition {|_, path| priority_paths.include?(path) }
125
+ priority_codes, non_priority_codes = codes.partition {|_, path| priority_paths.include?(path) }
126
+
127
+ priority_codes.each do |target, path|
128
+ Steep.logger.info { "Enqueueing TypeCheckCodeJob for guid=#{guid}, path=#{path}, target=#{target.name}" }
129
+ queue << TypeCheckCodeJob.new(guid: guid, path: path, target: target)
124
130
  end
125
131
 
126
- code_paths.each do |path|
127
- if priority_paths.include?(path)
128
- Steep.logger.info { "Enqueueing TypeCheckCodeJob for guid=#{guid}, path=#{path}" }
129
- queue << TypeCheckCodeJob.new(guid: guid, path: path)
130
- end
132
+ priority_sigs.each do |target, path|
133
+ Steep.logger.info { "Enqueueing ValidateAppSignatureJob for guid=#{guid}, path=#{path}, target=#{target.name}" }
134
+ queue << ValidateAppSignatureJob.new(guid: guid, path: path, target: target)
131
135
  end
132
136
 
133
- signature_paths.each do |path|
134
- if priority_paths.include?(path)
135
- Steep.logger.info { "Enqueueing ValidateAppSignatureJob for guid=#{guid}, path=#{path}" }
136
- queue << ValidateAppSignatureJob.new(guid: guid, path: path)
137
- end
137
+ priority_libs.each do |target, path|
138
+ Steep.logger.info { "Enqueueing ValidateLibrarySignatureJob for guid=#{guid}, path=#{path}, target=#{target.name}" }
139
+ queue << ValidateLibrarySignatureJob.new(guid: guid, path: path, target: target)
138
140
  end
139
141
 
140
- library_paths.each do |path|
141
- unless priority_paths.include?(path)
142
- Steep.logger.info { "Enqueueing ValidateLibrarySignatureJob for guid=#{guid}, path=#{path}" }
143
- queue << ValidateLibrarySignatureJob.new(guid: guid, path: path)
144
- end
142
+ non_priority_codes.each do |target, path|
143
+ Steep.logger.info { "Enqueueing TypeCheckCodeJob for guid=#{guid}, path=#{path}, target=#{target.name}" }
144
+ queue << TypeCheckCodeJob.new(guid: guid, path: path, target: target)
145
145
  end
146
146
 
147
- code_paths.each do |path|
148
- unless priority_paths.include?(path)
149
- Steep.logger.info { "Enqueueing TypeCheckCodeJob for guid=#{guid}, path=#{path}" }
150
- queue << TypeCheckCodeJob.new(guid: guid, path: path)
151
- end
147
+ non_priority_sigs.each do |target, path|
148
+ Steep.logger.info { "Enqueueing ValidateAppSignatureJob for guid=#{guid}, path=#{path}, target=#{target.name}" }
149
+ queue << ValidateAppSignatureJob.new(guid: guid, path: path, target: target)
152
150
  end
153
151
 
154
- signature_paths.each do |path|
155
- unless priority_paths.include?(path)
156
- Steep.logger.info { "Enqueueing ValidateAppSignatureJob for guid=#{guid}, path=#{path}" }
157
- queue << ValidateAppSignatureJob.new(guid: guid, path: path)
158
- end
152
+ non_priority_libs.each do |target, path|
153
+ Steep.logger.info { "Enqueueing ValidateLibrarySignatureJob for guid=#{guid}, path=#{path}, target=#{target.name}" }
154
+ queue << ValidateLibrarySignatureJob.new(guid: guid, path: path, target: target)
159
155
  end
160
156
  end
161
157
 
@@ -168,60 +164,37 @@ module Steep
168
164
  when ValidateAppSignatureJob
169
165
  if job.guid == current_type_check_guid
170
166
  Steep.logger.info { "Processing ValidateAppSignature for guid=#{job.guid}, path=#{job.path}" }
171
- service.validate_signature(path: project.relative_path(job.path)) do |path, diagnostics|
172
- formatter = Diagnostic::LSPFormatter.new({}, **{})
173
-
174
- writer.write(
175
- method: :"textDocument/publishDiagnostics",
176
- params: LSP::Interface::PublishDiagnosticsParams.new(
177
- uri: Steep::PathHelper.to_uri(job.path).to_s,
178
- diagnostics: diagnostics.map {|diagnostic|
179
- _ = formatter.format(diagnostic)
180
- }.uniq
181
- )
182
- )
183
- end
184
167
 
185
- typecheck_progress(path: job.path, guid: job.guid)
168
+ formatter = Diagnostic::LSPFormatter.new({}, **{})
169
+
170
+ diagnostics = service.validate_signature(path: project.relative_path(job.path), target: job.target)
171
+
172
+ typecheck_progress(
173
+ path: job.path,
174
+ guid: job.guid,
175
+ target: job.target,
176
+ diagnostics: diagnostics.filter_map { formatter.format(_1) }
177
+ )
186
178
  end
187
179
 
188
180
  when ValidateLibrarySignatureJob
189
181
  if job.guid == current_type_check_guid
190
182
  Steep.logger.info { "Processing ValidateLibrarySignature for guid=#{job.guid}, path=#{job.path}" }
191
- service.validate_signature(path: job.path) do |path, diagnostics|
192
- formatter = Diagnostic::LSPFormatter.new({}, **{})
193
-
194
- writer.write(
195
- method: :"textDocument/publishDiagnostics",
196
- params: LSP::Interface::PublishDiagnosticsParams.new(
197
- uri: Steep::PathHelper.to_uri(job.path).to_s,
198
- diagnostics: diagnostics.map {|diagnostic| _ = formatter.format(diagnostic) }.uniq.compact
199
- )
200
- )
201
- end
202
183
 
203
- typecheck_progress(path: job.path, guid: job.guid)
184
+ formatter = Diagnostic::LSPFormatter.new({}, **{})
185
+ diagnostics = service.validate_signature(path: job.path, target: job.target)
186
+
187
+ typecheck_progress(path: job.path, guid: job.guid, target: job.target, diagnostics: diagnostics.filter_map { formatter.format(_1) })
204
188
  end
205
189
 
206
190
  when TypeCheckCodeJob
207
191
  if job.guid == current_type_check_guid
208
- Steep.logger.info { "Processing TypeCheckCodeJob for guid=#{job.guid}, path=#{job.path}" }
209
- service.typecheck_source(path: project.relative_path(job.path)) do |path, diagnostics|
210
- target = project.target_for_source_path(path)
211
- formatter = Diagnostic::LSPFormatter.new(target&.code_diagnostics_config || {})
212
-
213
- writer.write(
214
- method: :"textDocument/publishDiagnostics",
215
- params: LSP::Interface::PublishDiagnosticsParams.new(
216
- uri: Steep::PathHelper.to_uri(job.path).to_s,
217
- diagnostics: diagnostics.map {|diagnostic|
218
- _ = formatter.format(diagnostic)
219
- }.uniq.compact
220
- )
221
- )
222
- end
223
-
224
- typecheck_progress(path: job.path, guid: job.guid)
192
+ Steep.logger.info { "Processing TypeCheckCodeJob for guid=#{job.guid}, path=#{job.path}, target=#{job.target.name}" }
193
+ group_target = project.group_for_source_path(job.path) || job.target
194
+ formatter = Diagnostic::LSPFormatter.new(group_target.code_diagnostics_config)
195
+ relative_path = project.relative_path(job.path)
196
+ diagnostics = service.typecheck_source(path: relative_path, target: job.target)
197
+ typecheck_progress(path: job.path, guid: job.guid, target: job.target, diagnostics: diagnostics&.filter_map { formatter.format(_1) })
225
198
  end
226
199
 
227
200
  when WorkspaceSymbolJob
@@ -242,16 +215,17 @@ module Steep
242
215
  end
243
216
  end
244
217
 
245
- def typecheck_progress(guid:, path:)
246
- writer.write(CustomMethods::TypeCheck__Progress.notification({ guid: guid, path: path.to_s }))
218
+ def typecheck_progress(guid:, path:, target:, diagnostics:)
219
+ writer.write(CustomMethods::TypeCheck__Progress.notification({ guid: guid, path: path.to_s, target: target.name.to_s, diagnostics: diagnostics }))
247
220
  end
248
221
 
249
222
  def workspace_symbol_result(query)
250
223
  Steep.measure "Generating workspace symbol list for query=`#{query}`" do
251
- indexes = project.targets.map {|target| service.signature_services[target.name].latest_rbs_index }
252
-
253
224
  provider = Index::SignatureSymbolProvider.new(project: project, assignment: assignment)
254
- provider.indexes.push(*indexes)
225
+ project.targets.each do |target|
226
+ index = service.signature_services[target.name].latest_rbs_index
227
+ provider.indexes[target] = index
228
+ end
255
229
 
256
230
  symbols = provider.query_symbol(query)
257
231
 
@@ -282,7 +256,7 @@ module Steep
282
256
  service.source_files.each_value do |file|
283
257
  next unless target.possible_source_file?(file.path)
284
258
  absolute_path = project.absolute_path(file.path)
285
- next unless assignment =~ absolute_path
259
+ next unless assignment =~ [target, absolute_path]
286
260
 
287
261
  stats << calculator.calc_stats(target, file: file)
288
262
  end
@@ -7,6 +7,29 @@ module Steep
7
7
  @base_dir = base_dir
8
8
  end
9
9
 
10
+ def each_path_in_target(target, command_line_patterns = [], &block)
11
+ if block
12
+ done = Set[] #: Set[Pathname]
13
+
14
+ handler = -> (path) do
15
+ unless done.include?(path)
16
+ done << path
17
+ yield path
18
+ end
19
+ end
20
+
21
+ target.groups.each do |group|
22
+ each_path_in_patterns(group.source_pattern, command_line_patterns, &handler)
23
+ each_path_in_patterns(group.signature_pattern, &handler)
24
+ end
25
+
26
+ each_path_in_patterns(target.source_pattern, command_line_patterns, &handler)
27
+ each_path_in_patterns(target.signature_pattern, &handler)
28
+ else
29
+ enum_for :each_path_in_target, target, command_line_patterns
30
+ end
31
+ end
32
+
10
33
  def each_path_in_patterns(pattern, commandline_patterns = [])
11
34
  if block_given?
12
35
  pats = commandline_patterns.empty? ? pattern.patterns : commandline_patterns
@@ -34,7 +34,7 @@ module Steep
34
34
  end
35
35
 
36
36
  def implementation(path:, line:, column:)
37
- locations = [] #: Array[loc]
37
+ locations = [] #: Array[target_loc]
38
38
 
39
39
  queries = query_at(path: path, line: line, column: column)
40
40
  queries.uniq!
@@ -46,15 +46,15 @@ module Steep
46
46
  when MethodQuery
47
47
  method_locations(query.name, locations: locations, in_ruby: true, in_rbs: false)
48
48
  when TypeNameQuery
49
- type_name_locations(query.name, locations: locations)
49
+ constant_definition_in_ruby(query.name, locations: locations)
50
50
  end
51
51
  end
52
52
 
53
- locations.uniq
53
+ locations.map { _1[1] }.uniq
54
54
  end
55
55
 
56
56
  def definition(path:, line:, column:)
57
- locations = [] #: Array[loc]
57
+ locations = [] #: Array[target_loc]
58
58
 
59
59
  queries = query_at(path: path, line: line, column: column)
60
60
  queries.uniq!
@@ -79,22 +79,24 @@ module Steep
79
79
  # Drop un-assigned paths here.
80
80
  # The path assignment makes sense only for `.rbs` files, because un-assigned `.rb` files are already skipped since they are not type checked.
81
81
  #
82
- locations.uniq.select do |loc|
82
+ locations.filter_map do |target, loc|
83
83
  case loc
84
84
  when RBS::Location
85
- assignment =~ loc.name
85
+ if assignment =~ [target, loc.name]
86
+ loc
87
+ end
86
88
  else
87
- true
89
+ loc
88
90
  end
89
- end
91
+ end.uniq
90
92
  end
91
93
 
92
94
  def type_definition(path:, line:, column:)
93
- locations = [] #: Array[loc]
95
+ locations = [] #: Array[target_loc]
94
96
 
95
97
  relative_path = project.relative_path(path)
96
98
 
97
- target = type_check.source_file?(relative_path) or return []
99
+ target = type_check.project.target_for_path(relative_path) or return []
98
100
  source = type_check.source_files[relative_path]
99
101
  typing, signature = type_check_path(target: target, path: relative_path, content: source.content, line: line, column: column)
100
102
 
@@ -112,14 +114,16 @@ module Steep
112
114
  type_name_locations(name, locations: locations)
113
115
  end
114
116
 
115
- locations.uniq.select do |loc|
117
+ locations.filter_map do |target, loc|
116
118
  case loc
117
119
  when RBS::Location
118
- assignment =~ loc.name
120
+ if assignment =~ [target, loc.name]
121
+ loc
122
+ end
119
123
  else
120
- true
124
+ loc
121
125
  end
122
- end
126
+ end.uniq
123
127
  end
124
128
 
125
129
  def each_type_name(type, &block)
@@ -158,8 +162,8 @@ module Steep
158
162
  relative_path = project.relative_path(path)
159
163
 
160
164
  case
161
- when target = type_check.source_file?(relative_path)
162
- source = type_check.source_files[relative_path]
165
+ when target = type_check.project.target_for_source_path(relative_path)
166
+ source = type_check.source_files[relative_path] or return []
163
167
  typing, _signature = type_check_path(target: target, path: relative_path, content: source.content, line: line, column: column)
164
168
  if typing
165
169
  node, *parents = typing.source.find_nodes(line: line, column: column)
@@ -295,23 +299,24 @@ module Steep
295
299
  end
296
300
 
297
301
  def constant_definition_in_rbs(name, locations:)
298
- type_check.signature_services.each_value do |signature|
302
+ project.targets.each do |target|
303
+ signature = type_check.signature_services.fetch(target.name)
299
304
  env = signature.latest_env #: RBS::Environment
300
305
 
301
306
  case entry = env.constant_entry(name)
302
307
  when RBS::Environment::ConstantEntry
303
308
  if entry.decl.location
304
- locations << entry.decl.location[:name]
309
+ locations << [target, entry.decl.location[:name]]
305
310
  end
306
311
  when RBS::Environment::ClassEntry, RBS::Environment::ModuleEntry
307
312
  entry.decls.each do |d|
308
313
  if d.decl.location
309
- locations << d.decl.location[:name]
314
+ locations << [target, d.decl.location[:name]]
310
315
  end
311
316
  end
312
317
  when RBS::Environment::ClassAliasEntry, RBS::Environment::ModuleAliasEntry
313
318
  if entry.decl.location
314
- locations << entry.decl.location[:new_name]
319
+ locations << [target, entry.decl.location[:new_name]]
315
320
  end
316
321
  end
317
322
  end
@@ -322,11 +327,12 @@ module Steep
322
327
  def constant_definition_in_ruby(name, locations:)
323
328
  type_check.source_files.each do |path, source|
324
329
  if typing = source.typing
330
+ target = project.target_for_source_path(path) or raise
325
331
  entry = typing.source_index.entry(constant: name)
326
332
  entry.definitions.each do |node|
327
333
  case node.type
328
334
  when :const
329
- locations << node.location.expression
335
+ locations << [target, node.location.expression]
330
336
  when :casgn
331
337
  parent = node.children[0]
332
338
  location =
@@ -335,7 +341,7 @@ module Steep
335
341
  else
336
342
  node.location.name
337
343
  end
338
- locations << location
344
+ locations << [target, location]
339
345
  end
340
346
  end
341
347
  end
@@ -348,6 +354,7 @@ module Steep
348
354
  if in_ruby
349
355
  type_check.source_files.each do |path, source|
350
356
  if typing = source.typing
357
+ target = project.target_for_source_path(path) or raise
351
358
  entry = typing.source_index.entry(method: name)
352
359
 
353
360
  if entry.definitions.empty?
@@ -360,9 +367,9 @@ module Steep
360
367
  entry.definitions.each do |node|
361
368
  case node.type
362
369
  when :def
363
- locations << node.location.name
370
+ locations << [target, node.location.name]
364
371
  when :defs
365
- locations << node.location.name
372
+ locations << [target, node.location.name]
366
373
  end
367
374
  end
368
375
  end
@@ -370,7 +377,8 @@ module Steep
370
377
  end
371
378
 
372
379
  if in_rbs
373
- type_check.signature_services.each_value do |signature|
380
+ project.targets.each do |target|
381
+ signature = type_check.signature_services.fetch(target.name)
374
382
  index = signature.latest_rbs_index
375
383
 
376
384
  entry = index.entry(method_name: name)
@@ -386,15 +394,15 @@ module Steep
386
394
  case decl
387
395
  when RBS::AST::Members::MethodDefinition
388
396
  if decl.location
389
- locations << decl.location[:name]
397
+ locations << [target, decl.location[:name]]
390
398
  end
391
399
  when RBS::AST::Members::Alias
392
400
  if decl.location
393
- locations << decl.location[:new_name]
401
+ locations << [target, decl.location[:new_name]]
394
402
  end
395
403
  when RBS::AST::Members::AttrAccessor, RBS::AST::Members::AttrReader, RBS::AST::Members::AttrWriter
396
404
  if decl.location
397
- locations << decl.location[:name]
405
+ locations << [target, decl.location[:name]]
398
406
  end
399
407
  end
400
408
  end
@@ -405,7 +413,8 @@ module Steep
405
413
  end
406
414
 
407
415
  def type_name_locations(name, locations: [])
408
- type_check.signature_services.each_value do |signature|
416
+ project.targets.each do |target|
417
+ signature = type_check.signature_services.fetch(target.name)
409
418
  index = signature.latest_rbs_index
410
419
 
411
420
  entry = index.entry(type_name: name)
@@ -413,11 +422,11 @@ module Steep
413
422
  case decl
414
423
  when RBS::AST::Declarations::Class, RBS::AST::Declarations::Module, RBS::AST::Declarations::Interface, RBS::AST::Declarations::TypeAlias
415
424
  if decl.location
416
- locations << decl.location[:name]
425
+ locations << [target, decl.location[:name]]
417
426
  end
418
427
  when RBS::AST::Declarations::AliasDecl
419
428
  if decl.location
420
- locations << decl.location[:new_name]
429
+ locations << [target, decl.location[:new_name]]
421
430
  end
422
431
  else
423
432
  raise
@@ -5,11 +5,11 @@ module Steep
5
5
  def content_for(service:, path:, line:, column:)
6
6
  project = service.project
7
7
 
8
- case (target = project.targets_for_path(path))
9
- when Project::Target
8
+ case
9
+ when target = project.target_for_source_path(path)
10
10
  Ruby.new(service: service).content_for(target: target, path: path, line: line, column: column)
11
- when Array
12
- RBS.new(service: service).content_for(target: target[0], path: path, line: line, column: column)
11
+ when target = project.target_for_signature_path(path)
12
+ RBS.new(service: service).content_for(target: target, path: path, line: line, column: column)
13
13
  end
14
14
  end
15
15
  end
@@ -13,14 +13,33 @@ module Steep
13
13
  new(index: 0, max_index: 1)
14
14
  end
15
15
 
16
- def =~(path)
17
- (cache[path] ||= self.class.index_for(path: path.to_s, max_index: max_index)) == index
16
+ def =~(target_path)
17
+ key = stringify(target_path)
18
+ (cache[key] ||= self.class.index_for(key: key, max_index: max_index)) == index
18
19
  end
19
20
 
20
21
  alias === =~
21
22
 
22
- def self.index_for(path:, max_index:)
23
- Digest::MD5.hexdigest(path).hex % max_index
23
+ def assign!(path, index)
24
+ key = stringify(path)
25
+ cache[key] = index
26
+ self
27
+ end
28
+
29
+ def stringify(target_path)
30
+ target =
31
+ case target_path[0]
32
+ when Project::Target
33
+ target_path[0].name.to_s
34
+ else
35
+ target_path[0].to_s
36
+ end
37
+ path = target_path[1].to_s
38
+ "#{target}::#{path}"
39
+ end
40
+
41
+ def self.index_for(key:, max_index:)
42
+ Digest::MD5.hexdigest(key).hex % max_index
24
43
  end
25
44
  end
26
45
  end