rcov 0.7.0.1-mswin32 → 0.8.0.0-mswin32

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 CHANGED
@@ -2,7 +2,7 @@
2
2
  Source code, additional information, screenshots... available at
3
3
  http://eigenclass.org/hiki.rb?rcov
4
4
  Release information:
5
- http://eigenclass.org/hiki.rb?rcov+0.7.0
5
+ http://eigenclass.org/hiki.rb?rcov+0.8.0
6
6
 
7
7
  If you're on win32, you can also find a pre-built rcovrt.so (which makes
8
8
  code coverage analysis >100 times faster) in the above-mentioned pages.
data/CHANGES CHANGED
@@ -1,6 +1,29 @@
1
1
 
2
2
  User-visible changes.
3
3
 
4
+ Since 0.7.0 (2006-08-04)
5
+ ========================
6
+ Features
7
+ --------
8
+ * --annotate mode, which dumps annotated source code which can be used to
9
+ follow the control flow (very useful when reading third-party code)
10
+ * --gcc option to display uncovered lines in GCC error format
11
+ * superior Emacs support: running rcov, jumping to uncovered code, navigate
12
+ through cross-referenced annotated code
13
+ * --[no-]validator-links
14
+
15
+ Bugfixes
16
+ --------
17
+ * differential code coverage reports work with filenames containing special
18
+ characters
19
+ * fixed recent segfaults happening with rspec
20
+ * more care name mangling
21
+
22
+ Minor enhancements
23
+ ------------------
24
+ * relevant summary values are identified using separate CSS classes
25
+ (microformat-style)
26
+
4
27
  Since 0.6.0 (2006-06-12)
5
28
  ========================
6
29
  Features
@@ -0,0 +1,64 @@
1
+
2
+ <tt>rcov.el</tt> allows you to use rcov from Emacs conveniently.
3
+ * Run unit tests and jump to uncovered code by <tt>C-x `</tt>.
4
+ * Run unit tests and save the current coverage status.
5
+ * Run unit tests and jump to uncovered code introduced since the last run.
6
+ * View cross-reference annotated code.
7
+
8
+ == Installation
9
+
10
+ Copy <tt>rcov.el</tt> to the appropriate directory, which is in load-path.
11
+ Then require it.
12
+ (require 'rcov)
13
+
14
+
15
+ == Usage
16
+
17
+ There are some commands to run rcov in Emacs.
18
+ All of them displays +rcov+ window, whose major-mode is compilation-mode.
19
+ Therefore you can jump to uncovered code by <tt>C-x `</tt>.
20
+
21
+ +rcov-command-line+, +rcovsave-command-line+, and +rcovdiff-command-line+ define
22
+ command line to run rcov.
23
+ If you do not use +rcov+ from Rake, you must modify them.
24
+
25
+ === Finding uncovered code
26
+
27
+ Type the following while editing your program:
28
+ M-x rcov
29
+
30
+ === Setting the reference point
31
+
32
+ +rcov+'s <tt>--text-coverage-diff</tt> mode compares the current coverage status against
33
+ the saved one. It therefore needs that information to be recorded
34
+ before you write new code (typically right after you perform a commit) in
35
+ order to have something to compare against.
36
+
37
+ You can save the current status with the <tt>--save</tt> option.
38
+
39
+ Type the following to save the current status in Emacs:
40
+ M-x rcovsave
41
+ If you do not use +rcov+ from Rake, you must modify +rcovsave-command-line+ variable.
42
+
43
+ === Finding new uncovered code
44
+
45
+ Type the following to save the current status in Emacs:
46
+ M-x rcovdiff
47
+
48
+ === Viewing cross-reference annotated code
49
+
50
+ If you read cross-reference annotated code, issue
51
+ rake rcov RCOVOPTS='-a'
52
+ at the beginning.
53
+ This command creates +coverage+ directory and many *.rb files in it.
54
+ Filenames of these Ruby scripts are converted from original path.
55
+ You can browse them by normally <tt>C-x C-f</tt>.
56
+ You can think of <tt>-a</tt> option as <tt>--xrefs</tt> option and output format is Ruby script.
57
+
58
+ After find-file-ed annotated script, the major-mode is rcov-xref-mode,
59
+ which is derived from ruby-mode and specializes navigation.
60
+
61
+ <tt>Tab</tt> and <tt>M-Tab</tt> goes forward/backward links.
62
+ <tt>Ret</tt> follows selected link.
63
+
64
+ This feature is useful to read third-party code or to follow control flow.
data/Rakefile CHANGED
@@ -60,11 +60,16 @@ Rake::TestTask.new(:test_pure_ruby) do |t|
60
60
  t.verbose = true
61
61
  end
62
62
 
63
- desc "Run the unit tests, both rcovrt and pure-Ruby modes"
64
- task :test => [:test_rcovrt, :test_pure_ruby]
63
+ desc "Run the unit tests"
64
+ task :test => [:test_rcovrt]
65
65
 
66
66
  task :default => :test
67
67
 
68
+ desc "install by setup.rb"
69
+ task :install do
70
+ sh "sudo ruby setup.rb install"
71
+ end
72
+
68
73
  desc "Generate rdoc documentation for the rcov library"
