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 +1 -1
- data/CHANGES +23 -0
- data/README.emacs +64 -0
- data/Rakefile +9 -4
- data/THANKS +16 -0
- data/bin/rcov +29 -2
- data/ext/rcovrt/rcovrt.c +15 -5
- data/lib/rcov/rcovtask.rb +1 -1
- data/lib/rcov/report.rb +210 -63
- data/lib/rcov/version.rb +2 -2
- data/lib/rcovrt.so +0 -0
- data/rcov.el +131 -0
- data/test/sample_04.rb +10 -0
- data/test/sample_05-new.rb +17 -0
- data/test/sample_05-old.rb +13 -0
- data/test/sample_05.rb +17 -0
- data/test/test_functional.rb +105 -0
- metadata +11 -3
    
        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. | 
| 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
         | 
    
        data/README.emacs
    ADDED
    
    | @@ -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 | 
| 64 | 
            -
            task :test => [:test_rcovrt | 
| 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 = ". | 
| 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 | 
            -
             | 
| 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:
         | 
    
        data/ext/rcovrt/rcovrt.c
    CHANGED
    
    | @@ -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( | 
| 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)  | 
| 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 {
         | 
    
        data/lib/rcov/rcovtask.rb
    CHANGED
    
    
    
        data/lib/rcov/report.rb
    CHANGED
    
    | @@ -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 | 
| 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 | 
            -
                     | 
| 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 | 
            -
                         | 
| 326 | 
            -
             | 
| 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,  | 
| 651 | 
            -
             | 
| 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,  | 
| 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_ " "
         | 
| 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 | 
            -
             | 
| 716 | 
            -
             | 
| 717 | 
            -
                                 | 
| 718 | 
            -
             | 
| 719 | 
            -
             | 
| 720 | 
            -
             | 
| 721 | 
            -
                                     | 
| 722 | 
            -
             | 
| 723 | 
            -
             | 
| 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 | 
            -
                     | 
| 771 | 
            -
             | 
| 772 | 
            -
             | 
| 773 | 
            -
             | 
| 774 | 
            -
             | 
| 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 | 
            -
                         | 
| 821 | 
            +
                        CGI.escapeHTML("%7d   %s" % 
         | 
| 822 | 
            +
                                           [ref.count, "#{ref.klass}##{ref.mid} " + where])
         | 
| 785 823 | 
             
                    end
         | 
| 786 | 
            -
                     | 
| 787 | 
            -
             | 
| 788 | 
            -
             | 
| 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 | 
            -
             | 
| 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 | 
            -
             | 
| 878 | 
            -
             | 
| 879 | 
            -
                                 | 
| 880 | 
            -
             | 
| 881 | 
            -
             | 
| 882 | 
            -
             | 
| 883 | 
            -
                                     | 
| 884 | 
            -
             | 
| 885 | 
            -
             | 
| 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:
         | 
    
        data/lib/rcov/version.rb
    CHANGED
    
    
    
        data/lib/rcovrt.so
    CHANGED
    
    | 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)
         | 
    
        data/test/sample_04.rb
    ADDED
    
    
    
        data/test/sample_05.rb
    ADDED
    
    
| @@ -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. | 
| 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 | 
            -
            date:  | 
| 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
         |