ruby-lsp 0.23.15 → 0.26.9

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/exe/ruby-lsp +17 -14
  4. data/exe/ruby-lsp-check +0 -4
  5. data/exe/ruby-lsp-launcher +41 -14
  6. data/exe/ruby-lsp-test-exec +6 -0
  7. data/lib/rubocop/cop/ruby_lsp/use_language_server_aliases.rb +0 -1
  8. data/lib/rubocop/cop/ruby_lsp/use_register_with_handler_method.rb +0 -1
  9. data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +4 -3
  10. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +42 -20
  11. data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +1 -7
  12. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +49 -62
  13. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +84 -74
  14. data/lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb +6 -9
  15. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +9 -14
  16. data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +12 -8
  17. data/lib/ruby_indexer/lib/ruby_indexer/visibility_scope.rb +4 -4
  18. data/lib/ruby_lsp/addon.rb +44 -15
  19. data/lib/ruby_lsp/base_server.rb +56 -37
  20. data/lib/ruby_lsp/client_capabilities.rb +6 -1
  21. data/lib/ruby_lsp/document.rb +174 -62
  22. data/lib/ruby_lsp/erb_document.rb +10 -8
  23. data/lib/ruby_lsp/global_state.rb +86 -33
  24. data/lib/ruby_lsp/internal.rb +6 -3
  25. data/lib/ruby_lsp/listeners/completion.rb +22 -11
  26. data/lib/ruby_lsp/listeners/definition.rb +41 -21
  27. data/lib/ruby_lsp/listeners/document_highlight.rb +26 -1
  28. data/lib/ruby_lsp/listeners/document_link.rb +64 -28
  29. data/lib/ruby_lsp/listeners/hover.rb +27 -16
  30. data/lib/ruby_lsp/listeners/inlay_hints.rb +5 -3
  31. data/lib/ruby_lsp/listeners/semantic_highlighting.rb +2 -2
  32. data/lib/ruby_lsp/listeners/signature_help.rb +2 -2
  33. data/lib/ruby_lsp/listeners/spec_style.rb +155 -79
  34. data/lib/ruby_lsp/listeners/test_discovery.rb +39 -21
  35. data/lib/ruby_lsp/listeners/test_style.rb +75 -35
  36. data/lib/ruby_lsp/rbs_document.rb +3 -6
  37. data/lib/ruby_lsp/requests/code_action_resolve.rb +83 -58
  38. data/lib/ruby_lsp/requests/code_actions.rb +20 -5
  39. data/lib/ruby_lsp/requests/code_lens.rb +27 -6
  40. data/lib/ruby_lsp/requests/completion.rb +3 -3
  41. data/lib/ruby_lsp/requests/completion_resolve.rb +8 -6
  42. data/lib/ruby_lsp/requests/definition.rb +4 -7
  43. data/lib/ruby_lsp/requests/discover_tests.rb +2 -2
  44. data/lib/ruby_lsp/requests/document_highlight.rb +2 -2
  45. data/lib/ruby_lsp/requests/document_link.rb +1 -1
  46. data/lib/ruby_lsp/requests/folding_ranges.rb +1 -1
  47. data/lib/ruby_lsp/requests/go_to_relevant_file.rb +64 -12
  48. data/lib/ruby_lsp/requests/hover.rb +3 -6
  49. data/lib/ruby_lsp/requests/inlay_hints.rb +4 -4
  50. data/lib/ruby_lsp/requests/on_type_formatting.rb +1 -1
  51. data/lib/ruby_lsp/requests/prepare_rename.rb +1 -1
  52. data/lib/ruby_lsp/requests/references.rb +10 -21
  53. data/lib/ruby_lsp/requests/rename.rb +9 -10
  54. data/lib/ruby_lsp/requests/request.rb +8 -8
  55. data/lib/ruby_lsp/requests/selection_ranges.rb +2 -2
  56. data/lib/ruby_lsp/requests/semantic_highlighting.rb +1 -1
  57. data/lib/ruby_lsp/requests/show_syntax_tree.rb +2 -2
  58. data/lib/ruby_lsp/requests/signature_help.rb +2 -2
  59. data/lib/ruby_lsp/requests/support/annotation.rb +1 -1
  60. data/lib/ruby_lsp/requests/support/common.rb +9 -12
  61. data/lib/ruby_lsp/requests/support/formatter.rb +16 -15
  62. data/lib/ruby_lsp/requests/support/package_url.rb +414 -0
  63. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +7 -1
  64. data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +2 -2
  65. data/lib/ruby_lsp/requests/support/rubocop_runner.rb +13 -3
  66. data/lib/ruby_lsp/requests/support/source_uri.rb +7 -4
  67. data/lib/ruby_lsp/requests/support/test_item.rb +7 -1
  68. data/lib/ruby_lsp/requests/workspace_symbol.rb +20 -12
  69. data/lib/ruby_lsp/response_builders/collection_response_builder.rb +1 -4
  70. data/lib/ruby_lsp/response_builders/document_symbol.rb +2 -3
  71. data/lib/ruby_lsp/response_builders/hover.rb +1 -4
  72. data/lib/ruby_lsp/response_builders/response_builder.rb +6 -7
  73. data/lib/ruby_lsp/response_builders/semantic_highlighting.rb +4 -5
  74. data/lib/ruby_lsp/response_builders/signature_help.rb +1 -2
  75. data/lib/ruby_lsp/response_builders/test_collection.rb +29 -3
  76. data/lib/ruby_lsp/ruby_document.rb +14 -42
  77. data/lib/ruby_lsp/scripts/compose_bundle.rb +3 -3
  78. data/lib/ruby_lsp/scripts/compose_bundle_windows.rb +3 -1
  79. data/lib/ruby_lsp/server.rb +173 -130
  80. data/lib/ruby_lsp/setup_bundler.rb +114 -47
  81. data/lib/ruby_lsp/static_docs.rb +1 -0
  82. data/lib/ruby_lsp/store.rb +6 -16
  83. data/lib/ruby_lsp/test_helper.rb +1 -4
  84. data/lib/ruby_lsp/test_reporters/lsp_reporter.rb +121 -17
  85. data/lib/ruby_lsp/test_reporters/minitest_reporter.rb +65 -25
  86. data/lib/ruby_lsp/test_reporters/test_unit_reporter.rb +16 -18
  87. data/lib/ruby_lsp/utils.rb +102 -13
  88. data/static_docs/break.md +103 -0
  89. metadata +8 -33
  90. data/lib/ruby_indexer/test/class_variables_test.rb +0 -140
  91. data/lib/ruby_indexer/test/classes_and_modules_test.rb +0 -770
  92. data/lib/ruby_indexer/test/configuration_test.rb +0 -280
  93. data/lib/ruby_indexer/test/constant_test.rb +0 -402
  94. data/lib/ruby_indexer/test/enhancements_test.rb +0 -325
  95. data/lib/ruby_indexer/test/global_variable_test.rb +0 -49
  96. data/lib/ruby_indexer/test/index_test.rb +0 -2190
  97. data/lib/ruby_indexer/test/instance_variables_test.rb +0 -240
  98. data/lib/ruby_indexer/test/method_test.rb +0 -973
  99. data/lib/ruby_indexer/test/prefix_tree_test.rb +0 -150
  100. data/lib/ruby_indexer/test/rbs_indexer_test.rb +0 -380
  101. data/lib/ruby_indexer/test/reference_finder_test.rb +0 -330
  102. data/lib/ruby_indexer/test/test_case.rb +0 -51
  103. data/lib/ruby_indexer/test/uri_test.rb +0 -85
  104. data/lib/ruby_lsp/load_sorbet.rb +0 -62
