ruby-lsp 0.17.3 → 0.17.5

Sign up to get free protection for your applications and to get access to all the features.
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