ruby-lsp 0.17.3 → 0.17.4

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 (31) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +241 -91
  4. data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +74 -102
  5. data/lib/ruby_indexer/lib/ruby_indexer/index.rb +81 -19
  6. data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +50 -2
  7. data/lib/ruby_indexer/test/classes_and_modules_test.rb +46 -0
  8. data/lib/ruby_indexer/test/index_test.rb +326 -27
  9. data/lib/ruby_indexer/test/instance_variables_test.rb +84 -7
  10. data/lib/ruby_indexer/test/method_test.rb +54 -24
  11. data/lib/ruby_indexer/test/rbs_indexer_test.rb +27 -2
  12. data/lib/ruby_lsp/document.rb +37 -8
  13. data/lib/ruby_lsp/global_state.rb +7 -3
  14. data/lib/ruby_lsp/internal.rb +1 -0
  15. data/lib/ruby_lsp/listeners/completion.rb +53 -14
  16. data/lib/ruby_lsp/listeners/definition.rb +11 -7
  17. data/lib/ruby_lsp/listeners/hover.rb +14 -7
  18. data/lib/ruby_lsp/listeners/signature_help.rb +5 -2
  19. data/lib/ruby_lsp/node_context.rb +6 -1
  20. data/lib/ruby_lsp/requests/completion.rb +5 -4
  21. data/lib/ruby_lsp/requests/completion_resolve.rb +8 -0
  22. data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +88 -0
  23. data/lib/ruby_lsp/requests/support/common.rb +19 -1
  24. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +12 -4
  25. data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +91 -0
  26. data/lib/ruby_lsp/requests/workspace_symbol.rb +1 -21
  27. data/lib/ruby_lsp/requests.rb +2 -0
  28. data/lib/ruby_lsp/server.rb +54 -15
  29. data/lib/ruby_lsp/test_helper.rb +1 -1
  30. data/lib/ruby_lsp/type_inferrer.rb +86 -0
  31. metadata +5 -2
@@ -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
@@ -1145,8 +1143,32 @@ module RubyIndexer
1145
1143
  assert_nil(@index.resolve("RSpec", []))
1146
1144
  end
1147
1145
 
1146
+ def test_object_superclass_indexing_and_resolution_with_reopened_object_class
1147
+ index(<<~RUBY)
1148
+ class Object; end
1149
+ RUBY
1150
+
1151
+ entries = @index["Object"]
1152
+ assert_equal(2, entries.length)
1153
+ reopened_entry = entries.last
1154
+ assert_equal("::BasicObject", reopened_entry.parent_class)
1155
+ assert_equal(["Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Object"))
1156
+ end
1157
+
1158
+ def test_object_superclass_indexing_and_resolution_with_reopened_basic_object_class
1159
+ index(<<~RUBY)
1160
+ class BasicObject; end
1161
+ RUBY
1162
+
1163
+ entries = @index["BasicObject"]
1164
+ assert_equal(2, entries.length)
1165
+ reopened_entry = entries.last
1166
+ assert_nil(reopened_entry.parent_class)
1167
+ assert_equal(["BasicObject"], @index.linearized_ancestors_of("BasicObject"))
1168
+ end
1169
+
1148
1170
  def test_object_superclass_resolution
1149
- @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
1171
+ index(<<~RUBY)
1150
1172
  module Foo
1151
1173
  class Object; end
1152
1174
 
@@ -1162,8 +1184,25 @@ module RubyIndexer
1162
1184
  )
1163
1185
  end
1164
1186
 
