Class: Astel::SourceFile

Inherits:
Object
  • Object
show all
Defined in:
lib/astel/source_file.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(code, path:, version: nil) ⇒ SourceFile

Returns a new instance of SourceFile.



17
18
19
20
21
22
23
24
25
26
# 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
  @parse_result = parse_source(code, path: @path, version: @version)
  @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

#astObject (readonly)

Returns the value of attribute ast.



7
8
9
# File 'lib/astel/source_file.rb', line 7

def ast
  @ast
end

#commentsObject (readonly)

Returns the value of attribute comments.



7
8
9
# File 'lib/astel/source_file.rb', line 7

def comments
  @comments
end

#errorsObject (readonly)

Returns the value of attribute errors.



7
8
9
# File 'lib/astel/source_file.rb', line 7

def errors
  @errors
end

#parse_resultObject (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

#pathObject (readonly)

Returns the value of attribute path.



7
8
9
# File 'lib/astel/source_file.rb', line 7

def path
  @path
end

#sourceObject (readonly)

Returns the value of attribute source.



7
8
9
# File 'lib/astel/source_file.rb', line 7

def source
  @source
end

#versionObject (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



58
59
60
61
62
63
64
# File 'lib/astel/source_file.rb', line 58

def attach_comments!
  return self if @comments_attached

  @parse_result.attach_comments!
  @comments_attached = true
  self
end

#bofObject



36
37
38
# File 'lib/astel/source_file.rb', line 36

def bof
  Location.point(offset: 0, line: 1, column: 0)
end

#column_at(byte_offset) ⇒ Object



71
72
73
74
# File 'lib/astel/source_file.rb', line 71

def column_at(byte_offset)
  validate_offset!(byte_offset)
  @parse_result.source.column(byte_offset)
end

#first_line_locationObject



40
41
42
43
44
45
46
47
48
49
50
# File 'lib/astel/source_file.rb', line 40

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_unitObject



112
113
114
# File 'lib/astel/source_file.rb', line 112

def indent_unit
  @indent_unit ||= detected_indent_unit
end

#indentation_at(byte_offset) ⇒ Object



107
108
109
110
# File 'lib/astel/source_file.rb', line 107

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



66
67
68
69
# File 'lib/astel/source_file.rb', line 66

def line_at(byte_offset)
  validate_offset!(byte_offset)
  @parse_result.source.line(byte_offset)
end

#line_end(byte_offset) ⇒ Object



81
82
83
84
85
86
87
88
# File 'lib/astel/source_file.rb', line 81

def line_end(byte_offset)
  validate_offset!(byte_offset)
  start = line_start(byte_offset)
  ending = @parse_result.source.line_end(byte_offset)
  ending -= 1 if ending > start && source.getbyte(ending - 1) == 10
  ending -= 1 if ending > start && source.getbyte(ending - 1) == 13
  ending
end

#line_location(byte_offset) ⇒ Object



90
91
92
# File 'lib/astel/source_file.rb', line 90

def line_location(byte_offset)
  location(line_start(byte_offset), line_end(byte_offset))
end

#line_location_with_newline(byte_offset) ⇒ Object



94
95
96
97
# File 'lib/astel/source_file.rb', line 94

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



76
77
78
79
# File 'lib/astel/source_file.rb', line 76

def line_start(byte_offset)
  validate_offset!(byte_offset)
  @parse_result.source.line_start(byte_offset)
end

#linesObject



28
29
30
# File 'lib/astel/source_file.rb', line 28

def lines
  @lines ||= source.lines(chomp: false).map!(&:freeze).freeze
end

#magic_comment?(name) ⇒ Boolean

Returns:

  • (Boolean)


52
53
54
55
56
# File 'lib/astel/source_file.rb', line 52

def magic_comment?(name)
  @parse_result.magic_comments.any? do |comment|
    comment.key == name.to_s && comment.value == 'true' && effective_magic_comment?(comment)
  end
end

#newlineObject



103
104
105
# File 'lib/astel/source_file.rb', line 103

def newline
  @newline ||= crlf_dominant? ? "\r\n" : "\n"
end

#slice(location) ⇒ Object



99
100
101
# File 'lib/astel/source_file.rb', line 99

def slice(location)
  source.byteslice(location.start_offset, location.end_offset - location.start_offset)
end

#valid?Boolean

Returns:

  • (Boolean)


32
33
34
# File 'lib/astel/source_file.rb', line 32

def valid?
  errors.empty?
end