ruby-lsp 0.23.11 → 0.26.6

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