class SyntaxTree::Index::ParserBackend::IndexVisitor

def comments_for(node)

def comments_for(node)
  comments = []
  body = statements.body
  line = node.location.start_line - 1
  index = body.index(node)
  return comments if index.nil?
  index -= 1
  while index >= 0 && body[index].is_a?(Comment) &&
          (line - body[index].location.start_line < 2)
    comments.unshift(body[index].value)
    line = body[index].location.start_line
    index -= 1
  end
  comments
end

def initialize

def initialize
  @results = []
  @nesting = []
  @statements = nil
end

def visit_alias(node)

def visit_alias(node)
  if node.left.is_a?(SymbolLiteral) && node.right.is_a?(SymbolLiteral)
    location =
      Location.new(
        node.location.start_line,
        node.location.start_column
      )
    results << AliasMethodDefinition.new(
      nesting.dup,
      node.left.value.value.to_sym,
      location,
      comments_for(node)
    )
  end
  super
end

def visit_assign(node)

def visit_assign(node)
  if node.target.is_a?(VarField) && node.target.value.is_a?(Const)
    location =
      Location.new(
        node.location.start_line,
        node.location.start_column
      )
    results << ConstantDefinition.new(
      nesting.dup,
      node.target.value.value.to_sym,
      location,
      comments_for(node)
    )
  end
  super
end

def visit_class(node)

def visit_class(node)
  names = node.constant.accept(ConstantNameVisitor.new)
  nesting << names
  location =
    Location.new(node.location.start_line, node.location.start_column)
  superclass =
    if node.superclass
      visited = node.superclass.accept(ConstantNameVisitor.new)
      if visited == [[]]
        raise NotImplementedError, "superclass with non constant path"
      end
      visited
    else
      []
    end
  results << ClassDefinition.new(
    nesting.dup,
    names.last,
    superclass,
    location,
    comments_for(node)
  )
  super
  nesting.pop
end

def visit_command(node)

def visit_command(node)
  case node.message.value
  when "attr_reader", "attr_writer", "attr_accessor"
    comments = comments_for(node)
    location =
      Location.new(
        node.location.start_line,
        node.location.start_column
      )
    node.arguments.parts.each do |argument|
      next unless argument.is_a?(SymbolLiteral)
      name = argument.value.value.to_sym
      if node.message.value != "attr_writer"
        results << MethodDefinition.new(
          nesting.dup,
          name,
          location,
          comments
        )
      end
      if node.message.value != "attr_reader"
        results << MethodDefinition.new(
          nesting.dup,
          :"#{name}=",
          location,
          comments
        )
      end
    end
  end
  super
end

def visit_def(node)

def visit_def(node)
  name = node.name.value.to_sym
  location =
    Location.new(node.location.start_line, node.location.start_column)
  results << if node.target.nil?
    MethodDefinition.new(
      nesting.dup,
      name,
      location,
      comments_for(node)
    )
  else
    SingletonMethodDefinition.new(
      nesting.dup,
      name,
      location,
      comments_for(node)
    )
  end
  super
end

def visit_module(node)

def visit_module(node)
  names = node.constant.accept(ConstantNameVisitor.new)
  nesting << names
  location =
    Location.new(node.location.start_line, node.location.start_column)
  results << ModuleDefinition.new(
    nesting.dup,
    names.last,
    location,
    comments_for(node)
  )
  super
  nesting.pop
end

def visit_program(node)

def visit_program(node)
  super
  results
end

def visit_statements(node)

def visit_statements(node)
  @statements = node
  super
end