Skip to content

Commit

Permalink
Adds support for attr_reader, attr_writer, attr_accessor with some
Browse files Browse the repository at this point in the history
tests.

Prob can use some cleanup
  • Loading branch information
tommycrumrine committed Nov 14, 2024
1 parent 0eaaee1 commit e68bf97
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 1 deletion.
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

0 comments on commit e68bf97

Please sign in to comment.