Class: Astel::SourceFile
- Inherits:
-
Object
- Object
- Astel::SourceFile
- Defined in:
- lib/astel/source_file.rb
Instance Attribute Summary collapse
-
#ast ⇒ Object
readonly
Returns the value of attribute ast.
-
#comments ⇒ Object
readonly
Returns the value of attribute comments.
-
#errors ⇒ Object
readonly
Returns the value of attribute errors.
-
#parse_result ⇒ Object
readonly
Returns the value of attribute parse_result.
-
#path ⇒ Object
readonly
Returns the value of attribute path.
-
#source ⇒ Object
readonly
Returns the value of attribute source.
-
#version ⇒ Object
readonly
Returns the value of attribute version.
Class Method Summary collapse
Instance Method Summary collapse
- #attach_comments! ⇒ Object
- #bof ⇒ Object
- #column_at(byte_offset) ⇒ Object
- #first_line_location ⇒ Object
- #indent_unit ⇒ Object
- #indentation_at(byte_offset) ⇒ Object
-
#initialize(code, path:, version: nil) ⇒ SourceFile
constructor
A new instance of SourceFile.
- #line_at(byte_offset) ⇒ Object
- #line_end(byte_offset) ⇒ Object
- #line_location(byte_offset) ⇒ Object
- #line_location_with_newline(byte_offset) ⇒ Object
- #line_start(byte_offset) ⇒ Object
- #lines ⇒ Object
- #magic_comment?(name) ⇒ Boolean
- #newline ⇒ Object
- #slice(location) ⇒ Object
- #valid? ⇒ Boolean
Constructor Details
#initialize(code, path:, version: nil) ⇒ SourceFile
Returns a new instance of SourceFile.
17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/astel/source_file.rb', line 17 def initialize(code, path:, version: nil) @path = path.to_s.freeze @version = normalize_version(version).freeze if version raw_source = code.dup.freeze = { filepath: @path } [:version] = @version if @version @parse_result = Prism.parse(raw_source, **) @source = @parse_result.source.source.freeze @ast = @parse_result.value @comments = @parse_result.comments.freeze @errors = @parse_result.errors.freeze @lines = nil end |
Instance Attribute Details
#ast ⇒ Object (readonly)
Returns the value of attribute ast.
7 8 9 |
# File 'lib/astel/source_file.rb', line 7 def ast @ast end |
#comments ⇒ Object (readonly)
Returns the value of attribute comments.
7 8 9 |
# File 'lib/astel/source_file.rb', line 7 def comments @comments end |
#errors ⇒ Object (readonly)
Returns the value of attribute errors.
7 8 9 |
# File 'lib/astel/source_file.rb', line 7 def errors @errors end |
#parse_result ⇒ Object (readonly)
Returns the value of attribute parse_result.
7 8 9 |
# File 'lib/astel/source_file.rb', line 7 def parse_result @parse_result end |
#path ⇒ Object (readonly)
Returns the value of attribute path.
7 8 9 |
# File 'lib/astel/source_file.rb', line 7 def path @path end |
#source ⇒ Object (readonly)
Returns the value of attribute source.
7 8 9 |
# File 'lib/astel/source_file.rb', line 7 def source @source end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
7 8 9 |
# File 'lib/astel/source_file.rb', line 7 def version @version end |
Class Method Details
.from_string(code, path: '(string)', version: nil) ⇒ Object
13 14 15 |
# File 'lib/astel/source_file.rb', line 13 def self.from_string(code, path: '(string)', version: nil) new(code, path: path, version: version) end |
.parse(path:, version: nil) ⇒ Object
9 10 11 |
# File 'lib/astel/source_file.rb', line 9 def self.parse(path:, version: nil) from_string(File.binread(path), path: path, version: version) end |
Instance Method Details
#attach_comments! ⇒ Object
63 64 65 66 67 68 69 |
# File 'lib/astel/source_file.rb', line 63 def attach_comments! return self if @comments_attached @parse_result.attach_comments! @comments_attached = true self end |
#bof ⇒ Object
39 40 41 |
# File 'lib/astel/source_file.rb', line 39 def bof Location.point(offset: 0, line: 1, column: 0) end |
#column_at(byte_offset) ⇒ Object
76 77 78 79 |
# File 'lib/astel/source_file.rb', line 76 def column_at(byte_offset) validate_offset!(byte_offset) @parse_result.source.column(byte_offset) end |
#first_line_location ⇒ Object
43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/astel/source_file.rb', line 43 def first_line_location line = lines.first || '' Location.new( start_offset: 0, end_offset: line.bytesize, start_line: 1, start_column: 0, end_line: 1, end_column: line.delete_suffix("\n").delete_suffix("\r").bytesize ) end |
#indent_unit ⇒ Object
119 120 121 122 123 124 125 126 127 128 129 130 |
# File 'lib/astel/source_file.rb', line 119 def indent_unit @indent_unit ||= begin indentations = lines.filter_map { |line| line[/\A[ \t]+/] } if indentations.any? { |indentation| indentation.include?("\t") } "\t" else widths = [0, *indentations.map(&:bytesize)].uniq.sort width = widths.each_cons(2).map { |left, right| right - left }.min width ? ' ' * width : ' ' end end end |
#indentation_at(byte_offset) ⇒ Object
114 115 116 117 |
# File 'lib/astel/source_file.rb', line 114 def indentation_at(byte_offset) start_offset = line_start(byte_offset) source.byteslice(start_offset, line_end(byte_offset) - start_offset)[/\A[ \t]*/] end |
#line_at(byte_offset) ⇒ Object
71 72 73 74 |
# File 'lib/astel/source_file.rb', line 71 def line_at(byte_offset) validate_offset!(byte_offset) @parse_result.source.line(byte_offset) end |
#line_end(byte_offset) ⇒ Object
86 87 88 89 90 91 92 |
# File 'lib/astel/source_file.rb', line 86 def line_end(byte_offset) validate_offset!(byte_offset) ending = @parse_result.source.line_end(byte_offset) ending -= 1 if ending.positive? && source.getbyte(ending - 1) == 10 ending -= 1 if ending.positive? && source.getbyte(ending - 1) == 13 ending end |
#line_location(byte_offset) ⇒ Object
94 95 96 |
# File 'lib/astel/source_file.rb', line 94 def line_location(byte_offset) location(line_start(byte_offset), line_end(byte_offset)) end |
#line_location_with_newline(byte_offset) ⇒ Object
98 99 100 101 |
# File 'lib/astel/source_file.rb', line 98 def line_location_with_newline(byte_offset) validate_offset!(byte_offset) location(line_start(byte_offset), @parse_result.source.line_end(byte_offset)) end |
#line_start(byte_offset) ⇒ Object
81 82 83 84 |
# File 'lib/astel/source_file.rb', line 81 def line_start(byte_offset) validate_offset!(byte_offset) @parse_result.source.line_start(byte_offset) end |
#lines ⇒ Object
31 32 33 |
# File 'lib/astel/source_file.rb', line 31 def lines @lines ||= source.lines(chomp: false).map!(&:freeze).freeze end |
#magic_comment?(name) ⇒ Boolean
55 56 57 58 59 60 61 |
# File 'lib/astel/source_file.rb', line 55 def magic_comment?(name) pattern = /\A#\s*#{Regexp.escape(name.to_s)}\s*:\s*true\b/ lines.first(2).any? do |line| candidate = line.start_with?("\uFEFF") ? line.delete_prefix("\uFEFF") : line candidate.match?(pattern) end end |
#newline ⇒ Object
107 108 109 110 111 112 |
# File 'lib/astel/source_file.rb', line 107 def newline @newline ||= begin crlf = source.b.scan(/\r\n/).length crlf > source.count("\n") - crlf ? "\r\n" : "\n" end end |
#slice(location) ⇒ Object
103 104 105 |
# File 'lib/astel/source_file.rb', line 103 def slice(location) source.byteslice(location.start_offset, location.end_offset - location.start_offset) end |
#valid? ⇒ Boolean
35 36 37 |
# File 'lib/astel/source_file.rb', line 35 def valid? errors.empty? end |