1187
+ def test_basic_object_superclass_resolution
1188
+ index(<<~RUBY)
1189
+ module Foo
1190
+ class BasicObject; end
1191
+
1192
+ class Bar; end
1193
+ class Baz < BasicObject; end
1194
+ end
1195
+ RUBY
1196
+
1197
+ assert_equal(["Foo::Bar", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Foo::Bar"))
1198
+ assert_equal(
1199
+ ["Foo::Baz", "Foo::BasicObject", "Object", "Kernel", "BasicObject"],
1200
+ @index.linearized_ancestors_of("Foo::Baz"),
1201
+ )
1202
+ end
1203
+
1165
1204
  def test_top_level_object_superclass_resolution
1166
- @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
1205
+ index(<<~RUBY)
1167
1206
  module Foo
1168
1207
  class Object; end
1169
1208
 
@@ -1173,5 +1212,265 @@ module RubyIndexer
1173
1212
 
1174
1213
  assert_equal(["Foo::Bar", "Object", "Kernel", "BasicObject"], @index.linearized_ancestors_of("Foo::Bar"))
1175
1214
  end
1215
+
1216
+ def test_top_level_basic_object_superclass_resolution
1217
+ index(<<~RUBY)
1218
+ module Foo
1219
+ class BasicObject; end
1220
+
1221
+ class Bar < ::BasicObject; end
1222
+ end
1223
+ RUBY
1224
+
1225
+ assert_equal(["Foo::Bar", "BasicObject"], @index.linearized_ancestors_of("Foo::Bar"))
1226
+ end
1227
+
1228
+ def test_resolving_method_inside_singleton_context
1229
+ @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
1230
+ module Foo
1231
+ class Bar
1232
+ class << self
1233
+ class Baz
1234
+ class << self
1235
+ def found_me!; end
1236
+ end
1237
+ end
1238
+ end
1239
+ end
1240
+ end
1241
+ RUBY
1242
+
1243
+ entry = @index.resolve_method("found_me!", "Foo::Bar::<Class:Bar>::Baz::<Class:Baz>")&.first
1244
+ refute_nil(entry)
1245
+
1246
+ assert_equal("found_me!", T.must(entry).name)
1247
+ end
1248
+
1249
+ def test_resolving_constants_in_singleton_contexts
1250
+ @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
1251
+ module Foo
1252
+ class Bar
1253
+ CONST = 3
1254
+
1255
+ class << self
1256
+ CONST = 2
1257
+
1258
+ class Baz
1259
+ CONST = 1
1260
+
1261
+ class << self
1262
+ end
1263
+ end
1264
+ end
1265
+ end
1266
+ end
1267
+ RUBY
1268
+
1269
+ entry = @index.resolve("CONST", ["Foo", "Bar", "<Class:Bar>", "Baz", "<Class:Baz>"])&.first
1270
+ refute_nil(entry)
1271
+ assert_equal(9, T.must(entry).location.start_line)
1272
+ end
1273
+
1274
+ def test_resolving_instance_variables_in_singleton_contexts
1275
+ @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
1276
+ module Foo
1277
+ class Bar
1278
+ @a = 123
1279
+
1280
+ class << self
1281
+ def hello
1282
+ @b = 123
1283
+ end
1284
+
1285
+ @c = 123
1286
+ end
1287
+ end
1288
+ end
1289
+ RUBY
1290
+
1291
+ entry = @index.resolve_instance_variable("@a", "Foo::Bar::<Class:Bar>")&.first
1292
+ refute_nil(entry)
1293
+ assert_equal("@a", T.must(entry).name)
1294
+
1295
+ entry = @index.resolve_instance_variable("@b", "Foo::Bar::<Class:Bar>")&.first
1296
+ refute_nil(entry)
1297
+ assert_equal("@b", T.must(entry).name)
1298
+
1299
+ entry = @index.resolve_instance_variable("@c", "Foo::Bar::<Class:Bar>::<Class:<Class:Bar>>")&.first
1300
+ refute_nil(entry)
1301
+ assert_equal("@c", T.must(entry).name)
1302
+ end
1303
+
1304
+ def test_instance_variable_completion_in_singleton_contexts
1305
+ @index.index_single(IndexablePath.new(nil, "/fake/path/foo.rb"), <<~RUBY)
1306
+ module Foo
1307
+ class Bar
1308
+ @a = 123
1309
+
1310
+ class << self
1311
+ def hello
1312
+ @b = 123
1313
+ end
1314
+
1315
+ @c = 123
1316
+ end
1317
+ end
1318
+ end
1319
+ RUBY
1320
+
1321
+ entries = @index.instance_variable_completion_candidates("@", "Foo::Bar::<Class:Bar>").map(&:name)
1322
+ assert_includes(entries, "@a")
1323
+ assert_includes(entries, "@b")
1324
+
1325
+ assert_includes(
1326
+ @index.instance_variable_completion_candidates("@", "Foo::Bar::<Class:Bar>::<Class:<Class:Bar>>").map(&:name),
1327
+ "@c",
1328
+ )
1329
+ end
1330
+
1331
+ def test_singletons_are_excluded_from_prefix_search
1332
+ index(<<~RUBY)
1333
+ class Zwq
1334
+ class << self
1335
+ end
1336
+ end
1337
+ RUBY
1338
+
1339
+ assert_empty(@index.prefix_search("Zwq::<C"))
1340
+ end
1341
+
1342
+ def test_singletons_are_excluded_from_fuzzy_search
1343
+ index(<<~RUBY)
1344
+ class Zwq
1345
+ class << self
1346
+ end
1347
+ end
1348
+ RUBY
1349
+
1350
+ results = @index.fuzzy_search("Zwq")
1351
+ assert_equal(1, results.length)
1352
+ assert_equal("Zwq", results.first.name)
1353
+ end
1354
+
1355
+ def test_resolving_method_aliases
1356
+ index(<<~RUBY)
1357
+ class Foo
1358
+ def bar(a, b, c)
1359
+ end
1360
+
1361
+ alias double_alias bar
1362
+ end
1363
+
1364
+ class Bar < Foo
1365
+ def hello(b); end
1366
+
1367
+ alias baz bar
1368
+ alias_method :qux, :hello
1369
+ alias double double_alias
1370
+ end
1371
+ RUBY
1372
+
1373
+ # baz
1374
+ methods = @index.resolve_method("baz", "Bar")
1375
+ refute_nil(methods)
1376
+
1377
+ entry = T.must(methods.first)
1378
+ assert_kind_of(Entry::MethodAlias, entry)
1379
+ assert_equal("bar", entry.target.name)
1380
+ assert_equal("Foo", T.must(entry.target.owner).name)
1381
+
1382
+ # qux
1383
+ methods = @index.resolve_method("qux", "Bar")
1384
+ refute_nil(methods)
1385
+
1386
+ entry = T.must(methods.first)
1387
+ assert_kind_of(Entry::MethodAlias, entry)
1388
+ assert_equal("hello", entry.target.name)
1389
+ assert_equal("Bar", T.must(entry.target.owner).name)
1390
+
1391
+ # double
1392
+ methods = @index.resolve_method("double", "Bar")
1393
+ refute_nil(methods)
1394
+
1395
+ entry = T.must(methods.first)
1396
+ assert_kind_of(Entry::MethodAlias, entry)
1397
+
1398
+ target = entry.target
1399
+ assert_equal("double_alias", target.name)
1400
+ assert_kind_of(Entry::MethodAlias, target)
1401
+ assert_equal("Foo", T.must(target.owner).name)
1402
+
1403
+ final_target = target.target
1404
+ assert_equal("bar", final_target.name)
1405
+ assert_kind_of(Entry::Method, final_target)
1406
+ assert_equal("Foo", T.must(final_target.owner).name)
1407
+ end
1408
+
1409
+ def test_resolving_circular_method_aliases
1410
+ index(<<~RUBY)
1411
+ class Foo
1412
+ alias bar bar
1413
+ end
1414
+ RUBY
1415
+
1416
+ # It's not possible to resolve an alias that points to itself
1417
+ methods = @index.resolve_method("bar", "Foo")
1418
+ assert_nil(methods)
1419
+
1420
+ entry = T.must(@index["bar"].first)
1421
+ assert_kind_of(Entry::UnresolvedMethodAlias, entry)
1422
+ end
1423
+
1424
+ def test_unresolable_method_aliases
1425
+ index(<<~RUBY)
1426
+ class Foo
1427
+ alias bar baz
1428
+ end
1429
+ RUBY
1430
+
1431
+ # `baz` does not exist, so resolving `bar` is not possible
1432
+ methods = @index.resolve_method("bar", "Foo")
1433
+ assert_nil(methods)
1434
+
1435
+ entry = T.must(@index["bar"].first)
1436
+ assert_kind_of(Entry::UnresolvedMethodAlias, entry)
1437
+ end
1438
+
1439
+ def test_only_aliases_for_the_right_owner_are_resolved
1440
+ index(<<~RUBY)
1441
+ class Foo
1442
+ attr_reader :name
1443
+ alias_method :decorated_name, :name
1444
+ end
1445
+
1446
+ class Bar
1447
+ alias_method :decorated_name, :to_s
1448
+ end
1449
+ RUBY
1450
+
1451
+ methods = @index.resolve_method("decorated_name", "Foo")
1452
+ refute_nil(methods)
1453
+
1454
+ entry = T.must(methods.first)
1455
+ assert_kind_of(Entry::MethodAlias, entry)
1456
+
1457
+ target = entry.target
1458
+ assert_equal("name", target.name)
1459
+ assert_kind_of(Entry::Accessor, target)
1460
+ assert_equal("Foo", T.must(target.owner).name)
1461
+
1462
+ other_decorated_name = T.must(@index["decorated_name"].find { |e| e.is_a?(Entry::UnresolvedMethodAlias) })
1463
+ assert_kind_of(Entry::UnresolvedMethodAlias, other_decorated_name)
1464
+ end
1465
+
1466
+ def test_completion_does_not_include_unresolved_aliases
1467
+ index(<<~RUBY)
1468
+ class Foo
1469
+ alias_method :bar, :missing
1470
+ end
1471
+ RUBY
1472
+
1473
+ assert_empty(@index.method_completion_candidates("bar", "Foo"))
1474
+ end
1176
1475
  end
1177
1476
  end
@@ -20,7 +20,9 @@ module RubyIndexer
20
20
  assert_entry("@a", Entry::InstanceVariable, "/fake/path/foo.rb:4-6:4-8")
21
21
 
22
22
  entry = T.must(@index["@a"]&.first)
23
- assert_equal("Foo::Bar", T.must(entry.owner).name)
23
+ owner = T.must(entry.owner)
24
+ assert_instance_of(Entry::Class, owner)
25
+ assert_equal("Foo::Bar", owner.name)
24
26
  end
25
27
 
26
28
  def test_instance_variable_and_write
@@ -38,7 +40,9 @@ module RubyIndexer
38
40
  assert_entry("@a", Entry::InstanceVariable, "/fake/path/foo.rb:4-6:4-8")
39
41
 
40
42
  entry = T.must(@index["@a"]&.first)
41
- assert_equal("Foo::Bar", T.must(entry.owner).name)
43
+ owner = T.must(entry.owner)
44
+ assert_instance_of(Entry::Class, owner)
45
+ assert_equal("Foo::Bar", owner.name)
42
46
  end
43
47
 
44
48
  def test_instance_variable_operator_write
@@ -56,7 +60,9 @@ module RubyIndexer
56
60
  assert_entry("@a", Entry::InstanceVariable, "/fake/path/foo.rb:4-6:4-8")
57
61
 
58
62
  entry = T.must(@index["@a"]&.first)
59
- assert_equal("Foo::Bar", T.must(entry.owner).name)
63
+ owner = T.must(entry.owner)
64
+ assert_instance_of(Entry::Class, owner)
65
+ assert_equal("Foo::Bar", owner.name)
60
66
  end
61
67
 
62
68
  def test_instance_variable_or_write
@@ -74,7 +80,9 @@ module RubyIndexer
74
80
  assert_entry("@a", Entry::InstanceVariable, "/fake/path/foo.rb:4-6:4-8")
75
81
 
76
82
  entry = T.must(@index["@a"]&.first)
77
- assert_equal("Foo::Bar", T.must(entry.owner).name)
83
+ owner = T.must(entry.owner)
84
+ assert_instance_of(Entry::Class, owner)
85
+ assert_equal("Foo::Bar", owner.name)
78
86
  end
79
87
 
80
88
  def test_instance_variable_target
@@ -93,10 +101,14 @@ module RubyIndexer
93
101
  assert_entry("@b", Entry::InstanceVariable, "/fake/path/foo.rb:4-10:4-12")
94
102
 
95
103
  entry = T.must(@index["@a"]&.first)
96
- assert_equal("Foo::Bar", T.must(entry.owner).name)
104
+ owner = T.must(entry.owner)
105
+ assert_instance_of(Entry::Class, owner)
106
+ assert_equal("Foo::Bar", owner.name)
97
107
 
98
108
  entry = T.must(@index["@b"]&.first)
99
- assert_equal("Foo::Bar", T.must(entry.owner).name)
109
+ owner = T.must(entry.owner)
110
+ assert_instance_of(Entry::Class, owner)
111
+ assert_equal("Foo::Bar", owner.name)
100
112
  end
101
113
 
102
114
  def test_empty_name_instance_variables
@@ -118,6 +130,14 @@ module RubyIndexer
118
130
  module Foo
119
131
  class Bar
120
132
  @a = 123
133
+
134
+ class << self
135
+ def hello
136
+ @b = 123
137
+ end
138
+
139
+ @c = 123
140
+ end
121
141
  end
122
142
  end
123
143
  RUBY
@@ -125,7 +145,64 @@ module RubyIndexer
125
145
  assert_entry("@a", Entry::InstanceVariable, "/fake/path/foo.rb:2-4:2-6")
126
146
 
127
147
  entry = T.must(@index["@a"]&.first)
128
- assert_equal("Foo::Bar", T.must(entry.owner).name)
148
+ owner = T.must(entry.owner)
149
+ assert_instance_of(Entry::SingletonClass, owner)
150
+ assert_equal("Foo::Bar::<Class:Bar>", owner.name)
151
+
152
+ assert_entry("@b", Entry::InstanceVariable, "/fake/path/foo.rb:6-8:6-10")
153
+
154
+ entry = T.must(@index["@b"]&.first)
155
+ owner = T.must(entry.owner)
156
+ assert_instance_of(Entry::SingletonClass, owner)
157
+ assert_equal("Foo::Bar::<Class:Bar>", owner.name)
158
+
159
+ assert_entry("@c", Entry::InstanceVariable, "/fake/path/foo.rb:9-6:9-8")
160
+
161
+ entry = T.must(@index["@c"]&.first)
162
+ owner = T.must(entry.owner)
163
+ assert_instance_of(Entry::SingletonClass, owner)
164
+ assert_equal("Foo::Bar::<Class:Bar>::<Class:<Class:Bar>>", owner.name)
165
+ end
166
+
167
+ def test_top_level_instance_variables
168
+ index(<<~RUBY)
169
+ @a = 123
170
+ RUBY
171
+
172
+ entry = T.must(@index["@a"]&.first)
173
+ assert_nil(entry.owner)
174
+ end
175
+
176
+ def test_class_instance_variables_inside_self_method
177
+ index(<<~RUBY)
178
+ class Foo
179
+ def self.bar
180
+ @a = 123
181
+ end
182
+ end
183
+ RUBY
184
+
185
+ entry = T.must(@index["@a"]&.first)
186
+ owner = T.must(entry.owner)
187
+ assert_instance_of(Entry::SingletonClass, owner)
188
+ assert_equal("Foo::<Class:Foo>", owner.name)
189
+ end
190
+
191
+ def test_instance_variable_inside_dynamic_method_declaration
192
+ index(<<~RUBY)
193
+ class Foo
194
+ def something.bar
195
+ @a = 123
196
+ end
197
+ end
198
+ RUBY
199
+
200
+ # If the surrounding method is beind defined on any dynamic value that isn't `self`, then we attribute the
201
+ # instance variable to the wrong owner since there's no way to understand that statically
202
+ entry = T.must(@index["@a"]&.first)
203
+ owner = T.must(entry.owner)
204
+ assert_instance_of(Entry::Class, owner)
205
+ assert_equal("Foo", owner.name)
129
206
  end
130
207
  end
131
208
  end