ruby-lsp 0.17.3 → 0.17.5

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -0
  3. data/VERSION +1 -1
  4. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +251 -100
  5. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +173 -114
  6. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +337 -77
  7. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +43 -14
  8. data/lib/ruby_indexer/test/classes_and_modules_test.rb +79 -3
  9. data/lib/ruby_indexer/test/index_test.rb +563 -29
  10. data/lib/ruby_indexer/test/instance_variables_test.rb +84 -7
  11. data/lib/ruby_indexer/test/method_test.rb +75 -25
  12. data/lib/ruby_indexer/test/rbs_indexer_test.rb +38 -2
  13. data/lib/ruby_indexer/test/test_case.rb +1 -5
  14. data/lib/ruby_lsp/addon.rb +13 -1
  15. data/lib/ruby_lsp/document.rb +50 -23
  16. data/lib/ruby_lsp/erb_document.rb +125 -0
  17. data/lib/ruby_lsp/global_state.rb +11 -4
  18. data/lib/ruby_lsp/internal.rb +3 -0
  19. data/lib/ruby_lsp/listeners/completion.rb +69 -34
  20. data/lib/ruby_lsp/listeners/definition.rb +34 -23
  21. data/lib/ruby_lsp/listeners/hover.rb +14 -7
  22. data/lib/ruby_lsp/listeners/signature_help.rb +5 -2
  23. data/lib/ruby_lsp/node_context.rb +6 -1
  24. data/lib/ruby_lsp/requests/code_action_resolve.rb +2 -2
  25. data/lib/ruby_lsp/requests/completion.rb +6 -5
  26. data/lib/ruby_lsp/requests/completion_resolve.rb +7 -4
  27. data/lib/ruby_lsp/requests/definition.rb +4 -3
  28. data/lib/ruby_lsp/requests/formatting.rb +2 -0
  29. data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +88 -0
  30. data/lib/ruby_lsp/requests/selection_ranges.rb +1 -1
  31. data/lib/ruby_lsp/requests/show_syntax_tree.rb +3 -2
  32. data/lib/ruby_lsp/requests/support/common.rb +19 -1
  33. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +12 -4
  34. data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +87 -0
  35. data/lib/ruby_lsp/requests/workspace_symbol.rb +1 -21
  36. data/lib/ruby_lsp/requests.rb +2 -0
  37. data/lib/ruby_lsp/ruby_document.rb +10 -0
  38. data/lib/ruby_lsp/server.rb +95 -26
  39. data/lib/ruby_lsp/store.rb +23 -8
  40. data/lib/ruby_lsp/test_helper.rb +3 -1
  41. data/lib/ruby_lsp/type_inferrer.rb +86 -0
  42. metadata +10 -6
@@ -93,30 +93,30 @@ module RubyIndexer
93
93
 
94
94
  def test_fuzzy_search
95
95
  @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
96
- class Bar; end
96
+ class Zws; end
97
97
 
98
- module Foo
99
- class Bar
98
+ module Qtl
99
+ class Zws
100
100
  end
101
101
 
102
- class Baz
102
+ class Zwo
103
103
  class Something
104
104
  end
105
105
  end
106
106
  end
107
107
  RUBY
108
108
 
109
- result = @index.fuzzy_search("Bar")
110
- assert_equal(3, result.length)
111
- assert_equal(["Bar", "Backtrace", "Base"], result.map(&:name))
112
-
113
- result = @index.fuzzy_search("foobarsomeking")
114
- assert_equal(6, result.length)
115
- assert_equal(["Foo::Baz::Something", "Foo::Bar", "Foo::Baz", "Foo", "Base", "Bar"], result.map(&:name))
109
+ result = @index.fuzzy_search("Zws")
110
+ assert_equal(2, result.length)
111
+ assert_equal(["Zws", "Qtl::Zwo::Something"], result.map(&:name))
116
112
 
117
- result = @index.fuzzy_search("FooBaz")
113
+ result = @index.fuzzy_search("qtlzwssomeking")
118
114
  assert_equal(5, result.length)
119
- assert_equal(["Foo::Baz", "Foo::Bar", "Foo", "Foo::Baz::Something", "Float"], result.map(&:name))
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
120
  end
121
121
 
122
122
  def test_index_single_ignores_directories
@@ -140,25 +140,23 @@ module RubyIndexer
140
140
  end
141
141
 
142
142
  def test_searching_for_entries_based_on_prefix
