Skip to content

Commit ee2db3f

Browse files
committed
attr_writer and attr_accessor
1 parent 31e4a47 commit ee2db3f

File tree

2 files changed

+61
-29
lines changed

2 files changed

+61
-29
lines changed

lib/syntax_tree/index.rb

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,22 @@ def find_constant_path(insns, index)
220220
end
221221
end
222222

223+
def find_attr_arguments(insns, index)
224+
orig_argc = insns[index][1][:orig_argc]
225+
names = []
226+
227+
current = index - 1
228+
while current >= 0 && names.length < orig_argc
229+
if insns[current].is_a?(Array) && insns[current][0] == :putobject
230+
names.unshift(insns[current][1])
231+
end
232+
233+
current -= 1
234+
end
235+
236+
names if insns[current] == [:putself] && names.length == orig_argc
237+
end
238+
223239
def index_iseq(iseq, file_comments)
224240
results = []
225241
queue = [[iseq, []]]
@@ -324,31 +340,29 @@ def index_iseq(iseq, file_comments)
324340
)
325341
when :opt_send_without_block, :send
326342
case insn[1][:mid]
327-
when :attr_reader
328-
# We're going to scan backward finding symbols until we hit a
329-
# different instruction. We'll then use that to determine the
330-
# receiver. It needs to be self if we're going to understand it.
331-
names = []
332-
current = index - 1
333-
334-
while current >= 0 && names.length < insn[1][:orig_argc]
335-
if insns[current].is_a?(Array) && insns[current][0] == :putobject
336-
names.unshift(insns[current][1])
337-
end
338-
339-
current -= 1
340-
end
341-
342-
next if insns[current] != [:putself]
343+
when :attr_reader, :attr_writer, :attr_accessor
344+
names = find_attr_arguments(insns, index)
345+
next unless names
343346

344347
location = Location.new(line, 0)
345348
names.each do |name|
346-
results << MethodDefinition.new(
347-
current_nesting,
348-
name,
349-
location,
350-
EntryComments.new(file_comments, location)
351-
)
349+
if insn[1][:mid] != :attr_writer
350+
results << MethodDefinition.new(
351+
current_nesting,
352+
name,
353+
location,
354+
EntryComments.new(file_comments, location)
355+
)
356+
end
357+
358+
if insn[1][:mid] != :attr_reader
359+
results << MethodDefinition.new(
360+
current_nesting,
361+
:"#{name}=",
362+
location,
363+
EntryComments.new(file_comments, location)
364+
)
365+
end
352366
end
353367
when :"core#set_method_alias"
354368
# Now we have to validate that the alias is happening with a
@@ -452,19 +466,23 @@ def visit_class(node)
452466
end
453467

454468
def visit_command(node)
455-
if node.message.value == "attr_reader"
469+
case node.message.value
470+
when "attr_reader", "attr_writer", "attr_accessor"
471+
comments = comments_for(node)
456472
location =
457473
Location.new(node.location.start_line, node.location.start_column)
458474

459475
node.arguments.parts.each do |argument|
460476
next unless argument.is_a?(SymbolLiteral)
477+
name = argument.value.value.to_sym
461478

462-
results << MethodDefinition.new(
463-
nesting.dup,
464-
argument.value.value.to_sym,
465-
location,
466-
comments_for(node)
467-
)
479+
if node.message.value != "attr_writer"
480+
results << MethodDefinition.new(nesting.dup, name, location, comments)
481+
end
482+
483+
if node.message.value != "attr_reader"
484+
results << MethodDefinition.new(nesting.dup, :"#{name}=", location, comments)
485+
end
468486
end
469487
end
470488

test/index_test.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,20 @@ def test_attr_reader
153153
end
154154
end
155155

156+
def test_attr_writer
157+
index_each("attr_writer :foo") do |entry|
158+
assert_equal :foo=, entry.name
159+
assert_empty entry.nesting
160+
end
161+
end
162+
163+
def test_attr_accessor
164+
index_each("attr_accessor :foo") do |entry|
165+
assert_equal :foo=, entry.name
166+
assert_empty entry.nesting
167+
end
168+
end
169+
156170
def test_this_file
157171
entries = Index.index_file(__FILE__, backend: Index::ParserBackend.new)
158172

0 commit comments

Comments
 (0)