class RBS::Environment

def insert_decl(decl, outer:, namespace:)

def insert_decl(decl, outer:, namespace:)
  case decl
  when AST::Declarations::Class, AST::Declarations::Module
    name = decl.name.with_prefix(namespace)
    if constant_decls.key?(name)
      raise DuplicatedDeclarationError.new(name, decl, constant_decls[name].decl)
    end
    unless class_decls.key?(name)
      case decl
      when AST::Declarations::Class
        class_decls[name] ||= ClassEntry.new(name: name)
      when AST::Declarations::Module
        class_decls[name] ||= ModuleEntry.new(name: name)
      end
    end
    existing_entry = class_decls[name]
    case
    when decl.is_a?(AST::Declarations::Module) && existing_entry.is_a?(ModuleEntry)
      # @type var existing_entry: ModuleEntry
      # @type var decl: AST::Declarations::Module
      existing_entry.insert(decl: decl, outer: outer)
    when decl.is_a?(AST::Declarations::Class) && existing_entry.is_a?(ClassEntry)
      # @type var existing_entry: ClassEntry
      # @type var decl: AST::Declarations::Class
      existing_entry.insert(decl: decl, outer: outer)
    else
      raise DuplicatedDeclarationError.new(name, decl, existing_entry.decls[0].decl)
    end
    prefix = outer + [decl]
    ns = name.to_namespace
    decl.each_decl do |d|
      insert_decl(d, outer: prefix, namespace: ns)
    end
  when AST::Declarations::Interface
    cache_name interface_decls, name: decl.name.with_prefix(namespace), decl: decl, outer: outer
  when AST::Declarations::Alias
    cache_name alias_decls, name: decl.name.with_prefix(namespace), decl: decl, outer: outer
  when AST::Declarations::Constant
    name = decl.name.with_prefix(namespace)
    if class_decls.key?(name)
      raise DuplicatedDeclarationError.new(name, decl, class_decls[name].decls[0].decl)
    end
    cache_name constant_decls, name: name, decl: decl, outer: outer
  when AST::Declarations::Global
    cache_name global_decls, name: decl.name, decl: decl, outer: outer
  end
end