relevance-rcov 0.8.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,41 @@
1
+
2
+ = +rcov+
3
+
4
+ +rcov+ is a:
5
+ 1. tool for code coverage analysis for Ruby
6
+ 2. library for collecting code coverage and execution count information
7
+ introspectively
8
+
9
+ If you want to use the command line tool, the output from
10
+ rcov -h
11
+ is self-explicative.
12
+
13
+ If you want to automate the execution of +rcov+ via Rake take a look at
14
+ readme_for_rake[link:files/README_rake.html].
15
+
16
+ If you want to use the associated library, read on.
17
+
18
+ == Usage of the +rcov+ runtime/library
19
+
20
+ +rcov+ is primarily a tool for code coverage analysis, but since 0.4.0 it
21
+ exposes some of its code so that you can build on top of its heuristics for
22
+ code analysis and its capabilities for coverage information and execution
23
+ count gathering.
24
+
25
+ The main classes of interest are Rcov::FileStatistics,
26
+ Rcov::CodeCoverageAnalyzer and Rcov::CallSiteAnalyzer.
27
+
28
+ Rcov::FileStatistics can use some heuristics to determine
29
+ which parts of the file are executable and which are mere comments.
30
+
31
+ Rcov::CodeCoverageAnalyzer is used to gather code coverage and execution
32
+ count information inside a running Ruby program.
33
+
34
+ Rcov::CallSiteAnalyzer is used to obtain information about where methods are
35
+ defined and who calls them.
36
+
37
+ The parts of +rcov+'s runtime meant to be reused (i.e. the external API) are
38
+ documented with RDoc. Those not meant to be used are clearly marked as so or
39
+ were deliberately removed from the present documentation.
40
+
41
+
@@ -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.
@@ -0,0 +1,62 @@
1
+
2
+ == Code coverage analysis automation with Rake
3
+
4
+ Since 0.4.0, <tt>rcov</tt> features a <tt>Rcov::RcovTask</tt> task for rake
5
+ which can be used to automate test coverage analysis. Basic usage is as
6
+ follows:
7
+
8
+ require 'rcov/rcovtask'
9
+ Rcov::RcovTask.new do |t|
10
+ t.test_files = FileList['test/test*.rb']
11
+ # t.verbose = true # uncomment to see the executed command
12
+ end
13
+
14
+ This will create by default a task named <tt>rcov</tt>, and also a task to
15
+ remove the output directory where the XHTML report is generated.
16
+ The latter will be named <tt>clobber_rcob</tt>, and will be added to the main
17
+ <tt>clobber</tt> target.
18
+
19
+ === Passing command line options to <tt>rcov</tt>
20
+
21
+ You can provide a description, change the name of the generated tasks (the
22
+ one used to generate the report(s) and the clobber_ one) and pass options to
23
+ <tt>rcov</tt>:
24
+
25
+ desc "Analyze code coverage of the unit tests."
26
+ Rcov::RcovTask.new(:coverage) do |t|
27
+ t.test_files = FileList['test/test*.rb']
28
+ t.verbose = true
29
+ ## get a text report on stdout when rake is run:
30
+ t.rcov_opts << "--text-report"
31
+ ## only report files under 80% coverage
32
+ t.rcov_opts << "--threshold 80"
33
+ end
34
+
35
+ That will generate a <tt>coverage</tt> task and the associated
36
+ <tt>clobber_coverage</tt> task to remove the directory the report is dumped
37
+ to ("<tt>coverage</tt>" by default).
38
+
39
+ You can specify a different destination directory, which comes handy if you
40
+ have several <tt>RcovTask</tt>s; the <tt>clobber_*</tt> will take care of
41
+ removing that directory:
42
+
43
+ desc "Analyze code coverage for the FileStatistics class."
44
+ Rcov::RcovTask.new(:rcov_sourcefile) do |t|
45
+ t.test_files = FileList['test/test_FileStatistics.rb']
46
+ t.verbose = true
47
+ t.rcov_opts << "--test-unit-only"
48
+ t.output_dir = "coverage.sourcefile"
49
+ end
50
+
51
+ Rcov::RcovTask.new(:rcov_ccanalyzer) do |t|
52
+ t.test_files = FileList['test/test_CodeCoverageAnalyzer.rb']
53
+ t.verbose = true
54
+ t.rcov_opts << "--test-unit-only"
55
+ t.output_dir = "coverage.ccanalyzer"
56
+ end
57
+
58
+ === Options passed through the <tt>rake</tt> command line
59
+
60
+ You can override the options defined in the RcovTask by passing the new
61
+ options at the time you invoke rake.
62
+ The documentation for the Rcov::RcovTask explains how this can be done.
@@ -0,0 +1,47 @@
1
+
2
+ <tt>rcov.vim</tt> allows you to run unit tests from vim and enter quickfix mode in
3
+ order to jump to uncovered code introduced since the last run.
4
+
5
+ == Installation
6
+ Copy <tt>rcov.vim</tt> to the appropriate "compiler" directory (typically
7
+ <tt>$HOME/.vim/compiler</tt>).
8
+
9
+ == Usage
10
+
11
+ === Setting the reference point
12
+
13
+ +rcov+'s <tt>--text-coverage-diff</tt> mode compares the current coverage status against
14
+ the saved one. It therefore needs that information to be recorded
15
+ before you write new code (typically right after you perform a commit) in
16
+ order to have something to compare against.
17
+
18
+ You can save the current status with the <tt>--save</tt> option.
19
+ If you're running +rcov+ from Rake, you can do something like
20
+ rake rcov_units RCOVOPTS="-T --save --rails"
21
+ in order to take the current status as the reference point.
22
+
23
+ === Finding new uncovered code
24
+
25
+ Type the following in command mode while editing your program:
26
+ :compiler rcov
27
+
28
+ rcov.vim assumes +rcov+ can be invoked with a rake task (see
29
+ readme_for_rake[link:files/README_rake.html] for
30
+ information on how to create it).
31
+
32
+ You can then execute +rcov+ and enter quickfix mode by typing
33
+
34
+ :make <taskname>
35
+
36
+ where taskname is the +rcov+ task you want to use; if you didn't override the
37
+ default name in the Rakefile, just
38
+
39
+ :make rcov
40
+
41
+ will do.
42
+
43
+ vim will then enter quickfix mode, allowing you to jump to the areas that were
44
+ not covered since the last time you saved the coverage data.
45
+
46
+ --------
47
+ # vim: ft=text :
@@ -0,0 +1,131 @@
1
+ ;;; rcov.el -- Ruby Coverage Analysis Tool
2
+
3
+ ;;; Copyright (c) 2006 rubikitch <rubikitch@ruby-lang.org>
4
+ ;;;
5
+ ;;; Use and distribution subject to the terms of the rcov license.
6
+
7
+ (defvar rcov-xref-before-visit-source-hook nil
8
+ "Hook executed before jump.")
9
+ (defvar rcov-xref-after-visit-source-hook nil
10
+ "Hook executed after jump.")
11
+ (defvar rcov-command-line "rake rcov RCOVOPTS='--gcc --no-html'"
12
+ "Rcov command line to find uncovered code.
13
+ It is good to use rcov with Rake because it `cd's appropriate directory.
14
+ `--gcc' option is strongly recommended because `rcov' uses compilation-mode.")
15
+ (defvar rcovsave-command-line "rake rcov RCOVOPTS='--gcc --no-html --save=coverage.info'"
16
+ "Rcov command line to save coverage status. See also `rcov-command-line'.")
17
+ (defvar rcovdiff-command-line "rake rcov RCOVOPTS='-D --gcc --no-html'"
18
+ "Rcov command line to find new uncovered code. See also `rcov-command-line'.")
19
+
20
+ ;;;; rcov-xref-mode
21
+ (define-derived-mode rcov-xref-mode ruby-mode "Rxref"
22
+ "Major mode for annotated Ruby scripts (coverage/*.rb) by rcov."
23
+ (setq truncate-lines t)
24
+ ;; ruby-electric-mode / pabbrev-mode hijacks TAB binding.
25
+ (and ruby-electric-mode (ruby-electric-mode -1))
26
+ (and (boundp 'pabbrev-mode) pabbrev-mode (pabbrev-mode -1))
27
+ (suppress-keymap rcov-xref-mode-map)
28
+ (define-key rcov-xref-mode-map "\C-i" 'rcov-xref-next-tag)
29
+ (define-key rcov-xref-mode-map "\M-\C-i" 'rcov-xref-previous-tag)
30
+ (define-key rcov-xref-mode-map "\C-m" 'rcov-xref-visit-source)
31
+ (set (make-local-variable 'automatic-hscrolling) nil)
32
+ )
33
+
34
+ (defvar rcov-xref-tag-regexp "\\[\\[\\(.*?\\)\\]\\]")
35
+
36
+ (defun rcov-xref-next-tag (n)
37
+ "Go to next LINK."
38
+ (interactive "p")
39
+ (when (looking-at rcov-xref-tag-regexp)
40
+ (goto-char (match-end 0)))
41
+ (when (re-search-forward rcov-xref-tag-regexp nil t n)
42
+ (goto-char (match-beginning 0)))
43
+ (rcov-xref-show-link))
44
+
45
+ (defun rcov-xref-previous-tag (n)
46
+ "Go to previous LINK."
47
+ (interactive "p")
48
+ (re-search-backward rcov-xref-tag-regexp nil t n)
49
+ (rcov-xref-show-link))
50
+
51
+ (defvar rcov-xref-link-tempbuffer " *rcov-link*")
52
+ (defun rcov-xref-show-link ()
53
+ "Follow current LINK."
54
+ (let ((link (match-string 1))
55
+ (eol (point-at-eol)))
56
+ (save-excursion
57
+ (when (and link
58
+ (re-search-backward "# \\(>>\\|<<\\) " (point-at-bol) t))
59
+ (while (re-search-forward rcov-xref-tag-regexp eol t)
60
+ (let ((matched (match-string 1)))
61
+ (when (string= link matched)
62
+ (add-text-properties 0 (length matched) '(face highlight) matched))
63
+ (with-current-buffer (get-buffer-create rcov-xref-link-tempbuffer)
64
+ (insert matched "\n"))))
65
+ (let (message-log-max) ; inhibit *Messages*
66
+ (message "%s" (with-current-buffer rcov-xref-link-tempbuffer
67
+ (substring (buffer-string) 0 -1)))) ; chomp
68
+ (kill-buffer rcov-xref-link-tempbuffer)))))
69
+
70
+
71
+ ;; copied from jw-visit-source
72
+ (defun rcov-xref-extract-file-lines (line)
73
+ "Extract a list of file/line pairs from the given line of text."
74
+ (let*
75
+ ((unix_fn "[^ \t\n\r\"'([<{]+")
76
+ (dos_fn "[a-zA-Z]:[^ \t\n\r\"'([<{]+")
77
+ (flre (concat "\\(" unix_fn "\\|" dos_fn "\\):\\([0-9]+\\)"))
78
+ (start nil)
79
+ (result nil))
80
+ (while (string-match flre line start)
81
+ (setq start (match-end 0))
82
+ (setq result
83
+ (cons (list
84
+ (substring line (match-beginning 1) (match-end 1))
85
+ (string-to-int (substring line (match-beginning 2) (match-end 2))))
86
+ result)))
87
+ result))
88
+
89
+ (defun rcov-xref-select-file-line (candidates)
90
+ "Select a file/line candidate that references an existing file."
91
+ (cond ((null candidates) nil)
92
+ ((file-readable-p (caar candidates)) (car candidates))
93
+ (t (rcov-xref-select-file-line (cdr candidates))) ))
94
+
95
+ (defun rcov-xref-visit-source ()
96
+ "If the current line contains text like '../src/program.rb:34', visit
97
+ that file in the other window and position point on that line."
98
+ (interactive)
99
+ (let* ((line (progn (looking-at rcov-xref-tag-regexp) (match-string 1)))
100
+ (candidates (rcov-xref-extract-file-lines line))
101
+ (file-line (rcov-xref-select-file-line candidates)))
102
+ (cond (file-line
103
+ (run-hooks 'rcov-xref-before-visit-source-hook)
104
+ (find-file (car file-line))
105
+ (goto-line (cadr file-line))
106
+ (run-hooks 'rcov-xref-after-visit-source-hook))
107
+ (t
108
+ (error "No source location on line.")) )))
109
+
110
+ ;;;; Running rcov with various options.
111
+ (defun rcov-internal (cmdline)
112
+ "Run rcov with various options."
113
+ (compile-internal cmdline ""
114
+ nil nil nil (lambda (x) "*rcov*")))
115
+
116
+ (defun rcov ()
117
+ "Run rcov to find uncovered code."
118
+ (interactive)
119
+ (rcov-internal rcov-command-line))
120
+
121
+ (defun rcovsave ()
122
+ "Run rcov to save coverage status."
123
+ (interactive)
124
+ (rcov-internal rcovsave-command-line))
125
+
126
+ (defun rcovdiff ()
127
+ "Run rcov to find new uncovered code."
128
+ (interactive)
129
+ (rcov-internal rcovdiff-command-line))
130
+
131
+ (provide 'rcov)
@@ -0,0 +1,38 @@
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 :
@@ -0,0 +1,242 @@
1
+ #include <ruby.h>
2
+ #include <env.h>
3
+ #include <node.h>
4
+ #include <st.h>
5
+ #include <stdlib.h>
6
+
7
+
8
+ static char callsite_hook_set_p;
9
+
10
+ typedef struct {
11
+ char *sourcefile;
12
+ unsigned int sourceline;
13
+ VALUE curr_meth;
14
+ } type_def_site;
15
+ static VALUE caller_info = 0;
16
+ static VALUE method_def_site_info = 0;
17
+
18
+ static caller_stack_len = 1;
19
+
20
+ /*
21
+ *
22
+ * callsite hook and associated functions
23
+ *
24
+ * */
25
+
26
+ static VALUE
27
+ record_callsite_info(VALUE args)
28
+ {
29
+ VALUE caller_ary;
30
+ VALUE curr_meth;
31
+ VALUE count_hash;
32
+ VALUE count;
33
+ VALUE *pargs = (VALUE *)args;
34
+
35
+ caller_ary = pargs[0];
36
+ curr_meth = pargs[1];
37
+ count_hash = rb_hash_aref(caller_info, curr_meth);
38
+ if(TYPE(count_hash) != T_HASH) {
39
+ /* Qnil, anything else should be impossible unless somebody's been
40
+ * messing with ObjectSpace */
41
+ count_hash = rb_hash_new();
42
+ rb_hash_aset(caller_info, curr_meth, count_hash);
43
+ }
44
+ count = rb_hash_aref(count_hash, caller_ary);
45
+ if(count == Qnil)
46
+ count = INT2FIX(0);
47
+ count = INT2FIX(FIX2UINT(count) + 1);
48
+ rb_hash_aset(count_hash, caller_ary, count);
49
+ /*
50
+ printf("CALLSITE: %s -> %s %d\n", RSTRING(rb_inspect(curr_meth))->ptr,
51
+ RSTRING(rb_inspect(caller_ary))->ptr, FIX2INT(count));
52
+ */
53
+
54
+ return Qnil;
55
+ }
56
+
57
+
58
+ static VALUE
59
+ record_method_def_site(VALUE args)
60
+ {
61
+ type_def_site *pargs = (type_def_site *)args;
62
+ VALUE def_site_info;
63
+ VALUE hash;
64
+
65
+ if( RTEST(rb_hash_aref(method_def_site_info, pargs->curr_meth)) )
66
+ return Qnil;
67
+ def_site_info = rb_ary_new();
68
+ rb_ary_push(def_site_info, rb_str_new2(pargs->sourcefile));
69
+ rb_ary_push(def_site_info, INT2NUM(pargs->sourceline+1));
70
+ rb_hash_aset(method_def_site_info, pargs->curr_meth, def_site_info);
71
+ /*
72
+ printf("DEFSITE: %s:%d for %s\n", pargs->sourcefile, pargs->sourceline+1,
73
+ RSTRING(rb_inspect(pargs->curr_meth))->ptr);
74
+ */
75
+
76
+ return Qnil;
77
+ }
78
+
79
+ static VALUE
80
+ callsite_custom_backtrace(int lev)
81
+ {
82
+ struct FRAME *frame = ruby_frame;
83
+ VALUE ary;
84
+ NODE *n;
85
+ VALUE level;
86
+ VALUE klass;
87
+
88
+ ary = rb_ary_new();
89
+ if (frame->last_func == ID_ALLOCATOR) {
90
+ frame = frame->prev;
91
+ }
92
+ for (; frame && (n = frame->node); frame = frame->prev) {
93
+ if (frame->prev && frame->prev->last_func) {
94
+ if (frame->prev->node == n) continue;
95
+ level = rb_ary_new();
96
+ klass = frame->prev->last_class ? frame->prev->last_class : Qnil;
97
+ if(TYPE(klass) == T_ICLASS) {
98
+ klass = CLASS_OF(klass);
99
+ }
100
+ rb_ary_push(level, klass);
101
+ rb_ary_push(level, ID2SYM(frame->prev->last_func));
102
+ rb_ary_push(level, rb_str_new2(n->nd_file));
103
+ rb_ary_push(level, INT2NUM(nd_line(n)));
104
+ }
105
+ else {
106
+ level = rb_ary_new();
107
+ rb_ary_push(level, Qnil);
108
+ rb_ary_push(level, Qnil);
109
+ rb_ary_push(level, rb_str_new2(n->nd_file));
110
+ rb_ary_push(level, INT2NUM(nd_line(n)));
111
+ }
112
+ rb_ary_push(ary, level);
113
+ if(--lev == 0)
114
+ break;
115
+ }
116
+
117
+ return ary;
118
+ }
119
+
120
+ static void
121
+ coverage_event_callsite_hook(rb_event_t event, NODE *node, VALUE self,
122
+ ID mid, VALUE klass)
123
+ {
124
+ VALUE caller_ary;
125
+ VALUE curr_meth;
126
+ VALUE args[2];
127
+ int status;
128
+
129
+ caller_ary = callsite_custom_backtrace(caller_stack_len);
130
+
131
+ if(TYPE(klass) == T_ICLASS) {
132
+ klass = CLASS_OF(klass);
133
+ }
134
+ curr_meth = rb_ary_new();
135
+ rb_ary_push(curr_meth, klass);
136
+ rb_ary_push(curr_meth, ID2SYM(mid));
137
+
138
+ args[0] = caller_ary;
139
+ args[1] = curr_meth;
140
+ rb_protect(record_callsite_info, (VALUE)args, &status);
141
+ if(!status && node) {
142
+ type_def_site args;
143
+
144
+ args.sourcefile = node->nd_file;
145
+ args.sourceline = nd_line(node) - 1;
146
+ args.curr_meth = curr_meth;
147
+ rb_protect(record_method_def_site, (VALUE)&args, NULL);
148
+ }
149
+ if(status)
150
+ rb_gv_set("$!", Qnil);
151
+ }
152
+
153
+
154
+ static VALUE
155
+ cov_install_callsite_hook(VALUE self)
156
+ {
157
+ if(!callsite_hook_set_p) {
158
+ if(TYPE(caller_info) != T_HASH)
159
+ caller_info = rb_hash_new();
160
+ callsite_hook_set_p = 1;
161
+ rb_add_event_hook(coverage_event_callsite_hook,
162
+ RUBY_EVENT_CALL);
163
+
164
+ return Qtrue;
165
+ } else
166
+ return Qfalse;
167
+ }
168
+
169
+
170
+ static VALUE
171
+ cov_remove_callsite_hook(VALUE self)
172
+ {
173
+ if(!callsite_hook_set_p)
174
+ return Qfalse;
175
+ else {
176
+ rb_remove_event_hook(coverage_event_callsite_hook);
177
+ callsite_hook_set_p = 0;
178
+ return Qtrue;
179
+ }
180
+ }
181
+
182
+
183
+ static VALUE
184
+ cov_generate_callsite_info(VALUE self)
185
+ {
186
+ VALUE ret;
187
+
188
+ ret = rb_ary_new();
189
+ rb_ary_push(ret, caller_info);
190
+ rb_ary_push(ret, method_def_site_info);
191
+ return ret;
192
+ }
193
+
194
+
195
+ static VALUE
196
+ cov_reset_callsite(VALUE self)
197
+ {
198
+ if(callsite_hook_set_p) {
199
+ rb_raise(rb_eRuntimeError,
200
+ "Cannot reset the callsite info in the middle of a traced run.");
201
+ return Qnil;
202
+ }
203
+
204
+ caller_info = rb_hash_new();
205
+ method_def_site_info = rb_hash_new();
206
+ return Qnil;
207
+ }
208
+
209
+ void
210
+ Init_rcov_callsite()
211
+ {
212
+ VALUE mRcov;
213
+ VALUE mRCOV__;
214
+ ID id_rcov = rb_intern("Rcov");
215
+ ID id_coverage__ = rb_intern("RCOV__");
216
+ ID id_script_lines__ = rb_intern("SCRIPT_LINES__");
217
+
218
+ if(rb_const_defined(rb_cObject, id_rcov))
219
+ mRcov = rb_const_get(rb_cObject, id_rcov);
220
+ else
221
+ mRcov = rb_define_module("Rcov");
222
+
223
+ if(rb_const_defined(mRcov, id_coverage__))
224
+ mRCOV__ = rb_const_get_at(mRcov, id_coverage__);
225
+ else
226
+ mRCOV__ = rb_define_module_under(mRcov, "RCOV__");
227
+
228
+ callsite_hook_set_p = 0;
229
+ caller_info = rb_hash_new();
230
+ method_def_site_info = rb_hash_new();
231
+ rb_gc_register_address(&caller_info);
232
+ rb_gc_register_address(&method_def_site_info);
233
+
234
+ rb_define_singleton_method(mRCOV__, "install_callsite_hook",
235
+ cov_install_callsite_hook, 0);
236
+ rb_define_singleton_method(mRCOV__, "remove_callsite_hook",
237
+ cov_remove_callsite_hook, 0);
238
+ rb_define_singleton_method(mRCOV__, "generate_callsite_info",
239
+ cov_generate_callsite_info, 0);
240
+ rb_define_singleton_method(mRCOV__, "reset_callsite", cov_reset_callsite, 0);
241
+ }
242
+ /* vim: set sw=8 expandtab: */