@@ -323,7 +323,34 @@ def index_iseq(iseq, file_comments)
323323 EntryComments . new ( file_comments , location )
324324 )
325325 when :opt_send_without_block , :send
326- if insn [ 1 ] [ :mid ] == :"core#set_method_alias"
326+ 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+
344+ location = Location . new ( line , 0 )
345+ names . each do |name |
346+ results << MethodDefinition . new (
347+ current_nesting ,
348+ name ,
349+ location ,
350+ EntryComments . new ( file_comments , location )
351+ )
352+ end
353+ when :"core#set_method_alias"
327354 # Now we have to validate that the alias is happening with a
328355 # non-interpolated value. To do this we'll match the specific
329356 # pattern we're expecting.
@@ -352,6 +379,20 @@ def index_iseq(iseq, file_comments)
352379 # It is not as fast as using the instruction sequences directly, but is
353380 # supported on all runtimes.
354381 class ParserBackend
382+ class ConstantNameVisitor < Visitor
383+ def visit_const_ref ( node )
384+ [ node . constant . value . to_sym ]
385+ end
386+
387+ def visit_const_path_ref ( node )
388+ visit ( node . parent ) << node . constant . value . to_sym
389+ end
390+
391+ def visit_var_ref ( node )
392+ [ node . value . value . to_sym ]
393+ end
394+ end
395+
355396 class IndexVisitor < Visitor
356397 attr_reader :results , :nesting , :statements
357398
@@ -374,18 +415,20 @@ def visit_alias(node)
374415 comments_for ( node )
375416 )
376417 end
418+
419+ super
377420 end
378421
379422 def visit_class ( node )
380- names = visit ( node . constant )
423+ names = node . constant . accept ( ConstantNameVisitor . new )
381424 nesting << names
382425
383426 location =
384427 Location . new ( node . location . start_line , node . location . start_column )
385428
386429 superclass =
387430 if node . superclass
388- visited = visit ( node . superclass )
431+ visited = node . superclass . accept ( ConstantNameVisitor . new )
389432
390433 if visited == [ [ ] ]
391434 raise NotImplementedError , "superclass with non constant path"
@@ -408,12 +451,24 @@ def visit_class(node)
408451 nesting . pop
409452 end
410453
411- def visit_const_ref ( node )
412- [ node . constant . value . to_sym ]
413- end
454+ def visit_command ( node )
455+ if node . message . value == "attr_reader"
456+ location =
457+ Location . new ( node . location . start_line , node . location . start_column )
458+
459+ node . arguments . parts . each do |argument |
460+ next unless argument . is_a? ( SymbolLiteral )
461+
462+ results << MethodDefinition . new (
463+ nesting . dup ,
464+ argument . value . value . to_sym ,
465+ location ,
466+ comments_for ( node )
467+ )
468+ end
469+ end
414470
415- def visit_const_path_ref ( node )
416- visit ( node . parent ) << node . constant . value . to_sym
471+ super
417472 end
418473
419474 def visit_def ( node )
@@ -436,10 +491,12 @@ def visit_def(node)
436491 comments_for ( node )
437492 )
438493 end
494+
495+ super
439496 end
440497
441498 def visit_module ( node )
442- names = visit ( node . constant )
499+ names = node . constant . accept ( ConstantNameVisitor . new )
443500 nesting << names
444501
445502 location =
@@ -465,10 +522,6 @@ def visit_statements(node)
465522 @statements = node
466523 super
467524 end
468-
469- def visit_var_ref ( node )
470- [ node . value . value . to_sym ]
471- end
472525 end
473526
474527 private
@@ -478,8 +531,10 @@ def comments_for(node)
478531
479532 body = statements . body
480533 line = node . location . start_line - 1
481- index = body . index ( node ) - 1
534+ index = body . index ( node )
535+ return comments if index . nil?
482536
537+ index -= 1
483538 while index >= 0 && body [ index ] . is_a? ( Comment ) &&
484539 ( line - body [ index ] . location . start_line < 2 )
485540 comments . unshift ( body [ index ] . value )
0 commit comments