From d27b55e94b30f88c919197a47f0a265d81ffa663 Mon Sep 17 00:00:00 2001 From: Vinicius Stock Date: Thu, 5 Mar 2026 09:16:00 -0500 Subject: [PATCH] Switch singleton class names to new style --- .../lib/ruby_indexer/declaration_listener.rb | 4 +- lib/ruby_indexer/lib/ruby_indexer/index.rb | 16 +-- .../lib/ruby_indexer/reference_finder.rb | 4 +- .../test/classes_and_modules_test.rb | 22 ++-- lib/ruby_indexer/test/enhancements_test.rb | 20 ++-- lib/ruby_indexer/test/index_test.rb | 102 +++++++++--------- .../test/instance_variables_test.rb | 10 +- lib/ruby_indexer/test/method_test.rb | 6 +- lib/ruby_indexer/test/rbs_indexer_test.rb | 10 +- .../test/reference_finder_test.rb | 2 +- lib/ruby_lsp/listeners/test_style.rb | 2 +- lib/ruby_lsp/node_context.rb | 4 +- lib/ruby_lsp/type_inferrer.rb | 10 +- test/requests/completion_resolve_test.rb | 2 +- test/ruby_document_test.rb | 6 +- test/server_test.rb | 4 +- test/type_inferrer_test.rb | 26 ++--- 17 files changed, 125 insertions(+), 125 deletions(-) diff --git a/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb b/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb index 174dc346ba..eb573cabfe 100644 --- a/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +++ b/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb @@ -129,7 +129,7 @@ def on_singleton_class_node_enter(node) if current_owner expression = node.expression - name = (expression.is_a?(Prism::SelfNode) ? "" : "") + name = (expression.is_a?(Prism::SelfNode) ? "<#{last_name_in_stack}>" : "<#{expression.slice}>") real_nesting = Index.actual_nesting(@stack, name) existing_entries = @index[real_nesting.join("::")] #: as Array[Entry::SingletonClass]? @@ -577,7 +577,7 @@ def handle_class_variable(node, loc) # set the class variable's owner to the attached context when defined within a singleton scope. if owner.is_a?(Entry::SingletonClass) - owner = @owner_stack.reverse.find { |entry| !entry.name.include?("" + nesting << "<#{nesting.last}>" end end @@ -616,7 +616,7 @@ def instance_variable_completion_candidates(name, owner_name) if class_variables.any? name_parts = owner_name.split("::") - if name_parts.last&.start_with?(" Entry::SingletonClass def existing_or_new_singleton_class(name) *_namespace, unqualified_name = name.split("::") - full_singleton_name = "#{name}::" + full_singleton_name = "#{name}::<#{unqualified_name}>" singleton = self[full_singleton_name]&.first #: as Entry::SingletonClass? unless singleton @@ -744,7 +744,7 @@ def entries_for(uri, type = nil) def linearized_attached_ancestors(name) name_parts = name.split("::") - if name_parts.last&.start_with?("" + parent_name_parts << "<#{parent_name_parts.last}>" end ancestors.concat(linearized_ancestors_of(parent_name_parts.join("::"))) @@ -878,7 +878,7 @@ def linearize_superclass( # rubocop:disable Metrics/ParameterLists class_class_name_parts = ["Class"] (singleton_levels - 1).times do - class_class_name_parts << "" + class_class_name_parts << "<#{class_class_name_parts.last}>" end ancestors.concat(linearized_ancestors_of(class_class_name_parts.join("::"))) @@ -892,7 +892,7 @@ def linearize_superclass( # rubocop:disable Metrics/ParameterLists module_class_name_parts = ["Module"] (singleton_levels - 1).times do - module_class_name_parts << "" + module_class_name_parts << "<#{module_class_name_parts.last}>" end ancestors.concat(linearized_ancestors_of(module_class_name_parts.join("::"))) diff --git a/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb b/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb index e521a4d070..8c167c40a8 100644 --- a/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +++ b/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb @@ -134,7 +134,7 @@ def on_singleton_class_node_enter(node) expression = node.expression return unless expression.is_a?(Prism::SelfNode) - @stack << "" + @stack << "<#{@stack.last}>" end #: (Prism::SingletonClassNode node) -> void @@ -239,7 +239,7 @@ def on_def_node_enter(node) end if node.receiver.is_a?(Prism::SelfNode) - @stack << "" + @stack << "<#{@stack.last}>" end end diff --git a/lib/ruby_indexer/test/classes_and_modules_test.rb b/lib/ruby_indexer/test/classes_and_modules_test.rb index 349465921f..6439aa5784 100644 --- a/lib/ruby_indexer/test/classes_and_modules_test.rb +++ b/lib/ruby_indexer/test/classes_and_modules_test.rb @@ -489,15 +489,15 @@ class ConstantPathReferences end RUBY - foo = @index["Foo::"] #: as !nil + foo = @index["Foo::"] #: as !nil .first #: as Entry::Class assert_equal(["A1", "A2", "A3", "A4", "A5", "A6"], foo.mixin_operation_module_names) - qux = @index["Foo::Qux::"] #: as !nil + qux = @index["Foo::Qux::"] #: as !nil .first #: as Entry::Class assert_equal(["Corge", "Corge", "Baz"], qux.mixin_operation_module_names) - constant_path_references = @index["ConstantPathReferences::"] #: as !nil + constant_path_references = @index["ConstantPathReferences::"] #: as !nil .first #: as Entry::Class assert_equal(["Foo::Bar", "Foo::Bar2"], constant_path_references.mixin_operation_module_names) end @@ -512,7 +512,7 @@ class << self end RUBY - foo = @index["Foo::"] #: as !nil + foo = @index["Foo::"] #: as !nil .first #: as Entry::SingletonClass assert_equal(4, foo.location.start_line) assert_equal("Some extra comments", foo.comments) @@ -527,7 +527,7 @@ class << bar end RUBY - singleton = @index["Foo::"] #: as !nil + singleton = @index["Foo::"] #: as !nil .first #: as Entry::SingletonClass # Even though this is not correct, we consider any dynamic singleton class block as a regular singleton class. @@ -547,7 +547,7 @@ class Bar end RUBY - assert_entry("Foo::::Bar", Entry::Class, "/fake/path/foo.rb:2-4:3-7") + assert_entry("Foo::::Bar", Entry::Class, "/fake/path/foo.rb:2-4:3-7") end def test_name_location_points_to_constant_path_location @@ -614,10 +614,10 @@ class << self entries = @index.instance_variable_get(:@entries) refute(entries.key?("::Foo")) refute(entries.key?("::Foo::Bar")) - refute(entries.key?("::Foo::Bar::")) + refute(entries.key?("::Foo::Bar::")) assert_entry("Foo", Entry::Module, "/fake/path/foo.rb:0-0:5-3") assert_entry("Foo::Bar", Entry::Class, "/fake/path/foo.rb:1-2:4-5") - assert_entry("Foo::Bar::", Entry::SingletonClass, "/fake/path/foo.rb:2-4:3-7") + assert_entry("Foo::Bar::", Entry::SingletonClass, "/fake/path/foo.rb:2-4:3-7") end def test_indexing_namespaces_inside_nested_top_level_references @@ -683,13 +683,13 @@ def baz; end RUBY # Verify we didn't index the incorrect name - assert_nil(@index["Foo::Bar::"]) + assert_nil(@index["Foo::Bar::"]) # Verify we indexed the correct name - assert_entry("Foo::Bar::", Entry::SingletonClass, "/fake/path/foo.rb:1-2:3-5") + assert_entry("Foo::Bar::", Entry::SingletonClass, "/fake/path/foo.rb:1-2:3-5") method = @index["baz"]&.first #: as Entry::Method - assert_equal("Foo::Bar::", method.owner&.name) + assert_equal("Foo::Bar::", method.owner&.name) end def test_lazy_comments_with_spaces_are_properly_attributed diff --git a/lib/ruby_indexer/test/enhancements_test.rb b/lib/ruby_indexer/test/enhancements_test.rb index aeadbabdc6..078606fa52 100644 --- a/lib/ruby_indexer/test/enhancements_test.rb +++ b/lib/ruby_indexer/test/enhancements_test.rb @@ -76,18 +76,18 @@ class User < ActiveRecord::Base assert_equal( [ - "User::", - "ActiveRecord::Base::", + "User::", + "ActiveRecord::Base::", "ActiveRecord::Associations::ClassMethods", - "Object::", - "BasicObject::", + "Object::", + "BasicObject::", "Class", "Module", "Object", "Kernel", "BasicObject", ], - @index.linearized_ancestors_of("User::"), + @index.linearized_ancestors_of("User::"), ) assert_entry("new_method", Entry::Method, "/fake/path/foo.rb:10-4:10-33") @@ -271,20 +271,20 @@ class User assert_equal( [ - "User::", + "User::", "MyConcern::ClassMethods", - "Object::", - "BasicObject::", + "Object::", + "BasicObject::", "Class", "Module", "Object", "Kernel", "BasicObject", ], - @index.linearized_ancestors_of("User::"), + @index.linearized_ancestors_of("User::"), ) - refute_nil(@index.resolve_method("foo", "User::")) + refute_nil(@index.resolve_method("foo", "User::")) end def test_creating_anonymous_classes_from_enhancement diff --git a/lib/ruby_indexer/test/index_test.rb b/lib/ruby_indexer/test/index_test.rb index f236bd00bf..a38be36291 100644 --- a/lib/ruby_indexer/test/index_test.rb +++ b/lib/ruby_indexer/test/index_test.rb @@ -1386,7 +1386,7 @@ def found_me!; end end RUBY - entry = @index.resolve_method("found_me!", "Foo::Bar::::Baz::")&.first #: as !nil + entry = @index.resolve_method("found_me!", "Foo::Bar::::Baz::")&.first #: as !nil refute_nil(entry) assert_equal("found_me!", entry.name) end @@ -1411,7 +1411,7 @@ class << self end RUBY - entry = @index.resolve("CONST", ["Foo", "Bar", "", "Baz", ""])&.first #: as !nil + entry = @index.resolve("CONST", ["Foo", "Bar", "", "Baz", ""])&.first #: as !nil refute_nil(entry) assert_equal(9, entry.location.start_line) end @@ -1433,15 +1433,15 @@ def hello end RUBY - entry = @index.resolve_instance_variable("@a", "Foo::Bar::")&.first #: as !nil + entry = @index.resolve_instance_variable("@a", "Foo::Bar::")&.first #: as !nil refute_nil(entry) assert_equal("@a", entry.name) - entry = @index.resolve_instance_variable("@b", "Foo::Bar::")&.first #: as !nil + entry = @index.resolve_instance_variable("@b", "Foo::Bar::")&.first #: as !nil refute_nil(entry) assert_equal("@b", entry.name) - entry = @index.resolve_instance_variable("@c", "Foo::Bar::::>")&.first #: as !nil + entry = @index.resolve_instance_variable("@c", "Foo::Bar::::<>")&.first #: as !nil refute_nil(entry) assert_equal("@c", entry.name) end @@ -1463,7 +1463,7 @@ def hello end RUBY - entries = @index.instance_variable_completion_candidates("@", "Foo::Bar::").map(&:name) + entries = @index.instance_variable_completion_candidates("@", "Foo::Bar::").map(&:name) assert_includes(entries, "@a") assert_includes(entries, "@b") end @@ -1724,37 +1724,37 @@ class << self assert_equal( [ - "Baz::::>", - "Bar::::>", - "Foo::::>", - "Object::::>", - "BasicObject::::>", - "Class::", - "Module::", - "Object::", - "BasicObject::", + "Baz::::<>", + "Bar::::<>", + "Foo::::<>", + "Object::::<>", + "BasicObject::::<>", + "Class::", + "Module::", + "Object::", + "BasicObject::", "Class", "Module", "Object", "Kernel", "BasicObject", ], - @index.linearized_ancestors_of("Baz::::>"), + @index.linearized_ancestors_of("Baz::::<>"), ) end def test_linearizing_singleton_object assert_equal( [ - "Object::", - "BasicObject::", + "Object::", + "BasicObject::", "Class", "Module", "Object", "Kernel", "BasicObject", ], - @index.linearized_ancestors_of("Object::"), + @index.linearized_ancestors_of("Object::"), ) end @@ -1771,7 +1771,7 @@ def baz end RUBY - ["bar", "baz"].product(["Foo", "Foo::"]).each do |method, receiver| + ["bar", "baz"].product(["Foo", "Foo::"]).each do |method, receiver| entry = @index.resolve_method(method, receiver)&.first #: as !nil refute_nil(entry) assert_equal(method, entry.name) @@ -1779,14 +1779,14 @@ def baz assert_equal( [ - "Foo::", + "Foo::", "Foo", "Module", "Object", "Kernel", "BasicObject", ], - @index.linearized_ancestors_of("Foo::"), + @index.linearized_ancestors_of("Foo::"), ) end @@ -1816,18 +1816,18 @@ class << self assert_equal( [ - "Foo::Bar::::Baz::", + "Foo::Bar::::Baz::", "Second", "First", - "Object::", - "BasicObject::", + "Object::", + "BasicObject::", "Class", "Module", "Object", "Kernel", "BasicObject", ], - @index.linearized_ancestors_of("Foo::Bar::::Baz::"), + @index.linearized_ancestors_of("Foo::Bar::::Baz::"), ) end @@ -1846,18 +1846,18 @@ class << self assert_equal( [ - "Baz::", - "Bar::", - "Foo::", - "Object::", - "BasicObject::", + "Baz::", + "Bar::", + "Foo::", + "Object::", + "BasicObject::", "Class", "Module", "Object", "Kernel", "BasicObject", ], - @index.linearized_ancestors_of("Baz::"), + @index.linearized_ancestors_of("Baz::"), ) end @@ -1868,19 +1868,19 @@ module A; end assert_equal( [ - "A::", + "A::", "Module", "Object", "Kernel", "BasicObject", ], - @index.linearized_ancestors_of("A::"), + @index.linearized_ancestors_of("A::"), ) end def test_linearizing_a_singleton_class_with_no_attached assert_raises(Index::NonExistingNamespaceError) do - @index.linearized_ancestors_of("A::") + @index.linearized_ancestors_of("A::") end end @@ -1894,17 +1894,17 @@ class User < ActiveRecord::Base assert_equal( [ - "User::", - "ActiveRecord::Base::", - "Object::", - "BasicObject::", + "User::", + "ActiveRecord::Base::", + "Object::", + "BasicObject::", "Class", "Module", "Object", "Kernel", "BasicObject", ], - @index.linearized_ancestors_of("User::"), + @index.linearized_ancestors_of("User::"), ) end @@ -1926,18 +1926,18 @@ class Child < Namespace::Parent assert_equal( [ - "Foo::Child::", - "Foo::Namespace::Parent::", + "Foo::Child::", + "Foo::Namespace::Parent::", "Bar", - "Object::", - "BasicObject::", + "Object::", + "BasicObject::", "Class", "Module", "Object", "Kernel", "BasicObject", ], - @index.linearized_ancestors_of("Foo::Child::"), + @index.linearized_ancestors_of("Foo::Child::"), ) end @@ -1972,13 +1972,13 @@ def self.my_singleton_def; end RUBY entries = @index.entries_for("file:///fake/path/foo.rb", Entry) #: as !nil - assert_equal(["Foo", "Bar", "my_def", "Bar::", "my_singleton_def"], entries.map(&:name)) + assert_equal(["Foo", "Bar", "my_def", "Bar::", "my_singleton_def"], entries.map(&:name)) entries = @index.entries_for("file:///fake/path/foo.rb", RubyIndexer::Entry::Namespace) #: as !nil - assert_equal(["Foo", "Bar", "Bar::"], entries.map(&:name)) + assert_equal(["Foo", "Bar", "Bar::"], entries.map(&:name)) entries = @index.entries_for("file:///fake/path/foo.rb") #: as !nil - assert_equal(["Foo", "Bar", "my_def", "Bar::", "my_singleton_def"], entries.map(&:name)) + assert_equal(["Foo", "Bar", "my_def", "Bar::", "my_singleton_def"], entries.map(&:name)) end def test_entries_for_returns_nil_if_no_matches @@ -2204,7 +2204,7 @@ def self.do end RUBY - adf, abc = @index.instance_variable_completion_candidates("@", "Child::") + adf, abc = @index.instance_variable_completion_candidates("@", "Child::") refute_nil(abc) refute_nil(adf) @@ -2223,7 +2223,7 @@ def self.do end RUBY - candidates = @index.class_variable_completion_candidates("@@", "Foo::") + candidates = @index.class_variable_completion_candidates("@@", "Foo::") refute_empty(candidates) assert_equal("@@hello", candidates.first&.name) @@ -2236,7 +2236,7 @@ class Foo end RUBY - candidates = @index.resolve_class_variable("@@hello", "Foo::") #: as !nil + candidates = @index.resolve_class_variable("@@hello", "Foo::") #: as !nil refute_empty(candidates) assert_equal("@@hello", candidates.first&.name) diff --git a/lib/ruby_indexer/test/instance_variables_test.rb b/lib/ruby_indexer/test/instance_variables_test.rb index b67adf685c..53dc73c6ba 100644 --- a/lib/ruby_indexer/test/instance_variables_test.rb +++ b/lib/ruby_indexer/test/instance_variables_test.rb @@ -159,21 +159,21 @@ def hello entry = @index["@a"]&.first #: as Entry::InstanceVariable owner = entry.owner assert_instance_of(Entry::SingletonClass, owner) - assert_equal("Foo::Bar::", owner&.name) + assert_equal("Foo::Bar::", owner&.name) assert_entry("@b", Entry::InstanceVariable, "/fake/path/foo.rb:6-8:6-10") entry = @index["@b"]&.first #: as Entry::InstanceVariable owner = entry.owner assert_instance_of(Entry::SingletonClass, owner) - assert_equal("Foo::Bar::", owner&.name) + assert_equal("Foo::Bar::", owner&.name) assert_entry("@c", Entry::InstanceVariable, "/fake/path/foo.rb:9-6:9-8") entry = @index["@c"]&.first #: as Entry::InstanceVariable owner = entry.owner assert_instance_of(Entry::SingletonClass, owner) - assert_equal("Foo::Bar::::>", owner&.name) + assert_equal("Foo::Bar::::<>", owner&.name) end def test_top_level_instance_variables @@ -197,7 +197,7 @@ def self.bar entry = @index["@a"]&.first #: as Entry::InstanceVariable owner = entry.owner assert_instance_of(Entry::SingletonClass, owner) - assert_equal("Foo::", owner&.name) + assert_equal("Foo::", owner&.name) end def test_instance_variable_inside_dynamic_method_declaration @@ -234,7 +234,7 @@ def something; end entry = @index["@a"]&.first #: as Entry::InstanceVariable owner = entry.owner assert_instance_of(Entry::SingletonClass, owner) - assert_equal("Foo::", owner&.name) + assert_equal("Foo::", owner&.name) end def test_class_instance_variable_comments diff --git a/lib/ruby_indexer/test/method_test.rb b/lib/ruby_indexer/test/method_test.rb index c188d75950..c81f8a4bd6 100644 --- a/lib/ruby_indexer/test/method_test.rb +++ b/lib/ruby_indexer/test/method_test.rb @@ -49,7 +49,7 @@ def self.bar entry = @index["bar"]&.first #: as Entry::Method owner = entry.owner - assert_equal("Foo::", owner&.name) + assert_equal("Foo::", owner&.name) assert_instance_of(Entry::SingletonClass, owner) end @@ -145,7 +145,7 @@ def bar; end assert_instance_of(Entry::Module, first_entry&.owner) assert_predicate(first_entry, :private?) # The second entry points to the public singleton method - assert_equal("Test::", second_entry&.owner&.name) + assert_equal("Test::", second_entry&.owner&.name) assert_instance_of(Entry::SingletonClass, second_entry&.owner) assert_equal(:public, second_entry&.visibility) end @@ -873,7 +873,7 @@ def qux; end assert_equal("Foo", instance_baz&.owner&.name) assert_predicate(singleton_baz, :public?) - assert_equal("Foo::", singleton_baz&.owner&.name) + assert_equal("Foo::", singleton_baz&.owner&.name) # After invoking `public`, the state of `module_function` is reset instance_qux, singleton_qux = @index["qux"] #: as Array[Entry::Method] diff --git a/lib/ruby_indexer/test/rbs_indexer_test.rb b/lib/ruby_indexer/test/rbs_indexer_test.rb index 4e026ca3c7..ea5a2c3b4a 100644 --- a/lib/ruby_indexer/test/rbs_indexer_test.rb +++ b/lib/ruby_indexer/test/rbs_indexer_test.rb @@ -89,7 +89,7 @@ def test_attaches_correct_owner_to_singleton_methods owner = entries.first&.owner #: as Entry::SingletonClass assert_instance_of(Entry::SingletonClass, owner) - assert_equal("File::", owner.name) + assert_equal("File::", owner.name) end def test_location_and_name_location_are_the_same @@ -122,7 +122,7 @@ def test_rbs_method_with_required_positionals def test_rbs_method_with_unnamed_required_positionals entries = @index["try_convert"] #: as Array[Entry::Method] - entry = entries.find { |entry| entry.owner&.name == "Array::" } #: as Entry::Method + entry = entries.find { |entry| entry.owner&.name == "Array::" } #: as Entry::Method parameters = entry.signatures[0]&.parameters #: as Array[Entry::Parameter] @@ -132,7 +132,7 @@ def test_rbs_method_with_unnamed_required_positionals def test_rbs_method_with_optional_positionals entries = @index["polar"] #: as Array[Entry::Method] - entry = entries.find { |entry| entry.owner&.name == "Complex::" } #: as Entry::Method + entry = entries.find { |entry| entry.owner&.name == "Complex::" } #: as Entry::Method # def self.polar: (Numeric, ?Numeric) -> Complex @@ -190,7 +190,7 @@ def test_rbs_method_with_required_and_optional_parameters def test_rbs_anonymous_block_parameter entries = @index["open"] #: as Array[Entry::Method] - entry = entries.find { |entry| entry.owner&.name == "File::" } #: as Entry::Method + entry = entries.find { |entry| entry.owner&.name == "File::" } #: as Entry::Method assert_equal(2, entry.signatures.length) @@ -227,7 +227,7 @@ def test_rbs_method_with_rest_positionals def test_rbs_method_with_trailing_positionals entries = @index["select"] #: as Array[Entry::Method] - entry = entries.find { |entry| entry.owner&.name == "IO::" } #: as !nil + entry = entries.find { |entry| entry.owner&.name == "IO::" } #: as !nil signatures = entry.signatures assert_equal(2, signatures.length) diff --git a/lib/ruby_indexer/test/reference_finder_test.rb b/lib/ruby_indexer/test/reference_finder_test.rb index ed5028d5af..45be86db4a 100644 --- a/lib/ruby_indexer/test/reference_finder_test.rb +++ b/lib/ruby_indexer/test/reference_finder_test.rb @@ -28,7 +28,7 @@ class Bar end def test_finds_constant_references_inside_singleton_contexts - refs = find_const_references("Foo::::Bar", <<~RUBY) + refs = find_const_references("Foo::::Bar", <<~RUBY) class Foo class << self class Bar diff --git a/lib/ruby_lsp/listeners/test_style.rb b/lib/ruby_lsp/listeners/test_style.rb index b18ed7d320..b29aeb204b 100644 --- a/lib/ruby_lsp/listeners/test_style.rb +++ b/lib/ruby_lsp/listeners/test_style.rb @@ -266,7 +266,7 @@ def non_declarative_minitest?(attached_ancestors, fully_qualified_name) # We only support regular Minitest tests. The declarative syntax provided by ActiveSupport is handled by the # Rails add-on name_parts = fully_qualified_name.split("::") - singleton_name = "#{name_parts.join("::")}::" + singleton_name = "#{name_parts.join("::")}::<#{name_parts.last}>" !@index.linearized_ancestors_of(singleton_name).include?("ActiveSupport::Testing::Declarative") rescue RubyIndexer::Index::NonExistingNamespaceError true diff --git a/lib/ruby_lsp/node_context.rb b/lib/ruby_lsp/node_context.rb index 1fe2c4631b..48d06f82c1 100644 --- a/lib/ruby_lsp/node_context.rb +++ b/lib/ruby_lsp/node_context.rb @@ -62,12 +62,12 @@ def handle_nesting_nodes(nodes) when Prism::ClassNode, Prism::ModuleNode nesting << node.constant_path.slice when Prism::SingletonClassNode - nesting << "" + nesting << "<#{nesting.flat_map { |n| n.split("::") }.last}>" when Prism::DefNode surrounding_method = node.name.to_s next unless node.receiver.is_a?(Prism::SelfNode) - nesting << "" + nesting << "<#{nesting.flat_map { |n| n.split("::") }.last}>" end end diff --git a/lib/ruby_lsp/type_inferrer.rb b/lib/ruby_lsp/type_inferrer.rb index e0b75d4f9c..35fbd6b3c3 100644 --- a/lib/ruby_lsp/type_inferrer.rb +++ b/lib/ruby_lsp/type_inferrer.rb @@ -86,9 +86,9 @@ def infer_receiver_for_call_node(node, node_context) return unless name *parts, last = name.split("::") - return Type.new("#{last}::") if parts.empty? + return Type.new("#{last}::<#{last}>") if parts.empty? - Type.new("#{parts.join("::")}::#{last}::") + Type.new("#{parts.join("::")}::#{last}::<#{last}>") when Prism::CallNode raw_receiver = receiver.message @@ -142,7 +142,7 @@ def self_receiver_handling(node_context) # If the class/module definition is using compact style (e.g.: `class Foo::Bar`), then we need to split the name # into its individual parts to build the correct singleton name parts = nesting.flat_map { |part| part.split("::") } - Type.new("#{parts.join("::")}::") + Type.new("#{parts.join("::")}::<#{parts.last}>") end #: (NodeContext node_context) -> Type? @@ -152,7 +152,7 @@ def infer_receiver_for_class_variables(node_context) return Type.new("Object") if nesting_parts.empty? nesting_parts.reverse_each do |part| - break unless part.include?("` part from its name + # Returns the attached version of this type by removing the `<...>` part from its name #: -> Type def attached Type.new( diff --git a/test/requests/completion_resolve_test.rb b/test/requests/completion_resolve_test.rb index e42785bdcb..c7664f66a9 100644 --- a/test/requests/completion_resolve_test.rb +++ b/test/requests/completion_resolve_test.rb @@ -122,7 +122,7 @@ def test_indicates_signature_count_in_label_details existing_item = { label: "try_convert", kind: RubyLsp::Constant::CompletionItemKind::METHOD, - data: { owner_name: "String::" }, + data: { owner_name: "String::" }, } server.process_message(id: 1, method: "completionItem/resolve", params: existing_item) diff --git a/test/ruby_document_test.rb b/test/ruby_document_test.rb index 0b677a43bd..fe96e6fcff 100644 --- a/test/ruby_document_test.rb +++ b/test/ruby_document_test.rb @@ -953,15 +953,15 @@ def qux assert_nil(node_context.surrounding_method) node_context = document.locate_node({ line: 4, character: 4 }) - assert_equal(["Foo", ""], node_context.nesting) + assert_equal(["Foo", ""], node_context.nesting) assert_equal("bar", node_context.surrounding_method) node_context = document.locate_node({ line: 8, character: 4 }) - assert_equal(["Foo", ""], node_context.nesting) + assert_equal(["Foo", ""], node_context.nesting) assert_nil(node_context.surrounding_method) node_context = document.locate_node({ line: 11, character: 6 }) - assert_equal(["Foo", ""], node_context.nesting) + assert_equal(["Foo", ""], node_context.nesting) assert_equal("baz", node_context.surrounding_method) node_context = document.locate_node({ line: 16, character: 6 }) diff --git a/test/server_test.rb b/test/server_test.rb index 725448fee9..9c6f3554d9 100644 --- a/test/server_test.rb +++ b/test/server_test.rb @@ -1024,7 +1024,7 @@ class Foo params: { textDocument: { uri: uri } }, }) - assert_equal(["Foo::", "Bar"], index.linearized_ancestors_of("Foo::")) + assert_equal(["Foo::", "Bar"], index.linearized_ancestors_of("Foo::")) # Delete the extend @server.process_message({ @@ -1063,7 +1063,7 @@ class Foo result = find_message(RubyLsp::Result, id: 2) refute_nil(result) - assert_equal(["Foo::"], index.linearized_ancestors_of("Foo::")) + assert_equal(["Foo::"], index.linearized_ancestors_of("Foo::")) end def test_edits_outside_of_declarations_do_not_trigger_indexing diff --git a/test/type_inferrer_test.rb b/test/type_inferrer_test.rb index 1425be9b5f..0afc1ef0e4 100644 --- a/test/type_inferrer_test.rb +++ b/test/type_inferrer_test.rb @@ -29,7 +29,7 @@ class Foo end RUBY - assert_equal("Foo::", @type_inferrer.infer_receiver_type(node_context).name) + assert_equal("Foo::", @type_inferrer.infer_receiver_type(node_context).name) end def test_infer_receiver_type_self_inside_singleton_method @@ -41,7 +41,7 @@ def self.bar end RUBY - assert_equal("Foo::", @type_inferrer.infer_receiver_type(node_context).name) + assert_equal("Foo::", @type_inferrer.infer_receiver_type(node_context).name) end def test_infer_receiver_type_self_inside_singleton_block_body @@ -53,7 +53,7 @@ class << self end RUBY - assert_equal("Foo::::>", @type_inferrer.infer_receiver_type(node_context).name) + assert_equal("Foo::::<>", @type_inferrer.infer_receiver_type(node_context).name) end def test_infer_receiver_type_self_inside_singleton_block_method @@ -67,7 +67,7 @@ def bar end RUBY - assert_equal("Foo::", @type_inferrer.infer_receiver_type(node_context).name) + assert_equal("Foo::", @type_inferrer.infer_receiver_type(node_context).name) end def test_infer_receiver_type_constant @@ -79,7 +79,7 @@ def bar; end Foo.bar RUBY - assert_equal("Foo::", @type_inferrer.infer_receiver_type(node_context).name) + assert_equal("Foo::", @type_inferrer.infer_receiver_type(node_context).name) end def test_infer_receiver_type_constant_path @@ -93,7 +93,7 @@ def baz; end Foo::Bar.baz RUBY - assert_equal("Foo::Bar::", @type_inferrer.infer_receiver_type(node_context).name) + assert_equal("Foo::Bar::", @type_inferrer.infer_receiver_type(node_context).name) end def test_infer_top_level_receiver @@ -111,7 +111,7 @@ class Foo end RUBY - assert_equal("Foo::", @type_inferrer.infer_receiver_type(node_context).name) + assert_equal("Foo::", @type_inferrer.infer_receiver_type(node_context).name) end def test_infer_receiver_type_instance_variables_in_singleton_method @@ -123,7 +123,7 @@ def self.bar end RUBY - assert_equal("Foo::", @type_inferrer.infer_receiver_type(node_context).name) + assert_equal("Foo::", @type_inferrer.infer_receiver_type(node_context).name) end def test_infer_receiver_type_instance_variables_in_singleton_block_body @@ -135,7 +135,7 @@ class << self end RUBY - assert_equal("Foo::::>", @type_inferrer.infer_receiver_type(node_context).name) + assert_equal("Foo::::<>", @type_inferrer.infer_receiver_type(node_context).name) end def test_infer_receiver_type_in_namespaced_singleton_method @@ -148,7 +148,7 @@ def self.foo RUBY result = @type_inferrer.infer_receiver_type(node_context).name - assert_equal("Foo::Bar::", result) + assert_equal("Foo::Bar::", result) end def test_infer_receiver_type_instance_variables_in_singleton_block_method @@ -162,7 +162,7 @@ def bar end RUBY - assert_equal("Foo::", @type_inferrer.infer_receiver_type(node_context).name) + assert_equal("Foo::", @type_inferrer.infer_receiver_type(node_context).name) end def test_infer_receiver_type_instance_variables_in_instance_method @@ -376,7 +376,7 @@ class Admin::User end RUBY - assert_equal("Admin::User::", @type_inferrer.infer_receiver_type(node_context).name) + assert_equal("Admin::User::", @type_inferrer.infer_receiver_type(node_context).name) end def test_infer_self_type_for_compact_namespace_inside_method @@ -400,7 +400,7 @@ def self.foo end RUBY - assert_equal("Admin::User::", @type_inferrer.infer_receiver_type(node_context).name) + assert_equal("Admin::User::", @type_inferrer.infer_receiver_type(node_context).name) end def test_infer_receiver_type_class_variables_in_class_body