class RBS::Buffer
Attributes
The content of the buffer.
[ Buffer, Array[Range[Integer]] ]?
Public Class Methods
(name: Pathname name, content: String content) → void
(content: String content, parent: [ Buffer, Array[Range[Integer]] ] parent) → void
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.1.3/lib/rbs/buffer.rb, line 9 def initialize(name: nil, content:, parent: nil) case when name && content @name = name @content = content @parent = nil when parent && content @name = parent[0].name @content = content @parent = parent end end
Public Instance Methods
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.1.3/lib/rbs/buffer.rb, line 168 def absolute_position(position) if parent_buffer pos = parent_position(position) or return parent_buffer.absolute_position(pos) else position end end
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.1.3/lib/rbs/buffer.rb, line 90 def character_offset(byte_offset) top = top_buffer return top.character_offset(byte_offset) unless top.equal?(self) keys, vals = (@character_offset_cache ||= [[0], [0]]) idx = keys.bsearch_index { |k| k > byte_offset } lo = idx ? idx - 1 : keys.size - 1 base_byte = keys[lo] base_char = vals[lo] delta = byte_offset - base_byte return base_char if delta == 0 result = base_char + (content.byteslice(base_byte, delta) or raise).length if base_byte == keys[-1] keys << byte_offset vals << result end result end
Translate a byte offset (into the top bufferโs source) to a character offset.
Resolution is delegated to the top buffer, which keeps a sparse cache of resolved (byte, char) pairs so successive calls scan only the delta from the nearest cached pair. Amortizes to O(content_size) across all calls; a single call is one byteslice + length.
() → Buffer
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.1.3/lib/rbs/buffer.rb, line 185 def detach Buffer.new(name: name, content: content) end
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.1.3/lib/rbs/buffer.rb, line 86 def inspect "#<RBS::Buffer:#{__id__} @name=#{name}, @content=#{content.bytesize} bytes, @lines=#{ranges.size} lines,>" end
() → Integer
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.1.3/lib/rbs/buffer.rb, line 78 def last_position if ranges.empty? 0 else ranges[-1].end end end
() → Integer
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.1.3/lib/rbs/buffer.rb, line 26 def line_count ranges.size end
Returns the number of the lines
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.1.3/lib/rbs/buffer.rb, line 22 def lines ranges.map { self.content[_1] || raise } #$ String end
Array of lines of the content, without the EOL
buffer = Buffer.new(name: name, content: "123\nabc") buffer.lines # => ["123", "abc"]
If the input has EOL at the end of the file, the lines has an empty string at the end.
buffer = Buffer.new(name: name, content: "123\nabc\n") buffer.lines # => ["123", "abc", ""]
(loc loc) → Integer
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.1.3/lib/rbs/buffer.rb, line 68 def loc_to_pos(loc) line, column = loc if range = ranges.fetch(line - 1, nil) range.begin + column else last_position end end
Translate location to position.
() → Buffer?
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.1.3/lib/rbs/buffer.rb, line 153 def parent_buffer if parent parent[0] end end
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.1.3/lib/rbs/buffer.rb, line 159 def parent_position(position) parent or raise "#parent_position is unavailable with buffer without parent" return nil unless position <= last_position line, column = pos_to_loc(position) parent_range = parent[1][line - 1] parent_range.begin + column end
(Integer pos) → loc
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.1.3/lib/rbs/buffer.rb, line 56 def pos_to_loc(pos) index = ranges.bsearch_index do |range| pos <= range.end ? true : false end if index [index + 1, pos - ranges[index].begin] else [ranges.size + 1, 0] end end
Translate position to location.
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.1.3/lib/rbs/buffer.rb, line 30 def ranges @ranges ||= begin if content.empty? ranges = [0...0] #: Array[Range[Integer]] lines = [""] else lines = content.lines lines << "" if content.end_with?("\n") ranges = [] #: Array[Range[Integer]] offset = 0 lines.each do |line| size0 = line.size line = line.chomp range = offset...(offset+line.size) ranges << range offset += size0 end end ranges end end
Array of ranges that stores the ranges of the each line, without the EOL
buffer = Buffer.new(name: name, content: "123\nabc\n") buffer.ranges # => [0...3, 4...7, 8...8]
(Prism::Location) → Location
(Prism::Location, Prism::Location) → Location
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.1.3/lib/rbs/buffer.rb, line 114 def rbs_location(location, loc2=nil) top = top_buffer if loc2 Location.new(top, character_offset(location.start_offset), character_offset(loc2.end_offset)) else Location.new(top, character_offset(location.start_offset), character_offset(location.end_offset)) end end
Translate Prism::Location to RBS::Location attached to this buffer
It assumes the Prism::Location has a source which is equivalent to self.
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.1.3/lib/rbs/buffer.rb, line 123 def sub_buffer(lines:, byte_lines_hint: nil) buf = +"" if byte_lines_hint byte_lines_hint.each_with_index do |range, index| slice = content.byteslice(range.begin, range.end - range.begin) or raise if slice.include?("\n") raise "Line #{index + 1} cannot contain newline character." end buf << slice buf << "\n" end else lines.each_with_index do |range, index| start_pos = range.begin end_pos = range.end slice = content[start_pos...end_pos] or raise if slice.include?("\n") raise "Line #{index + 1} cannot contain newline character." end buf << slice buf << "\n" end end buf.chomp! Buffer.new(content: buf, parent: [self, lines]) end
Construct a buffer from substrings of this buffer.
The returned buffer contains lines from given ranges.
buffer = Buffer.new(name: name, content: <<TEXT) 12345 abcde ABCDE TEXT buffer.sub_buffer(lines: [0...1, 2...3]) # => Buffer with content = 1\n34 buffer.sub_buffer(lines: [5..7]) # => Raises an error because the range contains newline
byte_lines_hint: is an optional performance hint: byte ranges corresponding to lines:. When provided, slicing uses byteslice (O(slice_size) per line) instead of content[char_range], which on a multi-byte string is O(content_size) per call. Result is identical either way.
() → Buffer
Source
# File vendor/bundle/ruby/4.0.0/gems/rbs-4.1.3/lib/rbs/buffer.rb, line 177 def top_buffer if parent_buffer parent_buffer.top_buffer else self end end