@@ -1,2190 +0,0 @@
1
- # typed: true
2
- # frozen_string_literal: true
3
-
4
- require_relative "test_case"
5
-
6
- module RubyIndexer
7
- class IndexTest < TestCase
8
- def test_deleting_one_entry_for_a_class
9
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
10
- class Foo
11
- end
12
- RUBY
13
- @index.index_single(URI::Generic.from_path(path: "/fake/path/other_foo.rb"), <<~RUBY)
14
- class Foo
15
- end
16
- RUBY
17
-
18
- entries = @index["Foo"] #: as !nil
19
- assert_equal(2, entries.length)
20
-
21
- @index.delete(URI::Generic.from_path(path: "/fake/path/other_foo.rb"))
22
- entries = @index["Foo"] #: as !nil
23
- assert_equal(1, entries.length)
24
- end
25
-
26
- def test_deleting_all_entries_for_a_class
27
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
28
- class Foo
29
- end
30
- RUBY
31
-
32
- entries = @index["Foo"] #: as !nil
33
- assert_equal(1, entries.length)
34
-
35
- @index.delete(URI::Generic.from_path(path: "/fake/path/foo.rb"))
36
- entries = @index["Foo"]
37
- assert_nil(entries)
38
- end
39
-
40
- def test_index_resolve
41
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
42
- class Bar; end
43
-
44
- module Foo
45
- class Bar
46
- end
47
-
48
- class Baz
49
- class Something
50
- end
51
- end
52
- end
53
- RUBY
54
-
55
- entries = @index.resolve("Something", ["Foo", "Baz"]) #: as !nil
56
- refute_empty(entries)
57
- assert_equal("Foo::Baz::Something", entries.first&.name)
58
-
59
- entries = @index.resolve("Bar", ["Foo"]) #: as !nil
60
- refute_empty(entries)
61
- assert_equal("Foo::Bar", entries.first&.name)
62
-
63
- entries = @index.resolve("Bar", ["Foo", "Baz"]) #: as !nil
64
- refute_empty(entries)
65
- assert_equal("Foo::Bar", entries.first&.name)
66
-
67
- entries = @index.resolve("Foo::Bar", ["Foo", "Baz"]) #: as !nil
68
- refute_empty(entries)
69
- assert_equal("Foo::Bar", entries.first&.name)
70
-
71
- assert_nil(@index.resolve("DoesNotExist", ["Foo"]))
72
- end
73
-
74
- def test_accessing_with_colon_colon_prefix
75
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
76
- class Bar; end
77
-
78
- module Foo
79
- class Bar
80
- end
81
-
82
- class Baz
83
- class Something
84
- end
85
- end
86
- end
87
- RUBY
88
-
89
- entries = @index["::Foo::Baz::Something"] #: as !nil
90
- refute_empty(entries)
91
- assert_equal("Foo::Baz::Something", entries.first&.name)
92
- end
93
-
94
- def test_fuzzy_search
95
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
96
- class Zws; end
97
-
98
- module Qtl
99
- class Zws
100
- end
101
-
102
- class Zwo
103
- class Something
104
- end
105
- end
106
- end
107
- RUBY
108
-
109
- result = @index.fuzzy_search("Zws")
110
- assert_equal(2, result.length)
111
- assert_equal(["Zws", "Qtl::Zwo::Something"], result.map(&:name))
112
-
113
- result = @index.fuzzy_search("qtlzwssomeking")
114
- assert_equal(5, result.length)
115
- assert_equal(["Qtl::Zwo::Something", "Qtl::Zws", "Qtl::Zwo", "Qtl", "Zws"], result.map(&:name))
116
-
117
- result = @index.fuzzy_search("QltZwo")
118
- assert_equal(4, result.length)
119
- assert_equal(["Qtl::Zwo", "Qtl::Zws", "Qtl::Zwo::Something", "Qtl"], result.map(&:name))
120
- end
121
-
122
- def test_index_single_ignores_directories
123
- path = "#{Dir.pwd}/lib/this_is_a_dir.rb"
124
- FileUtils.mkdir(path)
125
-
126
- begin
127
- @index.index_file(URI::Generic.from_path(path: path))
128
- ensure
129
- FileUtils.rm_r(path)
130
- end
131
- end
132
-
133
- def test_searching_for_require_paths
134
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb", load_path_entry: "/fake"), <<~RUBY)
135
- class Foo
136
- end
137
- RUBY
138
- @index.index_single(URI::Generic.from_path(path: "/fake/path/other_foo.rb", load_path_entry: "/fake"), <<~RUBY)
139
- class Foo
140
- end
141
- RUBY
142
-
143
- assert_equal(["path/other_foo", "path/foo"], @index.search_require_paths("path").map(&:require_path))
144
- end
145
-
146
- def test_searching_for_entries_based_on_prefix
147
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb", load_path_entry: "/fake"), <<~RUBY)
148
- class Foo::Bizw
149
- end
150
- RUBY
151
- @index.index_single(URI::Generic.from_path(path: "/fake/path/other_foo.rb", load_path_entry: "/fake"), <<~RUBY)
152
- class Foo::Bizw
153
- end
154
-
155
- class Foo::Bizt
156
- end
157
- RUBY
158
-
159
- results = @index.prefix_search("Foo", []).map { |entries| entries.map(&:name) }
160
- assert_equal([["Foo::Bizt"], ["Foo::Bizw", "Foo::Bizw"]], results)
161
-
162
- results = @index.prefix_search("Biz", ["Foo"]).map { |entries| entries.map(&:name) }
163
- assert_equal([["Foo::Bizt"], ["Foo::Bizw", "Foo::Bizw"]], results)
164
- end
165
-
166
- def test_resolve_normalizes_top_level_names
167
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb", load_path_entry: "/fake"), <<~RUBY)
168
- class Bar; end
169
-
170
- module Foo
171
- class Bar; end
172
- end
173
- RUBY
174
-
175
- entries = @index.resolve("::Foo::Bar", []) #: as !nil
176
- refute_nil(entries)
177
-
178
- assert_equal("Foo::Bar", entries.first&.name)
179
-
180
- entries = @index.resolve("::Bar", ["Foo"]) #: as !nil
181
- refute_nil(entries)
182
-
183
- assert_equal("Bar", entries.first&.name)
184
- end
185
-
186
- def test_resolving_aliases_to_non_existing_constants_with_conflicting_names
187
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb", load_path_entry: "/fake"), <<~RUBY)
188
- class Bar
189
- end
190
-
191
- module Foo
192
- class Bar < self
193
- BAZ = ::Bar::BAZ
194
- end
195
- end
196
- RUBY
197
-
198
- entry = @index.resolve("BAZ", ["Foo", "Bar"])&.first
199
- refute_nil(entry)
200
-
201
- assert_instance_of(Entry::UnresolvedConstantAlias, entry)
202
- end
203
-
204
- def test_visitor_does_not_visit_unnecessary_nodes
205
- concats = (0...10_000).map do |i|
206
- <<~STRING
207
- "string#{i}" \\
208
- STRING
209
- end.join
210
-
211
- index(<<~RUBY)
212
- module Foo
213
- local_var = #{concats}
214
- "final"
215
- @class_instance_var = #{concats}
216
- "final"
217
- @@class_var = #{concats}
218
- "final"
219
- $global_var = #{concats}
220
- "final"
221
- CONST = #{concats}
222
- "final"
223
- end
224
- RUBY
225
- end
226
-
227
- def test_resolve_method_with_known_receiver
228
- index(<<~RUBY)
229
- module Foo
230
- module Bar
231
- def baz; end
232
- end
233
- end
234
- RUBY
235
-
236
- entries = @index.resolve_method("baz", "Foo::Bar") #: as !nil
237
- assert_equal("baz", entries.first&.name)
238
- owner = entries.first&.owner #: as !nil
239
- assert_equal("Foo::Bar", owner.name)
240
- end
241
-
242
- def test_resolve_method_with_class_name_conflict
243
- index(<<~RUBY)
244
- class Array
245
- end
246
-
247
- class Foo
248
- def Array(*args); end
249
- end
250
- RUBY
251
-
252
- entries = @index.resolve_method("Array", "Foo") #: as !nil
253
- assert_equal("Array", entries.first&.name)
254
- owner = entries.first&.owner #: as !nil
255
- assert_equal("Foo", owner.name)
256
- end
257
-
258
- def test_resolve_method_attribute
259
- index(<<~RUBY)
260
- class Foo
261
- attr_reader :bar
262
- end
263
- RUBY
264
-
265
- entries = @index.resolve_method("bar", "Foo") #: as !nil
266
- assert_equal("bar", entries.first&.name)
267
- owner = entries.first&.owner #: as !nil
268
- assert_equal("Foo", owner.name)
269
- end
270
-
271
- def test_resolve_method_with_two_definitions
272
- index(<<~RUBY)
273
- class Foo
274
- # Hello from first `bar`
275
- def bar; end
276
- end
277
-
278
- class Foo
279
- # Hello from second `bar`
280
- def bar; end
281
- end
282
- RUBY
283
-
284
- first_entry, second_entry = @index.resolve_method("bar", "Foo") #: as !nil
285
-
286
- assert_equal("bar", first_entry&.name)
287
- owner = first_entry&.owner #: as !nil
288
- assert_equal("Foo", owner.name)
289
- assert_includes(first_entry&.comments, "Hello from first `bar`")
290
-
291
- assert_equal("bar", second_entry&.name)
292
- owner = second_entry&.owner #: as !nil
293
- assert_equal("Foo", owner.name)
294
- assert_includes(second_entry&.comments, "Hello from second `bar`")
295
- end
296
-
297
- def test_resolve_method_inherited_only
298
- index(<<~RUBY)
299
- class Bar
300
- def baz; end
301
- end
302
-
303
- class Foo < Bar
304
- def baz; end
305
- end
306
- RUBY
307
-
308
- entry = @index.resolve_method("baz", "Foo", inherited_only: true)&.first #: as !nil
309
- assert_equal("Bar", entry.owner&.name)
310
- end
311
-
312
- def test_resolve_method_inherited_only_for_prepended_module
313
- index(<<~RUBY)
314
- module Bar
315
- def baz
316
- super
317
- end
318
- end
319
-
320
- class Foo
321
- prepend Bar
322
-
323
- def baz; end
324
- end
325
- RUBY
326
-
327
- # This test is just to document the fact that we don't yet support resolving inherited methods for modules that
328
- # are prepended. The only way to support this is to find all namespaces that have the module a subtype, so that we
329
- # can show the results for everywhere the module has been prepended.
330
- assert_nil(@index.resolve_method("baz", "Bar", inherited_only: true))
331
- end
332
-
333
- def test_prefix_search_for_methods
334
- index(<<~RUBY)
335
- module Foo
336
- module Bar
337
- def qzx; end
338
- end
339
- end
340
- RUBY
341
-
342
- entries = @index.prefix_search("qz")
343
- refute_empty(entries)
344
-
345
- entry = entries.first&.first #: as !nil
346
- assert_equal("qzx", entry.name)
347
- end
348
-
349
- def test_indexing_prism_fixtures_succeeds
350
- unless Dir.exist?("test/fixtures/prism/test/prism/fixtures")
351
- raise "Prism fixtures not found. Run `git submodule update --init` to fetch them."
352
- end
353
-
354
- fixtures = Dir.glob("#{Dir.pwd}/test/fixtures/prism/test/prism/fixtures/**/*.txt")
355
-
356
- fixtures.each do |fixture|
357
- uri = URI::Generic.from_path(path: fixture)
358
- @index.index_file(uri)
359
- end
360
-
361
- refute_empty(@index)
362
- end
363
-
364
- def test_index_single_does_not_fail_for_non_existing_file
365
- @index.index_file(URI::Generic.from_path(path: "/fake/path/foo.rb"))
366
- entries_after_indexing = @index.names
367
- assert_equal(@default_indexed_entries.keys, entries_after_indexing)
368
- end
369
-
370
- def test_linearized_ancestors_basic_ordering
371
- index(<<~RUBY)
372
- module A; end
373
- module B; end
374
-
375
- class Foo
376
- prepend A
377
- prepend B
378
- end
379
-
380
- class Bar
381
- include A
382
- include B
383
- end
384
- RUBY
385
-
386
- assert_equal(
387
- [
388
- "B",
389
- "A",
390
- "Foo",
391
- "Object",
392
- "Kernel",
393
- "BasicObject",
394
- ],
395
- @index.linearized_ancestors_of("Foo"),
396
- )
397
-
398
- assert_equal(
399
- [
400
- "Bar",
401
- "B",
402
- "A",
403
- "Object",
404
- "Kernel",
405
- "BasicObject",
406
- ],
407
- @index.linearized_ancestors_of("Bar"),
408
- )
409
- end
410
-
411
- def test_linearized_ancestors
412
- index(<<~RUBY)
413
- module A; end
414
- module B; end
415
- module C; end
416
-
417
- module D
418
- include A
419
- end
420
-
421
- module E
422
- prepend B
423
- end
424
-
425
- module F
426
- include C
427
- include A
428
- end
429
-
430
- class Bar
431
- prepend F
432
- end
433
-
434
- class Foo < Bar
435
- include E
436
- prepend D
437
- end
438
- RUBY
439
-
440
- # Object, Kernel and BasicObject are intentionally commented out for now until we develop a strategy for indexing
441
- # declarations made in C code
442
- assert_equal(
443
- [
444
- "D",
445
- "A",
446
- "Foo",
447
- "B",
448
- "E",
449
- "F",
450
- "A",
451
- "C",
452
- "Bar",
453
- "Object",
454
- "Kernel",
455
- "BasicObject",
456
- ],
457
- @index.linearized_ancestors_of("Foo"),
458
- )
459
- end
460
-
461
- def test_linearized_ancestors_duplicates
462
- index(<<~RUBY)
463
- module A; end
464
- module B
465
- include A
466
- end
467
-
468
- class Foo
469
- include B
470
- include A
471
- end
472
-
473
- class Bar
474
- prepend B
475
- prepend A
476
- end
477
- RUBY
478
-
479
- assert_equal(
480
- [
481
- "Foo",
482
- "B",
483
- "A",
484
- "Object",
485
- "Kernel",
486
- "BasicObject",
487
- ],
488
- @index.linearized_ancestors_of("Foo"),
489
- )
490
-
491
- assert_equal(
492
- [
493
- "B",
494
- "A",
495
- "Bar",
496
- "Object",
497
- "Kernel",
498
- "BasicObject",
499
- ],
500
- @index.linearized_ancestors_of("Bar"),
501
- )
502
- end
503
-
504
- def test_linearizing_ancestors_is_cached
505
- index(<<~RUBY)
506
- module C; end
507
- module A; end
508
- module B
509
- include A
510
- end
511
-
512
- class Foo
513
- include B
514
- include A
515
- end
516
- RUBY
517
-
518
- @index.linearized_ancestors_of("Foo")
519
- ancestors = @index.instance_variable_get(:@ancestors)
520
- assert(ancestors.key?("Foo"))
521
- assert(ancestors.key?("A"))
522
- assert(ancestors.key?("B"))
523
- refute(ancestors.key?("C"))
524
- end
525
-
526
- def test_duplicate_prepend_include
527
- index(<<~RUBY)
528
- module A; end
529
-
530
- class Foo
531
- prepend A
532
- include A
533
- end
534
-
535
- class Bar
536
- include A
537
- prepend A
538
- end
539
- RUBY
540
-
541
- assert_equal(
542
- [
543
- "A",
544
- "Foo",
545
- "Object",
546
- "Kernel",
547
- "BasicObject",
548
- ],
549
- @index.linearized_ancestors_of("Foo"),
550
- )
551
-
552
- assert_equal(
553
- [
554
- "A",
555
- "Bar",
556
- "A",
557
- "Object",
558
- "Kernel",
559
- "BasicObject",
560
- ],
561
- @index.linearized_ancestors_of("Bar"),
562
- )
563
- end
564
-
565
- def test_linearizing_ancestors_handles_circular_parent_class
566
- index(<<~RUBY)
567
- class Foo < Foo
568
- end
569
- RUBY
570
-
571
- assert_equal(["Foo"], @index.linearized_ancestors_of("Foo"))
572
- end
573
-
574
- def test_ancestors_linearization_complex_prepend_duplication
575
- index(<<~RUBY)
576
- module A; end
577
- module B
578
- prepend A
579
- end
580
- module C
581
- prepend B
582
- end
583
-
584
- class Foo
585
- prepend A
586
- prepend C
587
- end
588
- RUBY
589
-
590
- assert_equal(
591
- [
592
- "A",
593
- "B",
594
- "C",
595
- "Foo",
596
- "Object",
597
- "Kernel",
598
- "BasicObject",
599
- ],
600
- @index.linearized_ancestors_of("Foo"),
601
- )
602
- end
603
-
604
- def test_ancestors_linearization_complex_include_duplication
605
- index(<<~RUBY)
606
- module A; end
607
- module B
608
- include A
609
- end
610
- module C
611
- include B
612
- end
613
-
614
- class Foo
615
- include A
616
- include C
617
- end
618
- RUBY
619
-
620
- assert_equal(
621
- [
622
- "Foo",
623
- "C",
624
- "B",
625
- "A",
626
- "Object",
627
- "Kernel",
628
- "BasicObject",
629
- ],
630
- @index.linearized_ancestors_of("Foo"),
631
- )
632
- end
633
-
634
- def test_linearizing_ancestors_that_need_to_be_resolved
635
- index(<<~RUBY)
636
- module Foo
637
- module Baz
638
- end
639
- module Qux
640
- end
641
-
642
- class Something; end
643
-
644
- class Bar < Something
645
- include Baz
646
- prepend Qux
647
- end
648
- end
649
- RUBY
650
-
651
- assert_equal(
652
- [
653
- "Foo::Qux",
654
- "Foo::Bar",
655
- "Foo::Baz",
656
- "Foo::Something",
657
- "Object",
658
- "Kernel",
659
- "BasicObject",
660
- ],
661
- @index.linearized_ancestors_of("Foo::Bar"),
662
- )
663
- end
664
-
665
- def test_linearizing_ancestors_for_non_existing_namespaces
666
- index(<<~RUBY)
667
- def Bar(a); end
668
- RUBY
669
-
670
- assert_raises(Index::NonExistingNamespaceError) do
671
- @index.linearized_ancestors_of("Foo")
672
- end
673
-
674
- assert_raises(Index::NonExistingNamespaceError) do
675
- @index.linearized_ancestors_of("Bar")
676
- end
677
- end
678
-
679
- def test_linearizing_circular_ancestors
680
- index(<<~RUBY)
681
- module M1
682
- include M2
683
- end
684
-
685
- module M2
686
- include M1
687
- end
688
-
689
- module A1
690
- include A2
691
- end
692
-
693
- module A2
694
- include A3
695
- end
696
-
697
- module A3
698
- include A1
699
- end
700
-
701
- class Foo < Foo
702
- include Foo
703
- end
704
-
705
- module Bar
706
- include Bar
707
- end
708
- RUBY
709
-
710
- assert_equal(["M2", "M1"], @index.linearized_ancestors_of("M2"))
711
- assert_equal(["A3", "A1", "A2"], @index.linearized_ancestors_of("A3"))
712
- assert_equal(["Foo"], @index.linearized_ancestors_of("Foo"))
713
- assert_equal(["Bar"], @index.linearized_ancestors_of("Bar"))
714
- end
715
-
716
- def test_linearizing_circular_aliased_dependency
717
- index(<<~RUBY)
718
- module A
719
- end
720
-
721
- ALIAS = A
722
-
723
- module A
724
- include ALIAS
725
- end
726
- RUBY
727
-
728
- assert_equal(["A", "ALIAS"], @index.linearized_ancestors_of("A"))
729
- end
730
-
731
- def test_resolving_an_inherited_method
732
- index(<<~RUBY)
733
- module Foo
734
- def baz; end
735
- end
736
-
737
- class Bar
738
- def qux; end
739
- end
740
-
741
- class Wow < Bar
742
- include Foo
743
- end
744
- RUBY
745
-
746
- entry = @index.resolve_method("baz", "Wow")&.first #: as !nil
747
- assert_equal("baz", entry.name)
748
- assert_equal("Foo", entry.owner&.name)
749
-
750
- entry = @index.resolve_method("qux", "Wow")&.first #: as !nil
751
- assert_equal("qux", entry.name)
752
- assert_equal("Bar", entry.owner&.name)
753
- end
754
-
755
- def test_resolving_an_inherited_method_lands_on_first_match
756
- index(<<~RUBY)
757
- module Foo
758
- def qux; end
759
- end
760
-
761
- class Bar
762
- def qux; end
763
- end
764
-
765
- class Wow < Bar
766
- prepend Foo
767
-
768
- def qux; end
769
- end
770
- RUBY
771
-
772
- entries = @index.resolve_method("qux", "Wow") #: as !nil
773
- assert_equal(1, entries.length)
774
-
775
- entry = entries.first #: as !nil
776
- assert_equal("qux", entry.name)
777
- assert_equal("Foo", entry.owner&.name)
778
- end
779
-
780
- def test_handle_change_clears_ancestor_cache_if_tree_changed
781
- Dir.mktmpdir do |dir|
782
- Dir.chdir(dir) do
783
- # Write the original file
784
- File.write(File.join(dir, "foo.rb"), <<~RUBY)
785
- module Foo
786
- end
787
-
788
- class Bar
789
- include Foo
790
- end
791
- RUBY
792
-
793
- uri = URI::Generic.from_path(path: File.join(dir, "foo.rb"))
794
- @index.index_file(uri)
795
-
796
- assert_equal(["Bar", "Foo", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Bar"))
797
-
798
- # Remove include to invalidate the ancestor tree
799
- File.write(File.join(dir, "foo.rb"), <<~RUBY)
800
- module Foo
801
- end
802
-
803
- class Bar
804
- end
805
- RUBY
806
-
807
- path = uri.full_path #: as !nil
808
- @index.handle_change(uri, File.read(path))
809
- assert_empty(@index.instance_variable_get(:@ancestors))
810
- assert_equal(["Bar", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Bar"))
811
- end
812
- end
813
- end
814
-
815
- def test_handle_change_does_not_clear_ancestor_cache_if_tree_not_changed
816
- Dir.mktmpdir do |dir|
817
- Dir.chdir(dir) do
818
- # Write the original file
819
- File.write(File.join(dir, "foo.rb"), <<~RUBY)
820
- module Foo
821
- end
822
-
823
- class Bar
824
- include Foo
825
- end
826
- RUBY
827
-
828
- uri = URI::Generic.from_path(path: File.join(dir, "foo.rb"))
829
- @index.index_file(uri)
830
-
831
- assert_equal(["Bar", "Foo", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Bar"))
832
-
833
- # Remove include to invalidate the ancestor tree
834
- File.write(File.join(dir, "foo.rb"), <<~RUBY)
835
- module Foo
836
- end
837
-
838
- class Bar
839
- include Foo
840
-
841
- def baz; end
842
- end
843
- RUBY
844
-
845
- path = uri.full_path #: as !nil
846
- @index.handle_change(uri, File.read(path))
847
- refute_empty(@index.instance_variable_get(:@ancestors))
848
- assert_equal(["Bar", "Foo", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Bar"))
849
- end
850
- end
851
- end
852
-
853
- def test_handle_change_clears_ancestor_cache_if_parent_class_changed
854
- Dir.mktmpdir do |dir|
855
- Dir.chdir(dir) do
856
- # Write the original file
857
- File.write(File.join(dir, "foo.rb"), <<~RUBY)
858
- class Foo
859
- end
860
-
861
- class Bar < Foo
862
- end
863
- RUBY
864
-
865
- uri = URI::Generic.from_path(path: File.join(dir, "foo.rb"))
866
- @index.index_file(uri)
867
-
868
- assert_equal(["Bar", "Foo", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Bar"))
869
-
870
- # Remove include to invalidate the ancestor tree
871
- File.write(File.join(dir, "foo.rb"), <<~RUBY)
872
- class Foo
873
- end
874
-
875
- class Bar
876
- end
877
- RUBY
878
-
879
- path = uri.full_path #: as !nil
880
- @index.handle_change(uri, File.read(path))
881
- assert_empty(@index.instance_variable_get(:@ancestors))
882
- assert_equal(["Bar", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Bar"))
883
- end
884
- end
885
- end
886
-
887
- def test_resolving_inherited_constants
888
- index(<<~RUBY)
889
- module Foo
890
- CONST = 1
891
- end
892
-
893
- module Baz
894
- CONST = 2
895
- end
896
-
897
- module Qux
898
- include Foo
899
- end
900
-
901
- module Namespace
902
- CONST = 3
903
-
904
- include Baz
905
-
906
- class Bar
907
- include Qux
908
- end
909
- end
910
-
911
- CONST = 4
912
- RUBY
913
-
914
- entry = @index.resolve("CONST", ["Namespace", "Bar"])&.first #: as !nil
915
- assert_equal(14, entry.location.start_line)
916
- end
917
-
918
- def test_resolving_inherited_aliased_namespace
919
- index(<<~RUBY)
920
- module Bar
921
- TARGET = 123
922
- end
923
-
924
- module Foo
925
- CONST = Bar
926
- end
927
-
928
- module Namespace
929
- class Bar
930
- include Foo
931
- end
932
- end
933
- RUBY
934
-
935
- entry = @index.resolve("Foo::CONST::TARGET", [])&.first #: as !nil
936
- assert_equal(2, entry.location.start_line)
937
-
938
- entry = @index.resolve("Namespace::Bar::CONST::TARGET", [])&.first #: as !nil
939
- assert_equal(2, entry.location.start_line)
940
- end
941
-
942
- def test_resolving_same_constant_from_different_scopes
943
- index(<<~RUBY)
944
- module Namespace
945
- CONST = 123
946
-
947
- class Parent
948
- CONST = 321
949
- end
950
-
951
- class Child < Parent
952
- end
953
- end
954
- RUBY
955
-
956
- entry = @index.resolve("CONST", ["Namespace", "Child"])&.first #: as !nil
957
- assert_equal(2, entry.location.start_line)
958
-
959
- entry = @index.resolve("Namespace::Child::CONST", [])&.first #: as !nil
960
- assert_equal(5, entry.location.start_line)
961
- end
962
-
963
- def test_resolving_prepended_constants
964
- index(<<~RUBY)
965
- module Included
966
- CONST = 123
967
- end
968
-
969
- module Prepended
970
- CONST = 321
971
- end
972
-
973
- class Foo
974
- include Included
975
- prepend Prepended
976
- end
977
-
978
- class Bar
979
- CONST = 456
980
- include Included
981
- prepend Prepended
982
- end
983
- RUBY
984
-
985
- entry = @index.resolve("CONST", ["Foo"])&.first #: as !nil
986
- assert_equal(6, entry.location.start_line)
987
-
988
- entry = @index.resolve("Foo::CONST", [])&.first #: as !nil
989
- assert_equal(6, entry.location.start_line)
990
-
991
- entry = @index.resolve("Bar::CONST", [])&.first #: as !nil
992
- assert_equal(15, entry.location.start_line)
993
- end
994
-
995
- def test_resolving_constants_favors_ancestors_over_top_level
996
- index(<<~RUBY)
997
- module Value1
998
- CONST = 1
999
- end
1000
-
1001
- module Value2
1002
- CONST = 2
1003
- end
1004
-
1005
- CONST = 3
1006
- module First
1007
- include Value1
1008
-
1009
- module Second
1010
- include Value2
1011
- end
1012
- end
1013
- RUBY
1014
-
1015
- entry = @index.resolve("CONST", ["First", "Second"])&.first #: as !nil
1016
- assert_equal(6, entry.location.start_line)
1017
- end
1018
-
1019
- def test_resolving_circular_alias
1020
- index(<<~RUBY)
1021
- module Namespace
1022
- FOO = BAR
1023
- BAR = FOO
1024
- end
1025
- RUBY
1026
-
1027
- foo_entry = @index.resolve("FOO", ["Namespace"])&.first #: as !nil
1028
- assert_equal(2, foo_entry.location.start_line)
1029
- assert_instance_of(Entry::ConstantAlias, foo_entry)
1030
-
1031
- bar_entry = @index.resolve("BAR", ["Namespace"])&.first #: as !nil
1032
- assert_equal(3, bar_entry.location.start_line)
1033
- assert_instance_of(Entry::ConstantAlias, bar_entry)
1034
- end
1035
-
1036
- def test_resolving_circular_alias_three_levels
1037
- index(<<~RUBY)
1038
- module Namespace
1039
- FOO = BAR
1040
- BAR = BAZ
1041
- BAZ = FOO
1042
- end
1043
- RUBY
1044
-
1045
- foo_entry = @index.resolve("FOO", ["Namespace"])&.first #: as !nil
1046
- assert_equal(2, foo_entry.location.start_line)
1047
- assert_instance_of(Entry::ConstantAlias, foo_entry)
1048
-
1049
- bar_entry = @index.resolve("BAR", ["Namespace"])&.first #: as !nil
1050
- assert_equal(3, bar_entry.location.start_line)
1051
- assert_instance_of(Entry::ConstantAlias, bar_entry)
1052
-
1053
- baz_entry = @index.resolve("BAZ", ["Namespace"])&.first #: as !nil
1054
- assert_equal(4, baz_entry.location.start_line)
1055
- assert_instance_of(Entry::ConstantAlias, baz_entry)
1056
- end
1057
-
1058
- def test_resolving_constants_in_aliased_namespace
1059
- index(<<~RUBY)
1060
- module Original
1061
- module Something
1062
- CONST = 123
1063
- end
1064
- end
1065
-
1066
- module Other
1067
- ALIAS = Original::Something
1068
- end
1069
-
1070
- module Third
1071
- Other::ALIAS::CONST
1072
- end
1073
- RUBY
1074
-
1075
- entry = @index.resolve("Other::ALIAS::CONST", ["Third"])&.first #: as !nil
1076
- assert_kind_of(Entry::Constant, entry)
1077
- assert_equal("Original::Something::CONST", entry.name)
1078
- end
1079
-
1080
- def test_resolving_top_level_aliases
1081
- index(<<~RUBY)
1082
- class Foo
1083
- CONST = 123
1084
- end
1085
-
1086
- FOO = Foo
1087
- FOO::CONST
1088
- RUBY
1089
-
1090
- entry = @index.resolve("FOO::CONST", [])&.first #: as !nil
1091
- assert_kind_of(Entry::Constant, entry)
1092
- assert_equal("Foo::CONST", entry.name)
1093
- end
1094
-
1095
- def test_resolving_top_level_compact_reference
1096
- index(<<~RUBY)
1097
- class Foo::Bar
1098
- end
1099
- RUBY
1100
-
1101
- foo_entry = @index.resolve("Foo::Bar", [])&.first #: as !nil
1102
- assert_equal(1, foo_entry.location.start_line)
1103
- assert_instance_of(Entry::Class, foo_entry)
1104
- end
1105
-
1106
- def test_resolving_references_with_redundant_namespaces
1107
- index(<<~RUBY)
1108
- module Bar
1109
- CONST = 1
1110
- end
1111
-
1112
- module A
1113
- CONST = 2
1114
-
1115
- module B
1116
- CONST = 3
1117
-
1118
- class Foo
1119
- include Bar
1120
- end
1121
-
1122
- A::B::Foo::CONST
1123
- end
1124
- end
1125
- RUBY
1126
-
1127
- foo_entry = @index.resolve("A::B::Foo::CONST", ["A", "B"])&.first #: as !nil
1128
- assert_equal(2, foo_entry.location.start_line)
1129
- end
1130
-
1131
- def test_resolving_qualified_references
1132
- index(<<~RUBY)
1133
- module Namespace
1134
- class Entry
1135
- CONST = 1
1136
- end
1137
- end
1138
-
1139
- module Namespace
1140
- class Index
1141
- end
1142
- end
1143
- RUBY
1144
-
1145
- foo_entry = @index.resolve("Entry::CONST", ["Namespace", "Index"])&.first #: as !nil
1146
- assert_equal(3, foo_entry.location.start_line)
1147
- end
1148
-
1149
- def test_resolving_unqualified_references
1150
- index(<<~RUBY)
1151
- module Foo
1152
- CONST = 1
1153
- end
1154
-
1155
- module Namespace
1156
- CONST = 2
1157
-
1158
- class Index
1159
- include Foo
1160
- end
1161
- end
1162
- RUBY
1163
-
1164
- foo_entry = @index.resolve("CONST", ["Namespace", "Index"])&.first #: as !nil
1165
- assert_equal(6, foo_entry.location.start_line)
1166
- end
1167
-
1168
- def test_resolving_references_with_only_top_level_declaration
1169
- index(<<~RUBY)
1170
- CONST = 1
1171
-
1172
- module Foo; end
1173
-
1174
- module Namespace
1175
- class Index
1176
- include Foo
1177
- end
1178
- end
1179
- RUBY
1180
-
1181
- foo_entry = @index.resolve("CONST", ["Namespace", "Index"])&.first #: as !nil
1182
- assert_equal(1, foo_entry.location.start_line)
1183
- end
1184
-
1185
- def test_instance_variables_completions_from_different_owners_with_conflicting_names
1186
- index(<<~RUBY)
1187
- class Foo
1188
- def initialize
1189
- @bar = 1
1190
- end
1191
- end
1192
-
1193
- class Bar
1194
- def initialize
1195
- @bar = 2
1196
- end
1197
- end
1198
- RUBY
1199
-
1200
- entry = @index.instance_variable_completion_candidates("@", "Bar").first #: as !nil
1201
- assert_equal("@bar", entry.name)
1202
- assert_equal("Bar", entry.owner&.name)
1203
- end
1204
-
1205
- def test_resolving_a_qualified_reference
1206
- index(<<~RUBY)
1207
- class Base
1208
- module Third
1209
- CONST = 1
1210
- end
1211
- end
1212
-
1213
- class Foo
1214
- module Third
1215
- CONST = 2
1216
- end
1217
-
1218
- class Second < Base
1219
- end
1220
- end
1221
- RUBY
1222
-
1223
- foo_entry = @index.resolve("Third::CONST", ["Foo"])&.first #: as !nil
1224
- assert_equal(9, foo_entry.location.start_line)
1225
- end
1226
-
1227
- def test_resolving_unindexed_constant_with_no_nesting
1228
- assert_nil(@index.resolve("RSpec", []))
1229
- end
1230
-
1231
- def test_object_superclass_indexing_and_resolution_with_reopened_object_class
1232
- index(<<~RUBY)
1233
- class Object; end
1234
- RUBY
1235
-
1236
- entries = @index["Object"] #: as !nil
1237
- assert_equal(2, entries.length)
1238
- reopened_entry = entries.last #: as Entry::Class
1239
- assert_equal("::BasicObject", reopened_entry.parent_class)
1240
- assert_equal(["Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Object"))
1241
- end
1242
-
1243
- def test_object_superclass_indexing_and_resolution_with_reopened_basic_object_class
1244
- index(<<~RUBY)
1245
- class BasicObject; end
1246
- RUBY
1247
-
1248
- entries = @index["BasicObject"] #: as !nil
1249
- assert_equal(2, entries.length)
1250
- reopened_entry = entries.last #: as Entry::Class
1251
- assert_nil(reopened_entry.parent_class)
1252
- assert_equal(["BasicObject"], @index.linearized_ancestors_of("BasicObject"))
1253
- end
1254
-
1255
- def test_object_superclass_resolution
1256
- index(<<~RUBY)
1257
- module Foo
1258
- class Object; end
1259
-
1260
- class Bar; end
1261
- class Baz < Object; end
1262
- end
1263
- RUBY
1264
-
1265
- assert_equal(["Foo::Bar", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Foo::Bar"))
1266
- assert_equal(
1267
- ["Foo::Baz", "Foo::Object", "Object", "Kernel", "BasicObject"],
1268
- @index.linearized_ancestors_of("Foo::Baz"),
1269
- )
1270
- end
1271
-
1272
- def test_basic_object_superclass_resolution
1273
- index(<<~RUBY)
1274
- module Foo
1275
- class BasicObject; end
1276
-
1277
- class Bar; end
1278
- class Baz < BasicObject; end
1279
- end
1280
- RUBY
1281
-
1282
- assert_equal(["Foo::Bar", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Foo::Bar"))
1283
- assert_equal(
1284
- ["Foo::Baz", "Foo::BasicObject", "Object", "Kernel", "BasicObject"],
1285
- @index.linearized_ancestors_of("Foo::Baz"),
1286
- )
1287
- end
1288
-
1289
- def test_top_level_object_superclass_resolution
1290
- index(<<~RUBY)
1291
- module Foo
1292
- class Object; end
1293
-
1294
- class Bar < ::Object; end
1295
- end
1296
- RUBY
1297
-
1298
- assert_equal(["Foo::Bar", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Foo::Bar"))
1299
- end
1300
-
1301
- def test_top_level_basic_object_superclass_resolution
1302
- index(<<~RUBY)
1303
- module Foo
1304
- class BasicObject; end
1305
-
1306
- class Bar < ::BasicObject; end
1307
- end
1308
- RUBY
1309
-
1310
- assert_equal(["Foo::Bar", "BasicObject"], @index.linearized_ancestors_of("Foo::Bar"))
1311
- end
1312
-
1313
- def test_resolving_method_inside_singleton_context
1314
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1315
- module Foo
1316
- class Bar
1317
- class << self
1318
- class Baz
1319
- class << self
1320
- def found_me!; end
1321
- end
1322
- end
1323
- end
1324
- end
1325
- end
1326
- RUBY
1327
-
1328
- entry = @index.resolve_method("found_me!", "Foo::Bar::<Class:Bar>::Baz::<Class:Baz>")&.first #: as !nil
1329
- refute_nil(entry)
1330
- assert_equal("found_me!", entry.name)
1331
- end
1332
-
1333
- def test_resolving_constants_in_singleton_contexts
1334
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1335
- module Foo
1336
- class Bar
1337
- CONST = 3
1338
-
1339
- class << self
1340
- CONST = 2
1341
-
1342
- class Baz
1343
- CONST = 1
1344
-
1345
- class << self
1346
- end
1347
- end
1348
- end
1349
- end
1350
- end
1351
- RUBY
1352
-
1353
- entry = @index.resolve("CONST", ["Foo", "Bar", "<Class:Bar>", "Baz", "<Class:Baz>"])&.first #: as !nil
1354
- refute_nil(entry)
1355
- assert_equal(9, entry.location.start_line)
1356
- end
1357
-
1358
- def test_resolving_instance_variables_in_singleton_contexts
1359
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1360
- module Foo
1361
- class Bar
1362
- @a = 123
1363
-
1364
- class << self
1365
- def hello
1366
- @b = 123
1367
- end
1368
-
1369
- @c = 123
1370
- end
1371
- end
1372
- end
1373
- RUBY
1374
-
1375
- entry = @index.resolve_instance_variable("@a", "Foo::Bar::<Class:Bar>")&.first #: as !nil
1376
- refute_nil(entry)
1377
- assert_equal("@a", entry.name)
1378
-
1379
- entry = @index.resolve_instance_variable("@b", "Foo::Bar::<Class:Bar>")&.first #: as !nil
1380
- refute_nil(entry)
1381
- assert_equal("@b", entry.name)
1382
-
1383
- entry = @index.resolve_instance_variable("@c", "Foo::Bar::<Class:Bar>::<Class:<Class:Bar>>")&.first #: as !nil
1384
- refute_nil(entry)
1385
- assert_equal("@c", entry.name)
1386
- end
1387
-
1388
- def test_instance_variable_completion_in_singleton_contexts
1389
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1390
- module Foo
1391
- class Bar
1392
- @a = 123
1393
-
1394
- class << self
1395
- def hello
1396
- @b = 123
1397
- end
1398
-
1399
- @c = 123
1400
- end
1401
- end
1402
- end
1403
- RUBY
1404
-
1405
- entries = @index.instance_variable_completion_candidates("@", "Foo::Bar::<Class:Bar>").map(&:name)
1406
- assert_includes(entries, "@a")
1407
- assert_includes(entries, "@b")
1408
- end
1409
-
1410
- def test_singletons_are_excluded_from_prefix_search
1411
- index(<<~RUBY)
1412
- class Zwq
1413
- class << self
1414
- end
1415
- end
1416
- RUBY
1417
-
1418
- assert_empty(@index.prefix_search("Zwq::<C"))
1419
- end
1420
-
1421
- def test_singletons_are_excluded_from_fuzzy_search
1422
- index(<<~RUBY)
1423
- class Zwq
1424
- class << self
1425
- end
1426
- end
1427
- RUBY
1428
-
1429
- results = @index.fuzzy_search("Zwq")
1430
- assert_equal(1, results.length)
1431
- assert_equal("Zwq", results.first&.name)
1432
- end
1433
-
1434
- def test_resolving_method_aliases
1435
- index(<<~RUBY)
1436
- class Foo
1437
- def bar(a, b, c)
1438
- end
1439
-
1440
- alias double_alias bar
1441
- end
1442
-
1443
- class Bar < Foo
1444
- def hello(b); end
1445
-
1446
- alias baz bar
1447
- alias_method :qux, :hello
1448
- alias double double_alias
1449
- end
1450
- RUBY
1451
-
1452
- # baz
1453
- methods = @index.resolve_method("baz", "Bar") #: as !nil
1454
- refute_nil(methods)
1455
-
1456
- entry = methods.first #: as Entry::MethodAlias
1457
- assert_kind_of(Entry::MethodAlias, entry)
1458
- assert_equal("bar", entry.target.name)
1459
- assert_equal("Foo", entry.target.owner&.name)
1460
-
1461
- # qux
1462
- methods = @index.resolve_method("qux", "Bar") #: as !nil
1463
- refute_nil(methods)
1464
-
1465
- entry = methods.first #: as Entry::MethodAlias
1466
- assert_kind_of(Entry::MethodAlias, entry)
1467
- assert_equal("hello", entry.target.name)
1468
- assert_equal("Bar", entry.target.owner&.name)
1469
-
1470
- # double
1471
- methods = @index.resolve_method("double", "Bar") #: as !nil
1472
- refute_nil(methods)
1473
-
1474
- entry = methods.first #: as Entry::MethodAlias
1475
- assert_kind_of(Entry::MethodAlias, entry)
1476
-
1477
- target = entry.target #: as Entry::MethodAlias
1478
- assert_equal("double_alias", target.name)
1479
- assert_kind_of(Entry::MethodAlias, target)
1480
- assert_equal("Foo", target.owner&.name)
1481
-
1482
- final_target = target.target
1483
- assert_equal("bar", final_target.name)
1484
- assert_kind_of(Entry::Method, final_target)
1485
- assert_equal("Foo", final_target.owner&.name)
1486
- end
1487
-
1488
- def test_resolving_circular_method_aliases
1489
- index(<<~RUBY)
1490
- class Foo
1491
- alias bar bar
1492
- end
1493
- RUBY
1494
-
1495
- # It's not possible to resolve an alias that points to itself
1496
- methods = @index.resolve_method("bar", "Foo")
1497
- assert_nil(methods)
1498
-
1499
- entry = @index["bar"]&.first
1500
- assert_kind_of(Entry::UnresolvedMethodAlias, entry)
1501
- end
1502
-
1503
- def test_unresolvable_method_aliases
1504
- index(<<~RUBY)
1505
- class Foo
1506
- alias bar baz
1507
- end
1508
- RUBY
1509
-
1510
- # `baz` does not exist, so resolving `bar` is not possible
1511
- methods = @index.resolve_method("bar", "Foo")
1512
- assert_nil(methods)
1513
-
1514
- entry = @index["bar"]&.first
1515
- assert_kind_of(Entry::UnresolvedMethodAlias, entry)
1516
- end
1517
-
1518
- def test_only_aliases_for_the_right_owner_are_resolved
1519
- index(<<~RUBY)
1520
- class Foo
1521
- attr_reader :name
1522
- alias_method :decorated_name, :name
1523
- end
1524
-
1525
- class Bar
1526
- alias_method :decorated_name, :to_s
1527
- end
1528
- RUBY
1529
-
1530
- methods = @index.resolve_method("decorated_name", "Foo") #: as !nil
1531
- refute_nil(methods)
1532
-
1533
- entry = methods.first #: as Entry::MethodAlias
1534
- assert_kind_of(Entry::MethodAlias, entry)
1535
-
1536
- target = entry.target
1537
- assert_equal("name", target.name)
1538
- assert_kind_of(Entry::Accessor, target)
1539
- assert_equal("Foo", target.owner&.name)
1540
-
1541
- other_decorated_name = @index["decorated_name"]&.find { |e| e.is_a?(Entry::UnresolvedMethodAlias) }
1542
- assert_kind_of(Entry::UnresolvedMethodAlias, other_decorated_name)
1543
- end
1544
-
1545
- def test_completion_does_not_include_unresolved_aliases
1546
- index(<<~RUBY)
1547
- class Foo
1548
- alias_method :bar, :missing
1549
- end
1550
- RUBY
1551
-
1552
- assert_empty(@index.method_completion_candidates("bar", "Foo"))
1553
- end
1554
-
1555
- def test_first_unqualified_const
1556
- index(<<~RUBY)
1557
- module Foo
1558
- class Bar; end
1559
- end
1560
-
1561
- module Baz
1562
- class Bar; end
1563
- end
1564
- RUBY
1565
-
1566
- entry = @index.first_unqualified_const("Bar")&.first #: as !nil
1567
- assert_equal("Foo::Bar", entry.name)
1568
- end
1569
-
1570
- def test_first_unqualified_const_prefers_exact_matches
1571
- index(<<~RUBY)
1572
- module Foo
1573
- class ParseResultType
1574
- end
1575
- end
1576
-
1577
- module Namespace
1578
- class Type
1579
- end
1580
- end
1581
- RUBY
1582
-
1583
- entry = @index.first_unqualified_const("Type")&.first #: as !nil
1584
- assert_equal("Namespace::Type", entry.name)
1585
- end
1586
-
1587
- def test_completion_does_not_duplicate_overridden_methods
1588
- index(<<~RUBY)
1589
- class Foo
1590
- def bar; end
1591
- end
1592
-
1593
- class Baz < Foo
1594
- def bar; end
1595
- end
1596
- RUBY
1597
-
1598
- entries = @index.method_completion_candidates("bar", "Baz")
1599
- assert_equal(["bar"], entries.map(&:name))
1600
- assert_equal("Baz", entries.first&.owner&.name)
1601
- end
1602
-
1603
- def test_completion_does_not_duplicate_methods_overridden_by_aliases
1604
- index(<<~RUBY)
1605
- class Foo
1606
- def bar; end
1607
- end
1608
-
1609
- class Baz < Foo
1610
- alias bar to_s
1611
- end
1612
- RUBY
1613
-
1614
- entries = @index.method_completion_candidates("bar", "Baz")
1615
- assert_equal(["bar"], entries.map(&:name))
1616
- assert_equal("Baz", entries.first&.owner&.name)
1617
- end
1618
-
1619
- def test_decorated_parameters
1620
- index(<<~RUBY)
1621
- class Foo
1622
- def bar(a, b = 1, c: 2)
1623
- end
1624
- end
1625
- RUBY
1626
-
1627
- methods = @index.resolve_method("bar", "Foo") #: as !nil
1628
- refute_nil(methods)
1629
-
1630
- entry = methods.first #: as Entry::Method
1631
- assert_equal("(a, b = <default>, c: <default>)", entry.decorated_parameters)
1632
- end
1633
-
1634
- def test_decorated_parameters_when_method_has_no_parameters
1635
- index(<<~RUBY)
1636
- class Foo
1637
- def bar
1638
- end
1639
- end
1640
- RUBY
1641
-
1642
- methods = @index.resolve_method("bar", "Foo") #: as !nil
1643
- refute_nil(methods)
1644
-
1645
- entry = methods.first #: as Entry::Method
1646
- assert_equal("()", entry.decorated_parameters)
1647
- end
1648
-
1649
- def test_linearizing_singleton_ancestors_of_singleton_when_class_has_parent
1650
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1651
- class Foo; end
1652
-
1653
- class Bar < Foo
1654
- end
1655
-
1656
- class Baz < Bar
1657
- class << self
1658
- class << self
1659
- end
1660
- end
1661
- end
1662
- RUBY
1663
-
1664
- assert_equal(
1665
- [
1666
- "Baz::<Class:Baz>::<Class:<Class:Baz>>",
1667
- "Bar::<Class:Bar>::<Class:<Class:Bar>>",
1668
- "Foo::<Class:Foo>::<Class:<Class:Foo>>",
1669
- "Object::<Class:Object>::<Class:<Class:Object>>",
1670
- "BasicObject::<Class:BasicObject>::<Class:<Class:BasicObject>>",
1671
- "Class::<Class:Class>",
1672
- "Module::<Class:Module>",
1673
- "Object::<Class:Object>",
1674
- "BasicObject::<Class:BasicObject>",
1675
- "Class",
1676
- "Module",
1677
- "Object",
1678
- "Kernel",
1679
- "BasicObject",
1680
- ],
1681
- @index.linearized_ancestors_of("Baz::<Class:Baz>::<Class:<Class:Baz>>"),
1682
- )
1683
- end
1684
-
1685
- def test_linearizing_singleton_object
1686
- assert_equal(
1687
- [
1688
- "Object::<Class:Object>",
1689
- "BasicObject::<Class:BasicObject>",
1690
- "Class",
1691
- "Module",
1692
- "Object",
1693
- "Kernel",
1694
- "BasicObject",
1695
- ],
1696
- @index.linearized_ancestors_of("Object::<Class:Object>"),
1697
- )
1698
- end
1699
-
1700
- def test_extend_self
1701
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1702
- module Foo
1703
- def bar
1704
- end
1705
-
1706
- extend self
1707
-
1708
- def baz
1709
- end
1710
- end
1711
- RUBY
1712
-
1713
- ["bar", "baz"].product(["Foo", "Foo::<Class:Foo>"]).each do |method, receiver|
1714
- entry = @index.resolve_method(method, receiver)&.first #: as !nil
1715
- refute_nil(entry)
1716
- assert_equal(method, entry.name)
1717
- end
1718
-
1719
- assert_equal(
1720
- [
1721
- "Foo::<Class:Foo>",
1722
- "Foo",
1723
- "Module",
1724
- "Object",
1725
- "Kernel",
1726
- "BasicObject",
1727
- ],
1728
- @index.linearized_ancestors_of("Foo::<Class:Foo>"),
1729
- )
1730
- end
1731
-
1732
- def test_linearizing_singleton_ancestors
1733
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1734
- module First
1735
- end
1736
-
1737
- module Second
1738
- include First
1739
- end
1740
-
1741
- module Foo
1742
- class Bar
1743
- class << self
1744
- class Baz
1745
- extend Second
1746
-
1747
- class << self
1748
- include First
1749
- end
1750
- end
1751
- end
1752
- end
1753
- end
1754
- RUBY
1755
-
1756
- assert_equal(
1757
- [
1758
- "Foo::Bar::<Class:Bar>::Baz::<Class:Baz>",
1759
- "Second",
1760
- "First",
1761
- "Object::<Class:Object>",
1762
- "BasicObject::<Class:BasicObject>",
1763
- "Class",
1764
- "Module",
1765
- "Object",
1766
- "Kernel",
1767
- "BasicObject",
1768
- ],
1769
- @index.linearized_ancestors_of("Foo::Bar::<Class:Bar>::Baz::<Class:Baz>"),
1770
- )
1771
- end
1772
-
1773
- def test_linearizing_singleton_ancestors_when_class_has_parent
1774
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1775
- class Foo; end
1776
-
1777
- class Bar < Foo
1778
- end
1779
-
1780
- class Baz < Bar
1781
- class << self
1782
- end
1783
- end
1784
- RUBY
1785
-
1786
- assert_equal(
1787
- [
1788
- "Baz::<Class:Baz>",
1789
- "Bar::<Class:Bar>",
1790
- "Foo::<Class:Foo>",
1791
- "Object::<Class:Object>",
1792
- "BasicObject::<Class:BasicObject>",
1793
- "Class",
1794
- "Module",
1795
- "Object",
1796
- "Kernel",
1797
- "BasicObject",
1798
- ],
1799
- @index.linearized_ancestors_of("Baz::<Class:Baz>"),
1800
- )
1801
- end
1802
-
1803
- def test_linearizing_a_module_singleton_class
1804
- @index.index_single(URI::Generic.from_path(path: "/fake/path/foo.rb"), <<~RUBY)
1805
- module A; end
1806
- RUBY
1807
-
1808
- assert_equal(
1809
- [
1810
- "A::<Class:A>",
1811
- "Module",
1812
- "Object",
1813
- "Kernel",
1814
- "BasicObject",
1815
- ],
1816
- @index.linearized_ancestors_of("A::<Class:A>"),
1817
- )
1818
- end
1819
-
1820
- def test_linearizing_a_singleton_class_with_no_attached
1821
- assert_raises(Index::NonExistingNamespaceError) do
1822
- @index.linearized_ancestors_of("A::<Class:A>")
1823
- end
1824
- end
1825
-
1826
- def test_linearizing_singleton_parent_class_with_namespace
1827
- index(<<~RUBY)
1828
- class ActiveRecord::Base; end
1829
-
1830
- class User < ActiveRecord::Base
1831
- end
1832
- RUBY
1833
-
1834
- assert_equal(
1835
- [
1836
- "User::<Class:User>",
1837
- "ActiveRecord::Base::<Class:Base>",
1838
- "Object::<Class:Object>",
1839
- "BasicObject::<Class:BasicObject>",
1840
- "Class",
1841
- "Module",
1842
- "Object",
1843
- "Kernel",
1844
- "BasicObject",
1845
- ],
1846
- @index.linearized_ancestors_of("User::<Class:User>"),
1847
- )
1848
- end
1849
-
1850
- def test_singleton_nesting_is_correctly_split_during_linearization
1851
- index(<<~RUBY)
1852
- module Bar; end
1853
-
1854
- module Foo
1855
- class Namespace::Parent
1856
- extend Bar
1857
- end
1858
- end
1859
-
1860
- module Foo
1861
- class Child < Namespace::Parent
1862
- end
1863
- end
1864
- RUBY
1865
-
1866
- assert_equal(
1867
- [
1868
- "Foo::Child::<Class:Child>",
1869
- "Foo::Namespace::Parent::<Class:Parent>",
1870
- "Bar",
1871
- "Object::<Class:Object>",
1872
- "BasicObject::<Class:BasicObject>",
1873
- "Class",
1874
- "Module",
1875
- "Object",
1876
- "Kernel",
1877
- "BasicObject",
1878
- ],
1879
- @index.linearized_ancestors_of("Foo::Child::<Class:Child>"),
1880
- )
1881
- end
1882
-
1883
- def test_resolving_circular_method_aliases_on_class_reopen
1884
- index(<<~RUBY)
1885
- class Foo
1886
- alias bar ==
1887
- def ==(other) = true
1888
- end
1889
-
1890
- class Foo
1891
- alias == bar
1892
- end
1893
- RUBY
1894
-
1895
- method = @index.resolve_method("==", "Foo")&.first #: as Entry::Method
1896
- assert_kind_of(Entry::Method, method)
1897
- assert_equal("==", method.name)
1898
-
1899
- candidates = @index.method_completion_candidates("=", "Foo")
1900
- assert_equal(["==", "==="], candidates.map(&:name))
1901
- end
1902
-
1903
- def test_entries_for
1904
- index(<<~RUBY)
1905
- class Foo; end
1906
-
1907
- module Bar
1908
- def my_def; end
1909
- def self.my_singleton_def; end
1910
- end
1911
- RUBY
1912
-
1913
- entries = @index.entries_for("file:///fake/path/foo.rb", Entry) #: as !nil
1914
- assert_equal(["Foo", "Bar", "my_def", "Bar::<Class:Bar>", "my_singleton_def"], entries.map(&:name))
1915
-
1916
- entries = @index.entries_for("file:///fake/path/foo.rb", RubyIndexer::Entry::Namespace) #: as !nil
1917
- assert_equal(["Foo", "Bar", "Bar::<Class:Bar>"], entries.map(&:name))
1918
-
1919
- entries = @index.entries_for("file:///fake/path/foo.rb") #: as !nil
1920
- assert_equal(["Foo", "Bar", "my_def", "Bar::<Class:Bar>", "my_singleton_def"], entries.map(&:name))
1921
- end
1922
-
1923
- def test_entries_for_returns_nil_if_no_matches
1924
- assert_nil(@index.entries_for("non_existing_file.rb", Entry::Namespace))
1925
- end
1926
-
1927
- def test_constant_completion_candidates_all_possible_constants
1928
- index(<<~RUBY)
1929
- XQRK = 3
1930
-
1931
- module Bar
1932
- XQRK = 2
1933
- end
1934
-
1935
- module Foo
1936
- XQRK = 1
1937
- end
1938
-
1939
- module Namespace
1940
- XQRK = 0
1941
-
1942
- class Baz
1943
- include Foo
1944
- include Bar
1945
- end
1946
- end
1947
- RUBY
1948
-
1949
- result = @index.constant_completion_candidates("X", ["Namespace", "Baz"])
1950
-
1951
- result.each do |entries|
1952
- name = entries.first&.name
1953
- assert(entries.all? { |e| e.name == name })
1954
- end
1955
-
1956
- assert_equal(["Namespace::XQRK", "Bar::XQRK", "XQRK"], result.map { |entries| entries.first&.name })
1957
-
1958
- result = @index.constant_completion_candidates("::X", ["Namespace", "Baz"])
1959
- assert_equal(["XQRK"], result.map { |entries| entries.first&.name })
1960
- end
1961
-
1962
- def test_constant_completion_candidates_for_empty_name
1963
- index(<<~RUBY)
1964
- module Foo
1965
- Bar = 1
1966
- end
1967
-
1968
- class Baz
1969
- include Foo
1970
- end
1971
- RUBY
1972
-
1973
- result = @index.constant_completion_candidates("Baz::", [])
1974
- assert_includes(result.map { |entries| entries.first&.name }, "Foo::Bar")
1975
- end
1976
-
1977
- def test_follow_alias_namespace
1978
- index(<<~RUBY)
1979
- module First
1980
- module Second
1981
- class Foo
1982
- end
1983
- end
1984
- end
1985
-
1986
- module Namespace
1987
- Second = First::Second
1988
- end
1989
- RUBY
1990
-
1991
- real_namespace = @index.follow_aliased_namespace("Namespace::Second")
1992
- assert_equal("First::Second", real_namespace)
1993
- end
1994
-
1995
- def test_resolving_alias_to_non_existing_namespace
1996
- index(<<~RUBY)
1997
- module Namespace
1998
- class Foo
1999
- module InnerNamespace
2000
- Constants = Namespace::Foo::Constants
2001
- end
2002
- end
2003
- end
2004
- RUBY
2005
-
2006
- entry = @index.resolve("Constants", ["Namespace", "Foo", "InnerNamespace"])&.first
2007
- assert_instance_of(Entry::UnresolvedConstantAlias, entry)
2008
-
2009
- entry = @index.resolve("Namespace::Foo::Constants", ["Namespace", "Foo", "InnerNamespace"])&.first
2010
- assert_nil(entry)
2011
- end
2012
-
2013
- def test_resolving_alias_to_existing_constant_from_inner_namespace
2014
- index(<<~RUBY)
2015
- module Parent
2016
- CONST = 123
2017
- end
2018
-
2019
- module First
2020
- module Namespace
2021
- class Foo
2022
- include Parent
2023
-
2024
- module InnerNamespace
2025
- Constants = Namespace::Foo::CONST
2026
- end
2027
- end
2028
- end
2029
- end
2030
- RUBY
2031
-
2032
- entry = @index.resolve("Namespace::Foo::CONST", ["First", "Namespace", "Foo", "InnerNamespace"])&.first #: as !nil
2033
- assert_equal("Parent::CONST", entry.name)
2034
- assert_instance_of(Entry::Constant, entry)
2035
- end
2036
-
2037
- def test_build_non_redundant_name
2038
- assert_equal(
2039
- "Namespace::Foo::Constants",
2040
- @index.send(
2041
- :build_non_redundant_full_name,
2042
- "Namespace::Foo::Constants",
2043
- ["Namespace", "Foo", "InnerNamespace"],
2044
- ),
2045
- )
2046
-
2047
- assert_equal(
2048
- "Namespace::Foo::Constants",
2049
- @index.send(
2050
- :build_non_redundant_full_name,
2051
- "Namespace::Foo::Constants",
2052
- ["Namespace", "Foo"],
2053
- ),
2054
- )
2055
-
2056
- assert_equal(
2057
- "Namespace::Foo::Constants",
2058
- @index.send(
2059
- :build_non_redundant_full_name,
2060
- "Foo::Constants",
2061
- ["Namespace", "Foo"],
2062
- ),
2063
- )
2064
-
2065
- assert_equal(
2066
- "Bar::Namespace::Foo::Constants",
2067
- @index.send(
2068
- :build_non_redundant_full_name,
2069
- "Namespace::Foo::Constants",
2070
- ["Bar"],
2071
- ),
2072
- )
2073
-
2074
- assert_equal(
2075
- "First::Namespace::Foo::Constants",
2076
- @index.send(
2077
- :build_non_redundant_full_name,
2078
- "Namespace::Foo::Constants",
2079
- ["First", "Namespace", "Foo", "InnerNamespace"],
2080
- ),
2081
- )
2082
- end
2083
-
2084
- def test_prevents_multiple_calls_to_index_all
2085
- @index.index_all
2086
-
2087
- assert_raises(Index::IndexNotEmptyError) do
2088
- @index.index_all
2089
- end
2090
- end
2091
-
2092
- def test_index_can_handle_entries_from_untitled_scheme
2093
- uri = URI("untitled:Untitled-1")
2094
-
2095
- index(<<~RUBY, uri: uri)
2096
- class Foo
2097
- end
2098
- RUBY
2099
-
2100
- entry = @index["Foo"]&.first #: as !nil
2101
- refute_nil(entry, "Expected indexer to be able to handle unsaved URIs")
2102
- assert_equal("untitled:Untitled-1", entry.uri.to_s)
2103
- assert_equal("Untitled-1", entry.file_name)
2104
- assert_nil(entry.file_path)
2105
-
2106
- @index.handle_change(uri, <<~RUBY)
2107
- # I added this comment!
2108
- class Foo
2109
- end
2110
- RUBY
2111
-
2112
- entry = @index["Foo"]&.first #: as !nil
2113
- refute_nil(entry, "Expected indexer to be able to handle unsaved URIs")
2114
- assert_equal("I added this comment!", entry.comments)
2115
- end
2116
-
2117
- def test_instance_variable_completion_returns_class_variables_too
2118
- index(<<~RUBY)
2119
- class Parent
2120
- @@abc = 123
2121
- end
2122
-
2123
- class Child < Parent
2124
- @@adf = 123
2125
-
2126
- def self.do
2127
- end
2128
- end
2129
- RUBY
2130
-
2131
- adf, abc = @index.instance_variable_completion_candidates("@", "Child::<Class:Child>")
2132
-
2133
- refute_nil(abc)
2134
- refute_nil(adf)
2135
-
2136
- assert_equal("@@abc", abc&.name)
2137
- assert_equal("@@adf", adf&.name)
2138
- end
2139
-
2140
- def test_class_variable_completion_from_singleton_context
2141
- index(<<~RUBY)
2142
- class Foo
2143
- @@hello = 123
2144
-
2145
- def self.do
2146
- end
2147
- end
2148
- RUBY
2149
-
2150
- candidates = @index.class_variable_completion_candidates("@@", "Foo::<Class:Foo>")
2151
- refute_empty(candidates)
2152
-
2153
- assert_equal("@@hello", candidates.first&.name)
2154
- end
2155
-
2156
- def test_resolve_class_variable_in_singleton_context
2157
- index(<<~RUBY)
2158
- class Foo
2159
- @@hello = 123
2160
- end
2161
- RUBY
2162
-
2163
- candidates = @index.resolve_class_variable("@@hello", "Foo::<Class:Foo>") #: as !nil
2164
- refute_empty(candidates)
2165
-
2166
- assert_equal("@@hello", candidates.first&.name)
2167
- end
2168
-
2169
- def test_actual_nesting
2170
- assert_equal(["Foo"], Index.actual_nesting([], "Foo"))
2171
- assert_equal(["TopLevel", "Foo"], Index.actual_nesting(["First", "::TopLevel"], "Foo"))
2172
- assert_equal(["TopLevel", "Another", "Foo"], Index.actual_nesting(["::TopLevel", "Another"], "Foo"))
2173
- assert_equal(["TopLevel"], Index.actual_nesting(["First", "::TopLevel"], nil))
2174
- end
2175
-
2176
- def test_constant_name
2177
- node = Prism.parse("class var::Foo; end").value.statements.body.first.constant_path
2178
- assert_nil(Index.constant_name(node))
2179
-
2180
- node = Prism.parse("class ; end").value.statements.body.first.constant_path
2181
- assert_nil(Index.constant_name(node))
2182
-
2183
- node = Prism.parse("class method_call; end").value.statements.body.first.constant_path
2184
- assert_nil(Index.constant_name(node))
2185
-
2186
- node = Prism.parse("class Foo; end").value.statements.body.first.constant_path
2187
- assert_equal("Foo", Index.constant_name(node))
2188
- end
2189
- end
2190
- end