rcov 0.9.11 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/rcov +26 -3
- data/ext/rcovrt/1.8/callsite.c +38 -53
- data/ext/rcovrt/1.8/rcovrt.c +84 -100
- data/ext/rcovrt/extconf.rb +7 -12
- data/lib/rcov/formatters/html_erb_template.rb +7 -7
- data/lib/rcov/formatters/html_profiling.rb +51 -0
- data/lib/rcov/formatters/ruby_annotation.rb +110 -0
- data/lib/rcov/templates/index.html.erb +18 -14
- data/lib/rcov/version.rb +2 -6
- metadata +35 -75
- data/BLURB +0 -111
- data/LICENSE +0 -53
- data/Rakefile +0 -103
- data/THANKS +0 -110
- data/doc/readme_for_api.markdown +0 -22
- data/doc/readme_for_emacs.markdown +0 -52
- data/doc/readme_for_rake.markdown +0 -51
- data/doc/readme_for_vim.markdown +0 -34
- data/editor-extensions/rcov.el +0 -131
- data/editor-extensions/rcov.vim +0 -38
- data/ext/rcovrt/1.9/callsite.c +0 -234
- data/ext/rcovrt/1.9/rcovrt.c +0 -264
- data/setup.rb +0 -1588
- data/test/assets/sample_01.rb +0 -7
- data/test/assets/sample_02.rb +0 -5
- data/test/assets/sample_03.rb +0 -20
- data/test/assets/sample_04.rb +0 -10
- data/test/assets/sample_05-new.rb +0 -17
- data/test/assets/sample_05-old.rb +0 -13
- data/test/assets/sample_05.rb +0 -17
- data/test/assets/sample_06.rb +0 -8
- data/test/call_site_analyzer_test.rb +0 -171
- data/test/code_coverage_analyzer_test.rb +0 -220
- data/test/expected_coverage/diff-gcc-all.out +0 -7
- data/test/expected_coverage/diff-gcc-diff.out +0 -11
- data/test/expected_coverage/diff-gcc-original.out +0 -5
- data/test/expected_coverage/diff-no-color.out +0 -12
- data/test/expected_coverage/diff.out +0 -12
- data/test/expected_coverage/gcc-text.out +0 -10
- data/test/expected_coverage/sample_03_rb.html +0 -651
- data/test/expected_coverage/sample_03_rb.rb +0 -28
- data/test/expected_coverage/sample_04_rb.html +0 -641
- data/test/file_statistics_test.rb +0 -471
- data/test/functional_test.rb +0 -91
- data/test/test_helper.rb +0 -4
- data/test/turn_off_rcovrt.rb +0 -4
@@ -1,51 +0,0 @@
|
|
1
|
-
# Code coverage analysis automation with Rake
|
2
|
-
|
3
|
-
Since 0.4.0, RCov features a `Rcov::RcovTask` task for rake
|
4
|
-
which can be used to automate test coverage analysis. Basic usage is as
|
5
|
-
follows:
|
6
|
-
<pre><code>
|
7
|
-
require 'rcov/rcovtask'
|
8
|
-
Rcov::RcovTask.new do |t|
|
9
|
-
t.test_files = FileList['test/test*.rb']
|
10
|
-
# t.verbose = true # uncomment to see the executed command
|
11
|
-
end
|
12
|
-
</pre></code>
|
13
|
-
|
14
|
-
This will create by default a task named `rcov`, and also a task to remove the output directory where the XHTML report is generated. The latter will be named `clobber_rcov`, and will be added to the main `clobber` target.
|
15
|
-
|
16
|
-
## Passing command line options to RCov
|
17
|
-
|
18
|
-
You can provide a description, change the name of the generated tasks (the one used to generate the report(s) and the `clobber_` one) and pass options to RCov:
|
19
|
-
<pre><code>
|
20
|
-
desc "Analyze code coverage of the unit tests."
|
21
|
-
Rcov::RcovTask.new(:coverage) do |t|
|
22
|
-
t.test_files = FileList['test/test*.rb']
|
23
|
-
t.verbose = true
|
24
|
-
## get a text report on stdout when rake is run:
|
25
|
-
t.rcov_opts << "--text-report"
|
26
|
-
## only report files under 80% coverage
|
27
|
-
t.rcov_opts << "--threshold 80"
|
28
|
-
end
|
29
|
-
</pre></code>
|
30
|
-
|
31
|
-
This will generate a `coverage` task and the associated `clobber_coverage` task to remove the directory the report is dumped to (`coverage` by default). You can specify a different destination directory, which comes handy if you have several `RcovTask`s; the `clobber_*` will take care of removing that directory:
|
32
|
-
<pre><code>
|
33
|
-
desc "Analyze code coverage for the FileStatistics class."
|
34
|
-
Rcov::RcovTask.new(:rcov_sourcefile) do |t|
|
35
|
-
t.test_files = FileList['test/test_FileStatistics.rb']
|
36
|
-
t.verbose = true
|
37
|
-
t.rcov_opts << "--test-unit-only"
|
38
|
-
t.output_dir = "coverage.sourcefile"
|
39
|
-
end
|
40
|
-
|
41
|
-
Rcov::RcovTask.new(:rcov_ccanalyzer) do |t|
|
42
|
-
t.test_files = FileList['test/test_CodeCoverageAnalyzer.rb']
|
43
|
-
t.verbose = true
|
44
|
-
t.rcov_opts << "--test-unit-only"
|
45
|
-
t.output_dir = "coverage.ccanalyzer"
|
46
|
-
end
|
47
|
-
</pre></code>
|
48
|
-
|
49
|
-
## Options passed through the `rake` command line
|
50
|
-
|
51
|
-
You can override the options defined in the RcovTask by passing the new options at the time you invoke rake. The documentation for the `Rcov::RcovTask` explains how this can be done.
|
data/doc/readme_for_vim.markdown
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
# rcov.vim
|
2
|
-
|
3
|
-
`rcov.vim` allows you to run unit tests from vim and enter quickfix mode in order to jump to uncovered code introduced since the last run.
|
4
|
-
|
5
|
-
## Installation
|
6
|
-
Copy `rcov.vim` to the appropriate `compiler` directory (typically `$HOME/.vim/compiler`).
|
7
|
-
|
8
|
-
### Usage
|
9
|
-
|
10
|
-
#### Setting the reference point
|
11
|
-
|
12
|
-
RCov's `--text-coverage-diff` mode compares the current coverage status against the saved one. It therefore needs that information to be recorded before you write new code (typically right after you perform a commit) in order to have something to compare against. You can save the current status with the `--save` option. If you're running RCov from Rake, you can do something like
|
13
|
-
|
14
|
-
`rake rcov_units RCOVOPTS="-T --save --rails"`
|
15
|
-
|
16
|
-
in order to take the current status as the reference point.
|
17
|
-
|
18
|
-
#### Finding new uncovered code
|
19
|
-
|
20
|
-
Type the following in command mode while editing your program:
|
21
|
-
|
22
|
-
`:compiler rcov`
|
23
|
-
|
24
|
-
`rcov.vim` assumes RCov can be invoked with a rake task (see [readme for rake]("http://github.com/relevance/rcov/blob/master/doc/readme_for_rake.markdown") for information on how to create it).
|
25
|
-
|
26
|
-
You can then execute +rcov+ and enter quickfix mode by typing
|
27
|
-
|
28
|
-
`:make <taskname>`
|
29
|
-
|
30
|
-
where taskname is the +rcov+ task you want to use; if you didn't override the default name in the Rakefile, just
|
31
|
-
|
32
|
-
`:make rcov`
|
33
|
-
|
34
|
-
will do. Vim will then enter quickfix mode, allowing you to jump to the areas that were not covered since the last time you saved the coverage data.
|
data/editor-extensions/rcov.el
DELETED
@@ -1,131 +0,0 @@
|
|
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/editor-extensions/rcov.vim
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
" Vim compiler file
|
2
|
-
" Language: Ruby
|
3
|
-
" Function: Code coverage information with rcov
|
4
|
-
" Maintainer: Mauricio Fernandez <mfp at acm dot org>
|
5
|
-
" Info:
|
6
|
-
" URL: http://eigenclass.org/hiki.rb?rcov
|
7
|
-
" ----------------------------------------------------------------------------
|
8
|
-
"
|
9
|
-
" Changelog:
|
10
|
-
" 0.1: initial version, shipped with rcov 0.6.0
|
11
|
-
"
|
12
|
-
" Comments:
|
13
|
-
" Initial attempt.
|
14
|
-
" ----------------------------------------------------------------------------
|
15
|
-
|
16
|
-
if exists("current_compiler")
|
17
|
-
finish
|
18
|
-
endif
|
19
|
-
let current_compiler = "rcov"
|
20
|
-
|
21
|
-
if exists(":CompilerSet") != 2 " older Vim always used :setlocal
|
22
|
-
command -nargs=* CompilerSet setlocal <args>
|
23
|
-
endif
|
24
|
-
|
25
|
-
let s:cpo_save = &cpo
|
26
|
-
set cpo-=C
|
27
|
-
|
28
|
-
CompilerSet makeprg=rake\ $*\ RCOVOPTS=\"-D\ --no-html\ --no-color\"\ $*
|
29
|
-
|
30
|
-
CompilerSet errorformat=
|
31
|
-
\%+W\#\#\#\ %f:%l\,
|
32
|
-
\%-C\ \ \ ,
|
33
|
-
\%-C!!\
|
34
|
-
|
35
|
-
let &cpo = s:cpo_save
|
36
|
-
unlet s:cpo_save
|
37
|
-
|
38
|
-
" vim: nowrap sw=2 sts=2 ts=8 ff=unix :
|
data/ext/rcovrt/1.9/callsite.c
DELETED
@@ -1,234 +0,0 @@
|
|
1
|
-
#include <ruby.h>
|
2
|
-
#include <ruby/st.h>
|
3
|
-
#include <stdlib.h>
|
4
|
-
|
5
|
-
#define DEBUG 0
|
6
|
-
|
7
|
-
static char callsite_hook_set_p;
|
8
|
-
|
9
|
-
typedef struct {
|
10
|
-
const char *sourcefile;
|
11
|
-
unsigned int sourceline;
|
12
|
-
VALUE curr_meth;
|
13
|
-
} type_def_site;
|
14
|
-
|
15
|
-
static VALUE caller_info = 0;
|
16
|
-
static VALUE method_def_site_info = 0;
|
17
|
-
|
18
|
-
static int caller_stack_len = 1;
|
19
|
-
|
20
|
-
static VALUE record_callsite_info(VALUE args) {
|
21
|
-
VALUE caller_ary;
|
22
|
-
VALUE curr_meth;
|
23
|
-
VALUE count_hash;
|
24
|
-
VALUE count;
|
25
|
-
VALUE *pargs = (VALUE *)args;
|
26
|
-
|
27
|
-
caller_ary = pargs[0];
|
28
|
-
curr_meth = pargs[1];
|
29
|
-
count_hash = rb_hash_aref(caller_info, curr_meth);
|
30
|
-
|
31
|
-
if(TYPE(count_hash) != T_HASH) {
|
32
|
-
/* Qnil, anything else should be impossible unless somebody's been
|
33
|
-
* messing with ObjectSpace */
|
34
|
-
count_hash = rb_hash_new();
|
35
|
-
rb_hash_aset(caller_info, curr_meth, count_hash);
|
36
|
-
}
|
37
|
-
|
38
|
-
count = rb_hash_aref(count_hash, caller_ary);
|
39
|
-
|
40
|
-
if(count == Qnil)
|
41
|
-
count = INT2FIX(0);
|
42
|
-
|
43
|
-
count = INT2FIX(FIX2UINT(count) + 1);
|
44
|
-
rb_hash_aset(count_hash, caller_ary, count);
|
45
|
-
|
46
|
-
if(DEBUG == 1)
|
47
|
-
printf("CALLSITE: %s -> %s %d\n", RSTRING_PTR(rb_inspect(curr_meth)), RSTRING_PTR(rb_inspect(caller_ary)), FIX2INT(count));
|
48
|
-
|
49
|
-
return Qnil;
|
50
|
-
}
|
51
|
-
|
52
|
-
static VALUE record_method_def_site(VALUE args) {
|
53
|
-
type_def_site *pargs = (type_def_site *)args;
|
54
|
-
VALUE def_site_info;
|
55
|
-
|
56
|
-
if( RTEST(rb_hash_aref(method_def_site_info, pargs->curr_meth)) )
|
57
|
-
return Qnil;
|
58
|
-
|
59
|
-
def_site_info = rb_ary_new();
|
60
|
-
rb_ary_push(def_site_info, rb_str_new2(pargs->sourcefile));
|
61
|
-
rb_ary_push(def_site_info, INT2NUM(pargs->sourceline+1));
|
62
|
-
rb_hash_aset(method_def_site_info, pargs->curr_meth, def_site_info);
|
63
|
-
|
64
|
-
if(DEBUG == 1)
|
65
|
-
printf("DEFSITE: %s:%d for %s\n", pargs->sourcefile, pargs->sourceline+1, RSTRING_PTR(rb_inspect(pargs->curr_meth)));
|
66
|
-
|
67
|
-
return Qnil;
|
68
|
-
}
|
69
|
-
|
70
|
-
static VALUE callsite_custom_backtrace(int lev) {
|
71
|
-
ID id;
|
72
|
-
VALUE klass;
|
73
|
-
VALUE klass_path;
|
74
|
-
VALUE eval_string;
|
75
|
-
|
76
|
-
rb_frame_method_id_and_class(&id, &klass);
|
77
|
-
|
78
|
-
if (id == ID_ALLOCATOR)
|
79
|
-
return Qnil;
|
80
|
-
|
81
|
-
if (klass) {
|
82
|
-
if (TYPE(klass) == T_ICLASS) {
|
83
|
-
klass = RBASIC(klass)->klass;
|
84
|
-
}
|
85
|
-
else if (FL_TEST(klass, FL_SINGLETON)) {
|
86
|
-
klass = rb_iv_get(klass, "__attached__");
|
87
|
-
}
|
88
|
-
}
|
89
|
-
// rb_sprintf("\"#<Class:%s>\"", RSTRING_PTR(klass_path))
|
90
|
-
|
91
|
-
/*
|
92
|
-
klass = class << klass; self end unless klass === eval("self", binding)
|
93
|
-
*/
|
94
|
-
|
95
|
-
klass_path = rb_class_path(klass);
|
96
|
-
VALUE reciever = rb_funcall(rb_binding_new(), rb_intern("eval"), 1, rb_str_new2("self"));
|
97
|
-
|
98
|
-
if (rb_funcall(klass, rb_intern("=="), 1, reciever) == Qtrue) {
|
99
|
-
klass_path = rb_sprintf("\"#<Class:%s>\"", RSTRING_PTR(klass_path));
|
100
|
-
OBJ_FREEZE(klass_path);
|
101
|
-
}
|
102
|
-
|
103
|
-
eval_string = rb_sprintf("caller[%d, 1].map do |line|\nmd = /^([^:]*)(?::(\\d+)(?::in `(?:block in )?(.*)'))?/.match(line)\nraise \"Bad backtrace format\" unless md\n[%s, md[3] ? md[3].to_sym : nil, md[1], (md[2] || '').to_i]\nend", lev, RSTRING_PTR(klass_path));
|
104
|
-
return rb_eval_string(RSTRING_PTR(eval_string));
|
105
|
-
}
|
106
|
-
|
107
|
-
static void coverage_event_callsite_hook(rb_event_flag_t event, VALUE node, VALUE self, ID mid, VALUE klass) {
|
108
|
-
VALUE caller_ary;
|
109
|
-
VALUE curr_meth;
|
110
|
-
VALUE args[2];
|
111
|
-
int status;
|
112
|
-
|
113
|
-
caller_ary = callsite_custom_backtrace(caller_stack_len);
|
114
|
-
|
115
|
-
VALUE klass_path;
|
116
|
-
curr_meth = rb_ary_new();
|
117
|
-
|
118
|
-
rb_frame_method_id_and_class(&mid, &klass);
|
119
|
-
|
120
|
-
if (mid == ID_ALLOCATOR)
|
121
|
-
return; //Qnil;
|
122
|
-
if (klass) {
|
123
|
-
if (TYPE(klass) == T_ICLASS) {
|
124
|
-
klass = RBASIC(klass)->klass;
|
125
|
-
}
|
126
|
-
else if (FL_TEST(klass, FL_SINGLETON)) {
|
127
|
-
klass = rb_iv_get(klass, "__attached__");
|
128
|
-
}
|
129
|
-
}
|
130
|
-
|
131
|
-
/*
|
132
|
-
klass = class << klass; self end unless klass === eval("self", binding)
|
133
|
-
*/
|
134
|
-
|
135
|
-
klass_path = rb_class_path(klass);
|
136
|
-
VALUE reciever = rb_funcall(rb_binding_new(), rb_intern("eval"), 1, rb_str_new2("self"));
|
137
|
-
|
138
|
-
if (rb_funcall(klass, rb_intern("=="), 1, reciever) == Qtrue) {
|
139
|
-
klass_path = rb_sprintf("#<Class:%s>", RSTRING_PTR(klass_path));
|
140
|
-
OBJ_FREEZE(klass_path);
|
141
|
-
}
|
142
|
-
|
143
|
-
rb_ary_push(curr_meth, klass_path);
|
144
|
-
rb_ary_push(curr_meth, ID2SYM(mid));
|
145
|
-
|
146
|
-
args[0] = caller_ary;
|
147
|
-
args[1] = curr_meth;
|
148
|
-
rb_protect(record_callsite_info, (VALUE)args, &status);
|
149
|
-
|
150
|
-
if(!status) {
|
151
|
-
type_def_site args;
|
152
|
-
|
153
|
-
args.sourcefile = rb_sourcefile();
|
154
|
-
args.sourceline = rb_sourceline();
|
155
|
-
args.curr_meth = curr_meth;
|
156
|
-
rb_protect(record_method_def_site, (VALUE)&args, NULL);
|
157
|
-
}
|
158
|
-
|
159
|
-
if(status)
|
160
|
-
rb_gv_set("$!", Qnil);
|
161
|
-
}
|
162
|
-
|
163
|
-
static VALUE cov_install_callsite_hook(VALUE self) {
|
164
|
-
if(!callsite_hook_set_p) {
|
165
|
-
if(TYPE(caller_info) != T_HASH)
|
166
|
-
caller_info = rb_hash_new();
|
167
|
-
callsite_hook_set_p = 1;
|
168
|
-
VALUE something = 0;
|
169
|
-
rb_add_event_hook(coverage_event_callsite_hook,
|
170
|
-
RUBY_EVENT_CALL, something);
|
171
|
-
return Qtrue;
|
172
|
-
}
|
173
|
-
else
|
174
|
-
return Qfalse;
|
175
|
-
}
|
176
|
-
|
177
|
-
static VALUE cov_remove_callsite_hook(VALUE self) {
|
178
|
-
if(!callsite_hook_set_p)
|
179
|
-
return Qfalse;
|
180
|
-
else {
|
181
|
-
rb_remove_event_hook(coverage_event_callsite_hook);
|
182
|
-
callsite_hook_set_p = 0;
|
183
|
-
return Qtrue;
|
184
|
-
}
|
185
|
-
}
|
186
|
-
|
187
|
-
static VALUE cov_generate_callsite_info(VALUE self) {
|
188
|
-
VALUE ret;
|
189
|
-
|
190
|
-
ret = rb_ary_new();
|
191
|
-
rb_ary_push(ret, caller_info);
|
192
|
-
rb_ary_push(ret, method_def_site_info);
|
193
|
-
return ret;
|
194
|
-
}
|
195
|
-
|
196
|
-
static VALUE cov_reset_callsite(VALUE self) {
|
197
|
-
if(callsite_hook_set_p) {
|
198
|
-
rb_raise(rb_eRuntimeError, "Cannot reset the callsite info in the middle of a traced run.");
|
199
|
-
return Qnil;
|
200
|
-
}
|
201
|
-
|
202
|
-
caller_info = rb_hash_new();
|
203
|
-
method_def_site_info = rb_hash_new();
|
204
|
-
return Qnil;
|
205
|
-
}
|
206
|
-
|
207
|
-
void Init_rcov_callsite() {
|
208
|
-
VALUE mRcov;
|
209
|
-
VALUE mRCOV__;
|
210
|
-
ID id_rcov = rb_intern("Rcov");
|
211
|
-
ID id_coverage__ = rb_intern("RCOV__");
|
212
|
-
// ID id_script_lines__ = rb_intern("SCRIPT_LINES__");
|
213
|
-
|
214
|
-
if(rb_const_defined(rb_cObject, id_rcov))
|
215
|
-
mRcov = rb_const_get(rb_cObject, id_rcov);
|
216
|
-
else
|
217
|
-
mRcov = rb_define_module("Rcov");
|
218
|
-
|
219
|
-
if(rb_const_defined(mRcov, id_coverage__))
|
220
|
-
mRCOV__ = rb_const_get_at(mRcov, id_coverage__);
|
221
|
-
else
|
222
|
-
mRCOV__ = rb_define_module_under(mRcov, "RCOV__");
|
223
|
-
|
224
|
-
callsite_hook_set_p = 0;
|
225
|
-
caller_info = rb_hash_new();
|
226
|
-
method_def_site_info = rb_hash_new();
|
227
|
-
rb_gc_register_address(&caller_info);
|
228
|
-
rb_gc_register_address(&method_def_site_info);
|
229
|
-
|
230
|
-
rb_define_singleton_method(mRCOV__, "install_callsite_hook", cov_install_callsite_hook, 0);
|
231
|
-
rb_define_singleton_method(mRCOV__, "remove_callsite_hook", cov_remove_callsite_hook, 0);
|
232
|
-
rb_define_singleton_method(mRCOV__, "generate_callsite_info", cov_generate_callsite_info, 0);
|
233
|
-
rb_define_singleton_method(mRCOV__, "reset_callsite", cov_reset_callsite, 0);
|
234
|
-
}
|