ruby-lsp 0.17.1 → 0.17.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 61194ff211ddd14d6598752e0a60409c16c2c5460c4d007ac1e1bc7e56b50116
4
- data.tar.gz: 29ed28f4392929f09a4ba4ea6a19612f9dfc3e2c0b2641c551627ac69a32b3c0
3
+ metadata.gz: c02fa9ec776002a86f4eeee4037132d8b0f9403f101ccff5c7a31c46385a2818
4
+ data.tar.gz: 3b788794763cee273e2ce677955c3750ebac90962c8d328946f91998a900eca5
5
5
  SHA512:
6
- metadata.gz: 56420391d81fe9e9c06a7fda2a04b1f99ac6fbb10211f064bfd65f36dd9148658d47743be437eb40240d5522786ec0566d0cea763b964630fb5ea67fe552687b
7
- data.tar.gz: f760fad5d7abf0d0071badf6dd04f82e2266a64b0122d3a08cd5c3c799be15e377c94da93a4e8164e1f6ae04350e5ca05b16afbb7a8e341a8e80590053728ed7
6
+ metadata.gz: e3e152e24d1dca4aca721537f64df9062ae48aeea65b361ffd80dc6710cd263b0e8d1181f970b6d06e6147882c1cad40ba91d25ef6f684e2f5374a9738e1fae9
7
+ data.tar.gz: 79c3eb785ac55de19c4e9031ed6c8ca0a9a6df27156244ba7ee3ca2109659f8f2b9ce6efe7259cfcd65922a0b8cefc384fca2215dbdffac41735d9149db651a0
data/README.md CHANGED
@@ -48,6 +48,8 @@ If using VS Code, all you have to do is install the [Ruby LSP
48
48
  extension](https://marketplace.visualstudio.com/items?itemName=Shopify.ruby-lsp) to get the extra features in the
49
49
  editor. Do not install the `ruby-lsp` gem manually.
50
50
 
51
+ For more information on using and configuring the extension, see [vscode/README.md](vscode/README.md).
52
+
51
53
  ### With other editors
52
54
 
53
55
  See [editors](EDITORS.md) for community instructions on setting up the Ruby LSP, which current includes Emacs, Neovim, Sublime Text, and Zed.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.17.1
1
+ 0.17.3
@@ -52,6 +52,7 @@ module RubyIndexer
52
52
  :on_instance_variable_operator_write_node_enter,
53
53
  :on_instance_variable_or_write_node_enter,
54
54
  :on_instance_variable_target_node_enter,
55
+ :on_alias_method_node_enter,
55
56
  )
56
57
  end
57
58
 
@@ -66,6 +67,8 @@ module RubyIndexer
66
67
  parent_class = case superclass
67
68
  when Prism::ConstantReadNode, Prism::ConstantPathNode
68
69
  superclass.slice
70
+ else
71
+ "::Object"
69
72
  end
70
73
 
71
74
  nesting = name.start_with?("::") ? [name.delete_prefix("::")] : @stack + [name.delete_prefix("::")]
@@ -209,6 +212,8 @@ module RubyIndexer
209
212
  handle_attribute(node, reader: false, writer: true)
210
213
  when :attr_accessor
211
214
  handle_attribute(node, reader: true, writer: true)
215
+ when :alias_method
216
+ handle_alias_method(node)
212
217
  when :include, :prepend, :extend
213
218
  handle_module_operation(node, message)
214
219
  when :public
@@ -338,6 +343,20 @@ module RubyIndexer
338
343
  )
339
344
  end
340
345
 
346
+ sig { params(node: Prism::AliasMethodNode).void }
347
+ def on_alias_method_node_enter(node)
348
+ method_name = node.new_name.slice
349
+ comments = collect_comments(node)
350
+ @index << Entry::UnresolvedMethodAlias.new(
351
+ method_name,
352
+ node.old_name.slice,
353
+ @owner_stack.last,
354
+ @file_path,
355
+ node.new_name.location,
356
+ comments,
357
+ )
358
+ end
359
+
341
360
  private
342
361
 
343
362
  sig { params(node: Prism::CallNode).void }
@@ -365,6 +384,43 @@ module RubyIndexer
365
384
  entries&.each { |entry| entry.visibility = Entry::Visibility::PRIVATE }
366
385
  end
367
386
 
