Parent

Parser::Source::Buffer

A buffer with source code. {Buffer} contains the source code itself, associated location information (name and first line), and takes care of encoding.

A source buffer is immutable once populated.

@!attribute [r] name

Buffer name. If the buffer was created from a file, the name corresponds
to relative path to the file.
@return [String] buffer name

@!attribute [r] first_line

First line of the buffer, 1 by default.
@return [Integer] first line

@api public

Constants

ENCODING_RE

@api private

Attributes

first_line[R]
name[R]

Public Class Methods

new(name, first_line = 1) click to toggle source
# File lib/parser/source/buffer.rb, line 101
def initialize(name, first_line = 1)
  @name        = name
  @source      = nil
  @first_line  = first_line

  @lines       = nil
  @line_begins = nil
end
recognize_encoding(string) click to toggle source

Try to recognize encoding of `string` as Ruby would, i.e. by looking for magic encoding comment or UTF-8 BOM. `string` can be in any encoding.

@param [String] string @return [String|nil] encoding name, if recognized

# File lib/parser/source/buffer.rb, line 49
def self.recognize_encoding(string)
  return if string.empty?

  # extract the first two lines in an efficient way
  string =~ /\A(.*)\n?(.*\n)?/
  first_line, second_line = $1, $2

  if first_line =~ /\A\xef\xbb\xbf/ # BOM
    return Encoding::UTF_8
  elsif first_line[0, 2] == '#!'
    encoding_line = second_line
  else
    encoding_line = first_line
  end

  if (result = ENCODING_RE.match(encoding_line))
    Encoding.find(result[2] || result[3] || result[5])
  else
    nil
  end
end
reencode_string(input) click to toggle source

Recognize encoding of `input` and process it so it could be lexed.

* If `input` does not contain BOM or magic encoding comment, it is
  kept in the original encoding.
* If the detected encoding is binary, `input` is kept in binary.
* Otherwise, `input` is re-encoded into UTF-8 and returned as a
  new string.

This method mutates the encoding of `input`, but not its content.

@param [String] input @return [String] @raise [EncodingError]

# File lib/parser/source/buffer.rb, line 86
def self.reencode_string(input)
  original_encoding = input.encoding
  detected_encoding = recognize_encoding(input.force_encoding(Encoding::BINARY))

  if detected_encoding.nil?
    input.force_encoding(original_encoding)
  elsif detected_encoding == Encoding::BINARY
    input
  else
    input.
      force_encoding(detected_encoding).
      encode(Encoding::UTF_8)
  end
end

Public Instance Methods

decompose_position(position) click to toggle source

Convert a character index into the source to a `[line, column]` tuple.

@param [Integer] position @return [[Integer, Integer]] `[line, column]`

# File lib/parser/source/buffer.rb, line 179
def decompose_position(position)
  line_no, line_begin = line_for(position)

  [ @first_line + line_no, position - line_begin ]
end
raw_source=(input) click to toggle source

Populate this buffer from a string without encoding autodetection.

@param [String] input @raise [ArgumentError] if already populated @return [String]

# File lib/parser/source/buffer.rb, line 165
def raw_source=(input)
  if @source
    raise ArgumentError, 'Source::Buffer is immutable'
  end

  @source = input.gsub("\r\n", "\n").freeze
end
read() click to toggle source

Populate this buffer from correspondingly named file.

@example

Parser::Source::Buffer.new('foo/bar.rb').read

@return [Buffer] self @raise [ArgumentError] if already populated

# File lib/parser/source/buffer.rb, line 119
def read
  File.open(@name, 'rb') do |io|
    self.source = io.read
  end

  self
end
source() click to toggle source

Source code contained in this buffer.

@return [String] source code @raise [RuntimeError] if buffer is not populated yet

# File lib/parser/source/buffer.rb, line 133
def source
  if @source.nil?
    raise RuntimeError, 'Cannot extract source from uninitialized Source::Buffer'
  end

  @source
end
source=(input) click to toggle source

Populate this buffer from a string with encoding autodetection. `input` is mutated if not frozen.

@param [String] input @raise [ArgumentError] if already populated @return [String]

# File lib/parser/source/buffer.rb, line 149
def source=(input)
  if defined?(Encoding)
    input = input.dup if input.frozen?
    input = self.class.reencode_string(input)
  end

  self.raw_source = input
end
source_line(lineno) click to toggle source

Extract line `lineno` from source, taking `first_line` into account.

@param [Integer] lineno @return [String] @raise [IndexError] if `lineno` is out of bounds

# File lib/parser/source/buffer.rb, line 192
def source_line(lineno)
  unless @lines
    @lines = @source.lines.to_a
    @lines.each { |line| line.chomp!("\n") }

    # If a file ends with a newline, the EOF token will appear
    # to be one line further than the end of file.
    @lines << ""
  end

  @lines.fetch(lineno - @first_line).dup
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.