# module RBS
#   class Location
#     attr_reader :buffer
#     attr_reader :start_pos
#     attr_reader :end_pos

#     def initialize(buffer, start_pos, end_pos)
#       @buffer = buffer
#       @start_pos = start_pos
#       @end_pos = end_pos
#     end

#     # def self.new(buffer_ = nil, start_pos_ = nil, end_pos_ = nil)
#     #   __skip__ = super(buffer_, start_pos_, end_pos_)
#     # end

#     # def inspect
#     #   "#<#{self.class}:#{self.__id__} @buffer=#{buffer.name}, @pos=#{start_pos}...#{end_pos}, source='#{source.lines.first}', start_line=#{start_line}, start_column=#{start_column}>"
#     # end

#     def name
#       buffer.name
#     end

#     def start_line
#       start_loc[0]
#     end

#     def start_column
#       start_loc[1]
#     end

#     def end_line
#       end_loc[0]
#     end

#     def end_column
#       end_loc[1]
#     end

#     def start_loc
#       @start_loc ||= buffer.pos_to_loc(start_pos)
#     end

#     def end_loc
#       @end_loc ||= buffer.pos_to_loc(end_pos)
#     end

#     def range
#       start_pos...end_pos
#     end

#     def source
#       @source ||= buffer.content[start_pos...end_pos] or raise
#     end

#     def to_s
#       "#{name || "-"}:#{start_line}:#{start_column}...#{end_line}:#{end_column}"
#     end

#     def self.to_string(location, default: "*:*:*...*:*")
#       location&.to_s || default
#     end

#     def ==(other)
#       other.is_a?(Location) &&
#         other.buffer == buffer &&
#         other.start_pos == start_pos &&
#         other.end_pos == end_pos
#     end

#     def +(other)
#       if other
#         raise "Invalid concat: buffer=#{buffer.name}, other.buffer=#{other.buffer.name}" unless other.buffer == buffer

#         self.class.new(buffer: buffer,
#                        start_pos: start_pos,
#                        end_pos: other.end_pos)
#       else
#         self
#       end
#     end

#     def concat(*others)
#       others.each { |other| self << other }
#       self
#     end

#     def <<(other)
#       if other
#         raise "Invalid concat: buffer=#{buffer.name}, other.buffer=#{other.buffer.name}" unless other.buffer == buffer
#         @end_pos = other.end_pos
#         @source = nil
#         @end_loc = nil
#       end
#       self
#     end

#     def pred?(loc)
#       loc.is_a?(Location) &&
#         loc.name == name &&
#         loc.start_pos == end_pos
#     end

#     def to_json(state = _ = nil)
#       {
#         start: {
#           line: start_line,
#           column: start_column
#         },
#         end: {
#           line: end_line,
#           column: end_column
#         },
#         buffer: {
#           name: name&.to_s
#         }
#       }.to_json(state)
#     end

#     def with_children(required: {}, optional: {})
#       # @type var required: Hash[Symbol, Range[Integer] | Location]
#       # @type var optional: Hash[Symbol, Range[Integer] | Location | nil]

#       this = WithChildren.new(buffer: buffer, start_pos: start_pos, end_pos: end_pos)

#       req = required.transform_values do |value|
#         case value
#         when Location
#           value.range
#         else
#           value
#         end
#       end

#       opt = optional.transform_values do |value|
#         case value
#         when Location
#           value.range
#         else
#           value
#         end
#       end

#       this.required_children.merge!(req)
#       this.optional_children.merge!(opt)

#       this
#     end

#     class WithChildren < Location
#       attr_reader :required_children, :optional_children

#       def initialize(buffer, start_pos, end_pos)
#         super(buffer, start_pos, end_pos)

#         @optional_children = {}
#         @required_children = {}
#       end

#       def initialize_copy(from)
#         required_children.merge!(from.required_children)
#         optional_children.merge!(from.optional_children)
#         self
#       end

#       def [](key)
#         case
#         when required_children.key?(_ = key)
#           range = required_children[_ = key]
#           Location.new(buffer: buffer, start_pos: range.begin, end_pos: range.end)
#         when optional_children.key?(_ = key)
#           range = required_children[_ = key] || optional_children[_ = key]
#           if range
#             Location.new(buffer: buffer, start_pos: range.begin, end_pos: range.end)
#           end
#         else
#           raise "Unknown key given: `#{key}`"
#         end
#       end

#       def merge_required(hash)
#         this = dup

#         h = hash.transform_values do |value|
#           case value
#           when Range
#             value
#           when Location
#             value.range
#           else
#             raise
#           end
#         end

#         this.required_children.merge!(h)

#         this
#       end

#       def merge_optional(hash)
#         this = dup

#         h = hash.transform_values do |value|
#           case value
#           when Range
#             value
#           when Location
#             value.range
#           else
#             nil
#           end
#         end

#         this.optional_children.merge!(h)

#         this
#       end
#     end
#   end
# end
