Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions lib/ruby_lsp/listeners/definition.rb
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,13 @@ def handle_instance_variable_definition(name)
def handle_method_definition(message, receiver_type, inherited_only: false)
methods = if receiver_type
@index.resolve_method(message, receiver_type.name, inherited_only: inherited_only)
else
# If the method doesn't have a receiver, then we provide a few candidates to jump to
# But we don't want to provide too many candidates, as it can be overwhelming
@index[message]&.take(MAX_NUMBER_OF_DEFINITION_CANDIDATES_WITHOUT_RECEIVER)
end

# If the method doesn't have a receiver, or the guessed receiver doesn't have any matched candidates,
# then we provide a few candidates to jump to
# But we don't want to provide too many candidates, as it can be overwhelming
if receiver_type.nil? || (receiver_type.is_a?(TypeInferrer::GuessedType) && methods.nil?)
methods = @index[message]&.take(MAX_NUMBER_OF_DEFINITION_CANDIDATES_WITHOUT_RECEIVER)
end

return unless methods
Expand Down
65 changes: 65 additions & 0 deletions test/requests/definition_expectations_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,71 @@ def foo; end
end
end

def test_definition_for_guessed_receiver_is_listed
source = <<~RUBY
# typed: false

class Cheetah
def meow; end
end

class Cat
def meow; end
end

cat = Cat.new
cat.meow
RUBY

with_server(source) do |server, uri|
server.process_message(
id: 1,
method: "textDocument/definition",
params: { textDocument: { uri: uri }, position: { character: 4, line: 11 } },
)
response = server.pop_response.response

# Only Cat#meow is listed
assert_equal(1, response.size)
assert_equal(7, response.first.target_range.start.line)
assert_equal(7, response.first.target_range.end.line)
assert_equal(2, response.first.target_range.start.character)
assert_equal(15, response.first.target_range.end.character)
end
end

def test_guessed_receiver_is_treated_as_unknown_when_no_declaration_exists
source = <<~RUBY
# typed: false

class Animal
def eat; end
end

class Cheetah
def meow; end
end

class Cat
def meow; end
end

animal = Cat.new
animal.meow
RUBY

with_server(source) do |server, uri|
server.process_message(
id: 1,
method: "textDocument/definition",
params: { textDocument: { uri: uri }, position: { character: 7, line: 15 } },
)
response = server.pop_response.response

assert_equal(2, response.size)
end
end

def test_definitions_for_unknown_receiver_is_capped
source = +"# typed: false\n"

Expand Down