Class: RBS::Buffer
- Inherits:
-
Object
- Object
- RBS::Buffer
- Defined in:
- lib/rbs/buffer.rb,
sig/buffer.rbs
Instance Attribute Summary collapse
-
#content ⇒ String
readonly
The content of the buffer.
-
#name ⇒ Pathname
readonly
Name to identify Buffer.
-
#parent ⇒ [Buffer, Array[Range[Integer]]]?
readonly
Returns the value of attribute parent.
Instance Method Summary collapse
- #absolute_position(position) ⇒ Object
-
#character_offset(byte_offset) ⇒ Integer
Translate a byte offset (into the top buffer's source) to a character offset.
- #detach ⇒ Object
-
#initialize(name: nil, content:, parent: nil) ⇒ Buffer
constructor
A new instance of Buffer.
- #inspect ⇒ Object
- #last_position ⇒ Integer
-
#line_count ⇒ Integer
Returns the number of the lines.
-
#lines ⇒ Array[String]
Array of lines of the content, without the EOL.
-
#loc_to_pos(loc) ⇒ Integer
Translate location to position.
- #parent_buffer ⇒ Object
- #parent_position(position) ⇒ Object
-
#pos_to_loc(pos) ⇒ loc
Translate position to location.
-
#ranges ⇒ Array[Range[Integer]]
Array of ranges that stores the ranges of the each line, without the EOL.
-
#rbs_location(location, loc2 = nil) ⇒ Object
Translate
Prism::LocationtoRBS::Locationattached to this buffer. - #sub_buffer(lines:, byte_lines_hint: nil) ⇒ Object
- #top_buffer ⇒ Object
Constructor Details
#initialize(name:, content:) ⇒ void #initialize(content:, parent:) ⇒ void
Returns a new instance of Buffer.
9 10 11 12 13 14 15 16 17 18 19 20 |
# File '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 |
Instance Attribute Details
#content ⇒ String (readonly)
The content of the buffer.
12 13 14 |
# File 'sig/buffer.rbs', line 12 def content @content end |
#name ⇒ Pathname (readonly)
Name to identify Buffer.
9 10 11 |
# File 'sig/buffer.rbs', line 9 def name @name end |
#parent ⇒ [Buffer, Array[Range[Integer]]]? (readonly)
Returns the value of attribute parent.
7 8 9 |
# File 'lib/rbs/buffer.rb', line 7 def parent @parent end |
Instance Method Details
#absolute_position(position) ⇒ Object
168 169 170 171 172 173 174 175 |
# File '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 |
#character_offset(byte_offset) ⇒ Integer
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.
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'sig/buffer.rbs', line 70 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 |
#detach ⇒ Object
185 186 187 |
# File 'lib/rbs/buffer.rb', line 185 def detach Buffer.new(name: name, content: content) end |
#inspect ⇒ Object
86 87 88 |
# File 'lib/rbs/buffer.rb', line 86 def inspect "#<RBS::Buffer:#{__id__} @name=#{name}, @content=#{content.bytesize} bytes, @lines=#{ranges.size} lines,>" end |
#last_position ⇒ Integer
78 79 80 81 82 83 84 |
# File 'lib/rbs/buffer.rb', line 78 def last_position if ranges.empty? 0 else ranges[-1].end end end |
#line_count ⇒ Integer
Returns the number of the lines
46 47 48 |
# File 'sig/buffer.rbs', line 46 def line_count ranges.size end |
#lines ⇒ Array[String]
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", ""]
33 34 35 |
# File 'sig/buffer.rbs', line 33 def lines ranges.map { self.content[_1] || raise } #$ String end |
#loc_to_pos(loc) ⇒ Integer
Translate location to position.
52 53 54 55 56 57 58 59 60 |
# File 'sig/buffer.rbs', line 52 def loc_to_pos(loc) line, column = loc if range = ranges.fetch(line - 1, nil) range.begin + column else last_position end end |
#parent_buffer ⇒ Object
153 154 155 156 157 |
# File 'lib/rbs/buffer.rb', line 153 def parent_buffer if parent parent[0] end end |
#parent_position(position) ⇒ Object
159 160 161 162 163 164 165 166 |
# File '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 |
#pos_to_loc(pos) ⇒ loc
Translate position to location.
49 50 51 52 53 54 55 56 57 58 59 |
# File 'sig/buffer.rbs', line 49 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 |
#ranges ⇒ Array[Range[Integer]]
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]
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'sig/buffer.rbs', line 43 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 |
#rbs_location(arg0) ⇒ Location #rbs_location(arg0, arg1) ⇒ Location
Translate Prism::Location to RBS::Location attached to this buffer
It assumes the Prism::Location has a source which is equivalent to self.
60 61 62 63 64 65 66 67 |
# File 'sig/buffer.rbs', line 60 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 |
#sub_buffer(lines:, byte_lines_hint: nil) ⇒ Object
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File '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 |
#top_buffer ⇒ Object
177 178 179 180 181 182 183 |
# File 'lib/rbs/buffer.rb', line 177 def top_buffer if parent_buffer parent_buffer.top_buffer else self end end |