class Steep::Typing::CursorContext

def block_range(node)

def block_range(node)
  case node.type
  when :block
    send_node, args_node, _ = node.children
    begin_pos = if send_node.type != :lambda && args_node.loc.expression
                  args_node.loc.expression.end_pos
                else
                  node.loc.begin.end_pos # steep:ignore NoMethod
                end
    end_pos = node.loc.end.begin_pos # steep:ignore NoMethod
  when :numblock
    send_node, _ = node.children
    begin_pos = node.loc.begin.end_pos # steep:ignore NoMethod
    end_pos = node.loc.end.begin_pos # steep:ignore NoMethod
  end
  begin_pos..end_pos
end

def context

def context
  _, context = data
  context
end

def initialize(index)

def initialize(index)
  @index = index
end

def range

def range
  range, _ = data
  range
end

def set(range, context = nil)

def set(range, context = nil)
  if range.is_a?(CursorContext)
    range, context = range.data
    range or return
    context or return
  end
  context or raise
  return unless index
  if current_range = self.range
    if range.begin <= index && index <= range.end
      if current_range.begin <= range.begin && range.end <= current_range.end
        @data = [range, context]
      end
    end
  else
    @data = [range, context]
  end
end

def set_body_context(node, context)

def set_body_context(node, context)
  case node.type
  when :class
    name_node, super_node, _ = node.children
    begin_pos = if super_node
                  super_node.loc.expression.end_pos
                else
                  name_node.loc.expression.end_pos
                end
    end_pos = node.loc.end.begin_pos # steep:ignore NoMethod
    set(begin_pos..end_pos, context)
  when :module
    name_node = node.children[0]
    begin_pos = name_node.loc.expression.end_pos
    end_pos = node.loc.end.begin_pos # steep:ignore NoMethod
    set(begin_pos..end_pos, context)
  when :sclass
    name_node = node.children[0]
    begin_pos = name_node.loc.expression.end_pos
    end_pos = node.loc.end.begin_pos # steep:ignore NoMethod
    set(begin_pos..end_pos, context)
  when :def, :defs
    if node.children.last
      args_node =
        case node.type
        when :def
          node.children[1]
        when :defs
          node.children[2]
        end
      body_begin_pos =
        case
        when node.loc.assignment # steep:ignore NoMethod
          # endless def
          node.loc.assignment.end_pos # steep:ignore NoMethod
        when args_node.loc.expression
          # with args
          args_node.loc.expression.end_pos
        else
          # without args
          node.loc.name.end_pos # steep:ignore NoMethod
        end
      body_end_pos =
        if node.loc.end # steep:ignore NoMethod
          node.loc.end.begin_pos # steep:ignore NoMethod
        else
          node.loc.expression.end_pos
        end
      set(body_begin_pos..body_end_pos, context)
    end
  when :block, :numblock
    range = block_range(node)
    set(range, context)
  when :for
    _, collection, _ = node.children
    begin_pos = collection.loc.expression.end_pos
    end_pos = node.loc.end.begin_pos # steep:ignore NoMethod
    set(begin_pos..end_pos, context)
  else
    raise "Unexpected node for insert_context: #{node.type}"
  end
end

def set_node_context(node, context)

def set_node_context(node, context)
  begin_pos = node.loc.expression.begin_pos
  end_pos = node.loc.expression.end_pos
  set(begin_pos..end_pos, context)
end