class Parser::Diagnostic


@return [Array<Parser::Source::Range>]
Supplementary error-related source ranges.
@!attribute [r] highlights
@return [Parser::Source::Range]
Main error-related source range.
@!attribute [r] location
@return [String] error message
@!attribute [r] message
@return [Symbol] extended arguments that describe the error
@see Parser::MESSAGES
@!attribute [r] arguments
@return [Symbol] reason for error
@see Parser::MESSAGES
@!attribute [r] reason
@return [Symbol] diagnostic level
@see LEVELS
@!attribute [r] level
@api public
#

def first_line_only(range)

Returns:
  • (Parser::Source::Range) -
def first_line_only(range)
  if range.line != range.last_line
    range.resize(range.source =~ /\n/)
  else
    range
  end
end

def initialize(level, reason, arguments, location, highlights=[])

Parameters:
  • highlights (Array) --
  • location (Parser::Source::Range) --
  • arguments (Hash) --
  • reason (Symbol) --
  • level (Symbol) --
def initialize(level, reason, arguments, location, highlights=[])
  unless LEVELS.include?(level)
    raise ArgumentError,
          "Diagnostic#level must be one of #{LEVELS.join(', ')}; " \
          "#{level.inspect} provided."
  end
  raise 'Expected a location' unless location
  @level       = level
  @reason      = reason
  @arguments   = (arguments || {}).dup.freeze
  @location    = location
  @highlights  = highlights.dup.freeze
  freeze
end

def last_line_only(range)

Returns:
  • (Parser::Source::Range) -
def last_line_only(range)
  if range.line != range.last_line
    range.adjust(begin_pos: range.source =~ /[^\n]*\z/)
  else
    range
  end
end

def message

Returns:
  • (String) - the rendered message.
def message
  Messages.compile(@reason, @arguments)
end

def render

Returns:
  • (Array) -
def render
  if @location.line == @location.last_line || @location.is?("\n")
    ["#{@location}: #{@level}: #{message}"] + render_line(@location)
  else
    # multi-line diagnostic
    first_line = first_line_only(@location)
    last_line  = last_line_only(@location)
    num_lines  = (@location.last_line - @location.line) + 1
    buffer     = @location.source_buffer
    last_lineno, last_column = buffer.decompose_position(@location.end_pos)
    ["#{@location}-#{last_lineno}:#{last_column}: #{@level}: #{message}"] +
      render_line(first_line, num_lines > 2, false) +
      render_line(last_line, false, true)
  end
end

def render_line(range, ellipsis=false, range_end=false)

Returns:
  • (Array) -
def render_line(range, ellipsis=false, range_end=false)
  source_line    = range.source_line
  highlight_line = ' ' * source_line.length
  @highlights.each do |highlight|
   line_range = range.source_buffer.line_range(range.line)
    if highlight = highlight.intersect(line_range)
      highlight_line[highlight.column_range] = '~' * highlight.size
    end
  end
  if range.is?("\n")
    highlight_line += "^"
  else
    if !range_end && range.size >= 1
      highlight_line[range.column_range] = '^' + '~' * (range.size - 1)
    else
      highlight_line[range.column_range] = '~' * range.size
    end
  end
  highlight_line += '...' if ellipsis
  [source_line, highlight_line].
    map { |line| "#{range.source_buffer.name}:#{range.line}: #{line}" }
end