Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
17 changes: 16 additions & 1 deletion lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -264,12 +264,27 @@ def on_def_node_leave(node)

sig { params(node: Prism::CallNode).void }
def on_call_node_enter(node)
if @target.is_a?(MethodTarget) && (name = node.name.to_s) == @target.method_name
return unless @target.is_a?(MethodTarget)

if (name = node.name.to_s) == @target.method_name
@references << Reference.new(name, T.must(node.message_loc), declaration: false)
elsif node.name == :attr_writer && attr_writer_matches_method(node.arguments.arguments, @target.method_name)
@references << Reference.new(@target.method_name, T.must(node.message_loc), declaration: true)
elsif node.name == :attr_reader && attr_reader_matches_method(node.arguments.arguments, @target.method_name)
@references << Reference.new(@target.method_name, T.must(node.message_loc), declaration: true)
elsif node.name == :attr_accessor && (attr_reader_matches_method(node.arguments.arguments, @target.method_name) || attr_writer_matches_method(node.arguments.arguments, @target.method_name))
@references << Reference.new(@target.method_name, T.must(node.message_loc), declaration: true)
end
end

private
def attr_reader_matches_method(arguments, method_name)
arguments.map(&:unescaped).include?(method_name)
end

def attr_writer_matches_method(arguments, method_name)
arguments.map(&:unescaped).any? { |unescaped_arg| "#{unescaped_arg}=" == method_name }
end

sig { params(name: String).returns(T::Array[String]) }
def actual_nesting(name)
Expand Down
130 changes: 130 additions & 0 deletions lib/ruby_indexer/test/reference_finder_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,136 @@ def baz
assert_equal(9, refs[1].location.start_line)
end

def test_matches_attr_writer
refs = find_method_references("foo=", <<~RUBY)
class Bar
def foo
end

attr_writer :foo

def baz
self.foo = 1
self.foo
end
end
RUBY

# We want to match `foo=` but not `foo`
assert_equal(2, refs.size)

assert_equal("foo=", refs[0].name)
assert_equal(5, refs[0].location.start_line)

assert_equal("foo=", refs[1].name)
assert_equal(8, refs[1].location.start_line)
end

def test_matches_attr_reader
refs = find_method_references("foo", <<~RUBY)
class Bar
def foo=(value)
end

attr_reader :foo

def baz
self.foo = 1
self.foo
end
end
RUBY

# We want to match `foo=` but not `foo`
assert_equal(2, refs.size)

assert_equal("foo", refs[0].name)
assert_equal(5, refs[0].location.start_line)

assert_equal("foo", refs[1].name)
assert_equal(9, refs[1].location.start_line)
end

def test_matches_attr_accessor
refs = find_method_references("foo=", <<~RUBY)
class Bar
attr_accessor :foo

def baz
self.foo = 1
self.foo
end
end
RUBY

# We want to match `foo=` but not `foo`
assert_equal(2, refs.size)

assert_equal("foo=", refs[0].name)
assert_equal(2, refs[0].location.start_line)

assert_equal("foo=", refs[1].name)
assert_equal(5, refs[1].location.start_line)

refs = find_method_references("foo", <<~RUBY)
class Bar
attr_accessor :foo

def baz
self.foo = 1
self.foo
end
end
RUBY


assert_equal("foo", refs[0].name)
assert_equal(2, refs[0].location.start_line)

assert_equal("foo", refs[1].name)
assert_equal(6, refs[1].location.start_line)
end

def test_matches_attr_accessor_multi
refs = find_method_references("foo=", <<~RUBY)
class Bar
attr_accessor :bar, :foo

def baz
self.foo = 1
self.foo
end
end
RUBY

# We want to match `foo=` but not `foo`
assert_equal(2, refs.size)

assert_equal("foo=", refs[0].name)
assert_equal(2, refs[0].location.start_line)

assert_equal("foo=", refs[1].name)
assert_equal(5, refs[1].location.start_line)

refs = find_method_references("foo", <<~RUBY)
class Bar
attr_accessor :foo

def baz
self.foo = 1
self.foo
end
end
RUBY


assert_equal("foo", refs[0].name)
assert_equal(2, refs[0].location.start_line)

assert_equal("foo", refs[1].name)
assert_equal(6, refs[1].location.start_line)
end

def test_find_inherited_methods
refs = find_method_references("foo", <<~RUBY)
class Bar
Expand Down
Loading