class RSpec::Core::Formatters::ExceptionPresenter

@private

def add_shared_group_lines(lines, colorizer)

def add_shared_group_lines(lines, colorizer)
  return lines if @skip_shared_group_trace
  example.metadata[:shared_group_inclusion_backtrace].each do |frame|
    lines << colorizer.wrap(frame.description, RSpec.configuration.default_color)
  end
  lines
end

def colorized_formatted_backtrace(colorizer=::RSpec::Core::Formatters::ConsoleCodes)

def colorized_formatted_backtrace(colorizer=::RSpec::Core::Formatters::ConsoleCodes)
  formatted_backtrace.map do |backtrace_info|
    colorizer.wrap "# #{backtrace_info}", RSpec.configuration.detail_color
  end
end

def colorized_message_lines(colorizer=::RSpec::Core::Formatters::ConsoleCodes)

def colorized_message_lines(colorizer=::RSpec::Core::Formatters::ConsoleCodes)
  add_shared_group_lines(failure_lines, colorizer).map do |line|
    colorizer.wrap line, message_color
  end
end

def encoded_string(string)

def encoded_string(string)
  RSpec::Support::EncodedString.new(string, Encoding.default_external)
end

def encoded_string(string)

def encoded_string(string)
  RSpec::Support::EncodedString.new(string)
end

def encoding_of(string)

def encoding_of(string)
  string.encoding
end

def encoding_of(_string)

:nocov:
for 1.8.7
def encoding_of(_string)
end

def exception_backtrace

def exception_backtrace
  exception.backtrace || []
end

def exception_class_name(exception=@exception)

def exception_class_name(exception=@exception)
  name = exception.class.name.to_s
  name = "(anonymous error class)" if name == ''
  name
end

def exception_lines

def exception_lines
  lines = []
  lines << "#{exception_class_name}:" unless exception_class_name =~ /RSpec/
  encoded_string(exception.message.to_s).split("\n").each do |line|
    lines << (line.empty? ? line : "  #{line}")
  end
  lines
end

def extra_failure_lines

def extra_failure_lines
  @extra_failure_lines ||= begin
    lines = Array(example.metadata[:extra_failure_lines])
    unless lines.empty?
      lines.unshift('')
      lines.push('')
    end
    lines
  end
end

def failure_lines

def failure_lines
  @failure_lines ||= [].tap do |lines|
    lines.concat(failure_slash_error_lines)
    sections = [failure_slash_error_lines, exception_lines]
    if sections.any? { |section| section.size > 1 } && !exception_lines.first.empty?
      lines << ''
    end
    lines.concat(exception_lines)
    lines.concat(extra_failure_lines)
  end
end

def failure_slash_error_lines

def failure_slash_error_lines
  lines = read_failed_lines
  if lines.count == 1
    lines[0] = "Failure/Error: #{lines[0].strip}"
  else
    least_indentation = SnippetExtractor.least_indentation_from(lines)
    lines = lines.map { |line| line.sub(/^#{least_indentation}/, '  ') }
    lines.unshift('Failure/Error:')
  end
  lines
end

def final_exception(exception, previous=[])

def final_exception(exception, previous=[])
  cause = exception.cause
  if cause && !previous.include?(cause)
    previous << cause
    final_exception(cause, previous)
  else
    exception
  end
end

def find_failed_line

def find_failed_line
  line_regex = RSpec.configuration.in_project_source_dir_regex
  loaded_spec_files = RSpec.configuration.loaded_spec_files
  exception_backtrace.find do |line|
    next unless (line_path = line[/(.+?):(\d+)(|:\d+)/, 1])
    path = File.expand_path(line_path)
    loaded_spec_files.include?(path) || path =~ line_regex
  end || exception_backtrace.first
end

def formatted_backtrace(exception=@exception)

def formatted_backtrace(exception=@exception)
  backtrace_formatter.format_backtrace(exception.backtrace, example.metadata) +
    formatted_cause(exception)
end

def formatted_cause(exception)

def formatted_cause(exception)
  last_cause = final_exception(exception)
  cause = []
  if exception.cause
    cause << '------------------'
    cause << '--- Caused by: ---'
    cause << "#{exception_class_name(last_cause)}:" unless exception_class_name(last_cause) =~ /RSpec/
    encoded_string(last_cause.message.to_s).split("\n").each do |line|
      cause << "  #{line}"
    end
    cause << ("  #{backtrace_formatter.format_backtrace(last_cause.backtrace, example.metadata).first}")
  end
  cause
end

def formatted_cause(_)

:nocov:
def formatted_cause(_)
  []
end

def formatted_message_and_backtrace(colorizer)

def formatted_message_and_backtrace(colorizer)
  lines = colorized_message_lines(colorizer) + colorized_formatted_backtrace(colorizer)
  encoding = encoding_of("")
  lines.map do |line|
    RSpec::Support::EncodedString.new(line, encoding)
  end
end

def fully_formatted(failure_number, colorizer=::RSpec::Core::Formatters::ConsoleCodes)

def fully_formatted(failure_number, colorizer=::RSpec::Core::Formatters::ConsoleCodes)
  lines = fully_formatted_lines(failure_number, colorizer)
  lines.join("\n") << "\n"
end

def fully_formatted_lines(failure_number, colorizer)

def fully_formatted_lines(failure_number, colorizer)
  lines = [
    description,
    detail_formatter.call(example, colorizer),
    formatted_message_and_backtrace(colorizer),
    extra_detail_formatter.call(failure_number, colorizer),
  ].compact.flatten
  lines = indent_lines(lines, failure_number)
  lines.unshift("")
  lines
end

def indent_lines(lines, failure_number)

def indent_lines(lines, failure_number)
  alignment_basis = "#{' ' * @indentation}#{failure_number}) "
  indentation = ' ' * alignment_basis.length
  lines.each_with_index.map do |line, index|
    if index == 0
      "#{alignment_basis}#{line}"
    elsif line.empty?
      line
    else
      "#{indentation}#{line}"
    end
  end
end

def initialize(exception, example, options={})

def initialize(exception, example, options={})
  @exception               = exception
  @example                 = example
  @message_color           = options.fetch(:message_color)          { RSpec.configuration.failure_color }
  @description             = options.fetch(:description)            { example.full_description }
  @detail_formatter        = options.fetch(:detail_formatter)       { Proc.new {} }
  @extra_detail_formatter  = options.fetch(:extra_detail_formatter) { Proc.new {} }
  @backtrace_formatter     = options.fetch(:backtrace_formatter)    { RSpec.configuration.backtrace_formatter }
  @indentation             = options.fetch(:indentation, 2)
  @skip_shared_group_trace = options.fetch(:skip_shared_group_trace, false)
  @failure_lines           = options[:failure_lines]
end

def message_lines

def message_lines
  add_shared_group_lines(failure_lines, Notifications::NullColorizer)
end

def read_failed_lines

def read_failed_lines
  matching_line = find_failed_line
  unless matching_line
    return ["Unable to find matching line from backtrace"]
  end
  file_path, line_number = matching_line.match(/(.+?):(\d+)(|:\d+)/)[1..2]
  max_line_count = RSpec.configuration.max_displayed_failure_line_count
  lines = SnippetExtractor.extract_expression_lines_at(file_path, line_number.to_i, max_line_count)
  RSpec.world.source_cache.syntax_highlighter.highlight(lines)
rescue SnippetExtractor::NoSuchFileError
  ["Unable to find #{file_path} to read failed line"]
rescue SnippetExtractor::NoSuchLineError
  ["Unable to find matching line in #{file_path}"]
rescue SecurityError
  ["Unable to read failed line"]
end