Class: Ibex::Runtime::CST::SourceText
- Inherits:
-
Object
- Object
- Ibex::Runtime::CST::SourceText
- Defined in:
- lib/json5/generated_parser.rb
Overview
Immutable byte-oriented source with lazy line/column conversion.
Instance Attribute Summary collapse
- #file ⇒ Object readonly
- #text ⇒ Object readonly
Instance Method Summary collapse
-
#apply(edits) ⇒ Object
Apply non-overlapping byte edits expressed against this source.
- #bytesize ⇒ Object
-
#initialize(text, file: nil) ⇒ SourceText
constructor
A new instance of SourceText.
- #line_text(line) ⇒ Object
- #location(range) ⇒ Object
-
#position(offset) ⇒ Object
Return one-based line and Unicode-scalar column for a byte offset.
Constructor Details
#initialize(text, file: nil) ⇒ SourceText
Returns a new instance of SourceText.
854 855 856 857 858 859 |
# File 'lib/json5/generated_parser.rb', line 854 def initialize(text, file: nil) @text = text.encoding == Encoding::BINARY && text.frozen? ? text : text.b.freeze @file = file&.then { |value| value.frozen? ? value : value.dup.freeze } @line_starts = build_line_starts.freeze #: Array[Integer] freeze end |
Instance Attribute Details
#file ⇒ Object (readonly)
851 852 853 |
# File 'lib/json5/generated_parser.rb', line 851 def file @file end |
#text ⇒ Object (readonly)
850 851 852 |
# File 'lib/json5/generated_parser.rb', line 850 def text @text end |
Instance Method Details
#apply(edits) ⇒ Object
Apply non-overlapping byte edits expressed against this source.
866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 |
# File 'lib/json5/generated_parser.rb', line 866 def apply(edits) ordered = TextEdit.normalize(edits) output = String.new(encoding: Encoding::BINARY) cursor = 0 ordered.each do |edit| raise ArgumentError, "text edits overlap" if edit.start < cursor raise RangeError, "text edit exceeds source" if edit.range.end > @text.bytesize output << (@text.byteslice(cursor, edit.start - cursor) || "".b) output << edit.insert_text cursor = edit.range.end end output << (@text.byteslice(cursor, @text.bytesize - cursor) || "".b) SourceText.new(output, file: @file) end |
#bytesize ⇒ Object
862 |
# File 'lib/json5/generated_parser.rb', line 862 def bytesize = @text.bytesize |
#line_text(line) ⇒ Object
907 908 909 910 911 912 913 914 |
# File 'lib/json5/generated_parser.rb', line 907 def line_text(line) raise ArgumentError, "line must be positive" unless line.positive? start_offset = @line_starts.fetch(line - 1) end_offset = @line_starts.fetch(line, @text.bytesize) value = @text.byteslice(start_offset, end_offset - start_offset) || "".b value.delete_suffix("\n".b).delete_suffix("\r".b) end |
#location(range) ⇒ Object
896 897 898 899 900 901 902 903 904 |
# File 'lib/json5/generated_parser.rb', line 896 def location(range) start_offset, end_offset = normalized_range(range) line, column = position(start_offset) end_line, end_column = position(end_offset) Ibex::Location.new( file: @file, line: line, column: column, end_line: end_line, end_column: end_column, start_byte: start_offset, end_byte: end_offset, source_line: line_text(line) ) end |
#position(offset) ⇒ Object
Return one-based line and Unicode-scalar column for a byte offset. Invalid UTF-8 bytes count as one replacement scalar each.
885 886 887 888 889 890 891 892 893 |
# File 'lib/json5/generated_parser.rb', line 885 def position(offset) validate_offset(offset) line_index = @line_starts.bsearch_index { |start| start > offset } line_index = line_index ? line_index - 1 : @line_starts.length - 1 line_start = @line_starts.fetch(line_index) prefix = @text.byteslice(line_start, offset - line_start) || "".b value = [line_index + 1, unicode_scalar_length(prefix) + 1] #: position value.freeze end |