143
- # For this test, it's easier if we don't include core classes and modules
144
- @index = Index.new
145
143
  @index.index_single(IndexablePath.new("/fake", "/fake/path/foo.rb"), <<~RUBY)
146
- class Foo::Bar
144
+ class Foo::Bizw
147
145
  end
148
146
  RUBY
149
147
  @index.index_single(IndexablePath.new("/fake", "/fake/path/other_foo.rb"), <<~RUBY)
150
- class Foo::Bar
148
+ class Foo::Bizw
151
149
  end
152
150
 
153
- class Foo::Baz
151
+ class Foo::Bizt
154
152
  end
155
153
  RUBY
156
154
 
157
155
  results = @index.prefix_search("Foo", []).map { |entries| entries.map(&:name) }
158
- assert_equal([["Foo::Bar", "Foo::Bar"], ["Foo::Baz"]], results)
156
+ assert_equal([["Foo::Bizw", "Foo::Bizw"], ["Foo::Bizt"]], results)
159
157
 
160
- results = @index.prefix_search("Ba", ["Foo"]).map { |entries| entries.map(&:name) }
161
- assert_equal([["Foo::Bar", "Foo::Bar"], ["Foo::Baz"]], results)
158
+ results = @index.prefix_search("Biz", ["Foo"]).map { |entries| entries.map(&:name) }
159
+ assert_equal([["Foo::Bizw", "Foo::Bizw"], ["Foo::Bizt"]], results)
162
160
  end
163
161
 
164
162
  def test_resolve_normalizes_top_level_names
@@ -291,16 +289,16 @@ module RubyIndexer
291
289
  index(<<~RUBY)
292
290
  module Foo
293
291
  module Bar
294
- def baz; end
292
+ def qzx; end
295
293
  end
296
294
  end
297
295
  RUBY
298
296
 
299
- entries = @index.prefix_search("ba")
297
+ entries = @index.prefix_search("qz")
300
298
  refute_empty(entries)
301
299
 
302
- entry = T.must(entries.first).first
303
- assert_equal("baz", entry.name)
300
+ entry = T.must(T.must(entries.first).first)
301
+ assert_equal("qzx", entry.name)
304
302
  end
305
303
 
306
304
  def test_indexing_prism_fixtures_succeeds
@@ -315,12 +313,12 @@ module RubyIndexer
315
313
  @index.index_single(indexable_path)
316
314
  end
317
315
 
318
- refute_empty(@index.instance_variable_get(:@entries))
316
+ refute_empty(@index)
319
317
  end
320
318
 
321
319
  def test_index_single_does_not_fail_for_non_existing_file
322
320
  @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"))
323
- entries_after_indexing = @index.instance_variable_get(:@entries).keys
321
+ entries_after_indexing = @index.names
324
322
  assert_equal(@default_indexed_entries.keys, entries_after_indexing)
325
323
  end
326
324
 
@@ -1009,6 +1007,43 @@ module RubyIndexer
1009
1007
  assert_instance_of(Entry::Alias, baz_entry)
1010
1008
  end
1011
1009
 
1010
+ def test_resolving_constants_in_aliased_namespace
1011
+ index(<<~RUBY)
1012
+ module Original
1013
+ module Something
1014
+ CONST = 123
1015
+ end
1016
+ end
1017
+
1018
+ module Other
1019
+ ALIAS = Original::Something
1020
+ end
1021
+
1022
+ module Third
1023
+ Other::ALIAS::CONST
1024
+ end
1025
+ RUBY
1026
+
1027
+ entry = T.must(@index.resolve("Other::ALIAS::CONST", ["Third"])&.first)
1028
+ assert_kind_of(Entry::Constant, entry)
1029
+ assert_equal("Original::Something::CONST", entry.name)
1030
+ end
1031
+
1032
+ def test_resolving_top_level_aliases
1033
+ index(<<~RUBY)
1034
+ class Foo
1035
+ CONST = 123
1036
+ end
1037
+
1038
+ FOO = Foo
1039
+ FOO::CONST
1040
+ RUBY
1041
+
1042
+ entry = T.must(@index.resolve("FOO::CONST", [])&.first)
1043
+ assert_kind_of(Entry::Constant, entry)
1044
+ assert_equal("Foo::CONST", entry.name)
1045
+ end
1046
+
1012
1047
  def test_resolving_top_level_compact_reference
1013
1048
  index(<<~RUBY)
1014
1049
  class Foo::Bar
@@ -1145,8 +1180,32 @@ module RubyIndexer
1145
1180
  assert_nil(@index.resolve("RSpec", []))
1146
1181
  end