69
74
  Rake::RDocTask.new("rdoc") { |rdoc|
70
75
  rdoc.rdoc_dir = 'doc'
@@ -82,7 +87,7 @@ Rake::RDocTask.new("rdoc") { |rdoc|
82
87
 
83
88
  require 'rcov/version'
84
89
 
85
- PKG_REVISION = ".1"
90
+ PKG_REVISION = ".0"
86
91
  PKG_FILES = FileList[
87
92
  "bin/rcov",
88
93
  "lib/**/*.rb",
@@ -90,7 +95,7 @@ PKG_FILES = FileList[
90
95
  "ext/rcovrt/*.c",
91
96
  "ext/rcovrt/*.h",
92
97
  "LEGAL", "LICENSE", "Rakefile", "Rantfile", "README.*", "THANKS", "test/*.rb",
93
- "mingw-rbconfig.rb", "rcov.vim",
98
+ "mingw-rbconfig.rb", "rcov.vim", "rcov.el",
94
99
  "setup.rb", "BLURB", "CHANGES"
95
100
  ]
96
101
 
data/THANKS CHANGED
@@ -44,9 +44,25 @@ Tim Shadel:
44
44
 
45
45
  Thomas Leitner:
46
46
  * reported that the SCRIPT_LINES__ workaround did not always work
47
+ * fixed the bug which broke differential reports for filenames with
48
+ special characters
47
49
 
48
50
  Assaph Mehr:
49
51
  * beta-tested 0.7.0 and found a bug in --aggregate (missing files)
50
52
 
51
53
  Ryan Kinderman:
52
54
  * suggested that -Ipath be passed to ruby instead of rcov in RcovTasks
55
+
56
+ Jan Svitok:
57
+ * reported typo in rcovtask.rb's RDoc
58
+
59
+ rubikitch:
60
+ * implemented --annotate mode
61
+ * implemented --gcc option
62
+ * superior emacs support
63
+ * testing, refactoring...
64
+ * many other things, see darcs changes
65
+
66
+
67
+ Zed A. Shaw:
68
+ * reported and fixed segfault triggered by rspec
data/bin/rcov CHANGED
@@ -1,4 +1,4 @@
1
- #! /home/batsman/usr/bin/ruby
1
+ #!/usr/bin/env ruby
2
2
  # rcov Copyright (c) 2004-2006 Mauricio Fernandez <mfp@acm.org>
3
3
  #
4
4
  # rcov originally based on
@@ -57,6 +57,8 @@ options.coverage_diff_save = false
57
57
  options.diff_cmd = "diff"
58
58
  options.report_cov_bug_for = nil
59
59
  options.aggregate_file = nil
60
+ options.gcc_output = false
61
+ options.show_validator_links = true
60
62
 
61
63
  EXTRA_HELP = <<-EOF
62
64
 
@@ -152,6 +154,15 @@ EOF
152
154
  "Color scale range for profiling info (dB).") do |val|
153
155
  options.range = val
154
156
  end
157
+ opts.on("-a", "--annotate",
158
+ "Generate annotated source code.") do
159
+ options.html = false
160
+ options.textmode = :annotate
161
+ options.crossrefs = true
162
+ options.callsites = true
163
+ options.skip = [ %r!/test/unit/! ]
164
+ end
165
+
155
166
  opts.on("-T", "--text-report", "Dump detailed plain-text report to stdout.",
156
167
  "(filename, LoC, total lines, coverage)") do
157
168
  options.textmode = :report
@@ -166,6 +177,9 @@ EOF
166
177
  "ANSI color sequences unless -n.") do
167
178
  options.textmode = :coverage
168
179
  end
180
+ opts.on("--gcc", "Dump uncovered line in GCC error format.") do
181
+ options.gcc_output = true
182
+ end
169
183
  opts.on("--aggregate FILE", "Aggregate data from previous runs",
170
184
  "in FILE. Overwrites FILE with the",
171
185
  "merged data. FILE is created if",
@@ -216,6 +230,10 @@ EOF
216
230
  end
217
231
  options.output_threshold = threshold
218
232
  end
233
+ opts.on("--[no-]validator-links", "Add link to W3C's validation services.",
234
+ "(default: true)") do |show_validator_links|
235
+ options.show_validator_links = show_validator_links
236
+ end
219
237
  opts.on("--only-uncovered", "Same as --threshold 100") do
220
238
  options.output_threshold = 100
221
239
  end
@@ -296,6 +314,7 @@ options.loadpaths.reverse_each{|x| $:.unshift x}
296
314
  require 'rcov'
297
315
 
298
316
  options.callsites = true if options.report_cov_bug_for
317
+ options.textmode = :gcc if !options.textmode and options.gcc_output
299
318
 
300
319
  def rcov_load_aggregate_data(file)
301
320
  require 'zlib'
@@ -344,7 +363,9 @@ make_formatter = lambda do |klass|
344
363
  :callsites => options.callsites,
345
364
  :cross_references => options.crossrefs,
346
365
  :diff_cmd => options.diff_cmd,
347
- :comments_run_by_default => options.comments_run_by_default
366
+ :comments_run_by_default => options.comments_run_by_default,
367
+ :gcc_output => options.gcc_output,
368
+ :validator_links => options.show_validator_links
348
369
  )
349
370
  end
350
371
 
@@ -357,6 +378,8 @@ if options.html
357
378
  end
358
379
  textual_formatters = {:counts => Rcov::FullTextReport,
359
380
  :coverage => Rcov::FullTextReport,
381
+ :gcc => Rcov::FullTextReport,
382
+ :annotate => Rcov::RubyAnnotation,
360
383
  :summary => Rcov::TextSummary, :report => Rcov::TextReport,
361
384
  :coverage_diff => Rcov::TextCoverageDiff}
362
385
 
@@ -1258,3 +1281,7 @@ if __FILE__ == $0
1258
1281
 
1259
1282
  end
1260
1283
  # vi: set sw=4:
1284
+ # Here is Emacs setting. DO NOT REMOVE!
1285
+ # Local Variables:
1286
+ # ruby-indent-level: 4
1287
+ # End:
@@ -4,6 +4,7 @@
4
4
  #include <node.h>
5
5
  #include <st.h>
6
6
  #include <stdlib.h>
7
+ #include <assert.h>
7
8
 
8
9
  #define COVERAGE_DEBUG_EVENTS 0
9
10
 
@@ -34,12 +35,15 @@ static char *cached_file = 0;
34
35
  * */
35
36
 
36
37
  static struct cov_array *
37
- coverage_increase_counter_uncached(char *sourcefile, int sourceline,
38
+ coverage_increase_counter_uncached(char *sourcefile, unsigned int sourceline,
38
39
  char mark_only)
39
40
  {
40
- struct cov_array *carray;
41
-
42
- if(!st_lookup(coverinfo, (st_data_t)sourcefile, (st_data_t*)&carray)) {
41
+ struct cov_array *carray = NULL;
42
+
43
+ if(sourcefile == NULL) {
44
+ /* "can't happen", just ignore and avoid segfault */
45
+ return NULL;
46
+ } else if(!st_lookup(coverinfo, (st_data_t)sourcefile, (st_data_t*)&carray)) {
43
47
  VALUE arr;
44
48
 
45
49
  arr = rb_hash_aref(oSCRIPT_LINES__, rb_str_new2(sourcefile));
@@ -51,7 +55,11 @@ coverage_increase_counter_uncached(char *sourcefile, int sourceline,
51
55
  carray->len = RARRAY(arr)->len;
52
56
  st_insert(coverinfo, (st_data_t)strdup(sourcefile),
53
57
  (st_data_t) carray);
58
+ } else {
59
+ /* recovered carray, sanity check */
60
+ assert(carray && "failed to create valid carray");
54
61
  }
62
+
55
63
  if(mark_only) {
56
64
  if(!carray->ptr[sourceline])
57
65
  carray->ptr[sourceline] = 1;
@@ -74,7 +82,9 @@ coverage_mark_caller()
74
82
  }
75
83
  for (; frame && (n = frame->node); frame = frame->prev) {
76
84
  if (frame->prev && frame->prev->last_func) {
77
- if (frame->prev->node == n) continue;
85
+ if (frame->prev->node == n) {
86
+ if (frame->prev->last_func == frame->last_func) continue;
87
+ }
78
88
  coverage_increase_counter_uncached(n->nd_file, nd_line(n) - 1, 1);
79
89
  }
80
90
  else {
@@ -42,7 +42,7 @@ module Rcov
42
42
  #
43
43
  class RcovTask < Rake::TaskLib
44
44
 
45
- # Name of test task. (default is :test)
45
+ # Name of test task. (default is :rcov)
46
46
  attr_accessor :name
47
47
 
48
48
  # List of directories to added to $LOAD_PATH before running the
@@ -1,6 +1,7 @@
1
1
  # rcov Copyright (c) 2004-2006 Mauricio Fernandez <mfp@acm.org>
2
2
  # See LEGAL and LICENSE for additional licensing information.
3
3
 
4
+ require 'pathname'
4
5
  module Rcov
5
6
 
6
7
  class Formatter # :nodoc:
@@ -30,6 +31,10 @@ class Formatter # :nodoc:
30
31
  @callsite_analyzer = options[:callsite_analyzer]
31
32
  @comments_run_by_default = options[:comments_run_by_default]
32
33
  @callsite_index = nil
34
+
35
+ @mangle_filename = Hash.new{|h,base|
36
+ h[base] = Pathname(base).cleanpath.to_s.gsub(%r{^\w:[/\\]}, "").gsub(/\./, "_").gsub(/[\\\/]/, "-") + ".html"
37
+ }
33
38
  end
34
39
 
35
40
  def add_file(filename, lines, coverage, counts)
@@ -53,7 +58,7 @@ class Formatter # :nodoc:
53
58
  end
54
59
 
55
60
  def mangle_filename(base)
56
- base.gsub(%r{^\w:[/\\]}, "").gsub(/\./, "_").gsub(/[\\\/]/, "-") + ".html"
61
+ @mangle_filename[base]
57
62
  end
58
63
 
59
64
  def each_file_pair_sorted(&b)
@@ -142,6 +147,29 @@ class Formatter # :nodoc:
142
147
  end
143
148
  index
144
149
  end
150
+
151
+ class XRefHelper < Struct.new(:file, :line, :klass, :mid, :count) # :nodoc:
152
+ end
153
+
154
+ def _get_defsites(ref_blocks, filename, lineno, linetext, label, &format_call_ref)
155
+ if @do_cross_references and
156
+ (rev_xref = reverse_cross_references_for(filename, lineno))
157
+ refs = rev_xref.map do |classname, methodname, defsite, count|
158
+ XRefHelper.new(defsite.file, defsite.line, classname, methodname, count)
159
+ end.sort_by{|r| r.count}.reverse
160
+ ref_blocks << [refs, label, format_call_ref]
161
+ end
162
+ end
163
+
164
+ def _get_callsites(ref_blocks, filename, lineno, linetext, label, &format_called_ref)
165
+ if @do_callsites and
166
+ (refs = cross_references_for(filename, lineno))
167
+ refs = refs.sort_by{|k,count| count}.map do |ref, count|
168
+ XRefHelper.new(ref.file, ref.line, ref.calling_class, ref.calling_method, count)
169
+ end.reverse
170
+ ref_blocks << [refs, label, format_called_ref]
171
+ end
172
+ end
145
173
  end
146
174
 
147
175
  class TextSummary < Formatter # :nodoc:
@@ -202,6 +230,8 @@ class FullTextReport < Formatter # :nodoc:
202
230
  case @textmode
203
231
  when :counts
204
232
  puts "%-70s| %6d" % [line.chomp[0,70], fileinfo.counts[i]]
233
+ when :gcc
234
+ puts "%s:%d:%s" % [filename, i+1, line.chomp] unless fileinfo.coverage[i]
205
235
  when :coverage
206
236
  if @color
207
237
  prefix = fileinfo.coverage[i] ? "\e[32;40m" : "\e[31;40m"
@@ -236,7 +266,8 @@ class TextCoverageDiff < Formatter # :nodoc:
236
266
  @mode = options[:coverage_diff_mode]
237
267
  @state_file = options[:coverage_diff_file]
238
268
  @diff_cmd = options[:diff_cmd]
239
- super(options)
269
+ @gcc_output = options[:gcc_output]
270
+ super(options)
240
271
  end
241
272
 
242
273
  def execute
@@ -264,7 +295,7 @@ class TextCoverageDiff < Formatter # :nodoc:
264
295
  $stderr.puts <<-EOF
265
296
  Couldn't save coverage data to #{@state_file}.
266
297
  EOF
267
- end
298
+ end # '
268
299
 
269
300
  require 'tempfile'
270
301
  def compare_state
@@ -275,7 +306,7 @@ EOF
275
306
  $stderr.puts <<-EOF
276
307
  Couldn't load coverage data from #{@state_file}.
277
308
  EOF
278
- return
309
+ return # '
279
310
  end
280
311
  if !(Array === format) or
281
312
  FORMAT_VERSION[0] != format[0] || FORMAT_VERSION[1] < format[1]
@@ -284,7 +315,7 @@ Couldn't load coverage data from #{@state_file}.
284
315
  The file is saved in the format #{format.inspect[0..20]}.
285
316
  This rcov executable understands #{FORMAT_VERSION.inspect}.
286
317
  EOF
287
- return
318
+ return # '
288
319
  end
289
320
  each_file_pair_sorted do |filename, fileinfo|
290
321
  old_data = Tempfile.new("#{mangle_filename(filename)}-old")
@@ -305,7 +336,7 @@ EOF
305
336
  end
306
337
  new_data.close
307
338
 
308
- diff = `#{@diff_cmd} -u #{old_data.path} #{new_data.path}`
339
+ diff = `#{@diff_cmd} -u "#{old_data.path}" "#{new_data.path}"`
309
340
  new_uncovered_hunks = process_unified_diff(filename, diff)
310
341
  old_data.close!
311
342
  new_data.close!
@@ -322,13 +353,21 @@ EOF
322
353
 
323
354
  EOF
324
355
  hunks.each do |offset, lines|
325
- puts "### #{filename}:#{offset}"
326
- if @color
356
+ if @gcc_output
357
+ lines.each_with_index do |line,i|
358
+ lineno = offset + i
359
+ flag = (/^!! / !~ line) ? "-" : ":"
360
+ prefix = "#{filename}#{flag}#{lineno}#{flag}"
361
+ puts "#{prefix}#{line[3..-1]}"
362
+ end
363
+ elsif @color
364
+ puts "### #{filename}:#{offset}"
327
365
  lines.each do |line|
328
366
  prefix = (/^!! / !~ line) ? "\e[32;40m" : "\e[31;40m"
329
367
  puts "#{prefix}#{line[3..-1].chomp}\e[37;40m"
330
368
  end
331
369
  else
370
+ puts "### #{filename}:#{offset}"
332
371
  puts lines
333
372
  end
334
373
  end
@@ -561,7 +600,9 @@ table.report td.text {
561
600
  border: #d0d0d0 1px solid;
562
601
  }
563
602
 
564
- table.report td.value {
603
+ table.report td.value,
604
+ table.report td.lines_total,
605
+ table.report td.lines_code {
565
606
  text-align: right;
566
607
  border: #d0d0d0 1px solid;
567
608
  }
@@ -574,7 +615,9 @@ table.report tr.dark {
574
615
  EOS
575
616
 
576
617
  DEFAULT_OPTS = {:color => false, :fsr => 30, :destdir => "coverage",
577
- :callsites => false, :cross_references => false}
618
+ :callsites => false, :cross_references => false,
619
+ :validator_links => true
620
+ }
578
621
  def initialize(opts = {})
579
622
  options = DEFAULT_OPTS.clone.update(opts)
580
623
  super(options)
@@ -584,6 +627,7 @@ EOS
584
627
  @do_callsites = options[:callsites]
585
628
  @do_cross_references = options[:cross_references]
586
629
  @span_class_index = 0
630
+ @show_validator_links = options[:validator_links]
587
631
  end
588
632
 
589
633
  def execute
@@ -647,16 +691,18 @@ EOS
647
691
  a_(:href => mangle_filename(f.name)){ t_ { f.name } }
648
692
  end
649
693
  }
650
- [f.num_lines, f.num_code_lines].each do |value|
651
- td_(:class => "value") { tt_{ value } }
694
+ [[f.num_lines, "lines_total"],
695
+ [f.num_code_lines, "lines_code"]].each do |value, css_class|
696
+ td_(:class => css_class) { tt_{ value } }
652
697
  end
653
- [f.total_coverage, f.code_coverage].each do |value|
698
+ [[f.total_coverage, "coverage_total"],
699
+ [f.code_coverage, "coverage_code"]].each do |value, css_class|
654
700
  value *= 100
655
701
  td_ {
656
702
  table_(:cellpadding => 0, :cellspacing => 0, :align => "right") {
657
703
  tr_ {
658
704
  td_ {
659
- tt_ { "%3.1f%%" % value }
705
+ tt_(:class => css_class) { "%3.1f%%" % value }
660
706
  x_ "&nbsp;"
661
707
  }
662
708
  ivalue = value.round
@@ -712,17 +758,20 @@ EOS
712
758
  x_{ format_overview(*files) }
713
759
  hr_
714
760
  x_{ blurb }
715
- p_ {
716
- a_(:href => "http://validator.w3.org/check/referer") {
717
- img_(:src => "http://www.w3.org/Icons/valid-xhtml11",
718
- :alt => "Valid XHTML 1.1!", :height => 31, :width => 88)
719
- }
720
- a_(:href => "http://jigsaw.w3.org/css-validator/check/referer") {
721
- img_(:style => "border:0;width:88px;height:31px",
722
- :src => "http://jigsaw.w3.org/css-validator/images/vcss",
723
- :alt => "Valid CSS!")
761
+
762
+ if @show_validator_links
763
+ p_ {
764
+ a_(:href => "http://validator.w3.org/check/referer") {
765
+ img_(:src => "http://www.w3.org/Icons/valid-xhtml11",
766
+ :alt => "Valid XHTML 1.1!", :height => 31, :width => 88)
767
+ }
768
+ a_(:href => "http://jigsaw.w3.org/css-validator/check/referer") {
769
+ img_(:style => "border:0;width:88px;height:31px",
770
+ :src => "http://jigsaw.w3.org/css-validator/images/vcss",
771
+ :alt => "Valid CSS!")
772
+ }
724
773
  }
725
- }
774
+ end
726
775
  }
727
776
  } }
728
777
  lines = output.pretty.to_a
@@ -760,41 +809,23 @@ EOS
760
809
  "<pre>#{result}</pre>"
761
810
  end
762
811
 
763
- class XRefHelper < Struct.new(:file, :line, :klass, :mid, :count) # :nodoc:
764
- end
765
-
766
812
  def create_cross_refs(filename, lineno, linetext)
767
813
  return linetext unless @callsite_analyzer && @do_callsites
768
- ret = ""
769
814
  ref_blocks = []
770
- if @do_cross_references and
771
- (rev_xref = reverse_cross_references_for(filename, lineno))
772
- refs = rev_xref.map do |classname, methodname, defsite, count|
773
- XRefHelper.new(defsite.file, defsite.line, classname, methodname, count)
774
- end.sort_by{|r| r.count}.reverse
775
- format_call_ref = lambda do |ref|
776
- if ref.file
777
- where = "at #{normalize_filename(ref.file)}:#{ref.line}"
778
- else
779
- where = "(C extension/core)"
780
- end
781
- CGI.escapeHTML("%7d %s" %
782
- [ref.count, "#{ref.klass}##{ref.mid} " + where])
815
+ _get_defsites(ref_blocks, filename, lineno, "Calls", linetext) do |ref|
816
+ if ref.file
817
+ where = "at #{normalize_filename(ref.file)}:#{ref.line}"
818
+ else
819
+ where = "(C extension/core)"
783
820
  end
784
- ref_blocks << [refs, "Calls", format_call_ref]
821
+ CGI.escapeHTML("%7d %s" %
822
+ [ref.count, "#{ref.klass}##{ref.mid} " + where])
785
823
  end
786
- if @do_callsites and
787
- (refs = cross_references_for(filename, lineno))
788
- refs = refs.sort_by{|k,count| count}.map do |ref, count|
789
- XRefHelper.new(ref.file, ref.line, ref.calling_class, ref.calling_method, count)
790
- end.reverse
791
- format_called_ref = lambda do |ref|
792
- r = "%7d %s" % [ref.count,
793
- "#{normalize_filename(ref.file||'C code')}:#{ref.line} " +
824
+ _get_callsites(ref_blocks, filename, lineno, "Called by", linetext) do |ref|
825
+ r = "%7d %s" % [ref.count,
826
+ "#{normalize_filename(ref.file||'C code')}:#{ref.line} " +
794
827
  "in '#{ref.klass}##{ref.mid}'"]
795
- CGI.escapeHTML(r)
796
- end
797
- ref_blocks << [refs, "Called by", format_called_ref]
828
+ CGI.escapeHTML(r)
798
829
  end
799
830
 
800
831
  create_cross_reference_block(linetext, ref_blocks)
@@ -874,17 +905,20 @@ EOS
874
905
  x_{ body }
875
906
  hr_
876
907
  x_ { blurb }
877
- p_ {
878
- a_(:href => "http://validator.w3.org/check/referer") {
879
- img_(:src => "http://www.w3.org/Icons/valid-xhtml10",
880
- :alt => "Valid XHTML 1.0!", :height => 31, :width => 88)
881
- }
882
- a_(:href => "http://jigsaw.w3.org/css-validator/check/referer") {
883
- img_(:style => "border:0;width:88px;height:31px",
884
- :src => "http://jigsaw.w3.org/css-validator/images/vcss",
885
- :alt => "Valid CSS!")
908
+
909
+ if @show_validator_links
910
+ p_ {
911
+ a_(:href => "http://validator.w3.org/check/referer") {
912
+ img_(:src => "http://www.w3.org/Icons/valid-xhtml10",
913
+ :alt => "Valid XHTML 1.0!", :height => 31, :width => 88)
914
+ }
915
+ a_(:href => "http://jigsaw.w3.org/css-validator/check/referer") {
916
+ img_(:style => "border:0;width:88px;height:31px",
917
+ :src => "http://jigsaw.w3.org/css-validator/images/vcss",
918
+ :alt => "Valid CSS!")
919
+ }
886
920
  }
887
- }
921
+ end
888
922
  }
889
923
  } }
890
924
  # .pretty needed to make sure DOCTYPE is in a separate line
@@ -1006,6 +1040,119 @@ class HTMLProfiling < HTMLCoverage # :nodoc:
1006
1040
  end
1007
1041
  end
1008
1042
 
1043
+ class RubyAnnotation < Formatter # :nodoc:
1044
+ DEFAULT_OPTS = { :destdir => "coverage" }
1045
+ def initialize(opts = {})
1046
+ options = DEFAULT_OPTS.clone.update(opts)
1047
+ super(options)
1048
+ @dest = options[:destdir]
1049
+ @do_callsites = true
1050
+ @do_cross_references = true
1051
+
1052
+ @mangle_filename = Hash.new{|h,base|
1053
+ h[base] = Pathname(base).cleanpath.to_s.gsub(%r{^\w:[/\\]}, "").gsub(/\./, "_").gsub(/[\\\/]/, "-") + ".rb"
1054
+ }
1055
+ end
1056
+
1057
+ def execute
1058
+ return if @files.empty?
1059
+ FileUtils.mkdir_p @dest
1060
+ each_file_pair_sorted do |filename, fileinfo|
1061
+ create_file(File.join(@dest, mangle_filename(filename)), fileinfo)
1062
+ end
1063
+ end
1064
+
1065
+ private
1066
+
1067
+ def format_lines(file)
1068
+ result = ""
1069
+ format_line = "%#{file.num_lines.to_s.size}d"
1070
+ file.num_lines.times do |i|
1071
+ line = file.lines[i].chomp
1072
+ marked = file.coverage[i]
1073
+ count = file.counts[i]
1074
+ result << create_cross_refs(file.name, i+1, line, marked) + "\n"
1075
+ end
1076
+ result
1077
+ end
1078
+
1079
+ def create_cross_refs(filename, lineno, linetext, marked)
1080
+ return linetext unless @callsite_analyzer && @do_callsites
1081
+ ref_blocks = []
1082
+ _get_defsites(ref_blocks, filename, lineno, linetext, ">>") do |ref|
1083
+ ref.file.sub!(%r!^./!, '')
1084
+ if ref.file
1085
+ where = "at #{mangle_filename(ref.file)}:#{ref.line}"
1086
+ else
1087
+ where = "(C extension/core)"
1088
+ end
1089
+ "#{ref.klass}##{ref.mid} " + where + ""
1090
+ end
1091
+ _get_callsites(ref_blocks, filename, lineno, linetext, "<<") do |ref| # "
1092
+ ref.file.sub!(%r!^./!, '')
1093
+ "#{mangle_filename(ref.file||'C code')}:#{ref.line} " +
1094
+ "in #{ref.klass}##{ref.mid}"
1095
+ end
1096
+
1097
+ create_cross_reference_block(linetext, ref_blocks, marked)
1098
+ end
1099
+
1100
+ def create_cross_reference_block(linetext, ref_blocks, marked)
1101
+ codelen = 75
1102
+ if ref_blocks.empty?
1103
+ if marked
1104
+ return "%-#{codelen}s #o" % linetext
1105
+ else
1106
+ return linetext
1107
+ end
1108
+ end
1109
+ ret = ""
1110
+ @cross_ref_idx ||= 0
1111
+ @known_files ||= sorted_file_pairs.map{|fname, finfo| normalize_filename(fname)}
1112
+ ret << "%-#{codelen}s # " % linetext
1113
+ ref_blocks.each do |refs, toplabel, label_proc|
1114
+ unless !toplabel || toplabel.empty?
1115
+ ret << toplabel << " "
1116
+ end
1117
+ refs.each do |dst|
1118
+ dstfile = normalize_filename(dst.file) if dst.file
1119
+ dstline = dst.line
1120
+ label = label_proc.call(dst)
1121
+ if dst.file && @known_files.include?(dstfile)
1122
+ ret << "[[" << label << "]], "
1123
+ else
1124
+ ret << label << ", "
1125
+ end
1126
+ end
1127
+ end
1128
+
1129
+ ret
1130
+ end
1131
+
1132
+ def create_file(destfile, fileinfo)
1133
+ #$stderr.puts "Generating #{destfile.inspect}"
1134
+ body = format_lines(fileinfo)
1135
+ File.open(destfile, "w") do |f|
1136
+ f.puts body
1137
+ f.puts footer(fileinfo)
1138
+ end
1139
+ end
1140
+
1141
+ def footer(fileinfo)
1142
+ s = "# Total lines : %d\n" % fileinfo.num_lines
1143
+ s << "# Lines of code : %d\n" % fileinfo.num_code_lines
1144
+ s << "# Total coverage : %3.1f%%\n" % [ fileinfo.total_coverage*100 ]
1145
+ s << "# Code coverage : %3.1f%%\n\n" % [ fileinfo.code_coverage*100 ]
1146
+ # prevents false positives on Emacs
1147
+ s << "# Local " "Variables:\n" "# mode: " "rcov-xref\n" "# End:\n"
1148
+ end
1149
+ end
1150
+
1151
+
1009
1152
  end # Rcov
1010
1153
 
1011
1154
  # vi: set sw=4:
1155
+ # Here is Emacs setting. DO NOT REMOVE!
1156
+ # Local Variables:
1157
+ # ruby-indent-level: 4
1158
+ # End:
@@ -4,8 +4,8 @@
4
4
 
5
5
  module Rcov
6
6
 
7
- VERSION = "0.7.0"
8
- RELEASE_DATE = "2006/08/04"
7
+ VERSION = "0.8.0"
8
+ RELEASE_DATE = "2007-02-28"
9
9
  RCOVRT_ABI = [2,0,0]
10
10
  UPSTREAM_URL = "http://eigenclass.org/hiki.rb?rcov"
11
11
 
Binary file
data/rcov.el ADDED
@@ -0,0 +1,131 @@
1
+ ;;; rcov.el -- Ruby Coverage Analysis Tool
2
+
3
+ ;;; Copyright (c) 2006 rubikitch <rubikitch@ruby-lang.org>
4
+ ;;;
5
+ ;;; Use and distribution subject to the terms of the rcov license.
6
+
7
+ (defvar rcov-xref-before-visit-source-hook nil
8
+ "Hook executed before jump.")
9
+ (defvar rcov-xref-after-visit-source-hook nil
10
+ "Hook executed after jump.")
11
+ (defvar rcov-command-line "rake rcov RCOVOPTS='--gcc --no-html'"
12
+ "Rcov command line to find uncovered code.
13
+ It is good to use rcov with Rake because it `cd's appropriate directory.
14
+ `--gcc' option is strongly recommended because `rcov' uses compilation-mode.")
15
+ (defvar rcovsave-command-line "rake rcov RCOVOPTS='--gcc --no-html --save=coverage.info'"
16
+ "Rcov command line to save coverage status. See also `rcov-command-line'.")
17
+ (defvar rcovdiff-command-line "rake rcov RCOVOPTS='-D --gcc --no-html'"
18
+ "Rcov command line to find new uncovered code. See also `rcov-command-line'.")
19
+
20
+ ;;;; rcov-xref-mode
21
+ (define-derived-mode rcov-xref-mode ruby-mode "Rxref"
22
+ "Major mode for annotated Ruby scripts (coverage/*.rb) by rcov."
23
+ (setq truncate-lines t)
24
+ ;; ruby-electric-mode / pabbrev-mode hijacks TAB binding.
25
+ (and ruby-electric-mode (ruby-electric-mode -1))
26
+ (and (boundp 'pabbrev-mode) pabbrev-mode (pabbrev-mode -1))
27
+ (suppress-keymap rcov-xref-mode-map)
28
+ (define-key rcov-xref-mode-map "\C-i" 'rcov-xref-next-tag)
29
+ (define-key rcov-xref-mode-map "\M-\C-i" 'rcov-xref-previous-tag)
30
+ (define-key rcov-xref-mode-map "\C-m" 'rcov-xref-visit-source)
31
+ (set (make-local-variable 'automatic-hscrolling) nil)
32
+ )
33
+
34
+ (defvar rcov-xref-tag-regexp "\\[\\[\\(.*?\\)\\]\\]")
35
+
36
+ (defun rcov-xref-next-tag (n)
37
+ "Go to next LINK."
38
+ (interactive "p")
39
+ (when (looking-at rcov-xref-tag-regexp)
40
+ (goto-char (match-end 0)))
41
+ (when (re-search-forward rcov-xref-tag-regexp nil t n)
42
+ (goto-char (match-beginning 0)))
43
+ (rcov-xref-show-link))
44
+
45
+ (defun rcov-xref-previous-tag (n)
46
+ "Go to previous LINK."
47
+ (interactive "p")
48
+ (re-search-backward rcov-xref-tag-regexp nil t n)
49
+ (rcov-xref-show-link))
50
+
51
+ (defvar rcov-xref-link-tempbuffer " *rcov-link*")
52
+ (defun rcov-xref-show-link ()
53
+ "Follow current LINK."
54
+ (let ((link (match-string 1))
55
+ (eol (point-at-eol)))
56
+ (save-excursion
57
+ (when (and link
58
+ (re-search-backward "# \\(>>\\|<<\\) " (point-at-bol) t))
59
+ (while (re-search-forward rcov-xref-tag-regexp eol t)
60
+ (let ((matched (match-string 1)))
61
+ (when (string= link matched)
62
+ (add-text-properties 0 (length matched) '(face highlight) matched))
63
+ (with-current-buffer (get-buffer-create rcov-xref-link-tempbuffer)
64
+ (insert matched "\n"))))
65
+ (let (message-log-max) ; inhibit *Messages*
66
+ (message "%s" (with-current-buffer rcov-xref-link-tempbuffer
67
+ (substring (buffer-string) 0 -1)))) ; chomp
68
+ (kill-buffer rcov-xref-link-tempbuffer)))))
69
+
70
+
71
+ ;; copied from jw-visit-source
72
+ (defun rcov-xref-extract-file-lines (line)
73
+ "Extract a list of file/line pairs from the given line of text."
74
+ (let*
75
+ ((unix_fn "[^ \t\n\r\"'([<{]+")
76
+ (dos_fn "[a-zA-Z]:[^ \t\n\r\"'([<{]+")
77
+ (flre (concat "\\(" unix_fn "\\|" dos_fn "\\):\\([0-9]+\\)"))
78
+ (start nil)
79
+ (result nil))
80
+ (while (string-match flre line start)
81
+ (setq start (match-end 0))
82
+ (setq result
83
+ (cons (list
84
+ (substring line (match-beginning 1) (match-end 1))
85
+ (string-to-int (substring line (match-beginning 2) (match-end 2))))
86
+ result)))
87
+ result))
88
+
89
+ (defun rcov-xref-select-file-line (candidates)
90
+ "Select a file/line candidate that references an existing file."
91
+ (cond ((null candidates) nil)
92
+ ((file-readable-p (caar candidates)) (car candidates))
93
+ (t (rcov-xref-select-file-line (cdr candidates))) ))
94
+
95
+ (defun rcov-xref-visit-source ()
96
+ "If the current line contains text like '../src/program.rb:34', visit
97
+ that file in the other window and position point on that line."
98
+ (interactive)
99
+ (let* ((line (progn (looking-at rcov-xref-tag-regexp) (match-string 1)))
100
+ (candidates (rcov-xref-extract-file-lines line))
101
+ (file-line (rcov-xref-select-file-line candidates)))
102
+ (cond (file-line
103
+ (run-hooks 'rcov-xref-before-visit-source-hook)
104
+ (find-file (car file-line))
105
+ (goto-line (cadr file-line))
106
+ (run-hooks 'rcov-xref-after-visit-source-hook))
107
+ (t
108
+ (error "No source location on line.")) )))
109
+
110
+ ;;;; Running rcov with various options.
111
+ (defun rcov-internal (cmdline)
112
+ "Run rcov with various options."
113
+ (compile-internal cmdline ""
114
+ nil nil nil (lambda (x) "*rcov*")))
115
+
116
+ (defun rcov ()
117
+ "Run rcov to find uncovered code."
118
+ (interactive)
119
+ (rcov-internal rcov-command-line))
120
+
121
+ (defun rcovsave ()
122
+ "Run rcov to save coverage status."
123
+ (interactive)
124
+ (rcov-internal rcovsave-command-line))
125
+
126
+ (defun rcovdiff ()
127
+ "Run rcov to find new uncovered code."
128
+ (interactive)
129
+ (rcov-internal rcovdiff-command-line))
130
+
131
+ (provide 'rcov)
@@ -0,0 +1,10 @@
1
+ $: << File.dirname(__FILE__)
2
+ require 'sample_03'
3
+
4
+ klass = Rcov::Test::Temporary::Sample03
5
+ obj = klass.new
6
+ obj.f1
7
+ obj.f2
8
+ obj.f3
9
+ #klass.g1 uncovered
10
+ klass.g2
@@ -0,0 +1,17 @@
1
+ def d(x)
2
+ 4*x
3
+ end
4
+
5
+ def a
6
+ b 10
7
+ end
8
+
9
+ def b(x)
10
+ x*10
11
+ end
12
+
13
+ def c(x)
14
+ 3*x
15
+ end
16
+
17
+ a()
@@ -0,0 +1,13 @@
1
+ def a
2
+ b 10
3
+ end
4
+
5
+ def b(x)
6
+ x*10
7
+ end
8
+
9
+ def c(x)
10
+ 3*x
11
+ end
12
+
13
+ a()
@@ -0,0 +1,17 @@
1
+ def d(x)
2
+ 4*x
3
+ end
4
+
5
+ def a
6
+ b 10
7
+ end
8
+
9
+ def b(x)
10
+ x*10
11
+ end
12
+
13
+ def c(x)
14
+ 3*x
15
+ end
16
+
17
+ a()
@@ -0,0 +1,105 @@
1
+ require 'test/unit'
2
+ require 'pathname'
3
+ require 'fileutils'
4
+
5
+ =begin
6
+ Updating functional testdata automatically is DANGEROUS, so I do manually.
7
+
8
+ == update functional test
9
+ cd ~/src/rcov/test
10
+ rcov="ruby ../bin/rcov -I../lib:../ext/rcovrt -o expected_coverage"
11
+
12
+ $rcov -a sample_04.rb
13
+ $rcov sample_04.rb
14
+ $rcov --gcc --include-file=sample --exclude=rcov sample_04.rb > expected_coverage/gcc-text.out
15
+
16
+ cp sample_05-old.rb sample_05.rb
17
+ $rcov --no-html --gcc --include-file=sample --exclude=rcov --save=coverage.info sample_05.rb > expected_coverage/diff-gcc-original.out
18
+ cp sample_05-new.rb sample_05.rb
19
+ $rcov --no-html --gcc -D --include-file=sample --exclude=rcov sample_05.rb > expected_coverage/diff-gcc-diff.out
20
+ $rcov --no-html -D --include-file=sample --exclude=rcov sample_05.rb > expected_coverage/diff.out
21
+ $rcov --no-html --no-color -D --include-file=sample --exclude=rcov sample_05.rb > expected_coverage/diff-no-color.out
22
+ $rcov --no-html --gcc --include-file=sample --exclude=rcov sample_05.rb > expected_coverage/diff-gcc-all.out
23
+
24
+ =end
25
+
26
+ class TestFunctional < Test::Unit::TestCase
27
+ @@dir = Pathname(__FILE__).expand_path.dirname
28
+
29
+ def strip_time(str)
30
+ str.sub(/Generated on.+$/, '')
31
+ end
32
+
33
+ def cmp(file)
34
+ content = lambda{|dir| strip_time(File.read(@@dir+dir+file))}
35
+ assert_equal(content["expected_coverage"], content["actual_coverage"])
36
+ end
37
+
38
+ def with_testdir(&block)
39
+ Dir.chdir(@@dir, &block)
40
+ end
41
+
42
+ def run_rcov(opts, script="sample_04.rb", opts_tail="")
43
+ rcov = @@dir+"../bin/rcov"
44
+ ruby_opts = "-I../lib:../ext/rcovrt"
45
+ with_testdir do
46
+ `cd #{@@dir}; ruby #{ruby_opts} #{rcov} #{opts} -o actual_coverage #{script} #{opts_tail}`
47
+ yield if block_given?
48
+ end
49
+ end
50
+
51
+ def test_annotation
52
+ run_rcov("-a") do
53
+ cmp "sample_04_rb.rb"
54
+ cmp "sample_03_rb.rb"
55
+ end
56
+ end
57
+
58
+ def test_html
59
+ run_rcov("") do
60
+ cmp "sample_04_rb.html"
61
+ cmp "sample_03_rb.html"
62
+ end
63
+ end
64
+
65
+ @@selection = "--include-file=sample --exclude=rcov"
66
+ def test_text_gcc
67
+ run_rcov("--gcc #{@@selection}",
68
+ "sample_04.rb",
69
+ "> actual_coverage/gcc-text.out") do
70
+ cmp "gcc-text.out"
71
+ end
72
+ end
73
+
74
+ def test_diff
75
+ with_testdir { FileUtils.cp "sample_05-old.rb", "sample_05.rb" }
76
+ run_rcov("--no-html --gcc #{@@selection} --save=coverage.info", "sample_05.rb",
77
+ "> actual_coverage/diff-gcc-original.out") do
78
+ cmp "diff-gcc-original.out"
79
+ end
80
+
81
+ with_testdir { FileUtils.cp "sample_05-new.rb", "sample_05.rb" }
82
+ run_rcov("--no-html -D --gcc #{@@selection}", "sample_05.rb",
83
+ "> actual_coverage/diff-gcc-diff.out") do
84
+ cmp "diff-gcc-diff.out"
85
+ end
86
+
87
+ run_rcov("--no-html -D #{@@selection}", "sample_05.rb",
88
+ "> actual_coverage/diff.out") do
89
+ cmp "diff.out"
90
+ end
91
+
92
+ run_rcov("--no-html --no-color -D #{@@selection}", "sample_05.rb",
93
+ "> actual_coverage/diff-no-color.out") do
94
+ cmp "diff-no-color.out"
95
+ end
96
+
97
+ run_rcov("--no-html --gcc #{@@selection}", "sample_05.rb",
98
+ "> actual_coverage/diff-gcc-all.out") do
99
+ cmp "diff-gcc-all.out"
100
+ end
101
+
102
+
103
+ end
104
+
105
+ end
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.9.0
2
+ rubygems_version: 0.9.1
3
3
  specification_version: 1
4
4
  name: rcov
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.7.0.1
7
- date: 2006-08-04 00:00:00 +02:00
6
+ version: 0.8.0.0
7
+ date: 2007-02-28 00:00:00 +01:00
8
8
  summary: Code coverage analysis tool for Ruby
9
9
  require_paths:
10
10
  - lib
@@ -48,16 +48,23 @@ files:
48
48
  - README.API
49
49
  - README.vim
50
50
  - README.rant
51
+ - README.emacs
51
52
  - THANKS
52
53
  - test/sample_02.rb
53
54
  - test/sample_01.rb
54
55
  - test/sample_03.rb
56
+ - test/sample_04.rb
55
57
  - test/test_CodeCoverageAnalyzer.rb
56
58
  - test/test_FileStatistics.rb
57
59
  - test/turn_off_rcovrt.rb
58
60
  - test/test_CallSiteAnalyzer.rb
61
+ - test/sample_05.rb
62
+ - test/test_functional.rb
63
+ - test/sample_05-new.rb
64
+ - test/sample_05-old.rb
59
65
  - mingw-rbconfig.rb
60
66
  - rcov.vim
67
+ - rcov.el
61
68
  - setup.rb
62
69
  - BLURB
63
70
  - CHANGES
@@ -66,6 +73,7 @@ test_files:
66
73
  - test/test_CodeCoverageAnalyzer.rb
67
74
  - test/test_FileStatistics.rb
68
75
  - test/test_CallSiteAnalyzer.rb
76
+ - test/test_functional.rb
69
77
  rdoc_options:
70
78
  - --main
71
79
  - README.API