Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support symbol procs in definition #1982

Merged
merged 1 commit into from Apr 29, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 16 additions & 7 deletions lib/ruby_lsp/listeners/definition.rb
Expand Up @@ -30,6 +30,7 @@ def initialize(response_builder, global_state, uri, nesting, dispatcher, typeche
dispatcher.register(
self,
:on_call_node_enter,
:on_block_argument_node_enter,
:on_constant_read_node_enter,
:on_constant_path_node_enter,
)
Expand All @@ -42,10 +43,21 @@ def on_call_node_enter(node)
if message == :require || message == :require_relative
handle_require_definition(node)
else
handle_method_definition(node)
handle_method_definition(message.to_s, self_receiver?(node))
end
end

sig { params(node: Prism::BlockArgumentNode).void }
def on_block_argument_node_enter(node)
expression = node.expression
return unless expression.is_a?(Prism::SymbolNode)

value = expression.value
return unless value

handle_method_definition(value, false)
end

sig { params(node: Prism::ConstantPathNode).void }
def on_constant_path_node_enter(node)
name = constant_name(node)
Expand All @@ -64,12 +76,9 @@ def on_constant_read_node_enter(node)

private

sig { params(node: Prism::CallNode).void }
def handle_method_definition(node)
message = node.message
return unless message

methods = if self_receiver?(node)
sig { params(message: String, self_receiver: T::Boolean).void }
def handle_method_definition(message, self_receiver)
methods = if self_receiver
@index.resolve_method(message, @nesting.join("::"))
else
# If the method doesn't have a receiver, then we provide a few candidates to jump to
Expand Down
2 changes: 1 addition & 1 deletion lib/ruby_lsp/requests/definition.rb
Expand Up @@ -47,7 +47,7 @@ def initialize(document, global_state, position, dispatcher, typechecker_enabled

target, parent, nesting = document.locate_node(
position,
node_types: [Prism::CallNode, Prism::ConstantReadNode, Prism::ConstantPathNode],
node_types: [Prism::CallNode, Prism::ConstantReadNode, Prism::ConstantPathNode, Prism::BlockArgumentNode],
)

if target.is_a?(Prism::ConstantReadNode) && parent.is_a?(Prism::ConstantPathNode)
Expand Down
10 changes: 6 additions & 4 deletions test/requests/definition_expectations_test.rb
Expand Up @@ -407,6 +407,8 @@ def test_definition_precision_for_methods_with_block_arguments
source = <<~RUBY
class Foo
def foo(&block); end
def argument; end
end
bar.foo(&:argument)
Expand All @@ -417,16 +419,16 @@ def foo(&block); end
server.process_message(
id: 1,
method: "textDocument/definition",
params: { textDocument: { uri: uri }, position: { character: 12, line: 4 } },
params: { textDocument: { uri: uri }, position: { character: 12, line: 6 } },
)
assert_empty(server.pop_response.response)
assert_equal(3, server.pop_response.response.first.range.start.line)

server.process_message(
id: 1,
method: "textDocument/definition",
params: { textDocument: { uri: uri }, position: { character: 4, line: 4 } },
params: { textDocument: { uri: uri }, position: { character: 4, line: 6 } },
)
refute_empty(server.pop_response.response)
assert_equal(1, server.pop_response.response.first.range.start.line)
end
end

Expand Down