Class: Covered::Coverage

Inherits:
Object
  • Object
show all
Includes:
Ratio
Defined in:
lib/covered/coverage.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Ratio

#complete?, #percentage, #ratio

Constructor Details

#initialize(source, counts = [], annotations = {}) ⇒ Coverage

Returns a new instance of Coverage.



32
33
34
35
36
# File 'lib/covered/coverage.rb', line 32

def initialize(source, counts = [], annotations = {})
	@source = source
	@counts = counts
	@annotations = annotations
end

Instance Attribute Details

#annotationsObject (readonly)

Returns the value of attribute annotations.



40
41
42
# File 'lib/covered/coverage.rb', line 40

def annotations
  @annotations
end

#countsObject (readonly)

Returns the value of attribute counts.



39
40
41
# File 'lib/covered/coverage.rb', line 39

def counts
  @counts
end

#sourceObject

Returns the value of attribute source.



38
39
40
# File 'lib/covered/coverage.rb', line 38

def source
  @source
end

Class Method Details

.deserialize(unpacker) ⇒ Object



190
191
192
193
194
195
196
# File 'lib/covered/coverage.rb', line 190

def self.deserialize(unpacker)
	source = unpacker.read
	counts = unpacker.read
	annotations = unpacker.read
	
	self.new(source, counts, annotations)
end

.for(path, **options) ⇒ Object



28
29
30
# File 'lib/covered/coverage.rb', line 28

def self.for(path, **options)
	self.new(Source.for(path, **options))
end

Instance Method Details

#[](line_number) ⇒ Object



143
144
145
# File 'lib/covered/coverage.rb', line 143

def [] line_number
	@counts[line_number]
end

#annotate(line_number, annotation) ⇒ Object



51
52
53
54
# File 'lib/covered/coverage.rb', line 51

def annotate(line_number, annotation)
	@annotations[line_number] ||= []
	@annotations[line_number] << annotation
end

#as_jsonObject



175
176
177
178
179
180
181
182
# File 'lib/covered/coverage.rb', line 175

def as_json
	{
		counts: counts,
		executable_count: executable_count,
		executed_count: executed_count,
		percentage: percentage.to_f.round(2),
	}
end

#emptyObject

Create an empty coverage with the same source.



47
48
49
# File 'lib/covered/coverage.rb', line 47

def empty
	self.class.new(@source, [nil] * @counts.size)
end

#executable_countObject



151
152
153
# File 'lib/covered/coverage.rb', line 151

def executable_count
	executable_lines.count
end

#executable_linesObject



147
148
149
# File 'lib/covered/coverage.rb', line 147

def executable_lines
	@counts.compact
end

#executed_countObject



159
160
161
# File 'lib/covered/coverage.rb', line 159

def executed_count
	executed_lines.count
end

#executed_linesObject



155
156
157
# File 'lib/covered/coverage.rb', line 155

def executed_lines
	executable_lines.reject(&:zero?)
end

#for_lines(line_numbers) ⇒ Object

Construct a new coverage object for the given line numbers. Only the given line numbers will be considered for the purposes of computing coverage.



86
87
88
89
90
91
92
93
# File 'lib/covered/coverage.rb', line 86

def for_lines(line_numbers)
	counts = [nil] * @counts.size
	line_numbers.each do |line_number|
		counts[line_number] = @counts[line_number]
	end
	
	self.class.new(@source, counts, @annotations)
end

#freezeObject



126
127
128
129
130
131
132
133
# File 'lib/covered/coverage.rb', line 126

def freeze
	return self if frozen?
	
	@counts.freeze
	@annotations.freeze
	
	super
end

#fresh?Boolean

Returns:

  • (Boolean)


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/covered/coverage.rb', line 103

def fresh?
	if @source.modified_time.nil?
		# We don't know when the file was last modified, so we assume it is stale:
		return false
	end
	
	unless File.exist?(@source.path)
		# The file no longer exists, so we assume it is stale:
		return false
	end
	
	if @source.modified_time >= File.mtime(@source.path)
		# The file has not been modified since we last processed it, so we assume it is fresh:
		return true
	end
	
	return false
end

#mark(line_number, value = 1) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/covered/coverage.rb', line 56

def mark(line_number, value = 1)
	# As currently implemented, @counts is base-zero rather than base-one.
	# Line numbers generally start at line 1, so the first line, line 1, is at index 1. This means that index[0] is usually nil.
	Array(value).each_with_index do |value, index|
		offset = line_number + index
		if @counts[offset]
			@counts[offset] += value
		else
			@counts[offset] = value
		end
	end
end

#merge!(other) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/covered/coverage.rb', line 69

def merge!(other)
	# If the counts are non-zero and don't match, that can indicate a problem.
	
	other.counts.each_with_index do |count, index|
		if count
			@counts[index] ||= 0
			@counts[index] += count
		end
	end
	
	@annotations.merge!(other.annotations) do |line_number, a, b|
		Array(a) + Array(b)
	end
end

#missing_countObject



163
164
165
# File 'lib/covered/coverage.rb', line 163

def missing_count
	executable_count - executed_count
end

#pathObject



95
96
97
# File 'lib/covered/coverage.rb', line 95

def path
	@source.path
end

#path=(value) ⇒ Object



99
100
101
# File 'lib/covered/coverage.rb', line 99

def path= value
	@source.path = value
end


167
168
169
# File 'lib/covered/coverage.rb', line 167

def print(output)
	output.puts "** #{executed_count}/#{executable_count} lines executed; #{percentage.to_f.round(2)}% covered."
end

#read(&block) ⇒ Object



122
123
124
# File 'lib/covered/coverage.rb', line 122

def read(&block)
	@source.read(&block)
end

#serialize(packer) ⇒ Object



184
185
186
187
188
# File 'lib/covered/coverage.rb', line 184

def serialize(packer)
	packer.write(@source)
	packer.write(@counts)
	packer.write(@annotations)
end

#to_aObject



135
136
137
# File 'lib/covered/coverage.rb', line 135

def to_a
	@counts
end

#to_sObject



171
172
173
# File 'lib/covered/coverage.rb', line 171

def to_s
	"\#<#{self.class} path=#{self.path} #{self.percentage.to_f.round(2)}% covered>"
end

#totalObject



42
43
44
# File 'lib/covered/coverage.rb', line 42

def total
	counts.sum{|count| count || 0}
end

#zero?Boolean

Returns:

  • (Boolean)


139
140
141
# File 'lib/covered/coverage.rb', line 139

def zero?
	total.zero?
end