387
+ sig { params(node: Prism::CallNode).void }
388
+ def handle_alias_method(node)
389
+ arguments = node.arguments&.arguments
390
+ return unless arguments
391
+
392
+ new_name, old_name = arguments
393
+ return unless new_name && old_name
394
+
395
+ new_name_value = case new_name
396
+ when Prism::StringNode
397
+ new_name.content
398
+ when Prism::SymbolNode
399
+ new_name.value
400
+ end
401
+
402
+ return unless new_name_value
403
+
404
+ old_name_value = case old_name
405
+ when Prism::StringNode
406
+ old_name.content
407
+ when Prism::SymbolNode
408
+ old_name.value
409
+ end
410
+
411
+ return unless old_name_value
412
+
413
+ comments = collect_comments(node)
414
+ @index << Entry::UnresolvedMethodAlias.new(
415
+ new_name_value,
416
+ old_name_value,
417
+ @owner_stack.last,
418
+ @file_path,
419
+ new_name.location,
420
+ comments,
421
+ )
422
+ end
423
+
368
424
  sig do
369
425
  params(
370
426
  node: T.any(
@@ -469,5 +469,33 @@ module RubyIndexer
469
469
  @owner = owner
470
470
  end
471
471
  end
472
+
473
+ class UnresolvedMethodAlias < Entry
474
+ extend T::Sig
475
+
476
+ sig { returns(String) }
477
+ attr_reader :new_name, :old_name
478
+
479
+ sig { returns(T.nilable(Entry::Namespace)) }
480
+ attr_reader :owner
481
+
482
+ sig do
483
+ params(
484
+ new_name: String,
485
+ old_name: String,
486
+ owner: T.nilable(Entry::Namespace),
487
+ file_path: String,
488
+ location: Prism::Location,
489
+ comments: T::Array[String],
490
+ ).void
491
+ end
492
+ def initialize(new_name, old_name, owner, file_path, location, comments) # rubocop:disable Metrics/ParameterLists
493
+ super(new_name, file_path, location, comments)
494
+
495
+ @new_name = new_name
496
+ @old_name = old_name
497
+ @owner = owner
498
+ end
499
+ end
472
500
  end
473
501
  end
@@ -140,35 +140,48 @@ module RubyIndexer
140
140
  candidates
141
141
  end
142
142
 
143
- # Try to find the entry based on the nesting from the most specific to the least specific. For example, if we have
144
- # the nesting as ["Foo", "Bar"] and the name as "Baz", we will try to find it in this order:
145
- # 1. Foo::Bar::Baz
146
- # 2. Foo::Baz
147
- # 3. Baz
148
- sig { params(name: String, nesting: T::Array[String]).returns(T.nilable(T::Array[Entry])) }
149
- def resolve(name, nesting)
143
+ # Resolve a constant to its declaration based on its name and the nesting where the reference was found. Parameter
144
+ # documentation:
145
+ #
146
+ # name: the name of the reference how it was found in the source code (qualified or not)
147
+ # nesting: the nesting structure where the reference was found (e.g.: ["Foo", "Bar"])
148
+ # seen_names: this parameter should not be used by consumers of the api. It is used to avoid infinite recursion when
149
+ # resolving circular references
150
+ sig do
151
+ params(
152
+ name: String,
153
+ nesting: T::Array[String],
154
+ seen_names: T::Array[String],
155
+ ).returns(T.nilable(T::Array[Entry]))
156
+ end
157
+ def resolve(name, nesting, seen_names = [])
158
+ # If we have a top level reference, then we just search for it straight away ignoring the nesting
150
159
  if name.start_with?("::")
151
- name = name.delete_prefix("::")
152
- results = @entries[name] || @entries[follow_aliased_namespace(name)]
153
- return results&.map { |e| e.is_a?(Entry::UnresolvedAlias) ? resolve_alias(e) : e }
160
+ entries = direct_or_aliased_constant(name.delete_prefix("::"), seen_names)
161
+ return entries if entries
154
162
  end
155
163
 
156
- nesting.length.downto(0).each do |i|
157
- namespace = T.must(nesting[0...i]).join("::")
158
- full_name = namespace.empty? ? name : "#{namespace}::#{name}"
164
+ # Non qualified reference path
165
+ full_name = nesting.any? ? "#{nesting.join("::")}::#{name}" : name
159
166
 
160
- # If we find an entry with `full_name` directly, then we can already return it, even if it contains aliases -
161
- # because the user might be trying to jump to the alias definition.
162
- #
163
- # However, if we don't find it, then we need to search for possible aliases in the namespace. For example, in
164
- # the LSP itself we alias `RubyLsp::Interface` to `LanguageServer::Protocol::Interface`, which means doing
165
- # `RubyLsp::Interface::Location` is allowed. For these cases, we need some way to realize that the
166
- # `RubyLsp::Interface` part is an alias, that has to be resolved
167
- entries = @entries[full_name] || @entries[follow_aliased_namespace(full_name)]
168
- return entries.map { |e| e.is_a?(Entry::UnresolvedAlias) ? resolve_alias(e) : e } if entries
169
- end
167
+ # When the name is not qualified with any namespaces, Ruby will take several steps to try to the resolve the
168
+ # constant. First, it will try to find the constant in the exact namespace where the reference was found
169
+ entries = direct_or_aliased_constant(full_name, seen_names)
170
+ return entries if entries
170
171
 
171
- nil
172
+ # If the constant is not found yet, then Ruby will try to find the constant in the enclosing lexical scopes,
173
+ # unwrapping each level one by one. Important note: the top level is not included because that's the fallback of
174
+ # the algorithm after every other possibility has been exhausted
175
+ entries = lookup_enclosing_scopes(name, nesting, seen_names)
176
+ return entries if entries
177
+
178
+ # If the constant does not exist in any enclosing scopes, then Ruby will search for it in the ancestors of the
179
+ # specific namespace where the reference was found
180
+ entries = lookup_ancestor_chain(name, nesting, seen_names)
181
+ return entries if entries
182
+
183
+ # Finally, as a fallback, Ruby will search for the constant in the top level namespace
184
+ search_top_level(name, seen_names)
172
185
  rescue UnresolvableAliasError
173
186
  nil
174
187
  end
@@ -222,8 +235,8 @@ module RubyIndexer
222
235
  # If we find an alias, then we want to follow its target. In the same example, if `Foo::Bar` is an alias to
223
236
  # `Something::Else`, then we first discover `Something::Else::Baz`. But `Something::Else::Baz` might contain other
224
237
  # aliases, so we have to invoke `follow_aliased_namespace` again to check until we only return a real name
225
- sig { params(name: String).returns(String) }
226
- def follow_aliased_namespace(name)
238
+ sig { params(name: String, seen_names: T::Array[String]).returns(String) }
239
+ def follow_aliased_namespace(name, seen_names = [])
227
240
  return name if @entries[name]
228
241
 
229
242
  parts = name.split("::")
@@ -236,16 +249,16 @@ module RubyIndexer
236
249
  case entry
237
250
  when Entry::Alias
238
251
  target = entry.target
239
- return follow_aliased_namespace("#{target}::#{real_parts.join("::")}")
252
+ return follow_aliased_namespace("#{target}::#{real_parts.join("::")}", seen_names)
240
253
  when Entry::UnresolvedAlias
241
- resolved = resolve_alias(entry)
254
+ resolved = resolve_alias(entry, seen_names)
242
255
 
243
256
  if resolved.is_a?(Entry::UnresolvedAlias)
244
257
  raise UnresolvableAliasError, "The constant #{resolved.name} is an alias to a non existing constant"
245
258
  end
246
259
 
247
260
  target = resolved.target
248
- return follow_aliased_namespace("#{target}::#{real_parts.join("::")}")
261
+ return follow_aliased_namespace("#{target}::#{real_parts.join("::")}", seen_names)
249
262
  else
250
263
  real_parts.unshift(T.must(parts[i]))
251
264
  end
@@ -291,6 +304,10 @@ module RubyIndexer
291
304
  cached_ancestors = @ancestors[fully_qualified_name]
292
305
  return cached_ancestors if cached_ancestors
293
306
 
307
+ # If we don't have an entry for `name`, raise
308
+ entries = self[fully_qualified_name]
309
+ raise NonExistingNamespaceError, "No entry found for #{fully_qualified_name}" unless entries
310
+
294
311
  ancestors = [fully_qualified_name]
295
312
 
296
313
  # Cache the linearized ancestors array eagerly. This is important because we might have circular dependencies and
@@ -298,10 +315,6 @@ module RubyIndexer
298
315
  # the cache will reflect the final result
299
316
  @ancestors[fully_qualified_name] = ancestors
300
317
 
301
- # If we don't have an entry for `name`, raise
302
- entries = resolve(fully_qualified_name, [])
303
- raise NonExistingNamespaceError, "No entry found for #{fully_qualified_name}" unless entries
304
-
305
318
  # If none of the entries for `name` are namespaces, raise
306
319
  namespaces = entries.filter_map do |entry|
307
320
  case entry
@@ -395,8 +408,8 @@ module RubyIndexer
395
408
  entries = T.cast(prefix_search(name).flatten, T::Array[Entry::InstanceVariable])
396
409
  ancestors = linearized_ancestors_of(owner_name)
397
410
 
398
- variables = entries.uniq(&:name)
399
- variables.select! { |e| ancestors.any?(e.owner&.name) }
411
+ variables = entries.select { |e| ancestors.any?(e.owner&.name) }
412
+ variables.uniq!(&:name)
400
413
  variables
401
414
  end
402
415
 
@@ -434,22 +447,125 @@ module RubyIndexer
434
447
 
435
448
  # Attempts to resolve an UnresolvedAlias into a resolved Alias. If the unresolved alias is pointing to a constant
436
449
  # that doesn't exist, then we return the same UnresolvedAlias
437
- sig { params(entry: Entry::UnresolvedAlias).returns(T.any(Entry::Alias, Entry::UnresolvedAlias)) }
438
- def resolve_alias(entry)
439
- target = resolve(entry.target, entry.nesting)
450
+ sig do
451
+ params(
452
+ entry: Entry::UnresolvedAlias,
453
+ seen_names: T::Array[String],
454
+ ).returns(T.any(Entry::Alias, Entry::UnresolvedAlias))
455
+ end
456
+ def resolve_alias(entry, seen_names)
457
+ alias_name = entry.name
458
+ return entry if seen_names.include?(alias_name)
459
+
460
+ seen_names << alias_name
461
+
462
+ target = resolve(entry.target, entry.nesting, seen_names)
440
463
  return entry unless target
441
464
 
442
465
  target_name = T.must(target.first).name
443
466
  resolved_alias = Entry::Alias.new(target_name, entry)
444
467
 
445
468
  # Replace the UnresolvedAlias by a resolved one so that we don't have to do this again later
446
- original_entries = T.must(@entries[entry.name])
469
+ original_entries = T.must(@entries[alias_name])
447
470
  original_entries.delete(entry)
448
471
  original_entries << resolved_alias
449
472
 
450
- @entries_tree.insert(entry.name, original_entries)
473
+ @entries_tree.insert(alias_name, original_entries)
451
474
 
452
475
  resolved_alias
453
476
  end
477
+
478
+ sig do
479
+ params(
480
+ name: String,
481
+ nesting: T::Array[String],
482
+ seen_names: T::Array[String],
483
+ ).returns(T.nilable(T::Array[Entry]))
484
+ end
485
+ def lookup_enclosing_scopes(name, nesting, seen_names)
486
+ nesting.length.downto(1).each do |i|
487
+ namespace = T.must(nesting[0...i]).join("::")
488
+
489
+ # If we find an entry with `full_name` directly, then we can already return it, even if it contains aliases -
490
+ # because the user might be trying to jump to the alias definition.
491
+ #
492
+ # However, if we don't find it, then we need to search for possible aliases in the namespace. For example, in
493
+ # the LSP itself we alias `RubyLsp::Interface` to `LanguageServer::Protocol::Interface`, which means doing
494
+ # `RubyLsp::Interface::Location` is allowed. For these cases, we need some way to realize that the
495
+ # `RubyLsp::Interface` part is an alias, that has to be resolved
496
+ entries = direct_or_aliased_constant("#{namespace}::#{name}", seen_names)
497
+ return entries if entries
498
+ end
499
+
500
+ nil
501
+ end
502
+
503
+ sig do
504
+ params(
505
+ name: String,
506
+ nesting: T::Array[String],
507
+ seen_names: T::Array[String],
508
+ ).returns(T.nilable(T::Array[Entry]))
509
+ end
510
+ def lookup_ancestor_chain(name, nesting, seen_names)
511
+ *nesting_parts, constant_name = build_non_redundant_full_name(name, nesting).split("::")
512
+ return if T.must(nesting_parts).empty?
513
+
514
+ namespace_entries = resolve(T.must(nesting_parts).join("::"), [], seen_names)
515
+ return unless namespace_entries
516
+
517
+ ancestors = T.must(nesting_parts).empty? ? [] : linearized_ancestors_of(T.must(namespace_entries.first).name)
518
+
519
+ ancestors.each do |ancestor_name|
520
+ entries = direct_or_aliased_constant("#{ancestor_name}::#{constant_name}", seen_names)
521
+ return entries if entries
522
+ end
523
+
524
+ nil
525
+ rescue NonExistingNamespaceError
526
+ nil
527
+ end
528
+
529
+ # Removes redudancy from a constant reference's full name. For example, if we find a reference to `A::B::Foo` inside
530
+ # of the ["A", "B"] nesting, then we should not concatenate the nesting with the name or else we'll end up with
531
+ # `A::B::A::B::Foo`. This method will remove any redundant parts from the final name based on the reference and the
532
+ # nesting
533
+ sig { params(name: String, nesting: T::Array[String]).returns(String) }
534
+ def build_non_redundant_full_name(name, nesting)
535
+ return name if nesting.empty?
536
+
537
+ namespace = nesting.join("::")
538
+
539
+ # If the name is not qualified, we can just concatenate the nesting and the name
540
+ return "#{namespace}::#{name}" unless name.include?("::")
541
+
542
+ name_parts = name.split("::")
543
+
544
+ # Find the first part of the name that is not in the nesting
545
+ index = name_parts.index { |part| !nesting.include?(part) }
546
+
547
+ if index.nil?
548
+ # All parts of the nesting are redundant because they are already present in the name. We can return the name
549
+ # directly
550
+ name
551
+ elsif index == 0
552
+ # No parts of the nesting are in the name, we can concatenate the namespace and the name
553
+ "#{namespace}::#{name}"
554
+ else
555
+ # The name includes some parts of the nesting. We need to remove the redundant parts
556
+ "#{namespace}::#{T.must(name_parts[index..-1]).join("::")}"
557
+ end
558
+ end
559
+
560
+ sig { params(full_name: String, seen_names: T::Array[String]).returns(T.nilable(T::Array[Entry])) }
561
+ def direct_or_aliased_constant(full_name, seen_names)
562
+ entries = @entries[full_name] || @entries[follow_aliased_namespace(full_name)]
563
+ entries&.map { |e| e.is_a?(Entry::UnresolvedAlias) ? resolve_alias(e, seen_names) : e }
564
+ end
565
+
566
+ sig { params(name: String, seen_names: T::Array[String]).returns(T.nilable(T::Array[Entry])) }
567
+ def search_top_level(name, seen_names)
568
+ @entries[name]&.map { |e| e.is_a?(Entry::UnresolvedAlias) ? resolve_alias(e, seen_names) : e }
569
+ end
454
570
  end
455
571
  end
@@ -0,0 +1,99 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RubyIndexer
5
+ class RBSIndexer
6
+ extend T::Sig
7
+
8
+ sig { params(index: Index).void }
9
+ def initialize(index)
10
+ @index = index
11
+ end
12
+
13
+ sig { void }
14
+ def index_ruby_core
15
+ loader = RBS::EnvironmentLoader.new
16
+ RBS::Environment.from_loader(loader).resolve_type_names
17
+
18
+ loader.each_signature do |source, pathname, _buffer, declarations, _directives|
19
+ process_signature(source, pathname, declarations)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ sig { params(source: T.untyped, pathname: Pathname, declarations: T::Array[RBS::AST::Declarations::Base]).void }
26
+ def process_signature(source, pathname, declarations)
27
+ declarations.each do |declaration|
28
+ process_declaration(declaration, pathname)
29
+ end
30
+ end
31
+
32
+ sig { params(declaration: RBS::AST::Declarations::Base, pathname: Pathname).void }
33
+ def process_declaration(declaration, pathname)
34
+ case declaration
35
+ when RBS::AST::Declarations::Class
36
+ handle_class_declaration(declaration, pathname)
37
+ when RBS::AST::Declarations::Module
38
+ handle_module_declaration(declaration, pathname)
39
+ else # rubocop:disable Style/EmptyElse
40
+ # Other kinds not yet handled
41
+ end
42
+ end
43
+
44
+ sig { params(declaration: RBS::AST::Declarations::Class, pathname: Pathname).void }
45
+ def handle_class_declaration(declaration, pathname)
46
+ nesting = [declaration.name.name.to_s]
47
+ file_path = pathname.to_s
48
+ location = to_ruby_indexer_location(declaration.location)
49
+ comments = Array(declaration.comment&.string)
50
+ parent_class = declaration.super_class&.name&.name&.to_s
51
+ class_entry = Entry::Class.new(nesting, file_path, location, comments, parent_class)
52
+ add_declaration_mixins_to_entry(declaration, class_entry)
53
+ @index << class_entry
54
+ end
55
+
56
+ sig { params(declaration: RBS::AST::Declarations::Module, pathname: Pathname).void }
57
+ def handle_module_declaration(declaration, pathname)
58
+ nesting = [declaration.name.name.to_s]
59
+ file_path = pathname.to_s
60
+ location = to_ruby_indexer_location(declaration.location)
61
+ comments = Array(declaration.comment&.string)
62
+ module_entry = Entry::Module.new(nesting, file_path, location, comments)
63
+ add_declaration_mixins_to_entry(declaration, module_entry)
64
+ @index << module_entry
65
+ end
66
+
67
+ sig { params(rbs_location: RBS::Location).returns(RubyIndexer::Location) }
68
+ def to_ruby_indexer_location(rbs_location)
69
+ RubyIndexer::Location.new(
70
+ rbs_location.start_line,
71
+ rbs_location.end_line,
72
+ rbs_location.start_column,
73
+ rbs_location.end_column,
74
+ )
75
+ end
76
+
77
+ sig do
78
+ params(
79
+ declaration: T.any(RBS::AST::Declarations::Class, RBS::AST::Declarations::Module),
80
+ entry: Entry::Namespace,
81
+ ).void
82
+ end
83
+ def add_declaration_mixins_to_entry(declaration, entry)
84
+ declaration.each_mixin do |mixin|
85
+ name = mixin.name.name.to_s
86
+ mixin_operation =
87
+ case mixin
88
+ when RBS::AST::Members::Include
89
+ Entry::Include.new(name)
90
+ when RBS::AST::Members::Extend
91
+ Entry::Extend.new(name)
92
+ when RBS::AST::Members::Prepend
93
+ Entry::Prepend.new(name)
94
+ end
95
+ entry.mixin_operations << mixin_operation if mixin_operation
96
+ end
97
+ end
98
+ end
99
+ end
@@ -11,6 +11,7 @@ require "ruby_indexer/lib/ruby_indexer/entry"
11
11
  require "ruby_indexer/lib/ruby_indexer/configuration"
12
12
  require "ruby_indexer/lib/ruby_indexer/prefix_tree"
13
13
  require "ruby_indexer/lib/ruby_indexer/location"
14
+ require "ruby_indexer/lib/ruby_indexer/rbs_indexer"
14
15
 
15
16
  module RubyIndexer
16
17
  @configuration = T.let(Configuration.new, Configuration)
@@ -191,7 +191,8 @@ module RubyIndexer
191
191
 
192
192
  @index.delete(IndexablePath.new(nil, "/fake/path/foo.rb"))
193
193
  refute_entry("Foo")
194
- assert_empty(@index.instance_variable_get(:@files_to_entries))
194
+
195
+ assert_no_indexed_entries
195
196
  end
196
197
 
197
198
  def test_comments_can_be_attached_to_a_class
@@ -323,7 +324,7 @@ module RubyIndexer
323
324
  assert_equal("Bar", foo.parent_class)
324
325
 
325
326
  baz = T.must(@index["Baz"].first)
326
- assert_nil(baz.parent_class)
327
+ assert_equal("::Object", baz.parent_class)
327
328
 
328
329
  qux = T.must(@index["Something::Qux"].first)
329
330
  assert_equal("::Baz", qux.parent_class)
@@ -54,7 +54,7 @@ module RubyIndexer
54
54
 
55
55
  assert_includes(indexables, "#{RbConfig::CONFIG["rubylibdir"]}/pathname.rb")
56
56
  assert_includes(indexables, "#{RbConfig::CONFIG["rubylibdir"]}/ipaddr.rb")
57
- assert_includes(indexables, "#{RbConfig::CONFIG["rubylibdir"]}/abbrev.rb")
57
+ assert_includes(indexables, "#{RbConfig::CONFIG["rubylibdir"]}/erb.rb")
58
58
  end
59
59
 
60
60
  def test_indexables_includes_project_files
@@ -105,7 +105,7 @@ module RubyIndexer
105
105
  self.class::FOO = 1
106
106
  RUBY
107
107
 
108
- assert_no_entries
108
+ assert_no_indexed_entries
109
109
  end
110
110
 
111
111
  def test_private_constant_indexing