1147
1182
 
1183
+ def test_object_superclass_indexing_and_resolution_with_reopened_object_class
1184
+ index(<<~RUBY)
1185
+ class Object; end
1186
+ RUBY
1187
+
1188
+ entries = @index["Object"]
1189
+ assert_equal(2, entries.length)
1190
+ reopened_entry = entries.last
1191
+ assert_equal("::BasicObject", reopened_entry.parent_class)
1192
+ assert_equal(["Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Object"))
1193
+ end
1194
+
1195
+ def test_object_superclass_indexing_and_resolution_with_reopened_basic_object_class
1196
+ index(<<~RUBY)
1197
+ class BasicObject; end
1198
+ RUBY
1199
+
1200
+ entries = @index["BasicObject"]
1201
+ assert_equal(2, entries.length)
1202
+ reopened_entry = entries.last
1203
+ assert_nil(reopened_entry.parent_class)
1204
+ assert_equal(["BasicObject"], @index.linearized_ancestors_of("BasicObject"))
1205
+ end
1206
+
1148
1207
  def test_object_superclass_resolution
1149
- @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
1208
+ index(<<~RUBY)
1150
1209
  module Foo
1151
1210
  class Object; end
1152
1211
 
@@ -1162,8 +1221,25 @@ module RubyIndexer
1162
1221
  )
1163
1222
  end
1164
1223
 
