# Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
require_relative 'statistics'
require_relative 'wrapper'
require 'rainbow'
module Covered
class Summary
def initialize(threshold: 1.0)
@threshold = threshold
end
def each(wrapper)
statistics = Statistics.new
wrapper.each do |coverage|
statistics << coverage
if @threshold.nil? or coverage.ratio < @threshold
yield coverage
end
end
return statistics
end
def print_annotations(output, coverage, line, line_offset)
if annotations = coverage.annotations[line_offset]
output.write("#{line_offset}|".rjust(8))
output.write("*|".rjust(8))
output.write line.match(/^\s+/)
output.write '# '
output.puts Rainbow(annotations.join(", ")).bright
end
end
# A coverage array gives, for each line, the number of line execution by the interpreter. A nil value means coverage is disabled for this line (lines like else and end).
def call(wrapper, output = $stdout)
statistics = self.each(wrapper) do |coverage|
line_offset = 1
path = wrapper.relative_path(coverage.path)
output.puts "", Rainbow(path).bold.underline
counts = coverage.counts
coverage.read do |file|
file.each_line do |line|
count = counts[line_offset]
print_annotations(output, coverage, line, line_offset)
output.write("#{line_offset}|".rjust(8))
output.write("#{count}|".rjust(8))
if count == nil
output.write Rainbow(line).faint
elsif count == 0
output.write Rainbow(line).red
else
output.write Rainbow(line).green
end
# If there was no newline at end of file, we add one:
unless line.end_with? $/
output.puts
end
line_offset += 1
end
end
coverage.print(output)
end
statistics.print(output)
end
end
class BriefSummary < Summary
def call(wrapper, output = $stdout, before: 4, after: 4)
ordered = []
statistics = self.each(wrapper) do |coverage|
ordered << coverage unless coverage.complete?
end
output.puts
statistics.print(output)
if ordered.any?
output.puts "", "Least Coverage:"
ordered.sort_by!(&:missing_count).reverse!
ordered.first(5).each do |coverage|
path = wrapper.relative_path(coverage.path)
output.write Rainbow(path).orange
output.puts ": #{coverage.missing_count} lines not executed!"
end
end
end
end
class PartialSummary < Summary
def call(wrapper, output = $stdout, before: 4, after: 4)
statistics = self.each(wrapper) do |coverage|
line_offset = 1
path = wrapper.relative_path(coverage.path)
output.puts "", Rainbow(path).bold.underline
counts = coverage.counts
last_line = nil
unless coverage.zero?
coverage.read do |file|
file.each_line do |line|
range = Range.new([line_offset - before, 0].max, line_offset+after)
if counts[range]&.include?(0)
count = counts[line_offset]
if last_line and last_line != line_offset-1
output.puts ":".rjust(16)
end
print_annotations(output, coverage, line, line_offset)
prefix = "#{line_offset}|".rjust(8) + "#{count}|".rjust(8)
if count == nil
output.write prefix
output.write Rainbow(line).faint
elsif count == 0
output.write Rainbow(prefix).background(:darkred)
output.write Rainbow(line).red
else
output.write Rainbow(prefix).background(:darkgreen)
output.write Rainbow(line).green
end
# If there was no newline at end of file, we add one:
unless line.end_with? $/
output.puts
end
last_line = line_offset
end
line_offset += 1
end
end
end
coverage.print(output)
end
output.puts
statistics.print(output)
end
end
end