Skip to content

Commit

Permalink
Add CallNode field to NodeContext
Browse files Browse the repository at this point in the history
  • Loading branch information
andyw8 committed May 31, 2024
1 parent 1f0f3c2 commit 60f5ed8
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 5 deletions.
7 changes: 6 additions & 1 deletion lib/ruby_lsp/document.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ def locate(node, char_position, node_types: [])
closest = node
parent = T.let(nil, T.nilable(Prism::Node))
nesting = T.let([], T::Array[T.any(Prism::ClassNode, Prism::ModuleNode)])
call_node = T.let(nil, T.nilable(Prism::CallNode))

until queue.empty?
candidate = queue.shift
Expand Down Expand Up @@ -159,6 +160,10 @@ def locate(node, char_position, node_types: [])
nesting << candidate
end

if candidate.is_a?(Prism::CallNode)
call_node = candidate
end

# If there are node types to filter by, and the current node is not one of those types, then skip it
next if node_types.any? && node_types.none? { |type| candidate.class == type }

Expand All @@ -170,7 +175,7 @@ def locate(node, char_position, node_types: [])
end
end

NodeContext.new(closest, parent, nesting.map { |n| n.constant_path.location.slice })
NodeContext.new(closest, parent, nesting.map { |n| n.constant_path.location.slice }, call_node)
end

sig { returns(T::Boolean) }
Expand Down
19 changes: 15 additions & 4 deletions lib/ruby_lsp/node_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
# frozen_string_literal: true

module RubyLsp
# This class allows listeners to access contextual information about a node in the AST, such as its parent
# and its namespace nesting.
# This class allows listeners to access contextual information about a node in the AST, such as its parent,
# its namespace nesting, and the surrounding CallNode (e.g. a method call).
class NodeContext
extend T::Sig

Expand All @@ -13,11 +13,22 @@ class NodeContext
sig { returns(T::Array[String]) }
attr_reader :nesting

sig { params(node: T.nilable(Prism::Node), parent: T.nilable(Prism::Node), nesting: T::Array[String]).void }
def initialize(node, parent, nesting)
sig { returns(T.nilable(Prism::CallNode)) }
attr_reader :call_node

sig do
params(
node: T.nilable(Prism::Node),
parent: T.nilable(Prism::Node),
nesting: T::Array[String],
call_node: T.nilable(Prism::CallNode),
).void
end
def initialize(node, parent, nesting, call_node)
@node = node
@parent = parent
@nesting = nesting
@call_node = call_node
end

sig { returns(String) }
Expand Down
21 changes: 21 additions & 0 deletions test/ruby_document_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,27 @@ def baz
assert_equal(["Foo", "Other"], node_context.nesting)
end

def test_locate_returns_call_node
document = RubyLsp::RubyDocument.new(source: <<~RUBY, version: 1, uri: URI("file:///foo/bar.rb"))
module Foo
class Other
def do_it
hello :foo
:bar
end
end
end
RUBY

node_context = document.locate_node({ line: 3, character: 14 })
assert_equal(":foo", T.must(node_context.node).slice)
assert_equal(:hello, T.must(node_context.call_node).name)

node_context = document.locate_node({ line: 4, character: 8 })
assert_equal(":bar", T.must(node_context.node).slice)
assert_nil(node_context.call_node)
end

def test_locate_returns_correct_nesting_when_specifying_target_classes
document = RubyLsp::RubyDocument.new(source: <<~RUBY, version: 1, uri: URI("file:///foo/bar.rb"))
module Foo
Expand Down

0 comments on commit 60f5ed8

Please sign in to comment.