1224
+ def test_basic_object_superclass_resolution
1225
+ index(<<~RUBY)
1226
+ module Foo
1227
+ class BasicObject; end
1228
+
1229
+ class Bar; end
1230
+ class Baz < BasicObject; end
1231
+ end
1232
+ RUBY
1233
+
1234
+ assert_equal(["Foo::Bar", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Foo::Bar"))
1235
+ assert_equal(
1236
+ ["Foo::Baz", "Foo::BasicObject", "Object", "Kernel", "BasicObject"],
1237
+ @index.linearized_ancestors_of("Foo::Baz"),
1238
+ )
1239
+ end
1240
+
1165
1241
  def test_top_level_object_superclass_resolution
1166
- @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
1242
+ index(<<~RUBY)
1167
1243
  module Foo
1168
1244
  class Object; end
1169
1245
 
@@ -1173,5 +1249,463 @@ module RubyIndexer
1173
1249
 
1174
1250
  assert_equal(["Foo::Bar", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Foo::Bar"))
1175
1251
  end
1252
+
1253
+ def test_top_level_basic_object_superclass_resolution
1254
+ index(<<~RUBY)
1255
+ module Foo
1256
+ class BasicObject; end
1257
+
1258
+ class Bar < ::BasicObject; end
1259
+ end
1260
+ RUBY
1261
+
1262
+ assert_equal(["Foo::Bar", "BasicObject"], @index.linearized_ancestors_of("Foo::Bar"))
1263
+ end
1264
+
1265
+ def test_resolving_method_inside_singleton_context
1266
+ @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
1267
+ module Foo
1268
+ class Bar
1269
+ class << self
1270
+ class Baz
1271
+ class << self
1272
+ def found_me!; end
1273
+ end
1274
+ end
1275
+ end
1276
+ end
1277
+ end
1278
+ RUBY
1279
+
1280
+ entry = @index.resolve_method("found_me!", "Foo::Bar::<Class:Bar>::Baz::<Class:Baz>")&.first
1281
+ refute_nil(entry)
1282
+
1283
+ assert_equal("found_me!", T.must(entry).name)
1284
+ end
1285
+
1286
+ def test_resolving_constants_in_singleton_contexts
1287
+ @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
1288
+ module Foo
1289
+ class Bar
1290
+ CONST = 3
1291
+
1292
+ class << self
1293
+ CONST = 2
1294
+
1295
+ class Baz
1296
+ CONST = 1
1297
+
1298
+ class << self
1299
+ end
1300
+ end
1301
+ end
1302
+ end
1303
+ end
1304
+ RUBY
1305
+
1306
+ entry = @index.resolve("CONST", ["Foo", "Bar", "<Class:Bar>", "Baz", "<Class:Baz>"])&.first
1307
+ refute_nil(entry)
1308
+ assert_equal(9, T.must(entry).location.start_line)
1309
+ end
1310
+
1311
+ def test_resolving_instance_variables_in_singleton_contexts
1312
+ @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
1313
+ module Foo
1314
+ class Bar
1315
+ @a = 123
1316
+
1317
+ class << self
1318
+ def hello
1319
+ @b = 123
1320
+ end
1321
+
1322
+ @c = 123
1323
+ end
1324
+ end
1325
+ end
1326
+ RUBY
1327
+
1328
+ entry = @index.resolve_instance_variable("@a", "Foo::Bar::<Class:Bar>")&.first
1329
+ refute_nil(entry)
1330
+ assert_equal("@a", T.must(entry).name)
1331
+
1332
+ entry = @index.resolve_instance_variable("@b", "Foo::Bar::<Class:Bar>")&.first
1333
+ refute_nil(entry)
1334
+ assert_equal("@b", T.must(entry).name)
1335
+
1336
+ entry = @index.resolve_instance_variable("@c", "Foo::Bar::<Class:Bar>::<Class:<Class:Bar>>")&.first
1337
+ refute_nil(entry)
1338
+ assert_equal("@c", T.must(entry).name)
1339
+ end
1340
+
1341
+ def test_instance_variable_completion_in_singleton_contexts
1342
+ @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
1343
+ module Foo
1344
+ class Bar
1345
+ @a = 123
1346
+
1347
+ class << self
1348
+ def hello
1349
+ @b = 123
1350
+ end
1351
+
1352
+ @c = 123
1353
+ end
1354
+ end
1355
+ end
1356
+ RUBY
1357
+
1358
+ entries = @index.instance_variable_completion_candidates("@", "Foo::Bar::<Class:Bar>").map(&:name)
1359
+ assert_includes(entries, "@a")
1360
+ assert_includes(entries, "@b")
1361
+ end
1362
+
1363
+ def test_singletons_are_excluded_from_prefix_search
1364
+ index(<<~RUBY)
1365
+ class Zwq
1366
+ class << self
1367
+ end
1368
+ end
1369
+ RUBY
1370
+
1371
+ assert_empty(@index.prefix_search("Zwq::<C"))
1372
+ end
1373
+
1374
+ def test_singletons_are_excluded_from_fuzzy_search
1375
+ index(<<~RUBY)
1376
+ class Zwq
1377
+ class << self
1378
+ end
1379
+ end
1380
+ RUBY
1381
+
1382
+ results = @index.fuzzy_search("Zwq")
1383
+ assert_equal(1, results.length)
1384
+ assert_equal("Zwq", results.first.name)
1385
+ end
1386
+
1387
+ def test_resolving_method_aliases
1388
+ index(<<~RUBY)
1389
+ class Foo
1390
+ def bar(a, b, c)
1391
+ end
1392
+
1393
+ alias double_alias bar
1394
+ end
1395
+
1396
+ class Bar < Foo
1397
+ def hello(b); end
1398
+
1399
+ alias baz bar
1400
+ alias_method :qux, :hello
1401
+ alias double double_alias
1402
+ end
1403
+ RUBY
1404
+
1405
+ # baz
1406
+ methods = @index.resolve_method("baz", "Bar")
1407
+ refute_nil(methods)
1408
+
1409
+ entry = T.must(methods.first)
1410
+ assert_kind_of(Entry::MethodAlias, entry)
1411
+ assert_equal("bar", entry.target.name)
1412
+ assert_equal("Foo", T.must(entry.target.owner).name)
1413
+
1414
+ # qux
1415
+ methods = @index.resolve_method("qux", "Bar")
1416
+ refute_nil(methods)
1417
+
1418
+ entry = T.must(methods.first)
1419
+ assert_kind_of(Entry::MethodAlias, entry)
1420
+ assert_equal("hello", entry.target.name)
1421
+ assert_equal("Bar", T.must(entry.target.owner).name)
1422
+
1423
+ # double
1424
+ methods = @index.resolve_method("double", "Bar")
1425
+ refute_nil(methods)
1426
+
1427
+ entry = T.must(methods.first)
1428
+ assert_kind_of(Entry::MethodAlias, entry)
1429
+
1430
+ target = entry.target
1431
+ assert_equal("double_alias", target.name)
1432
+ assert_kind_of(Entry::MethodAlias, target)
1433
+ assert_equal("Foo", T.must(target.owner).name)
1434
+
1435
+ final_target = target.target
1436
+ assert_equal("bar", final_target.name)
1437
+ assert_kind_of(Entry::Method, final_target)
1438
+ assert_equal("Foo", T.must(final_target.owner).name)
1439
+ end
1440
+
1441
+ def test_resolving_circular_method_aliases
1442
+ index(<<~RUBY)
1443
+ class Foo
1444
+ alias bar bar
1445
+ end
1446
+ RUBY
1447
+
1448
+ # It's not possible to resolve an alias that points to itself
1449
+ methods = @index.resolve_method("bar", "Foo")
1450
+ assert_nil(methods)
1451
+
1452
+ entry = T.must(@index["bar"].first)
1453
+ assert_kind_of(Entry::UnresolvedMethodAlias, entry)
1454
+ end
1455
+
1456
+ def test_unresolable_method_aliases
1457
+ index(<<~RUBY)
1458
+ class Foo
1459
+ alias bar baz
1460
+ end
1461
+ RUBY
1462
+
1463
+ # `baz` does not exist, so resolving `bar` is not possible
1464
+ methods = @index.resolve_method("bar", "Foo")
1465
+ assert_nil(methods)
1466
+
1467
+ entry = T.must(@index["bar"].first)
1468
+ assert_kind_of(Entry::UnresolvedMethodAlias, entry)
1469
+ end
1470
+
1471
+ def test_only_aliases_for_the_right_owner_are_resolved
1472
+ index(<<~RUBY)
1473
+ class Foo
1474
+ attr_reader :name
1475
+ alias_method :decorated_name, :name
1476
+ end
1477
+
1478
+ class Bar
1479
+ alias_method :decorated_name, :to_s
1480
+ end
1481
+ RUBY
1482
+
1483
+ methods = @index.resolve_method("decorated_name", "Foo")
1484
+ refute_nil(methods)
1485
+
1486
+ entry = T.must(methods.first)
1487
+ assert_kind_of(Entry::MethodAlias, entry)
1488
+
1489
+ target = entry.target
1490
+ assert_equal("name", target.name)
1491
+ assert_kind_of(Entry::Accessor, target)
1492
+ assert_equal("Foo", T.must(target.owner).name)
1493
+
1494
+ other_decorated_name = T.must(@index["decorated_name"].find { |e| e.is_a?(Entry::UnresolvedMethodAlias) })
1495
+ assert_kind_of(Entry::UnresolvedMethodAlias, other_decorated_name)
1496
+ end
1497
+
1498
+ def test_completion_does_not_include_unresolved_aliases
1499
+ index(<<~RUBY)
1500
+ class Foo
1501
+ alias_method :bar, :missing
1502
+ end
1503
+ RUBY
1504
+
1505
+ assert_empty(@index.method_completion_candidates("bar", "Foo"))
1506
+ end
1507
+
1508
+ def test_completion_does_not_duplicate_overridden_methods
1509
+ index(<<~RUBY)
1510
+ class Foo
1511
+ def bar; end
1512
+ end
1513
+
1514
+ class Baz < Foo
1515
+ def bar; end
1516
+ end
1517
+ RUBY
1518
+
1519
+ entries = @index.method_completion_candidates("bar", "Baz")
1520
+ assert_equal(["bar"], entries.map(&:name))
1521
+ assert_equal("Baz", T.must(entries.first.owner).name)
1522
+ end
1523
+
1524
+ def test_completion_does_not_duplicate_methods_overridden_by_aliases
1525
+ index(<<~RUBY)
1526
+ class Foo
1527
+ def bar; end
1528
+ end
1529
+
1530
+ class Baz < Foo
1531
+ alias bar to_s
1532
+ end
1533
+ RUBY
1534
+
1535
+ entries = @index.method_completion_candidates("bar", "Baz")
1536
+ assert_equal(["bar"], entries.map(&:name))
1537
+ assert_equal("Baz", T.must(entries.first.owner).name)
1538
+ end
1539
+
1540
+ def test_decorated_parameters
1541
+ index(<<~RUBY)
1542
+ class Foo
1543
+ def bar(a, b = 1, c: 2)
1544
+ end
1545
+ end
1546
+ RUBY
1547
+
1548
+ methods = @index.resolve_method("bar", "Foo")
1549
+ refute_nil(methods)
1550
+
1551
+ entry = T.must(methods.first)
1552
+
1553
+ assert_equal("(a, b = <default>, c: <default>)", entry.decorated_parameters)
1554
+ end
1555
+
1556
+ def test_decorated_parameters_when_method_has_no_parameters
1557
+ index(<<~RUBY)
1558
+ class Foo
1559
+ def bar
1560
+ end
1561
+ end
1562
+ RUBY
1563
+
1564
+ methods = @index.resolve_method("bar", "Foo")
1565
+ refute_nil(methods)
1566
+
1567
+ entry = T.must(methods.first)
1568
+
1569
+ assert_equal("()", entry.decorated_parameters)
1570
+ end
1571
+
1572
+ def test_linearizing_singleton_ancestors_of_singleton_when_class_has_parent
1573
+ @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
1574
+ class Foo; end
1575
+
1576
+ class Bar < Foo
1577
+ end
1578
+
1579
+ class Baz < Bar
1580
+ class << self
1581
+ class << self
1582
+ end
1583
+ end
1584
+ end
1585
+ RUBY
1586
+
1587
+ assert_equal(
1588
+ [
1589
+ "Baz::<Class:Baz>::<Class:<Class:Baz>>",
1590
+ "Bar::<Class:Bar>::<Class:<Class:Bar>>",
1591
+ "Foo::<Class:Foo>::<Class:<Class:Foo>>",
1592
+ "Object::<Class:Object>::<Class:<Class:Object>>",
1593
+ "BasicObject::<Class:BasicObject>::<Class:<Class:BasicObject>>",
1594
+ "Class::<Class:Class>",
1595
+ "Module::<Class:Module>",
1596
+ "Object::<Class:Object>",
1597
+ "BasicObject::<Class:BasicObject>",
1598
+ "Class",
1599
+ "Module",
1600
+ "Object",
1601
+ "Kernel",
1602
+ "BasicObject",
1603
+ ],
1604
+ @index.linearized_ancestors_of("Baz::<Class:Baz>::<Class:<Class:Baz>>"),
1605
+ )
1606
+ end
1607
+
1608
+ def test_linearizing_singleton_object
1609
+ assert_equal(
1610
+ [
1611
+ "Object::<Class:Object>",
1612
+ "BasicObject::<Class:BasicObject>",
1613
+ "Class",
1614
+ "Module",
1615
+ "Object",
1616
+ "Kernel",
1617
+ "BasicObject",
1618
+ ],
1619
+ @index.linearized_ancestors_of("Object::<Class:Object>"),
1620
+ )
1621
+ end
1622
+
1623
+ def test_linearizing_singleton_ancestors
1624
+ @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
1625
+ module First
1626
+ end
1627
+
1628
+ module Second
1629
+ include First
1630
+ end
1631
+
1632
+ module Foo
1633
+ class Bar
1634
+ class << self
1635
+ class Baz
1636
+ extend Second
1637
+
1638
+ class << self
1639
+ include First
1640
+ end
1641
+ end
1642
+ end
1643
+ end
1644
+ end
1645
+ RUBY
1646
+
1647
+ assert_equal(
1648
+ [
1649
+ "Foo::Bar::<Class:Bar>::Baz::<Class:Baz>",
1650
+ "Second",
1651
+ "First",
1652
+ "Object::<Class:Object>",
1653
+ "BasicObject::<Class:BasicObject>",
1654
+ "Class",
1655
+ "Module",
1656
+ "Object",
1657
+ "Kernel",
1658
+ "BasicObject",
1659
+ ],
1660
+ @index.linearized_ancestors_of("Foo::Bar::<Class:Bar>::Baz::<Class:Baz>"),
1661
+ )
1662
+ end
1663
+
1664
+ def test_linearizing_singleton_ancestors_when_class_has_parent
1665
+ @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
1666
+ class Foo; end
1667
+
1668
+ class Bar < Foo
1669
+ end
1670
+
1671
+ class Baz < Bar
1672
+ class << self
1673
+ end
1674
+ end
1675
+ RUBY
1676
+
1677
+ assert_equal(
1678
+ [
1679
+ "Baz::<Class:Baz>",
1680
+ "Bar::<Class:Bar>",
1681
+ "Foo::<Class:Foo>",
1682
+ "Object::<Class:Object>",
1683
+ "BasicObject::<Class:BasicObject>",
1684
+ "Class",
1685
+ "Module",
1686
+ "Object",
1687
+ "Kernel",
1688
+ "BasicObject",
1689
+ ],
1690
+ @index.linearized_ancestors_of("Baz::<Class:Baz>"),
1691
+ )
1692
+ end
1693
+
1694
+ def test_linearizing_a_module_singleton_class
1695
+ @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
1696
+ module A; end
1697
+ RUBY
1698
+
1699
+ assert_equal(
1700
+ [
1701
+ "A::<Class:A>",
1702
+ "Module",
1703
+ "Object",
1704
+ "Kernel",
1705
+ "BasicObject",
1706
+ ],
1707
+ @index.linearized_ancestors_of("A::<Class:A>"),
1708
+ )
1709
+ end
1176
1710
  end
1177
1711
  end