gigpark-rcov 0.8.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/BLURB +111 -0
- data/LICENSE +53 -0
- data/Rakefile +78 -0
- data/THANKS +96 -0
- data/bin/rcov +508 -0
- data/doc/readme_for_api.markdown +22 -0
- data/doc/readme_for_emacs.markdown +52 -0
- data/doc/readme_for_rake.markdown +51 -0
- data/doc/readme_for_vim.markdown +34 -0
- data/editor-extensions/rcov.el +131 -0
- data/editor-extensions/rcov.vim +38 -0
- data/ext/rcovrt/1.8/callsite.c +216 -0
- data/ext/rcovrt/1.8/rcovrt.c +287 -0
- data/ext/rcovrt/1.9/callsite.c +234 -0
- data/ext/rcovrt/1.9/rcovrt.c +264 -0
- data/ext/rcovrt/extconf.rb +21 -0
- data/lib/rcov.rb +33 -0
- data/lib/rcov/call_site_analyzer.rb +225 -0
- data/lib/rcov/code_coverage_analyzer.rb +268 -0
- data/lib/rcov/coverage_info.rb +36 -0
- data/lib/rcov/differential_analyzer.rb +116 -0
- data/lib/rcov/file_statistics.rb +334 -0
- data/lib/rcov/formatters.rb +13 -0
- data/lib/rcov/formatters/base_formatter.rb +168 -0
- data/lib/rcov/formatters/failure_report.rb +15 -0
- data/lib/rcov/formatters/full_text_report.rb +48 -0
- data/lib/rcov/formatters/html_coverage.rb +244 -0
- data/lib/rcov/formatters/html_erb_template.rb +45 -0
- data/lib/rcov/formatters/text_coverage_diff.rb +193 -0
- data/lib/rcov/formatters/text_report.rb +32 -0
- data/lib/rcov/formatters/text_summary.rb +11 -0
- data/lib/rcov/lowlevel.rb +146 -0
- data/lib/rcov/rcovtask.rb +155 -0
- data/lib/rcov/templates/detail.html.erb +78 -0
- data/lib/rcov/templates/index.html.erb +76 -0
- data/lib/rcov/templates/screen.css +168 -0
- data/lib/rcov/version.rb +10 -0
- data/setup.rb +1588 -0
- data/test/assets/sample_01.rb +7 -0
- data/test/assets/sample_02.rb +5 -0
- data/test/assets/sample_03.rb +20 -0
- data/test/assets/sample_04.rb +10 -0
- data/test/assets/sample_05-new.rb +17 -0
- data/test/assets/sample_05-old.rb +13 -0
- data/test/assets/sample_05.rb +17 -0
- data/test/call_site_analyzer_test.rb +171 -0
- data/test/code_coverage_analyzer_test.rb +184 -0
- data/test/file_statistics_test.rb +471 -0
- data/test/functional_test.rb +89 -0
- data/test/turn_off_rcovrt.rb +4 -0
- metadata +109 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rcov/formatters/html_erb_template'
|
2
|
+
require 'rcov/formatters/base_formatter'
|
3
|
+
require 'rcov/formatters/text_summary'
|
4
|
+
require 'rcov/formatters/text_report'
|
5
|
+
require 'rcov/formatters/text_coverage_diff'
|
6
|
+
require 'rcov/formatters/full_text_report'
|
7
|
+
require 'rcov/formatters/html_coverage'
|
8
|
+
require 'rcov/formatters/failure_report'
|
9
|
+
|
10
|
+
module Rcov
|
11
|
+
module Formatters
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
module Rcov
|
2
|
+
class BaseFormatter # :nodoc:
|
3
|
+
require 'pathname'
|
4
|
+
require 'mkmf'
|
5
|
+
ignore_files = [/\A#{Regexp.escape(Pathname.new(::Config::CONFIG['libdir']).cleanpath.to_s)}/, /\btc_[^.]*.rb/, /_test\.rb\z/, /\btest\//, /\bvendor\//, /\A#{Regexp.escape(__FILE__)}\z/]
|
6
|
+
|
7
|
+
DEFAULT_OPTS = { :ignore => ignore_files, :sort => :name, :sort_reverse => false,
|
8
|
+
:output_threshold => 101, :dont_ignore => [], :callsite_analyzer => nil, \
|
9
|
+
:comments_run_by_default => false }
|
10
|
+
|
11
|
+
def initialize(opts = {})
|
12
|
+
options = DEFAULT_OPTS.clone.update(opts)
|
13
|
+
@failure_threshold = options[:failure_threshold]
|
14
|
+
@files = {}
|
15
|
+
@ignore_files = options[:ignore]
|
16
|
+
@dont_ignore_files = options[:dont_ignore]
|
17
|
+
@sort_criterium = case options[:sort]
|
18
|
+
when :loc then lambda{|fname, finfo| finfo.num_code_lines}
|
19
|
+
when :coverage then lambda{|fname, finfo| finfo.code_coverage}
|
20
|
+
else lambda { |fname, finfo| fname }
|
21
|
+
end
|
22
|
+
@sort_reverse = options[:sort_reverse]
|
23
|
+
@output_threshold = options[:output_threshold]
|
24
|
+
@callsite_analyzer = options[:callsite_analyzer]
|
25
|
+
@comments_run_by_default = options[:comments_run_by_default]
|
26
|
+
@callsite_index = nil
|
27
|
+
|
28
|
+
@mangle_filename = Hash.new{|h,base|
|
29
|
+
h[base] = Pathname.new(base).cleanpath.to_s.gsub(%r{^\w:[/\\]}, "").gsub(/\./, "_").gsub(/[\\\/]/, "-") + ".html"
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_file(filename, lines, coverage, counts)
|
34
|
+
old_filename = filename
|
35
|
+
filename = normalize_filename(filename)
|
36
|
+
SCRIPT_LINES__[filename] = SCRIPT_LINES__[old_filename]
|
37
|
+
if @ignore_files.any?{|x| x === filename} &&
|
38
|
+
!@dont_ignore_files.any?{|x| x === filename}
|
39
|
+
return nil
|
40
|
+
end
|
41
|
+
if @files[filename]
|
42
|
+
@files[filename].merge(lines, coverage, counts)
|
43
|
+
else
|
44
|
+
@files[filename] = FileStatistics.new(filename, lines, counts,
|
45
|
+
@comments_run_by_default)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def normalize_filename(filename)
|
50
|
+
File.expand_path(filename).gsub(/^#{Regexp.escape(Dir.getwd)}\//, '')
|
51
|
+
end
|
52
|
+
|
53
|
+
def mangle_filename(base)
|
54
|
+
@mangle_filename[base]
|
55
|
+
end
|
56
|
+
|
57
|
+
def each_file_pair_sorted(&b)
|
58
|
+
return sorted_file_pairs unless block_given?
|
59
|
+
sorted_file_pairs.each(&b)
|
60
|
+
end
|
61
|
+
|
62
|
+
def sorted_file_pairs
|
63
|
+
pairs = @files.sort_by do |fname, finfo|
|
64
|
+
@sort_criterium.call(fname, finfo)
|
65
|
+
end.select{|_, finfo| 100 * finfo.code_coverage < @output_threshold}
|
66
|
+
@sort_reverse ? pairs.reverse : pairs
|
67
|
+
end
|
68
|
+
|
69
|
+
def total_coverage
|
70
|
+
lines = 0
|
71
|
+
total = 0.0
|
72
|
+
@files.each do |k,f|
|
73
|
+
total += f.num_lines * f.total_coverage
|
74
|
+
lines += f.num_lines
|
75
|
+
end
|
76
|
+
return 0 if lines == 0
|
77
|
+
total / lines
|
78
|
+
end
|
79
|
+
|
80
|
+
def code_coverage
|
81
|
+
lines = 0
|
82
|
+
total = 0.0
|
83
|
+
@files.each do |k,f|
|
84
|
+
total += f.num_code_lines * f.code_coverage
|
85
|
+
lines += f.num_code_lines
|
86
|
+
end
|
87
|
+
return 0 if lines == 0
|
88
|
+
total / lines
|
89
|
+
end
|
90
|
+
|
91
|
+
def num_code_lines
|
92
|
+
lines = 0
|
93
|
+
@files.each{|k, f| lines += f.num_code_lines }
|
94
|
+
lines
|
95
|
+
end
|
96
|
+
|
97
|
+
def num_lines
|
98
|
+
lines = 0
|
99
|
+
@files.each{|k, f| lines += f.num_lines }
|
100
|
+
lines
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def cross_references_for(filename, lineno)
|
106
|
+
return nil unless @callsite_analyzer
|
107
|
+
@callsite_index ||= build_callsite_index
|
108
|
+
@callsite_index[normalize_filename(filename)][lineno]
|
109
|
+
end
|
110
|
+
|
111
|
+
def reverse_cross_references_for(filename, lineno)
|
112
|
+
return nil unless @callsite_analyzer
|
113
|
+
@callsite_reverse_index ||= build_reverse_callsite_index
|
114
|
+
@callsite_reverse_index[normalize_filename(filename)][lineno]
|
115
|
+
end
|
116
|
+
|
117
|
+
def build_callsite_index
|
118
|
+
index = Hash.new{|h,k| h[k] = {}}
|
119
|
+
@callsite_analyzer.analyzed_classes.each do |classname|
|
120
|
+
@callsite_analyzer.analyzed_methods(classname).each do |methname|
|
121
|
+
defsite = @callsite_analyzer.defsite(classname, methname)
|
122
|
+
index[normalize_filename(defsite.file)][defsite.line] =
|
123
|
+
@callsite_analyzer.callsites(classname, methname)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
index
|
127
|
+
end
|
128
|
+
|
129
|
+
def build_reverse_callsite_index
|
130
|
+
index = Hash.new{|h,k| h[k] = {}}
|
131
|
+
@callsite_analyzer.analyzed_classes.each do |classname|
|
132
|
+
@callsite_analyzer.analyzed_methods(classname).each do |methname|
|
133
|
+
callsites = @callsite_analyzer.callsites(classname, methname)
|
134
|
+
defsite = @callsite_analyzer.defsite(classname, methname)
|
135
|
+
callsites.each_pair do |callsite, count|
|
136
|
+
next unless callsite.file
|
137
|
+
fname = normalize_filename(callsite.file)
|
138
|
+
(index[fname][callsite.line] ||= []) << [classname, methname, defsite, count]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
index
|
143
|
+
end
|
144
|
+
|
145
|
+
class XRefHelper < Struct.new(:file, :line, :klass, :mid, :count) # :nodoc:
|
146
|
+
end
|
147
|
+
|
148
|
+
def _get_defsites(ref_blocks, filename, lineno, linetext, label, &format_call_ref)
|
149
|
+
if @do_cross_references and
|
150
|
+
(rev_xref = reverse_cross_references_for(filename, lineno))
|
151
|
+
refs = rev_xref.map do |classname, methodname, defsite, count|
|
152
|
+
XRefHelper.new(defsite.file, defsite.line, classname, methodname, count)
|
153
|
+
end.sort_by{|r| r.count}.reverse
|
154
|
+
ref_blocks << [refs, label, format_call_ref]
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
def _get_callsites(ref_blocks, filename, lineno, linetext, label, &format_called_ref)
|
159
|
+
if @do_callsites and
|
160
|
+
(refs = cross_references_for(filename, lineno))
|
161
|
+
refs = refs.sort_by{|k,count| count}.map do |ref, count|
|
162
|
+
XRefHelper.new(ref.file, ref.line, ref.calling_class, ref.calling_method, count)
|
163
|
+
end.reverse
|
164
|
+
ref_blocks << [refs, label, format_called_ref]
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Rcov
|
2
|
+
class FailureReport < TextSummary # :nodoc:
|
3
|
+
def execute
|
4
|
+
puts summary
|
5
|
+
coverage = code_coverage * 100
|
6
|
+
if coverage < @failure_threshold
|
7
|
+
puts "You failed to satisfy the coverage theshold of #{@failure_threshold}%"
|
8
|
+
exit(1)
|
9
|
+
end
|
10
|
+
if (coverage - @failure_threshold) > 3
|
11
|
+
puts "Your coverage has significantly increased over your threshold of #{@failure_threshold}. Please increase it."
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Rcov
|
2
|
+
class FullTextReport < BaseFormatter # :nodoc:
|
3
|
+
DEFAULT_OPTS = {:textmode => :coverage}
|
4
|
+
|
5
|
+
def initialize(opts = {})
|
6
|
+
options = DEFAULT_OPTS.clone.update(opts)
|
7
|
+
@textmode = options[:textmode]
|
8
|
+
@color = options[:color]
|
9
|
+
super(options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute
|
13
|
+
each_file_pair_sorted do |filename, fileinfo|
|
14
|
+
puts "=" * 80
|
15
|
+
puts filename
|
16
|
+
puts "=" * 80
|
17
|
+
lines = SCRIPT_LINES__[filename]
|
18
|
+
|
19
|
+
unless lines
|
20
|
+
# try to get the source code from the global code coverage
|
21
|
+
# analyzer
|
22
|
+
re = /#{Regexp.escape(filename)}\z/
|
23
|
+
if $rcov_code_coverage_analyzer and
|
24
|
+
(data = $rcov_code_coverage_analyzer.data_matching(re))
|
25
|
+
lines = data[0]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
(lines || []).each_with_index do |line, i|
|
30
|
+
case @textmode
|
31
|
+
when :counts
|
32
|
+
puts "%-70s| %6d" % [line.chomp[0,70], fileinfo.counts[i]]
|
33
|
+
when :gcc
|
34
|
+
puts "%s:%d:%s" % [filename, i+1, line.chomp] unless fileinfo.coverage[i]
|
35
|
+
when :coverage
|
36
|
+
if @color
|
37
|
+
prefix = fileinfo.coverage[i] ? "\e[32;40m" : "\e[31;40m"
|
38
|
+
puts "#{prefix}%s\e[37;40m" % line.chomp
|
39
|
+
else
|
40
|
+
prefix = fileinfo.coverage[i] ? " " : "!! "
|
41
|
+
puts "#{prefix}#{line}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,244 @@
|
|
1
|
+
module Rcov
|
2
|
+
class HTMLCoverage < BaseFormatter # :nodoc:
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
DEFAULT_OPTS = {:color => false, :fsr => 30, :destdir => "coverage",
|
6
|
+
:callsites => false, :cross_references => false,
|
7
|
+
:charset => nil }
|
8
|
+
|
9
|
+
def initialize(opts = {})
|
10
|
+
options = DEFAULT_OPTS.clone.update(opts)
|
11
|
+
super(options)
|
12
|
+
@dest = options[:destdir]
|
13
|
+
@color = options[:color]
|
14
|
+
@fsr = options[:fsr]
|
15
|
+
@do_callsites = options[:callsites]
|
16
|
+
@do_cross_references = options[:cross_references]
|
17
|
+
@span_class_index = 0
|
18
|
+
@charset = options[:charset]
|
19
|
+
end
|
20
|
+
|
21
|
+
def execute
|
22
|
+
return if @files.empty?
|
23
|
+
FileUtils.mkdir_p @dest
|
24
|
+
css_file = File.expand_path("#{File.dirname(__FILE__)}/../templates/screen.css")
|
25
|
+
FileUtils.cp(css_file, File.join(@dest, "screen.css"))
|
26
|
+
|
27
|
+
create_index(File.join(@dest, "index.html"))
|
28
|
+
|
29
|
+
each_file_pair_sorted do |filename, fileinfo|
|
30
|
+
create_file(File.join(@dest, mangle_filename(filename)), fileinfo)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
class SummaryFileInfo # :nodoc:
|
37
|
+
def initialize(obj)
|
38
|
+
@o = obj
|
39
|
+
end
|
40
|
+
|
41
|
+
def num_lines
|
42
|
+
@o.num_lines
|
43
|
+
end
|
44
|
+
|
45
|
+
def num_code_lines
|
46
|
+
@o.num_code_lines
|
47
|
+
end
|
48
|
+
|
49
|
+
def code_coverage
|
50
|
+
@o.code_coverage
|
51
|
+
end
|
52
|
+
|
53
|
+
def code_coverage_for_report
|
54
|
+
code_coverage * 100
|
55
|
+
end
|
56
|
+
|
57
|
+
def total_coverage
|
58
|
+
@o.total_coverage
|
59
|
+
end
|
60
|
+
|
61
|
+
def total_coverage_for_report
|
62
|
+
total_coverage * 100
|
63
|
+
end
|
64
|
+
|
65
|
+
def name
|
66
|
+
"TOTAL"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def create_index(destname)
|
71
|
+
files = [SummaryFileInfo.new(self)] + each_file_pair_sorted.map{|k,v| v}
|
72
|
+
doc = Rcov::Formatters::HtmlErbTemplate.new('index.html.erb', :title => 'C0 Coverage Information - RCov',
|
73
|
+
:generated_on => Time.now,
|
74
|
+
:rcov => Rcov,
|
75
|
+
:formatter => self,
|
76
|
+
:output_threshold => @output_threshold,
|
77
|
+
:files => files)
|
78
|
+
File.open(destname, "w") { |f| f.puts doc.render }
|
79
|
+
end
|
80
|
+
|
81
|
+
def create_file(destfile, fileinfo)
|
82
|
+
doc = Rcov::Formatters::HtmlErbTemplate.new('detail.html.erb', :title => fileinfo.name,
|
83
|
+
:generated_on => Time.now,
|
84
|
+
:rcov => Rcov,
|
85
|
+
:formatter => self,
|
86
|
+
:output_threshold => @output_threshold,
|
87
|
+
:fileinfo => fileinfo)
|
88
|
+
File.open(destfile, "w") { |f| f.puts doc.render }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class HTMLProfiling < HTMLCoverage # :nodoc:
|
93
|
+
DEFAULT_OPTS = {:destdir => "profiling"}
|
94
|
+
def initialize(opts = {})
|
95
|
+
options = DEFAULT_OPTS.clone.update(opts)
|
96
|
+
super(options)
|
97
|
+
@max_cache = {}
|
98
|
+
@median_cache = {}
|
99
|
+
end
|
100
|
+
|
101
|
+
def default_title
|
102
|
+
"Bogo-profile information"
|
103
|
+
end
|
104
|
+
|
105
|
+
def default_color
|
106
|
+
if @color
|
107
|
+
"rgb(179,205,255)"
|
108
|
+
else
|
109
|
+
"rgb(255, 255, 255)"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def output_color_table?
|
114
|
+
false
|
115
|
+
end
|
116
|
+
|
117
|
+
def span_class(sourceinfo, marked, count)
|
118
|
+
full_scale_range = @fsr # dB
|
119
|
+
nz_count = sourceinfo.counts.select{|x| x && x != 0}
|
120
|
+
nz_count << 1 # avoid div by 0
|
121
|
+
max = @max_cache[sourceinfo] ||= nz_count.max
|
122
|
+
#avg = @median_cache[sourceinfo] ||= 1.0 *
|
123
|
+
# nz_count.inject{|a,b| a+b} / nz_count.size
|
124
|
+
median = @median_cache[sourceinfo] ||= 1.0 * nz_count.sort[nz_count.size/2]
|
125
|
+
max ||= 2
|
126
|
+
max = 2 if max == 1
|
127
|
+
if marked == true
|
128
|
+
count = 1 if !count || count == 0
|
129
|
+
idx = 50 + 1.0 * (500/full_scale_range) * Math.log(count/median) / Math.log(10)
|
130
|
+
idx = idx.to_i
|
131
|
+
idx = 0 if idx < 0
|
132
|
+
idx = 100 if idx > 100
|
133
|
+
"run#{idx}"
|
134
|
+
else
|
135
|
+
nil
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class RubyAnnotation < BaseFormatter # :nodoc:
|
141
|
+
DEFAULT_OPTS = { :destdir => "coverage" }
|
142
|
+
def initialize(opts = {})
|
143
|
+
options = DEFAULT_OPTS.clone.update(opts)
|
144
|
+
super(options)
|
145
|
+
@dest = options[:destdir]
|
146
|
+
@do_callsites = true
|
147
|
+
@do_cross_references = true
|
148
|
+
|
149
|
+
@mangle_filename = Hash.new{ |h,base|
|
150
|
+
h[base] = Pathname.new(base).cleanpath.to_s.gsub(%r{^\w:[/\\]}, "").gsub(/\./, "_").gsub(/[\\\/]/, "-") + ".rb"
|
151
|
+
}
|
152
|
+
end
|
153
|
+
|
154
|
+
def execute
|
155
|
+
return if @files.empty?
|
156
|
+
FileUtils.mkdir_p @dest
|
157
|
+
each_file_pair_sorted do |filename, fileinfo|
|
158
|
+
create_file(File.join(@dest, mangle_filename(filename)), fileinfo)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
private
|
163
|
+
|
164
|
+
def format_lines(file)
|
165
|
+
result = ""
|
166
|
+
format_line = "%#{file.num_lines.to_s.size}d"
|
167
|
+
file.num_lines.times do |i|
|
168
|
+
line = file.lines[i].chomp
|
169
|
+
marked = file.coverage[i]
|
170
|
+
count = file.counts[i]
|
171
|
+
result << create_cross_refs(file.name, i+1, line, marked) + "\n"
|
172
|
+
end
|
173
|
+
result
|
174
|
+
end
|
175
|
+
|
176
|
+
def create_cross_refs(filename, lineno, linetext, marked)
|
177
|
+
return linetext unless @callsite_analyzer && @do_callsites
|
178
|
+
ref_blocks = []
|
179
|
+
_get_defsites(ref_blocks, filename, lineno, linetext, ">>") do |ref|
|
180
|
+
if ref.file
|
181
|
+
ref.file.sub!(%r!^./!, '')
|
182
|
+
where = "at #{mangle_filename(ref.file)}:#{ref.line}"
|
183
|
+
else
|
184
|
+
where = "(C extension/core)"
|
185
|
+
end
|
186
|
+
"#{ref.klass}##{ref.mid} " + where + ""
|
187
|
+
end
|
188
|
+
_get_callsites(ref_blocks, filename, lineno, linetext, "<<") do |ref| # "
|
189
|
+
ref.file.sub!(%r!^./!, '')
|
190
|
+
"#{mangle_filename(ref.file||'C code')}:#{ref.line} " + "in #{ref.klass}##{ref.mid}"
|
191
|
+
end
|
192
|
+
|
193
|
+
create_cross_reference_block(linetext, ref_blocks, marked)
|
194
|
+
end
|
195
|
+
|
196
|
+
def create_cross_reference_block(linetext, ref_blocks, marked)
|
197
|
+
codelen = 75
|
198
|
+
if ref_blocks.empty?
|
199
|
+
if marked
|
200
|
+
return "%-#{codelen}s #o" % linetext
|
201
|
+
else
|
202
|
+
return linetext
|
203
|
+
end
|
204
|
+
end
|
205
|
+
ret = ""
|
206
|
+
@cross_ref_idx ||= 0
|
207
|
+
@known_files ||= sorted_file_pairs.map{|fname, finfo| normalize_filename(fname)}
|
208
|
+
ret << "%-#{codelen}s # " % linetext
|
209
|
+
ref_blocks.each do |refs, toplabel, label_proc|
|
210
|
+
unless !toplabel || toplabel.empty?
|
211
|
+
ret << toplabel << " "
|
212
|
+
end
|
213
|
+
refs.each do |dst|
|
214
|
+
dstfile = normalize_filename(dst.file) if dst.file
|
215
|
+
dstline = dst.line
|
216
|
+
label = label_proc.call(dst)
|
217
|
+
if dst.file && @known_files.include?(dstfile)
|
218
|
+
ret << "[[" << label << "]], "
|
219
|
+
else
|
220
|
+
ret << label << ", "
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
ret
|
225
|
+
end
|
226
|
+
|
227
|
+
def create_file(destfile, fileinfo)
|
228
|
+
#body = format_lines(fileinfo)
|
229
|
+
#File.open(destfile, "w") do |f|
|
230
|
+
#f.puts body
|
231
|
+
#f.puts footer(fileinfo)
|
232
|
+
#end
|
233
|
+
end
|
234
|
+
|
235
|
+
def footer(fileinfo)
|
236
|
+
s = "# Total lines : %d\n" % fileinfo.num_lines
|
237
|
+
s << "# Lines of code : %d\n" % fileinfo.num_code_lines
|
238
|
+
s << "# Total coverage : %3.1f%%\n" % [ fileinfo.total_coverage*100 ]
|
239
|
+
s << "# Code coverage : %3.1f%%\n\n" % [ fileinfo.code_coverage*100 ]
|
240
|
+
# prevents false positives on Emacs
|
241
|
+
s << "# Local " "Variables:\n" "# mode: " "rcov-xref\n" "# End:\n"
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|