/usr/lib/ruby/vendor_ruby/rspec/core/formatters/html_snippet_extractor.rb is in ruby-rspec-core 3.5.0c3e0m0s0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | module RSpec
module Core
module Formatters
# @api private
#
# Extracts code snippets by looking at the backtrace of the passed error
# and applies synax highlighting and line numbers using html.
class HtmlSnippetExtractor
# @private
module NullConverter
def self.convert(code)
%Q(#{code}\n<span class="comment"># Install the coderay gem to get syntax highlighting</span>)
end
end
# @private
module CoderayConverter
def self.convert(code)
CodeRay.scan(code, :ruby).html(:line_numbers => false)
end
end
# rubocop:disable Style/ClassVars
@@converter = NullConverter
begin
require 'coderay'
@@converter = CoderayConverter
# rubocop:disable Lint/HandleExceptions
rescue LoadError
# it'll fall back to the NullConverter assigned above
# rubocop:enable Lint/HandleExceptions
end
# rubocop:enable Style/ClassVars
# @api private
#
# Extract lines of code corresponding to a backtrace.
#
# @param backtrace [String] the backtrace from a test failure
# @return [String] highlighted code snippet indicating where the test
# failure occured
#
# @see #post_process
def snippet(backtrace)
raw_code, line = snippet_for(backtrace[0])
highlighted = @@converter.convert(raw_code)
post_process(highlighted, line)
end
# rubocop:enable Style/ClassVars
# @api private
#
# Create a snippet from a line of code.
#
# @param error_line [String] file name with line number (i.e.
# 'foo_spec.rb:12')
# @return [String] lines around the target line within the file
#
# @see #lines_around
def snippet_for(error_line)
if error_line =~ /(.*):(\d+)/
file = Regexp.last_match[1]
line = Regexp.last_match[2].to_i
[lines_around(file, line), line]
else
["# Couldn't get snippet for #{error_line}", 1]
end
end
# @api private
#
# Extract lines of code centered around a particular line within a
# source file.
#
# @param file [String] filename
# @param line [Fixnum] line number
# @return [String] lines around the target line within the file (2 above
# and 1 below).
def lines_around(file, line)
if File.file?(file)
lines = File.read(file).split("\n")
min = [0, line - 3].max
max = [line + 1, lines.length - 1].min
selected_lines = []
selected_lines.join("\n")
lines[min..max].join("\n")
else
"# Couldn't get snippet for #{file}"
end
rescue SecurityError
"# Couldn't get snippet for #{file}"
end
# @api private
#
# Adds line numbers to all lines and highlights the line where the
# failure occurred using html `span` tags.
#
# @param highlighted [String] syntax-highlighted snippet surrounding the
# offending line of code
# @param offending_line [Fixnum] line where failure occured
# @return [String] completed snippet
def post_process(highlighted, offending_line)
new_lines = []
highlighted.split("\n").each_with_index do |line, i|
new_line = "<span class=\"linenum\">#{offending_line + i - 2}</span>#{line}"
new_line = "<span class=\"offending\">#{new_line}</span>" if i == 2
new_lines << new_line
end
new_lines.join("\n")
end
end
end
end
end
|