class Steep::TypeInference::ContextArray

def self.from_source(source:, range: nil, context: nil)

def self.from_source(source:, range: nil, context: nil)
  content = if source.node
              source.node.location.expression.source_buffer.source
            else
              ""
            end
  buffer = RBS::Buffer.new(name: source.path, content: content)
  new(buffer: buffer, context: context, range: range || 0..buffer.content.size)
end

def [](index)

def [](index)
  context_at(index)
end

def at(line:, column:)

def at(line:, column:)
  pos = buffer.loc_to_pos([line, column])
  self[pos]
end

def context_at(index, entry: self.root)

def context_at(index, entry: self.root)
  return nil if index < entry.range.begin || entry.range.end < index
  sub = entry.sub_entries.find do |sub|
    sub.range.begin <= index && index <= sub.range.end
  end
  if sub
    context_at(index, entry: sub)
  else
    entry.context
  end
end

def each_entry

def each_entry
  if block_given?
    es = [root]
    until es.empty?
      e = es.pop
      es.push(*e.sub_entries.to_a)
      yield e
    end
  else
    enum_for :each_entry
  end
end

def initialize(buffer:, context:, range: 0..buffer.content.size)

def initialize(buffer:, context:, range: 0..buffer.content.size)
  @buffer = buffer
  @root = Entry.new(range: range, context: context)
end

def insert_context(range, context:, entry: self.root)

def insert_context(range, context:, entry: self.root)
  entry.sub_entries.each do |sub|
    next if sub.range.begin <= range.begin && range.end <= sub.range.end
    next if range.begin <= sub.range.begin && sub.range.end <= range.end
    next if range.end <= sub.range.begin
    next if sub.range.end <= range.begin
    Steep.logger.error { "Range crossing: sub range=#{sub.range}, new range=#{range}" }
    raise
  end
  sup = entry.sub_entries.find do |sub|
    sub.range.begin < range.begin && range.end <= sub.range.end
  end
  if sup
    insert_context(range, context: context, entry: sup)
  else
    subs = entry.sub_entries.select do |sub|
      range.begin < sub.range.begin && sub.range.end <= range.end
    end
    new_entry = Entry.new(range: range, context: context)
    entry.sub_entries.subtract(subs)
    new_entry.sub_entries.merge(subs)
    entry.sub_entries << new_entry
  end
end

def merge(subtree)

def merge(subtree)
  subtree.each_entry do |entry|
    if entry.context
      insert_context entry.range, context: entry.context
    end
  end
end

def range

def range
  root.range
end