Class: Rcov::TextCoverageDiff
Overview
Constant Summary
collapse
- FORMAT_VERSION =
[0, 1, 0]
- DEFAULT_OPTS =
{ :textmode => :coverage_diff, :coverage_diff_mode => :record,
:coverage_diff_file => "coverage.info", :diff_cmd => "diff", :comments_run_by_default => true }
/@@ -\d+,\d+ \+(\d+),(\d+) @@/
Instance Method Summary
collapse
#add_file, #code_coverage, #each_file_pair_sorted, #mangle_filename, #normalize_filename, #num_code_lines, #num_lines, #sorted_file_pairs, #total_coverage
Constructor Details
Returns a new instance of TextCoverageDiff.
16
17
18
19
20
21
22
23
24
25
|
# File 'lib/rcov/formatters/text_coverage_diff.rb', line 16
def initialize(opts = {})
options = DEFAULT_OPTS.clone.update(opts)
@textmode = options[:textmode]
@color = options[:color]
@mode = options[:coverage_diff_mode]
@state_file = options[:coverage_diff_file]
@diff_cmd = options[:diff_cmd]
@gcc_output = options[:gcc_output]
super(options)
end
|
Instance Method Details
#compare_state ⇒ Object
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
|
# File 'lib/rcov/formatters/text_coverage_diff.rb', line 53
def compare_state
return unless verify_diff_available
begin
format, prev_state = File.open(@state_file){|f| self.SERIALIZER.load(f) }
rescue
$stderr.puts <<-EOF
Couldn't load coverage data from #{@state_file}.
EOF
return end
if !(Array === format) or
FORMAT_VERSION[0] != format[0] || FORMAT_VERSION[1] < format[1]
$stderr.puts <<-EOF
Couldn't load coverage data from #{@state_file}.
The file is saved in the format #{format.inspect[0..20]}.
This rcov executable understands #{FORMAT_VERSION.inspect}.
EOF
return end
each_file_pair_sorted do |filename, fileinfo|
old_data = Tempfile.new("#{mangle_filename(filename)}-old")
new_data = Tempfile.new("#{mangle_filename(filename)}-new")
if prev_state.has_key? filename
old_code, old_cov = prev_state[filename].values_at(:lines, :coverage)
old_code.each_with_index do |line, i|
prefix = old_cov[i] ? " " : "!! "
old_data.write "#{prefix}#{line}"
end
else
old_data.write ""
end
old_data.close
SCRIPT_LINES__[filename].each_with_index do |line, i|
prefix = fileinfo.coverage[i] ? " " : "!! "
new_data.write "#{prefix}#{line}"
end
new_data.close
diff = `#{@diff_cmd} -u "#{old_data.path}" "#{new_data.path}"`
new_uncovered_hunks = process_unified_diff(filename, diff)
old_data.close!
new_data.close!
display_hunks(filename, new_uncovered_hunks)
end
end
|
#display_hunks(filename, hunks) ⇒ Object
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
# File 'lib/rcov/formatters/text_coverage_diff.rb', line 99
def display_hunks(filename, hunks)
return if hunks.empty?
puts
puts "=" * 80
puts "!!!!! Uncovered code introduced in #{filename}"
hunks.each do |offset, lines|
if @gcc_output
lines.each_with_index do |line,i|
lineno = offset + i
flag = (/^!! / !~ line) ? "-" : ":"
prefix = "#{filename}#{flag}#{lineno}#{flag}"
puts "#{prefix}#{line[3..-1]}"
end
elsif @color
puts "### #{filename}:#{offset}"
lines.each do |line|
prefix = (/^!! / !~ line) ? "\e[32;40m" : "\e[31;40m"
puts "#{prefix}#{line[3..-1].chomp}\e[37;40m"
end
else
puts "### #{filename}:#{offset}"
puts lines
end
end
end
|
#execute ⇒ Object
27
28
29
30
31
32
33
34
35
36
|
# File 'lib/rcov/formatters/text_coverage_diff.rb', line 27
def execute
case @mode
when :record
record_state
when :compare
compare_state
else
raise "Unknown TextCoverageDiff mode: #{mode.inspect}."
end
end
|
#process_unified_diff(filename, diff) ⇒ Object
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
|
# File 'lib/rcov/formatters/text_coverage_diff.rb', line 155
def process_unified_diff(filename, diff)
current_hunk = []
current_hunk_start = 0
keep_current_hunk = false
state = :init
interesting_hunks = []
diff.each_with_index do |line, i|
case state
when :init
if md = HUNK_HEADER.match(line)
current_hunk = []
current_hunk_start = md[1].to_i
state = :body
end
when :body
case line
when HUNK_HEADER
new_start = $1.to_i
if keep_current_hunk
interesting_hunks << [current_hunk_start, current_hunk]
end
current_hunk_start = new_start
current_hunk = []
keep_current_hunk = false
when /^-/
when /^\+!! /
keep_current_hunk = true
current_hunk << line[1..-1]
else
current_hunk << line[1..-1]
end
end
end
if keep_current_hunk
interesting_hunks << [current_hunk_start, current_hunk]
end
interesting_hunks
end
|
#record_state ⇒ Object
38
39
40
41
42
43
44
45
46
47
48
49
50
|
# File 'lib/rcov/formatters/text_coverage_diff.rb', line 38
def record_state
state = {}
each_file_pair_sorted do |filename, fileinfo|
state[filename] = {:lines => SCRIPT_LINES__[filename], :coverage => fileinfo.coverage.to_a,:counts => fileinfo.counts}
end
File.open(@state_file, "w") do |f|
self.SERIALIZER.dump([FORMAT_VERSION, state], f)
end
rescue
$stderr.puts <<-EOF
Couldn't save coverage data to #{@state_file}.
EOF
end
|
#SERIALIZER ⇒ Object
9
10
11
12
13
14
|
# File 'lib/rcov/formatters/text_coverage_diff.rb', line 9
def SERIALIZER
Marshal
end
|
#verify_diff_available ⇒ Object
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
# File 'lib/rcov/formatters/text_coverage_diff.rb', line 126
def verify_diff_available
old_stderr = STDERR.dup
old_stdout = STDOUT.dup
new_stderr = Tempfile.new("rcov_check_diff")
STDERR.reopen new_stderr.path
STDOUT.reopen new_stderr.path
retval = system "#{@diff_cmd} --version"
unless retval
old_stderr.puts <<EOF
The '#{@diff_cmd}' executable seems not to be available.
You can specify which diff executable should be used with --diff-cmd.
If your system doesn't have one, you might want to use Diff::LCS's:
gem install diff-lcs
and use --diff-cmd=ldiff.
EOF
return false
end
true
ensure
STDOUT.reopen old_stdout
STDERR.reopen old_stderr
new_stderr.close!
end
|