module Solargraph::Parser::ParserGem::NodeMethods

def any_splatted_call?(nodes)

Parameters:
  • nodes (Enumerable) --
def any_splatted_call?(nodes)
  nodes.any? { |n| splatted_call?(n) }
end

def call_nodes_from node

Returns:
  • (Array) -

Parameters:
  • node (Parser::AST::Node) --

Other tags:
    Todo: - Temporarily here for testing. Move to Solargraph::Parser.
def call_nodes_from node
  return [] unless node.is_a?(::Parser::AST::Node)
  result = []
  if node.type == :block
    result.push node
    if Parser.is_ast_node?(node.children[0]) && node.children[0].children.length > 2
      node.children[0].children[2..-1].each { |child| result.concat call_nodes_from(child) }
    end
    node.children[1..-1].each { |child| result.concat call_nodes_from(child) }
  elsif node.type == :send
    result.push node
    node.children[2..-1].each { |child| result.concat call_nodes_from(child) }
  elsif [:super, :zsuper].include?(node.type)
    result.push node
    node.children.each { |child| result.concat call_nodes_from(child) }
  else
    node.children.each { |child| result.concat call_nodes_from(child) }
  end
  result
end

def const_nodes_from node

Returns:
  • (Array) -

Parameters:
  • node (Parser::AST::Node) --
def const_nodes_from node
  return [] unless Parser.is_ast_node?(node)
  result = []
  if node.type == :const
    result.push node
  else
    node.children.each { |child| result.concat const_nodes_from(child) }
  end
  result
end

def convert_hash node

Returns:
  • (Hash{Parser::AST::Node => Chain}) -

Parameters:
  • node (Parser::AST::Node) --
def convert_hash node
  return {} unless Parser.is_ast_node?(node)
  return convert_hash(node.children[0]) if node.type == :kwsplat
  return convert_hash(node.children[0]) if Parser.is_ast_node?(node.children[0]) && node.children[0].type == :kwsplat
  return {} unless node.type == :hash
  result = {}
  node.children.each do |pair|
    result[pair.children[0].children[0]] = Solargraph::Parser.chain(pair.children[1])
  end
  result
end

def drill_signature node, signature

Returns:
  • (String) -

Parameters:
  • signature (String) --
  • node (Parser::AST::Node) --
def drill_signature node, signature
  return signature unless node.is_a?(AST::Node)
  if node.type == :const or node.type == :cbase
    unless node.children[0].nil?
      signature += drill_signature(node.children[0], signature)
    end
    signature += '::' unless signature.empty?
    signature += node.children[1].to_s
  elsif node.type == :lvar or node.type == :ivar or node.type == :cvar
    signature += '.' unless signature.empty?
    signature += node.children[0].to_s
  elsif node.type == :send
    unless node.children[0].nil?
      signature += drill_signature(node.children[0], signature)
    end
    signature += '.' unless signature.empty?
    signature += node.children[1].to_s
  end
  signature
end

def find_recipient_node cursor

Returns:
  • (Parser::AST::Node, nil) -

Parameters:
  • cursor (Solargraph::Source::Cursor) --
def find_recipient_node cursor
  return repaired_find_recipient_node(cursor) if cursor.source.repaired? && cursor.source.code[cursor.offset - 1] == '('
  source = cursor.source
  position = cursor.position
  offset = cursor.offset
  tree = if source.synchronized?
    match = source.code[0..offset-1].match(/,\s*\z/)
    if match
      source.tree_at(position.line, position.column - match[0].length)
    else
      source.tree_at(position.line, position.column)
    end
  else
    source.tree_at(position.line, position.column - 1)
  end
  prev = nil
  tree.each do |node|
    if node.type == :send
      args = node.children[2..-1]
      if !args.empty?
        return node if prev && args.include?(prev)
      else
        if source.synchronized?
          return node if source.code[0..offset-1] =~ /\(\s*\z/ && source.code[offset..-1] =~ /^\s*\)/
        else
          return node if source.code[0..offset-1] =~ /\([^\(]*\z/
        end
      end
    end
    prev = node
  end
  nil
end

def get_node_end_position(node)

Returns:
  • (Position) -

Parameters:
  • node (Parser::AST::Node) --
def get_node_end_position(node)
  Position.new(node.loc.last_line, node.loc.last_column)
end

def get_node_start_position(node)

Returns:
  • (Position) -

Parameters:
  • node (Parser::AST::Node) --
def get_node_start_position(node)
  Position.new(node.loc.line, node.loc.column)
end

def infer_literal_node_type node

Returns:
  • (String, nil) -

Parameters:
  • node (Parser::AST::Node) --
def infer_literal_node_type node
  return nil unless node.is_a?(AST::Node)
  if node.type == :str || node.type == :dstr
    return '::String'
  elsif node.type == :array
    return '::Array'
  elsif node.type == :hash
    return '::Hash'
  elsif node.type == :int
    return '::Integer'
  elsif node.type == :float
    return '::Float'
  elsif node.type == :sym || node.type == :dsym
    return '::Symbol'
  elsif node.type == :regexp
    return '::Regexp'
  elsif node.type == :irange
    return '::Range'
  elsif node.type == :true || node.type == :false
    return '::Boolean'
    # @todo Support `nil` keyword in types

  # elsif node.type == :nil

  #   return 'NilClass'

  end
  nil
end

def pack_name(node)

Returns:
  • (Array) -

Parameters:
  • node (Parser::AST::Node) --
def pack_name(node)
  # @type [Array<String>]

  parts = []
  if node.is_a?(AST::Node)
    node.children.each { |n|
      if n.is_a?(AST::Node)
        if n.type == :cbase
          parts = [''] + pack_name(n)
        else
          parts += pack_name(n)
        end
      else
        parts.push n unless n.nil?
      end
    }
  end
  parts
end

def repaired_find_recipient_node cursor

Returns:
  • (Parser::AST::Node, nil) -

Parameters:
  • cursor (Solargraph::Source::Cursor) --
def repaired_find_recipient_node cursor
  cursor = cursor.source.cursor_at([cursor.position.line, cursor.position.column - 1])
  node = cursor.source.tree_at(cursor.position.line, cursor.position.column).first
  return node if node && node.type == :send
end

def returns_from_method_body node

Returns:
  • (Array) -

Parameters:
  • node (Parser::AST::Node) --
def returns_from_method_body node
  # @todo is the || NIL_NODE necessary?

  # STDERR.puts("Evaluating expression: #{node.inspect}")

  DeepInference.from_method_body(node).map { |n| n || NIL_NODE }
end

def splatted_call? node

Parameters:
  • node (Parser::AST::Node) --
def splatted_call? node
  return false unless Parser.is_ast_node?(node)
  Parser.is_ast_node?(node.children[0]) && node.children[0].type == :kwsplat && node.children[0].children[0].type != :hash
end

def splatted_hash? node

Parameters:
  • node (Parser::AST::Node) --
def splatted_hash? node
  Parser.is_ast_node?(node.children[0]) && node.children[0].type == :kwsplat
end

def unpack_name(node)

Returns:
  • (String) -

Parameters:
  • node (Parser::AST::Node) --
def unpack_name(node)
  pack_name(node).join("::")
end

def value_position_nodes_only(node)

Returns:
  • (Array) - low-level value nodes in

Parameters:
  • node (Parser::AST::Node) --
def value_position_nodes_only(node)
  DeepInference.value_position_nodes_only(node).map { |n| n || NIL_NODE }
end