rcov 0.8.1.2.0 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- data/BLURB +2 -40
- data/LICENSE +2 -5
- data/Rakefile +32 -106
- data/THANKS +14 -0
- data/bin/rcov +277 -1090
- data/doc/readme_for_api.markdown +22 -0
- data/doc/readme_for_emacs.markdown +52 -0
- data/doc/readme_for_rake.markdown +51 -0
- data/doc/readme_for_vim.markdown +34 -0
- data/{rcov.el → editor-extensions/rcov.el} +0 -0
- data/{rcov.vim → editor-extensions/rcov.vim} +0 -0
- data/ext/rcovrt/1.8/callsite.c +216 -0
- data/ext/rcovrt/1.8/rcovrt.c +287 -0
- data/ext/rcovrt/1.9/callsite.c +234 -0
- data/ext/rcovrt/1.9/rcovrt.c +264 -0
- data/ext/rcovrt/extconf.rb +12 -2
- data/lib/rcov.rb +13 -968
- data/lib/rcov/call_site_analyzer.rb +225 -0
- data/lib/rcov/code_coverage_analyzer.rb +268 -0
- data/lib/rcov/coverage_info.rb +36 -0
- data/lib/rcov/differential_analyzer.rb +116 -0
- data/lib/rcov/file_statistics.rb +334 -0
- data/lib/rcov/formatters.rb +13 -0
- data/lib/rcov/formatters/base_formatter.rb +173 -0
- data/lib/rcov/formatters/failure_report.rb +15 -0
- data/lib/rcov/formatters/full_text_report.rb +48 -0
- data/lib/rcov/formatters/html_coverage.rb +274 -0
- data/lib/rcov/formatters/html_erb_template.rb +62 -0
- data/lib/rcov/formatters/text_coverage_diff.rb +193 -0
- data/lib/rcov/formatters/text_report.rb +32 -0
- data/lib/rcov/formatters/text_summary.rb +11 -0
- data/lib/rcov/lowlevel.rb +16 -17
- data/lib/rcov/rcovtask.rb +21 -22
- data/lib/rcov/templates/detail.html.erb +64 -0
- data/lib/rcov/templates/index.html.erb +93 -0
- data/lib/rcov/templates/jquery-1.3.2.min.js +19 -0
- data/lib/rcov/templates/jquery.tablesorter.min.js +15 -0
- data/lib/rcov/templates/print.css +12 -0
- data/lib/rcov/templates/rcov.js +42 -0
- data/lib/rcov/templates/screen.css +270 -0
- data/lib/rcov/version.rb +5 -8
- data/setup.rb +5 -2
- data/test/{sample_01.rb → assets/sample_01.rb} +0 -0
- data/test/{sample_02.rb → assets/sample_02.rb} +0 -0
- data/test/{sample_03.rb → assets/sample_03.rb} +0 -0
- data/test/{sample_04.rb → assets/sample_04.rb} +0 -0
- data/test/{sample_05-new.rb → assets/sample_05-new.rb} +0 -0
- data/test/{sample_05-old.rb → assets/sample_05-old.rb} +0 -0
- data/test/{sample_05.rb → assets/sample_05.rb} +0 -0
- data/test/{test_CallSiteAnalyzer.rb → call_site_analyzer_test.rb} +57 -81
- data/test/{test_CodeCoverageAnalyzer.rb → code_coverage_analyzer_test.rb} +71 -35
- data/test/{test_FileStatistics.rb → file_statistics_test.rb} +34 -36
- data/test/{test_functional.rb → functional_test.rb} +21 -35
- metadata +91 -69
- data/CHANGES +0 -177
- data/LEGAL +0 -36
- data/README.API +0 -42
- data/README.emacs +0 -64
- data/README.en +0 -130
- data/README.rake +0 -62
- data/README.rant +0 -68
- data/README.vim +0 -47
- data/Rantfile +0 -76
- data/ext/rcovrt/callsite.c +0 -242
- data/ext/rcovrt/rcovrt.c +0 -329
- data/lib/rcov/rant.rb +0 -87
- data/lib/rcov/report.rb +0 -1236
- data/mingw-rbconfig.rb +0 -174
data/BLURB
CHANGED
@@ -1,10 +1,3 @@
|
|
1
|
-
|
2
|
-
Source code, additional information, screenshots... available at
|
3
|
-
http://eigenclass.org/hiki/rcov
|
4
|
-
|
5
|
-
If you're on win32, you can also find a pre-built rcovrt.so (which makes
|
6
|
-
code coverage analysis >100 times faster) in the above-mentioned pages.
|
7
|
-
|
8
1
|
Overview
|
9
2
|
========
|
10
3
|
rcov is a code coverage tool for Ruby. It is commonly used for viewing overall
|
@@ -17,7 +10,7 @@ test coverage of target code. It features:
|
|
17
10
|
* fairly accurate coverage information through code linkage inference using
|
18
11
|
simple heuristics
|
19
12
|
* cross-referenced XHTML and several kinds of text reports
|
20
|
-
* support for easy automation with Rake
|
13
|
+
* support for easy automation with Rake
|
21
14
|
* colorblind-friendliness
|
22
15
|
|
23
16
|
How do I use it?
|
@@ -38,7 +31,7 @@ files: the tests themselves, files installed in Ruby's standard locations,
|
|
38
31
|
etc. See rcov --help for the list of regexps rcov matches filenames
|
39
32
|
against.
|
40
33
|
|
41
|
-
rcov can also be used from Rake; see
|
34
|
+
rcov can also be used from Rake; see readme_for_rake or the RDoc documentation
|
42
35
|
for more information.
|
43
36
|
|
44
37
|
rcov can output information in several formats, and perform different kinds
|
@@ -48,8 +41,6 @@ description of the available options.
|
|
48
41
|
Sample output
|
49
42
|
=============
|
50
43
|
|
51
|
-
See http://eigenclass.org/hiki.rb?rcov (once again) for screenshots.
|
52
|
-
|
53
44
|
The text report (also used by default in RcovTasks) resembles
|
54
45
|
|
55
46
|
|
@@ -118,32 +109,3 @@ tests:
|
|
118
109
|
License
|
119
110
|
-------
|
120
111
|
rcov is released under the terms of Ruby's license.
|
121
|
-
rcov includes xx 0.1.0, which is subject to the following conditions:
|
122
|
-
|
123
|
-
ePark Labs Public License version 1
|
124
|
-
Copyright (c) 2005, ePark Labs, Inc. and contributors
|
125
|
-
All rights reserved.
|
126
|
-
|
127
|
-
Redistribution and use in source and binary forms, with or without modification,
|
128
|
-
are permitted provided that the following conditions are met:
|
129
|
-
|
130
|
-
1. Redistributions of source code must retain the above copyright notice, this
|
131
|
-
list of conditions and the following disclaimer.
|
132
|
-
2. Redistributions in binary form must reproduce the above copyright notice,
|
133
|
-
this list of conditions and the following disclaimer in the documentation
|
134
|
-
and/or other materials provided with the distribution.
|
135
|
-
3. Neither the name of ePark Labs nor the names of its contributors may be
|
136
|
-
used to endorse or promote products derived from this software without
|
137
|
-
specific prior written permission.
|
138
|
-
|
139
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
140
|
-
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
141
|
-
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
142
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
143
|
-
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
144
|
-
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
145
|
-
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
146
|
-
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
147
|
-
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
148
|
-
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
149
|
-
|
data/LICENSE
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
rcov is copyrighted free software by Mauricio Fernandez <mfp@acm.org>.
|
2
|
-
You can redistribute it and/or modify it under either the terms of the GPL
|
3
|
-
|
2
|
+
You can redistribute it and/or modify it under either the terms of the GPL,
|
3
|
+
or the conditions below:
|
4
4
|
|
5
5
|
1. You may make and give away verbatim copies of the source form of the
|
6
6
|
software without restriction, provided that you duplicate all of the
|
@@ -41,9 +41,6 @@ You can redistribute it and/or modify it under either the terms of the GPL
|
|
41
41
|
software (possibly commercial). But some files in the distribution
|
42
42
|
are not written by the author, so that they are not under these terms.
|
43
43
|
|
44
|
-
For the list of those files and their copying conditions, see the
|
45
|
-
file LEGAL.
|
46
|
-
|
47
44
|
5. The scripts and library files supplied as input to or produced as
|
48
45
|
output from the software do not automatically fall under the
|
49
46
|
copyright of the software, but belong to whomever generated them,
|
data/Rakefile
CHANGED
@@ -1,11 +1,10 @@
|
|
1
|
-
# This Rakefile serves as an example of how to use Rcov::RcovTask.
|
2
|
-
# Take a look at the RDoc documentation (or README.rake) for further
|
3
|
-
# information.
|
4
|
-
|
5
1
|
$:.unshift "lib" if File.directory? "lib"
|
6
2
|
require 'rcov/rcovtask'
|
3
|
+
require 'rcov/version'
|
7
4
|
require 'rake/testtask'
|
8
5
|
require 'rake/rdoctask'
|
6
|
+
require 'rake/gempackagetask'
|
7
|
+
require 'rake/clean'
|
9
8
|
|
10
9
|
# Use the specified rcov executable instead of the one in $PATH
|
11
10
|
# (this way we get a sort of informal functional test).
|
@@ -14,11 +13,10 @@ require 'rake/rdoctask'
|
|
14
13
|
ENV["RCOVPATH"] = "bin/rcov"
|
15
14
|
|
16
15
|
# The following task is largely equivalent to:
|
17
|
-
#
|
18
|
-
# (really!)
|
16
|
+
# Rcov::RcovTask.new
|
19
17
|
desc "Create a cross-referenced code coverage report."
|
20
18
|
Rcov::RcovTask.new do |t|
|
21
|
-
t.test_files = FileList['test
|
19
|
+
t.test_files = FileList['test/*_test.rb']
|
22
20
|
t.ruby_opts << "-Ilib:ext/rcovrt" # in order to use this rcov
|
23
21
|
t.rcov_opts << "--xrefs" # comment to disable cross-references
|
24
22
|
t.verbose = true
|
@@ -26,7 +24,7 @@ end
|
|
26
24
|
|
27
25
|
desc "Analyze code coverage for the FileStatistics class."
|
28
26
|
Rcov::RcovTask.new(:rcov_sourcefile) do |t|
|
29
|
-
t.test_files = FileList['test/
|
27
|
+
t.test_files = FileList['test/file_statistics_test.rb']
|
30
28
|
t.verbose = true
|
31
29
|
t.rcov_opts << "--test-unit-only"
|
32
30
|
t.ruby_opts << "-Ilib:ext/rcovrt" # in order to use this rcov
|
@@ -34,7 +32,7 @@ Rcov::RcovTask.new(:rcov_sourcefile) do |t|
|
|
34
32
|
end
|
35
33
|
|
36
34
|
Rcov::RcovTask.new(:rcov_ccanalyzer) do |t|
|
37
|
-
t.test_files = FileList['test/
|
35
|
+
t.test_files = FileList['test/code_coverage_analyzer_test.rb']
|
38
36
|
t.verbose = true
|
39
37
|
t.rcov_opts << "--test-unit-only"
|
40
38
|
t.ruby_opts << "-Ilib:ext/rcovrt" # in order to use this rcov
|
@@ -42,10 +40,27 @@ Rcov::RcovTask.new(:rcov_ccanalyzer) do |t|
|
|
42
40
|
end
|
43
41
|
|
44
42
|
desc "Run the unit tests with rcovrt."
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
43
|
+
if RUBY_PLATFORM == 'java'
|
44
|
+
Rake::TestTask.new(:test_rcovrt => ["lib/rcovrt.jar"]) do |t|
|
45
|
+
t.libs << "lib"
|
46
|
+
t.ruby_opts << "--debug"
|
47
|
+
t.test_files = FileList['test/*_test.rb']
|
48
|
+
t.verbose = true
|
49
|
+
end
|
50
|
+
|
51
|
+
file "lib/rcovrt.jar" => FileList["ext/java/**/*.java"] do |t|
|
52
|
+
rm_f "lib/rcovrt.jar"
|
53
|
+
mkdir_p "pkg/classes"
|
54
|
+
sh "javac -classpath #{Java::JavaLang::System.getProperty('java.class.path')} -d pkg/classes #{t.prerequisites.join(' ')}"
|
55
|
+
sh "jar cf #{t.name} -C pkg/classes ."
|
56
|
+
end
|
57
|
+
else
|
58
|
+
Rake::TestTask.new(:test_rcovrt => ["ext/rcovrt/rcovrt.so"]) do |t|
|
59
|
+
system("cd ext/rcovrt && make clean && rm Makefile")
|
60
|
+
t.libs << "ext/rcovrt"
|
61
|
+
t.test_files = FileList['test/*_test.rb']
|
62
|
+
t.verbose = true
|
63
|
+
end
|
49
64
|
end
|
50
65
|
|
51
66
|
file "ext/rcovrt/rcovrt.so" => FileList["ext/rcovrt/*.c"] do
|
@@ -53,116 +68,27 @@ file "ext/rcovrt/rcovrt.so" => FileList["ext/rcovrt/*.c"] do
|
|
53
68
|
ruby "setup.rb setup"
|
54
69
|
end
|
55
70
|
|
56
|
-
desc "Run the unit tests in pure-Ruby mode."
|
71
|
+
desc "Run the unit tests in pure-Ruby mode ."
|
57
72
|
Rake::TestTask.new(:test_pure_ruby) do |t|
|
58
73
|
t.libs << "ext/rcovrt"
|
59
|
-
t.test_files = FileList['test/turn_off_rcovrt.rb', 'test
|
74
|
+
t.test_files = FileList['test/turn_off_rcovrt.rb', 'test/*_test.rb']
|
60
75
|
t.verbose = true
|
61
76
|
end
|
62
77
|
|
63
78
|
desc "Run the unit tests"
|
64
79
|
task :test => [:test_rcovrt]
|
65
80
|
|
66
|
-
task :default => :test
|
67
|
-
|
68
81
|
desc "install by setup.rb"
|
69
82
|
task :install do
|
70
83
|
sh "sudo ruby setup.rb install"
|
71
84
|
end
|
72
85
|
|
86
|
+
task :default => :test
|
87
|
+
|
73
88
|
desc "Generate rdoc documentation for the rcov library"
|
74
89
|
Rake::RDocTask.new("rdoc") { |rdoc|
|
75
90
|
rdoc.rdoc_dir = 'doc'
|
76
91
|
rdoc.title = "rcov"
|
77
92
|
rdoc.options << "--line-numbers" << "--inline-source"
|
78
|
-
rdoc.rdoc_files.include('README.API')
|
79
|
-
rdoc.rdoc_files.include('README.rake')
|
80
|
-
rdoc.rdoc_files.include('README.rant')
|
81
|
-
rdoc.rdoc_files.include('README.vim')
|
82
93
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
83
94
|
}
|
84
|
-
|
85
|
-
|
86
|
-
# {{{ Package tasks
|
87
|
-
|
88
|
-
require 'rcov/version'
|
89
|
-
|
90
|
-
PKG_REVISION = ".0"
|
91
|
-
PKG_FILES = FileList[
|
92
|
-
"bin/rcov",
|
93
|
-
"lib/**/*.rb",
|
94
|
-
"ext/rcovrt/extconf.rb",
|
95
|
-
"ext/rcovrt/*.c",
|
96
|
-
"ext/rcovrt/*.h",
|
97
|
-
"LEGAL", "LICENSE", "Rakefile", "Rantfile", "README.*", "THANKS", "test/*.rb",
|
98
|
-
"mingw-rbconfig.rb", "rcov.vim", "rcov.el",
|
99
|
-
"setup.rb", "BLURB", "CHANGES"
|
100
|
-
]
|
101
|
-
|
102
|
-
require 'rake/gempackagetask'
|
103
|
-
Spec = Gem::Specification.new do |s|
|
104
|
-
s.name = "rcov"
|
105
|
-
s.version = Rcov::VERSION + PKG_REVISION
|
106
|
-
s.summary = "Code coverage analysis tool for Ruby"
|
107
|
-
s.description = <<EOF
|
108
|
-
rcov is a code coverage tool for Ruby. It is commonly used for viewing overall
|
109
|
-
test unit coverage of target code. It features fast execution (20-300 times
|
110
|
-
faster than previous tools), multiple analysis modes, XHTML and several kinds
|
111
|
-
of text reports, easy automation with Rake via a RcovTask, fairly accurate
|
112
|
-
coverage information through code linkage inference using simple heuristics,
|
113
|
-
colorblind-friendliness...
|
114
|
-
EOF
|
115
|
-
s.files = PKG_FILES.to_a
|
116
|
-
s.require_path = 'lib'
|
117
|
-
s.extensions << "ext/rcovrt/extconf.rb"
|
118
|
-
s.author = "Mauricio Fernandez"
|
119
|
-
s.email = "mfp@acm.org"
|
120
|
-
s.homepage = "http://eigenclass.org/hiki.rb?rcov"
|
121
|
-
s.bindir = "bin" # Use these for applications.
|
122
|
-
s.executables = ["rcov"]
|
123
|
-
s.has_rdoc = true
|
124
|
-
s.extra_rdoc_files = %w[README.API README.rake README.rant README.vim]
|
125
|
-
s.rdoc_options << "--main" << "README.API" << "--title" << 'rcov code coverage tool'
|
126
|
-
s.test_files = Dir["test/test_*.rb"]
|
127
|
-
end
|
128
|
-
|
129
|
-
task :gem => [:test]
|
130
|
-
Rake::GemPackageTask.new(Spec) do |p|
|
131
|
-
p.need_tar = true
|
132
|
-
end
|
133
|
-
|
134
|
-
# {{{ Cross-compilation and building of a binary RubyGems package for mswin32
|
135
|
-
|
136
|
-
require 'rake/clean'
|
137
|
-
|
138
|
-
WIN32_PKG_DIR = "rcov-" + Rcov::VERSION + PKG_REVISION
|
139
|
-
|
140
|
-
file "#{WIN32_PKG_DIR}" => [:package] do
|
141
|
-
sh "tar zxf pkg/#{WIN32_PKG_DIR}.tgz"
|
142
|
-
end
|
143
|
-
|
144
|
-
desc "Cross-compile the rcovrt.so extension for win32"
|
145
|
-
file "rcovrt_win32" => ["#{WIN32_PKG_DIR}"] do
|
146
|
-
cp "mingw-rbconfig.rb", "#{WIN32_PKG_DIR}/ext/rcovrt/rbconfig.rb"
|
147
|
-
sh "cd #{WIN32_PKG_DIR}/ext/rcovrt/ && ruby -I. extconf.rb && make"
|
148
|
-
mv "#{WIN32_PKG_DIR}/ext/rcovrt/rcovrt.so", "#{WIN32_PKG_DIR}/lib"
|
149
|
-
end
|
150
|
-
|
151
|
-
Win32Spec = Spec.clone
|
152
|
-
Win32Spec.platform = Gem::Platform::WIN32
|
153
|
-
Win32Spec.extensions = []
|
154
|
-
Win32Spec.files += ["lib/rcovrt.so"]
|
155
|
-
|
156
|
-
desc "Build the binary RubyGems package for win32"
|
157
|
-
task :rubygems_win32 => ["rcovrt_win32"] do
|
158
|
-
Dir.chdir("#{WIN32_PKG_DIR}") do
|
159
|
-
Gem::Builder.new(Win32Spec).build
|
160
|
-
verbose(true) {
|
161
|
-
mv Dir["*.gem"].first, "../pkg/rcov-#{Rcov::VERSION + PKG_REVISION}-mswin32.gem"
|
162
|
-
}
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
CLEAN.include "#{WIN32_PKG_DIR}"
|
167
|
-
|
168
|
-
# vim: set sw=2 ft=ruby:
|
data/THANKS
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
Jay McGaffigan:
|
2
|
+
* JRuby support integrated from original rcov4j
|
3
|
+
|
4
|
+
Aaron Bedra:
|
5
|
+
* major refactoring
|
6
|
+
* added threshold testing
|
7
|
+
* Took on the task of keeping RCov going
|
8
|
+
|
9
|
+
Corey Ehmke (Bantik):
|
10
|
+
* redesigned index and detail XHTML
|
11
|
+
* added sortable columns in coverage table
|
12
|
+
* added file and coverage threshold filters to index XHTML
|
13
|
+
* added print-specific style sheet
|
14
|
+
* added support for custom CSS for XHTML output
|
1
15
|
|
2
16
|
Tom Dolbilin:
|
3
17
|
* identified and fixed backslash problem on win32 for generated filenames
|
data/bin/rcov
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# -*- coding: iso-8859-1 -*-
|
2
3
|
# rcov Copyright (c) 2004-2006 Mauricio Fernandez <mfp@acm.org>
|
3
4
|
#
|
4
5
|
# rcov originally based on
|
@@ -9,28 +10,14 @@
|
|
9
10
|
#
|
10
11
|
# See LEGAL and LICENSE for additional licensing information.
|
11
12
|
#
|
12
|
-
|
13
13
|
require 'cgi'
|
14
14
|
require 'rbconfig'
|
15
15
|
require 'optparse'
|
16
16
|
require 'ostruct'
|
17
|
-
# load xx-0.1.0-1
|
18
|
-
eval File.read(File.expand_path(__FILE__)).gsub(/.*^__END__$/m,"")
|
19
|
-
|
20
|
-
# extend XX
|
21
|
-
module XX
|
22
|
-
module XMLish
|
23
|
-
include Markup
|
24
|
-
|
25
|
-
def xmlish_ *a, &b
|
26
|
-
xx_which(XMLish){ xx_with_doc_in_effect(*a, &b)}
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
17
|
|
31
18
|
SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
|
32
19
|
require 'rcov/version'
|
33
|
-
require 'rcov/
|
20
|
+
require 'rcov/formatters'
|
34
21
|
|
35
22
|
#{{{ "main" code
|
36
23
|
options = OpenStruct.new
|
@@ -40,15 +27,17 @@ options.profiling = false
|
|
40
27
|
options.destdir = nil
|
41
28
|
options.loadpaths = []
|
42
29
|
options.textmode = false
|
43
|
-
options.skip = Rcov::
|
30
|
+
options.skip = Rcov::BaseFormatter::DEFAULT_OPTS[:ignore]
|
44
31
|
options.include = []
|
45
32
|
options.html = true
|
33
|
+
options.css = nil
|
46
34
|
options.comments_run_by_default = false
|
47
35
|
options.test_unit_only = false
|
48
36
|
options.spec_only = false
|
49
37
|
options.sort = :name
|
50
38
|
options.sort_reverse = false
|
51
39
|
options.output_threshold = 101
|
40
|
+
options.failure_threshold = nil
|
52
41
|
options.replace_prog_name = false
|
53
42
|
options.callsites = false
|
54
43
|
options.crossrefs = false
|
@@ -59,7 +48,6 @@ options.diff_cmd = "diff"
|
|
59
48
|
options.report_cov_bug_for = nil
|
60
49
|
options.aggregate_file = nil
|
61
50
|
options.gcc_output = false
|
62
|
-
options.show_validator_links = true
|
63
51
|
options.charset = nil
|
64
52
|
|
65
53
|
EXTRA_HELP = <<-EOF
|
@@ -80,239 +68,258 @@ $PROGRAM_NAME (aka. $0) will be set before each file is load()ed if
|
|
80
68
|
--replace-progname is used.
|
81
69
|
EOF
|
82
70
|
|
71
|
+
def deprecated(opt)
|
72
|
+
puts "#{opt} is now depricated. Please remove it from you Rakefile or scripts. It will be removed in the next release."
|
73
|
+
end
|
74
|
+
|
83
75
|
#{{{ OptionParser
|
84
76
|
opts = OptionParser.new do |opts|
|
85
77
|
opts.banner = <<-EOF
|
86
78
|
rcov #{Rcov::VERSION} #{Rcov::RELEASE_DATE}
|
87
79
|
Usage: rcov [options] <script1.rb> [script2.rb] [-- --extra-options]
|
88
80
|
EOF
|
89
|
-
|
90
|
-
|
91
|
-
opts.on("-o", "--output PATH", "Destination directory.") do |dir|
|
92
|
-
options.destdir = dir
|
93
|
-
end
|
94
|
-
opts.on("-I", "--include PATHS",
|
95
|
-
"Prepend PATHS to $: (colon separated list)") do |paths|
|
96
|
-
options.loadpaths = paths.split(/:/)
|
97
|
-
end
|
98
|
-
opts.on("--[no-]comments",
|
99
|
-
"Mark all comments by default.",
|
100
|
-
"(default: --no-comments)") do |comments_run_p|
|
101
|
-
options.comments_run_by_default = comments_run_p
|
102
|
-
end
|
103
|
-
opts.on("--test-unit-only",
|
104
|
-
"Only trace code executed inside TestCases.") do
|
105
|
-
options.test_unit_only = true
|
106
|
-
end
|
107
|
-
opts.on("--spec-only",
|
108
|
-
"Only trace code executed inside RSpec specs.") do
|
109
|
-
options.spec_only = true
|
110
|
-
end
|
111
|
-
opts.on("-n", "--no-color", "Create colorblind-safe output.") do
|
112
|
-
options.color = false
|
113
|
-
end
|
114
|
-
opts.on("-i", "--include-file PATTERNS",
|
115
|
-
"Generate info for files matching a",
|
116
|
-
"pattern (comma-separated regexp list)") do |list|
|
117
|
-
begin
|
118
|
-
regexps = list.split(/,/).map{|x| Regexp.new(x) }
|
119
|
-
options.include += regexps
|
120
|
-
rescue RegexpError => e
|
121
|
-
raise OptionParser::InvalidArgument, e.message
|
122
|
-
end
|
123
|
-
end
|
124
|
-
opts.on("-x", "--exclude PATTERNS",
|
125
|
-
"Don't generate info for files matching a",
|
126
|
-
"pattern (comma-separated regexp list)") do |list|
|
127
|
-
begin
|
128
|
-
regexps = list.split(/,/).map{|x| Regexp.new x}
|
129
|
-
options.skip += regexps
|
130
|
-
rescue RegexpError => e
|
131
|
-
raise OptionParser::InvalidArgument, e.message
|
132
|
-
end
|
133
|
-
end
|
134
|
-
opts.on("--exclude-only PATTERNS",
|
135
|
-
"Skip info only for files matching the",
|
136
|
-
"given patterns.") do |list|
|
137
|
-
begin
|
138
|
-
options.skip = list.split(/,/).map{|x| Regexp.new(x) }
|
139
|
-
rescue RegexpError => e
|
140
|
-
raise OptionParser::InvalidArgument, e.message
|
141
|
-
end
|
142
|
-
end
|
143
|
-
opts.on("--rails", "Skip config/, environment/ and vendor/.") do
|
144
|
-
options.skip.concat [%r{\bvendor/},%r{\bconfig/},%r{\benvironment/}]
|
145
|
-
end
|
146
|
-
opts.on("--[no-]callsites", "Show callsites in generated XHTML report.",
|
147
|
-
"(somewhat slower; disabled by default)") do |val|
|
148
|
-
options.callsites = val
|
149
|
-
end
|
150
|
-
opts.on("--[no-]xrefs", "Generate fully cross-referenced report.",
|
151
|
-
"(includes --callsites)") do |val|
|
152
|
-
options.crossrefs = val
|
153
|
-
options.callsites ||= val
|
154
|
-
end
|
155
|
-
opts.on("-p", "--profile", "Generate bogo-profiling info.") do
|
156
|
-
options.profiling = true
|
157
|
-
options.destdir ||= "profiling"
|
158
|
-
end
|
159
|
-
opts.on("-r", "--range RANGE", Float,
|
160
|
-
"Color scale range for profiling info (dB).") do |val|
|
161
|
-
options.range = val
|
162
|
-
end
|
163
|
-
opts.on("-a", "--annotate",
|
164
|
-
"Generate annotated source code.") do
|
165
|
-
options.html = false
|
166
|
-
options.textmode = :annotate
|
167
|
-
options.crossrefs = true
|
168
|
-
options.callsites = true
|
169
|
-
options.skip = [ %r!/test/unit/! ]
|
170
|
-
end
|
81
|
+
opts.separator ""
|
82
|
+
opts.separator "Options:"
|
171
83
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
options.coverage_diff_mode = :compare
|
205
|
-
options.coverage_diff_file = file if file && !file.empty?
|
206
|
-
end
|
207
|
-
opts.on("--save [FILE]", "Save coverage data to FILE,",
|
208
|
-
"for later use with rcov -D.",
|
209
|
-
"(default: coverage.info)") do |file|
|
210
|
-
options.coverage_diff_save = true
|
211
|
-
options.coverage_diff_mode = :record
|
212
|
-
if options.textmode == :coverage_diff
|
213
|
-
raise "You shouldn't use --save and --text-coverage-diff at a time."
|
214
|
-
end
|
215
|
-
options.coverage_diff_file = file if file && !file.empty?
|
216
|
-
end
|
217
|
-
opts.on("--[no-]html", "Generate HTML output.",
|
218
|
-
"(default: --html)") do |val|
|
219
|
-
options.html = val
|
220
|
-
end
|
221
|
-
opts.on("--sort CRITERION", [:name, :loc, :coverage],
|
222
|
-
"Sort files in the output by the specified",
|
223
|
-
"field (name, loc, coverage)") do |criterion|
|
224
|
-
options.sort = criterion
|
225
|
-
end
|
226
|
-
opts.on("--sort-reverse", "Reverse files in the output.") do
|
227
|
-
options.sort_reverse = true
|
228
|
-
end
|
229
|
-
opts.on("--threshold INT", "Only list files with coverage < INT %.",
|
230
|
-
"(default: 101)") do |threshold|
|
231
|
-
begin
|
232
|
-
threshold = Integer(threshold)
|
233
|
-
raise if threshold <= 0 || threshold > 101
|
234
|
-
rescue Exception
|
235
|
-
raise OptionParser::InvalidArgument, threshold
|
236
|
-
end
|
237
|
-
options.output_threshold = threshold
|
238
|
-
end
|
239
|
-
opts.on("--charset CHARSET",
|
240
|
-
"Charset used in Content-Type declaration of HTML reports.") do |c|
|
241
|
-
options.charset = c
|
242
|
-
end
|
243
|
-
opts.on("--[no-]validator-links", "Add link to W3C's validation services.",
|
244
|
-
"(default: true)") do |show_validator_links|
|
245
|
-
options.show_validator_links = show_validator_links
|
246
|
-
end
|
247
|
-
opts.on("--only-uncovered", "Same as --threshold 100") do
|
248
|
-
options.output_threshold = 100
|
84
|
+
opts.on("-o", "--output PATH", "Destination directory.") do |dir|
|
85
|
+
options.destdir = dir
|
86
|
+
end
|
87
|
+
|
88
|
+
opts.on("-I", "--include PATHS", "Prepend PATHS to $: (colon separated list)") do |paths|
|
89
|
+
options.loadpaths = paths.split(/:/)
|
90
|
+
end
|
91
|
+
|
92
|
+
opts.on("--[no-]comments", "Mark all comments by default.", "(default: --no-comments)") do |comments_run_p|
|
93
|
+
options.comments_run_by_default = comments_run_p
|
94
|
+
end
|
95
|
+
|
96
|
+
opts.on("--test-unit-only", "Only trace code executed inside TestCases.") do
|
97
|
+
deprecated("--test-unit-only")
|
98
|
+
end
|
99
|
+
|
100
|
+
opts.on("--spec-only", "Only trace code executed inside RSpec specs.") do
|
101
|
+
deprecated("--spec-only")
|
102
|
+
end
|
103
|
+
|
104
|
+
opts.on("-n", "--no-color", "Create colorblind-safe output.") do
|
105
|
+
options.color = false
|
106
|
+
end
|
107
|
+
|
108
|
+
opts.on("-i", "--include-file PATTERNS",
|
109
|
+
"Generate info for files matching a",
|
110
|
+
"pattern (comma-separated regexp list)") do |list|
|
111
|
+
begin
|
112
|
+
regexps = list.split(/,/).map{|x| Regexp.new(x) }
|
113
|
+
options.include += regexps
|
114
|
+
rescue RegexpError => e
|
115
|
+
raise OptionParser::InvalidArgument, e.message
|
249
116
|
end
|
250
|
-
|
251
|
-
|
117
|
+
end
|
118
|
+
|
119
|
+
opts.on("-x", "--exclude PATTERNS", "Don't generate info for files matching a","pattern (comma-separated regexp list)") do |list|
|
120
|
+
begin
|
121
|
+
regexps = list.split(/,/).map{|x| Regexp.new x}
|
122
|
+
options.skip += regexps
|
123
|
+
rescue RegexpError => e
|
124
|
+
raise OptionParser::InvalidArgument, e.message
|
252
125
|
end
|
253
|
-
|
254
|
-
|
126
|
+
end
|
127
|
+
|
128
|
+
opts.on("--exclude-only PATTERNS", "Skip info only for files matching the", "given patterns.") do |list|
|
129
|
+
begin
|
130
|
+
options.skip = list.split(/,/).map{|x| Regexp.new(x) }
|
131
|
+
rescue RegexpError => e
|
132
|
+
raise OptionParser::InvalidArgument, e.message
|
255
133
|
end
|
256
|
-
|
257
|
-
|
258
|
-
|
134
|
+
end
|
135
|
+
|
136
|
+
opts.on("--rails", "Skip config/, environment/ and vendor/.") do
|
137
|
+
options.skip.concat [%r{\bvendor/},%r{\bconfig/},%r{\benvironment/}]
|
138
|
+
end
|
139
|
+
|
140
|
+
opts.on("--[no-]callsites", "Show callsites in generated XHTML report.", "(somewhat slower; disabled by default)") do |val|
|
141
|
+
options.callsites = val
|
142
|
+
end
|
143
|
+
|
144
|
+
opts.on("--[no-]xrefs", "Generate fully cross-referenced report.", "(includes --callsites)") do |val|
|
145
|
+
options.crossrefs = val
|
146
|
+
options.callsites ||= val
|
147
|
+
end
|
148
|
+
|
149
|
+
opts.on("-p", "--profile", "Generate bogo-profiling info.") do
|
150
|
+
options.profiling = true
|
151
|
+
options.destdir ||= "profiling"
|
152
|
+
end
|
153
|
+
|
154
|
+
opts.on("-r", "--range RANGE", Float, "Color scale range for profiling info (dB).") do |val|
|
155
|
+
options.range = val
|
156
|
+
end
|
157
|
+
|
158
|
+
opts.on("-a", "--annotate", "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
|
+
|
166
|
+
opts.on("-T", "--text-report", "Dump detailed plain-text report to stdout.", "(filename, LoC, total lines, coverage)") do
|
167
|
+
options.textmode = :report
|
168
|
+
end
|
169
|
+
|
170
|
+
opts.on("-t", "--text-summary", "Dump plain-text summary to stdout.") do
|
171
|
+
options.textmode = :summary
|
172
|
+
end
|
173
|
+
|
174
|
+
opts.on("--text-counts", "Dump execution counts in plaintext.") do
|
175
|
+
options.textmode = :counts
|
176
|
+
end
|
177
|
+
|
178
|
+
opts.on("--text-coverage", "Dump coverage info to stdout, using", "ANSI color sequences unless -n.") do
|
179
|
+
options.textmode = :coverage
|
180
|
+
end
|
181
|
+
|
182
|
+
opts.on("--gcc", "Dump uncovered line in GCC error format.") do
|
183
|
+
options.gcc_output = true
|
184
|
+
end
|
185
|
+
|
186
|
+
opts.on("--aggregate FILE", "Aggregate data from previous runs",
|
187
|
+
"in FILE. Overwrites FILE with the",
|
188
|
+
"merged data. FILE is created if",
|
189
|
+
"necessary.") do |file|
|
190
|
+
options.aggregate_file = file
|
191
|
+
end
|
192
|
+
|
193
|
+
opts.on("-D [FILE]", "--text-coverage-diff [FILE]",
|
194
|
+
"Compare code coverage with saved state",
|
195
|
+
"in FILE, defaults to coverage.info.",
|
196
|
+
"Implies --comments.") do |file|
|
197
|
+
options.textmode = :coverage_diff
|
198
|
+
options.comments_run_by_default = true
|
199
|
+
if options.coverage_diff_save
|
200
|
+
raise "You shouldn't use --save and --text-coverage-diff at a time."
|
201
|
+
end
|
202
|
+
options.coverage_diff_mode = :compare
|
203
|
+
options.coverage_diff_file = file if file && !file.empty?
|
204
|
+
end
|
205
|
+
|
206
|
+
opts.on("--save [FILE]", "Save coverage data to FILE,", "for later use with rcov -D.", "(default: coverage.info)") do |file|
|
207
|
+
options.coverage_diff_save = true
|
208
|
+
options.coverage_diff_mode = :record
|
209
|
+
if options.textmode == :coverage_diff
|
210
|
+
raise "You shouldn't use --save and --text-coverage-diff at a time."
|
259
211
|
end
|
260
|
-
|
261
|
-
|
262
|
-
|
212
|
+
options.coverage_diff_file = file if file && !file.empty?
|
213
|
+
end
|
214
|
+
|
215
|
+
opts.on("--[no-]html", "Generate HTML output.", "(default: --html)") do |val|
|
216
|
+
options.html = val
|
217
|
+
end
|
218
|
+
|
219
|
+
opts.on("--css relative/path/to/custom.css", "Use a custom CSS file for HTML output.", "Specified as a relative path.") do |val|
|
220
|
+
options.css = val
|
221
|
+
end
|
222
|
+
|
223
|
+
opts.on("--sort CRITERION", [:name, :loc, :coverage], "Sort files in the output by the specified", "field (name, loc, coverage)") do |criterion|
|
224
|
+
options.sort = criterion
|
225
|
+
end
|
226
|
+
|
227
|
+
opts.on("--sort-reverse", "Reverse files in the output.") do
|
228
|
+
options.sort_reverse = true
|
229
|
+
end
|
230
|
+
|
231
|
+
opts.on("--threshold INT", "Only list files with coverage < INT %.", "(default: 101)") do |threshold|
|
232
|
+
begin
|
233
|
+
threshold = Integer(threshold)
|
234
|
+
raise if threshold <= 0 || threshold > 101
|
235
|
+
rescue Exception
|
236
|
+
raise OptionParser::InvalidArgument, threshold
|
263
237
|
end
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
238
|
+
options.output_threshold = threshold
|
239
|
+
end
|
240
|
+
|
241
|
+
opts.on("--failure-threshold [INT]", "Fail if the coverage is below the threshold", "(default: 100)") do |threshold|
|
242
|
+
options.failure_threshold = (threshold || 100).to_i
|
243
|
+
options.textmode = :failure_report
|
244
|
+
end
|
245
|
+
|
246
|
+
opts.on("--charset CHARSET", "Charset used in Content-Type declaration of HTML reports.") do |c|
|
247
|
+
options.charset = c
|
248
|
+
end
|
249
|
+
|
250
|
+
opts.on("--only-uncovered", "Same as --threshold 100") do
|
251
|
+
options.output_threshold = 100
|
252
|
+
end
|
253
|
+
|
254
|
+
opts.on("--replace-progname", "Replace $0 when loading the .rb files.") do
|
255
|
+
options.replace_prog_name = true
|
256
|
+
end
|
257
|
+
|
258
|
+
opts.on("-w", "Turn warnings on (like ruby).") do
|
259
|
+
$VERBOSE = true
|
260
|
+
end
|
261
|
+
|
262
|
+
opts.on("--no-rcovrt", "Do not use the optimized C runtime.", "(will run 30-300 times slower)") do
|
263
|
+
$rcov_do_not_use_rcovrt = true
|
264
|
+
end
|
265
|
+
|
266
|
+
opts.on("--diff-cmd PROGNAME", "Use PROGNAME for --text-coverage-diff.",
|
267
|
+
"(default: diff)") do |cmd|
|
268
|
+
options.diff_cmd = cmd
|
269
|
+
end
|
270
|
+
|
271
|
+
opts.separator ""
|
272
|
+
|
273
|
+
opts.on_tail("-h", "--help", "Show extended help message") do
|
274
|
+
require 'pp'
|
275
|
+
puts opts
|
276
|
+
puts <<EOF
|
269
277
|
|
270
278
|
Files matching any of the following regexps will be omitted in the report(s):
|
271
279
|
#{PP.pp(options.skip, "").chomp}
|
272
280
|
EOF
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
raise OptionParser::InvalidArgument, selector
|
284
|
-
end
|
285
|
-
options.textmode = nil
|
286
|
-
options.html = false
|
287
|
-
options.callsites = true
|
288
|
-
end
|
289
|
-
opts.on_tail("--version", "Show version") do
|
290
|
-
puts "rcov " + Rcov::VERSION + " " + Rcov::RELEASE_DATE
|
291
|
-
exit
|
281
|
+
puts EXTRA_HELP
|
282
|
+
exit
|
283
|
+
end
|
284
|
+
|
285
|
+
opts.on_tail("--report-cov-bug SELECTOR", "Report coverage analysis bug for the",
|
286
|
+
"method specified by SELECTOR", "(format: Foo::Bar#method, A::B.method)") do |selector|
|
287
|
+
case selector
|
288
|
+
when /([^.]+)(#|\.)(.*)/ then options.report_cov_bug_for = selector
|
289
|
+
else
|
290
|
+
raise OptionParser::InvalidArgument, selector
|
292
291
|
end
|
292
|
+
options.textmode = nil
|
293
|
+
options.html = false
|
294
|
+
options.callsites = true
|
295
|
+
end
|
296
|
+
opts.on_tail("--version", "Show version") do
|
297
|
+
puts "rcov " + Rcov::VERSION + " " + Rcov::RELEASE_DATE
|
298
|
+
exit
|
299
|
+
end
|
293
300
|
end
|
294
301
|
|
295
302
|
$ORIGINAL_ARGV = ARGV.clone
|
296
303
|
if (idx = ARGV.index("--"))
|
297
|
-
|
298
|
-
|
304
|
+
extra_args = ARGV[idx+1..-1]
|
305
|
+
ARGV.replace(ARGV[0,idx])
|
299
306
|
else
|
300
|
-
|
307
|
+
extra_args = []
|
301
308
|
end
|
302
309
|
|
303
310
|
begin
|
304
|
-
|
305
|
-
rescue OptionParser::InvalidOption, OptionParser::InvalidArgument,
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
exit(-1)
|
311
|
+
opts.parse! ARGV
|
312
|
+
rescue OptionParser::InvalidOption, OptionParser::InvalidArgument, OptionParser::MissingArgument => e
|
313
|
+
puts opts
|
314
|
+
puts
|
315
|
+
puts e.message
|
316
|
+
exit(-1)
|
311
317
|
end
|
318
|
+
|
312
319
|
options.destdir ||= "coverage"
|
313
320
|
unless ARGV[0] or options.aggregate_file && File.file?(options.aggregate_file)
|
314
|
-
|
315
|
-
|
321
|
+
puts opts
|
322
|
+
exit
|
316
323
|
end
|
317
324
|
|
318
325
|
# {{{ set loadpath
|
@@ -327,35 +334,34 @@ options.callsites = true if options.report_cov_bug_for
|
|
327
334
|
options.textmode = :gcc if !options.textmode and options.gcc_output
|
328
335
|
|
329
336
|
def rcov_load_aggregate_data(file)
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
337
|
+
require 'zlib'
|
338
|
+
begin
|
339
|
+
old_data = nil
|
340
|
+
Zlib::GzipReader.open(file){|gz| old_data = Marshal.load(gz) }
|
341
|
+
rescue
|
342
|
+
old_data = {}
|
343
|
+
end
|
344
|
+
old_data || {}
|
338
345
|
end
|
339
346
|
|
340
347
|
def rcov_save_aggregate_data(file)
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
end
|
348
|
+
require 'zlib'
|
349
|
+
Zlib::GzipWriter.open(file) do |f|
|
350
|
+
Marshal.dump({:callsites => $rcov_callsite_analyzer, :coverage => $rcov_code_coverage_analyzer}, f)
|
351
|
+
end
|
346
352
|
end
|
347
353
|
|
348
354
|
if options.callsites
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
end
|
355
|
+
if options.aggregate_file
|
356
|
+
saved_aggregate_data = rcov_load_aggregate_data(options.aggregate_file)
|
357
|
+
if saved_aggregate_data[:callsites]
|
358
|
+
$rcov_callsite_analyzer = saved_aggregate_data[:callsites]
|
354
359
|
end
|
355
|
-
|
356
|
-
|
360
|
+
end
|
361
|
+
$rcov_callsite_analyzer ||= Rcov::CallSiteAnalyzer.new
|
362
|
+
$rcov_callsite_analyzer.install_hook
|
357
363
|
else
|
358
|
-
|
364
|
+
$rcov_callsite_analyzer = nil
|
359
365
|
end
|
360
366
|
|
361
367
|
# {{{ create formatters
|
@@ -375,37 +381,38 @@ make_formatter = lambda do |klass|
|
|
375
381
|
:diff_cmd => options.diff_cmd,
|
376
382
|
:comments_run_by_default => options.comments_run_by_default,
|
377
383
|
:gcc_output => options.gcc_output,
|
378
|
-
:
|
379
|
-
:
|
384
|
+
:charset => options.charset,
|
385
|
+
:css => options.css,
|
386
|
+
:failure_threshold => options.failure_threshold
|
380
387
|
)
|
381
388
|
end
|
382
389
|
|
383
390
|
if options.html
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
391
|
+
if options.profiling
|
392
|
+
formatters << make_formatter[Rcov::HTMLProfiling]
|
393
|
+
else
|
394
|
+
formatters << make_formatter[Rcov::HTMLCoverage]
|
395
|
+
end
|
389
396
|
end
|
390
|
-
|
391
|
-
|
392
|
-
:gcc => Rcov::FullTextReport,
|
393
|
-
:annotate => Rcov::RubyAnnotation,
|
397
|
+
|
398
|
+
textual_formatters = { :counts => Rcov::FullTextReport, :coverage => Rcov::FullTextReport,
|
399
|
+
:gcc => Rcov::FullTextReport, :annotate => Rcov::RubyAnnotation,
|
394
400
|
:summary => Rcov::TextSummary, :report => Rcov::TextReport,
|
395
|
-
:coverage_diff => Rcov::TextCoverageDiff}
|
401
|
+
:coverage_diff => Rcov::TextCoverageDiff, :failure_report => Rcov::FailureReport }
|
396
402
|
|
397
403
|
if textual_formatters[options.textmode]
|
398
|
-
|
404
|
+
formatters << make_formatter[textual_formatters[options.textmode]]
|
399
405
|
end
|
400
406
|
|
401
407
|
formatters << make_formatter[Rcov::TextCoverageDiff] if options.coverage_diff_save
|
402
408
|
|
403
409
|
if options.aggregate_file
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
410
|
+
saved_aggregate_data ||= rcov_load_aggregate_data(options.aggregate_file)
|
411
|
+
if saved_aggregate_data[:coverage]
|
412
|
+
$rcov_code_coverage_analyzer = saved_aggregate_data[:coverage]
|
413
|
+
end
|
408
414
|
end
|
415
|
+
|
409
416
|
$rcov_code_coverage_analyzer ||= Rcov::CodeCoverageAnalyzer.new
|
410
417
|
|
411
418
|
# must be registered before test/unit puts its own
|
@@ -433,10 +440,9 @@ EOF
|
|
433
440
|
|
434
441
|
Please fill in the blanks in the following report.
|
435
442
|
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
http://eigenclass.org/hiki.rb?rcov+#{VERSION}
|
443
|
+
|
444
|
+
You can post bugs to
|
445
|
+
http://github.com/relevance/rcov/issues
|
440
446
|
|
441
447
|
Thank you!
|
442
448
|
|
@@ -462,7 +468,7 @@ EOF
|
|
462
468
|
end
|
463
469
|
exit
|
464
470
|
end
|
465
|
-
|
471
|
+
if !formatters.empty? and formatters.all?{|formatter| formatter.sorted_file_pairs.empty? }
|
466
472
|
require 'pp'
|
467
473
|
$stderr.puts <<-EOF
|
468
474
|
|
@@ -488,840 +494,21 @@ EOF
|
|
488
494
|
raise $__rcov_exit_exception if $__rcov_exit_exception
|
489
495
|
}
|
490
496
|
|
491
|
-
|
492
|
-
require 'test/unit'
|
493
|
-
module Test::Unit
|
494
|
-
class TestCase
|
495
|
-
remove_method(:run) if instance_methods.include? "run"
|
496
|
-
def run(result)
|
497
|
-
yield(STARTED, name)
|
498
|
-
@_result = result
|
499
|
-
begin
|
500
|
-
$rcov_code_coverage_analyzer.run_hooked do
|
501
|
-
setup
|
502
|
-
__send__(@method_name)
|
503
|
-
end
|
504
|
-
rescue AssertionFailedError => e
|
505
|
-
add_failure(e.message, e.backtrace)
|
506
|
-
rescue StandardError, ScriptError
|
507
|
-
add_error($!)
|
508
|
-
ensure
|
509
|
-
begin
|
510
|
-
$rcov_code_coverage_analyzer.run_hooked { teardown }
|
511
|
-
rescue AssertionFailedError => e
|
512
|
-
add_failure(e.message, e.backtrace)
|
513
|
-
rescue StandardError, ScriptError
|
514
|
-
add_error($!)
|
515
|
-
end
|
516
|
-
end
|
517
|
-
result.add_run
|
518
|
-
yield(FINISHED, name)
|
519
|
-
end
|
520
|
-
end
|
521
|
-
end
|
522
|
-
elsif options.spec_only
|
523
|
-
require 'spec'
|
524
|
-
override_run = lambda do
|
525
|
-
oldrun = instance_method(:run)
|
526
|
-
define_method(:run) do |*args|
|
527
|
-
$rcov_code_coverage_analyzer.run_hooked { oldrun.bind(self).call(*args) }
|
528
|
-
end
|
529
|
-
end
|
530
|
-
if defined? Spec::DSL::Example
|
531
|
-
Spec::DSL::Example.instance_eval(&override_run)
|
532
|
-
elsif defined? Spec::Example::ExampleGroup
|
533
|
-
Spec::Example::ExampleGroup.instance_eval(&override_run)
|
534
|
-
else
|
535
|
-
$stderr.puts <<-EOF
|
536
|
-
Your RSpec version isn't supported. If it's a old one, consider upgrading;
|
537
|
-
otherwise, please report the problem.
|
538
|
-
EOF
|
539
|
-
exit(-1)
|
540
|
-
end
|
541
|
-
else
|
542
|
-
$rcov_code_coverage_analyzer.install_hook
|
543
|
-
end
|
497
|
+
$rcov_code_coverage_analyzer.install_hook
|
544
498
|
|
545
499
|
#{{{ Load scripts
|
546
500
|
begin
|
547
|
-
pending_scripts = ARGV.clone
|
548
|
-
ARGV.replace extra_args
|
549
|
-
until pending_scripts.empty?
|
501
|
+
pending_scripts = ARGV.clone
|
502
|
+
ARGV.replace extra_args
|
503
|
+
until pending_scripts.empty?
|
550
504
|
prog = pending_scripts.shift
|
551
505
|
if options.replace_prog_name
|
552
|
-
|
506
|
+
$0 = File.basename(File.expand_path(prog))
|
553
507
|
end
|
554
508
|
load prog
|
555
|
-
end
|
509
|
+
end
|
556
510
|
rescue Object => err
|
557
511
|
$__rcov_exit_exception = err
|
558
512
|
end
|
559
513
|
|
560
|
-
# xx-0.1.0-1 follows
|
561
514
|
__END__
|
562
|
-
# xx can be redistributed and used under the following conditions
|
563
|
-
# (just keep the following copyright notice, list of conditions and disclaimer
|
564
|
-
# in order to satisfy rcov's "Ruby license" and xx's license simultaneously).
|
565
|
-
#
|
566
|
-
#ePark Labs Public License version 1
|
567
|
-
#Copyright (c) 2005, ePark Labs, Inc. and contributors
|
568
|
-
#All rights reserved.
|
569
|
-
#
|
570
|
-
#Redistribution and use in source and binary forms, with or without modification,
|
571
|
-
#are permitted provided that the following conditions are met:
|
572
|
-
#
|
573
|
-
# 1. Redistributions of source code must retain the above copyright notice, this
|
574
|
-
# list of conditions and the following disclaimer.
|
575
|
-
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
576
|
-
# this list of conditions and the following disclaimer in the documentation
|
577
|
-
# and/or other materials provided with the distribution.
|
578
|
-
# 3. Neither the name of ePark Labs nor the names of its contributors may be
|
579
|
-
# used to endorse or promote products derived from this software without
|
580
|
-
# specific prior written permission.
|
581
|
-
#
|
582
|
-
#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
583
|
-
#ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
584
|
-
#WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
585
|
-
#DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
586
|
-
#ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
587
|
-
#(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
588
|
-
#LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
589
|
-
#ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
590
|
-
#(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
591
|
-
#SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
592
|
-
|
593
|
-
unless defined? $__xx_rb__
|
594
|
-
|
595
|
-
require "rexml/document"
|
596
|
-
|
597
|
-
|
598
|
-
module XX
|
599
|
-
#--{{{
|
600
|
-
VERSION = "0.1.0"
|
601
|
-
|
602
|
-
%w(
|
603
|
-
CRAZY_LIKE_A_HELL
|
604
|
-
PERMISSIVE
|
605
|
-
STRICT
|
606
|
-
ANY
|
607
|
-
).each{|c| const_set c, c}
|
608
|
-
|
609
|
-
class Document
|
610
|
-
#--{{{
|
611
|
-
attr "doc"
|
612
|
-
attr "stack"
|
613
|
-
attr "size"
|
614
|
-
|
615
|
-
def initialize *a, &b
|
616
|
-
#--{{{
|
617
|
-
@doc = ::REXML::Document::new(*a, &b)
|
618
|
-
@stack = [@doc]
|
619
|
-
@size = 0
|
620
|
-
#--}}}
|
621
|
-
end
|
622
|
-
def top
|
623
|
-
#--{{{
|
624
|
-
@stack.last
|
625
|
-
#--}}}
|
626
|
-
end
|
627
|
-
def push element
|
628
|
-
#--{{{
|
629
|
-
@stack.push element
|
630
|
-
#--}}}
|
631
|
-
end
|
632
|
-
def pop
|
633
|
-
#--{{{
|
634
|
-
@stack.pop unless @stack.size == 1
|
635
|
-
#--}}}
|
636
|
-
end
|
637
|
-
def tracking_additions
|
638
|
-
#--{{{
|
639
|
-
n = @size
|
640
|
-
yield
|
641
|
-
return @size - n
|
642
|
-
#--}}}
|
643
|
-
end
|
644
|
-
def to_str port = ""
|
645
|
-
#--{{{
|
646
|
-
@doc.write port, indent=-1, transitive=false, ie_hack=true
|
647
|
-
port
|
648
|
-
#--}}}
|
649
|
-
end
|
650
|
-
alias_method "to_s", "to_str"
|
651
|
-
def pretty port = ''
|
652
|
-
#--{{{
|
653
|
-
@doc.write port, indent=2, transitive=false, ie_hack=true
|
654
|
-
port
|
655
|
-
#--}}}
|
656
|
-
end
|
657
|
-
def create element
|
658
|
-
#--{{{
|
659
|
-
push element
|
660
|
-
begin
|
661
|
-
object = nil
|
662
|
-
additions =
|
663
|
-
tracking_additions do
|
664
|
-
object = yield element if block_given?
|
665
|
-
end
|
666
|
-
if object and additions.zero?
|
667
|
-
self << object
|
668
|
-
end
|
669
|
-
ensure
|
670
|
-
pop
|
671
|
-
end
|
672
|
-
self << element
|
673
|
-
element
|
674
|
-
#--}}}
|
675
|
-
end
|
676
|
-
def << object
|
677
|
-
#--{{{
|
678
|
-
t, x = top, object
|
679
|
-
|
680
|
-
if x
|
681
|
-
case t
|
682
|
-
when ::REXML::Document
|
683
|
-
|
684
|
-
begin
|
685
|
-
t <<
|
686
|
-
case x
|
687
|
-
when ::REXML::Document
|
688
|
-
x.root || ::REXML::Text::new(x.to_s)
|
689
|
-
when ::REXML::Element
|
690
|
-
x
|
691
|
-
when ::REXML::CData
|
692
|
-
x
|
693
|
-
when ::REXML::Text
|
694
|
-
x
|
695
|
-
else # string
|
696
|
-
::REXML::Text::new(x.to_s)
|
697
|
-
end
|
698
|
-
rescue
|
699
|
-
if t.respond_to? "root"
|
700
|
-
t = t.root
|
701
|
-
retry
|
702
|
-
else
|
703
|
-
raise
|
704
|
-
end
|
705
|
-
end
|
706
|
-
|
707
|
-
when ::REXML::Element
|
708
|
-
t <<
|
709
|
-
case x
|
710
|
-
when ::REXML::Document
|
711
|
-
x.root || ::REXML::Text::new(x.to_s)
|
712
|
-
when ::REXML::Element
|
713
|
-
x
|
714
|
-
when ::REXML::CData
|
715
|
-
#::REXML::Text::new(x.write(""))
|
716
|
-
x
|
717
|
-
when ::REXML::Text
|
718
|
-
x
|
719
|
-
else # string
|
720
|
-
::REXML::Text::new(x.to_s)
|
721
|
-
end
|
722
|
-
|
723
|
-
when ::REXML::Text
|
724
|
-
t <<
|
725
|
-
case x
|
726
|
-
when ::REXML::Document
|
727
|
-
x.write ""
|
728
|
-
when ::REXML::Element
|
729
|
-
x.write ""
|
730
|
-
when ::REXML::CData
|
731
|
-
x.write ""
|
732
|
-
when ::REXML::Text
|
733
|
-
x.write ""
|
734
|
-
else # string
|
735
|
-
x.to_s
|
736
|
-
end
|
737
|
-
|
738
|
-
else # other - try anyhow
|
739
|
-
t <<
|
740
|
-
case x
|
741
|
-
when ::REXML::Document
|
742
|
-
x.write ""
|
743
|
-
when ::REXML::Element
|
744
|
-
x.write ""
|
745
|
-
when ::REXML::CData
|
746
|
-
x.write ""
|
747
|
-
when ::REXML::Text
|
748
|
-
x.write ""
|
749
|
-
else # string
|
750
|
-
x.to_s
|
751
|
-
end
|
752
|
-
end
|
753
|
-
end
|
754
|
-
|
755
|
-
@size += 1
|
756
|
-
self
|
757
|
-
#--}}}
|
758
|
-
end
|
759
|
-
#--}}}
|
760
|
-
end
|
761
|
-
|
762
|
-
module Markup
|
763
|
-
#--{{{
|
764
|
-
class Error < ::StandardError; end
|
765
|
-
|
766
|
-
module InstanceMethods
|
767
|
-
#--{{{
|
768
|
-
def method_missing m, *a, &b
|
769
|
-
#--{{{
|
770
|
-
m = m.to_s
|
771
|
-
|
772
|
-
tag_method, tag_name = xx_class::xx_tag_method_name m
|
773
|
-
|
774
|
-
c_method_missing = xx_class::xx_config_for "method_missing", xx_which
|
775
|
-
c_tags = xx_class::xx_config_for "tags", xx_which
|
776
|
-
|
777
|
-
pat =
|
778
|
-
case c_method_missing
|
779
|
-
when ::XX::CRAZY_LIKE_A_HELL
|
780
|
-
%r/.*/
|
781
|
-
when ::XX::PERMISSIVE
|
782
|
-
%r/_$/o
|
783
|
-
when ::XX::STRICT
|
784
|
-
%r/_$/o
|
785
|
-
else
|
786
|
-
super(m.to_sym, *a, &b)
|
787
|
-
end
|
788
|
-
|
789
|
-
super(m.to_sym, *a, &b) unless m =~ pat
|
790
|
-
|
791
|
-
if c_method_missing == ::XX::STRICT
|
792
|
-
super(m.to_sym, *a, &b) unless c_tags.include? tag_name
|
793
|
-
end
|
794
|
-
|
795
|
-
ret, defined = nil
|
796
|
-
|
797
|
-
begin
|
798
|
-
xx_class::xx_define_tmp_method tag_method
|
799
|
-
xx_class::xx_define_tag_method tag_method, tag_name
|
800
|
-
ret = send tag_method, *a, &b
|
801
|
-
defined = true
|
802
|
-
ensure
|
803
|
-
xx_class::xx_remove_tag_method tag_method unless defined
|
804
|
-
end
|
805
|
-
|
806
|
-
ret
|
807
|
-
#--}}}
|
808
|
-
end
|
809
|
-
def xx_tag_ tag_name, *a, &b
|
810
|
-
#--{{{
|
811
|
-
tag_method, tag_name = xx_class::xx_tag_method_name tag_name
|
812
|
-
|
813
|
-
ret, defined = nil
|
814
|
-
|
815
|
-
begin
|
816
|
-
xx_class::xx_define_tmp_method tag_method
|
817
|
-
xx_class::xx_define_tag_method tag_method, tag_name
|
818
|
-
ret = send tag_method, *a, &b
|
819
|
-
defined = true
|
820
|
-
ensure
|
821
|
-
xx_class::xx_remove_tag_method tag_method unless defined
|
822
|
-
end
|
823
|
-
|
824
|
-
ret
|
825
|
-
#--}}}
|
826
|
-
end
|
827
|
-
alias_method "g_", "xx_tag_"
|
828
|
-
def xx_which *argv
|
829
|
-
#--{{{
|
830
|
-
@xx_which = nil unless defined? @xx_which
|
831
|
-
if argv.empty?
|
832
|
-
@xx_which
|
833
|
-
else
|
834
|
-
xx_which = @xx_which
|
835
|
-
begin
|
836
|
-
@xx_which = argv.shift
|
837
|
-
return yield
|
838
|
-
ensure
|
839
|
-
@xx_which = xx_which
|
840
|
-
end
|
841
|
-
end
|
842
|
-
#--}}}
|
843
|
-
end
|
844
|
-
def xx_with_doc_in_effect *a, &b
|
845
|
-
#--{{{
|
846
|
-
@xx_docs ||= []
|
847
|
-
doc = ::XX::Document::new(*a)
|
848
|
-
ddoc = doc.doc
|
849
|
-
begin
|
850
|
-
@xx_docs.push doc
|
851
|
-
b.call doc if b
|
852
|
-
|
853
|
-
doctype = xx_config_for "doctype", xx_which
|
854
|
-
if doctype
|
855
|
-
unless ddoc.doctype
|
856
|
-
doctype = ::REXML::DocType::new doctype unless
|
857
|
-
::REXML::DocType === doctype
|
858
|
-
ddoc << doctype
|
859
|
-
end
|
860
|
-
end
|
861
|
-
|
862
|
-
xmldecl = xx_config_for "xmldecl", xx_which
|
863
|
-
if xmldecl
|
864
|
-
if ddoc.xml_decl == ::REXML::XMLDecl::default
|
865
|
-
xmldecl = ::REXML::XMLDecl::new xmldecl unless
|
866
|
-
::REXML::XMLDecl === xmldecl
|
867
|
-
ddoc << xmldecl
|
868
|
-
end
|
869
|
-
end
|
870
|
-
|
871
|
-
return doc
|
872
|
-
ensure
|
873
|
-
@xx_docs.pop
|
874
|
-
end
|
875
|
-
#--}}}
|
876
|
-
end
|
877
|
-
def xx_doc
|
878
|
-
#--{{{
|
879
|
-
@xx_docs.last rescue raise "no xx_doc in effect!"
|
880
|
-
#--}}}
|
881
|
-
end
|
882
|
-
def xx_text_ *objects, &b
|
883
|
-
#--{{{
|
884
|
-
doc = xx_doc
|
885
|
-
|
886
|
-
text =
|
887
|
-
::REXML::Text::new("",
|
888
|
-
respect_whitespace=true, parent=nil
|
889
|
-
)
|
890
|
-
|
891
|
-
objects.each do |object|
|
892
|
-
text << object.to_s if object
|
893
|
-
end
|
894
|
-
|
895
|
-
doc.create text, &b
|
896
|
-
#--}}}
|
897
|
-
end
|
898
|
-
alias_method "text_", "xx_text_"
|
899
|
-
alias_method "t_", "xx_text_"
|
900
|
-
def xx_markup_ *objects, &b
|
901
|
-
#--{{{
|
902
|
-
doc = xx_doc
|
903
|
-
|
904
|
-
doc2 = ::REXML::Document::new ""
|
905
|
-
|
906
|
-
objects.each do |object|
|
907
|
-
(doc2.root ? doc2.root : doc2) << ::REXML::Document::new(object.to_s)
|
908
|
-
end
|
909
|
-
|
910
|
-
|
911
|
-
ret = doc.create doc2, &b
|
912
|
-
puts doc2.to_s
|
913
|
-
STDIN.gets
|
914
|
-
ret
|
915
|
-
#--}}}
|
916
|
-
end
|
917
|
-
alias_method "x_", "xx_markup_"
|
918
|
-
def xx_any_ *objects, &b
|
919
|
-
#--{{{
|
920
|
-
doc = xx_doc
|
921
|
-
nothing = %r/.^/m
|
922
|
-
|
923
|
-
text =
|
924
|
-
::REXML::Text::new("",
|
925
|
-
respect_whitespace=true, parent=nil, raw=true, entity_filter=nil, illegal=nothing
|
926
|
-
)
|
927
|
-
|
928
|
-
objects.each do |object|
|
929
|
-
text << object.to_s if object
|
930
|
-
end
|
931
|
-
|
932
|
-
doc.create text, &b
|
933
|
-
#--}}}
|
934
|
-
end
|
935
|
-
alias_method "h_", "xx_any_"
|
936
|
-
remove_method "x_" if instance_methods.include? "x_"
|
937
|
-
alias_method "x_", "xx_any_" # supplant for now
|
938
|
-
def xx_cdata_ *objects, &b
|
939
|
-
#--{{{
|
940
|
-
doc = xx_doc
|
941
|
-
|
942
|
-
cdata = ::REXML::CData::new ""
|
943
|
-
|
944
|
-
objects.each do |object|
|
945
|
-
cdata << object.to_s if object
|
946
|
-
end
|
947
|
-
|
948
|
-
doc.create cdata, &b
|
949
|
-
#--}}}
|
950
|
-
end
|
951
|
-
alias_method "c_", "xx_cdata_"
|
952
|
-
def xx_parse_attributes string
|
953
|
-
#--{{{
|
954
|
-
string = string.to_s
|
955
|
-
tokens = string.split %r/,/o
|
956
|
-
tokens.map{|t| t.sub!(%r/[^=]+=/){|key_eq| key_eq.chop << " : "}}
|
957
|
-
xx_parse_yaml_attributes(tokens.join(','))
|
958
|
-
#--}}}
|
959
|
-
end
|
960
|
-
alias_method "att_", "xx_parse_attributes"
|
961
|
-
def xx_parse_yaml_attributes string
|
962
|
-
#--{{{
|
963
|
-
require "yaml"
|
964
|
-
string = string.to_s
|
965
|
-
string = "{" << string unless string =~ %r/^\s*[{]/o
|
966
|
-
string = string << "}" unless string =~ %r/[}]\s*$/o
|
967
|
-
obj = ::YAML::load string
|
968
|
-
raise ArgumentError, "<#{ obj.class }> not Hash!" unless Hash === obj
|
969
|
-
obj
|
970
|
-
#--}}}
|
971
|
-
end
|
972
|
-
alias_method "at_", "xx_parse_yaml_attributes"
|
973
|
-
alias_method "yat_", "xx_parse_yaml_attributes"
|
974
|
-
def xx_class
|
975
|
-
#--{{{
|
976
|
-
@xx_class ||= self.class
|
977
|
-
#--}}}
|
978
|
-
end
|
979
|
-
def xx_tag_method_name *a, &b
|
980
|
-
#--{{{
|
981
|
-
xx_class.xx_tag_method_name(*a, &b)
|
982
|
-
#--}}}
|
983
|
-
end
|
984
|
-
def xx_define_tmp_method *a, &b
|
985
|
-
#--{{{
|
986
|
-
xx_class.xx_define_tmp_methodr(*a, &b)
|
987
|
-
#--}}}
|
988
|
-
end
|
989
|
-
def xx_define_tag_method *a, &b
|
990
|
-
#--{{{
|
991
|
-
xx_class.xx_define_tag_method(*a, &b)
|
992
|
-
#--}}}
|
993
|
-
end
|
994
|
-
def xx_remove_tag_method *a, &b
|
995
|
-
#--{{{
|
996
|
-
xx_class.xx_tag_remove_method(*a, &b)
|
997
|
-
#--}}}
|
998
|
-
end
|
999
|
-
def xx_ancestors
|
1000
|
-
#--{{{
|
1001
|
-
raise Error, "no xx_which in effect" unless xx_which
|
1002
|
-
xx_class.xx_ancestors xx_which
|
1003
|
-
#--}}}
|
1004
|
-
end
|
1005
|
-
def xx_config
|
1006
|
-
#--{{{
|
1007
|
-
xx_class.xx_config
|
1008
|
-
#--}}}
|
1009
|
-
end
|
1010
|
-
def xx_config_for *a, &b
|
1011
|
-
#--{{{
|
1012
|
-
xx_class.xx_config_for(*a, &b)
|
1013
|
-
#--}}}
|
1014
|
-
end
|
1015
|
-
def xx_configure *a, &b
|
1016
|
-
#--{{{
|
1017
|
-
xx_class.xx_configure(*a, &b)
|
1018
|
-
#--}}}
|
1019
|
-
end
|
1020
|
-
#--}}}
|
1021
|
-
end
|
1022
|
-
|
1023
|
-
module ClassMethods
|
1024
|
-
#--{{{
|
1025
|
-
def xx_tag_method_name m
|
1026
|
-
#--{{{
|
1027
|
-
m = m.to_s
|
1028
|
-
tag_method, tag_name = m, m.gsub(%r/_+$/, "")
|
1029
|
-
[ tag_method, tag_name ]
|
1030
|
-
#--}}}
|
1031
|
-
end
|
1032
|
-
def xx_define_tmp_method m
|
1033
|
-
#--{{{
|
1034
|
-
define_method(m){ raise NotImplementedError, m.to_s }
|
1035
|
-
#--}}}
|
1036
|
-
end
|
1037
|
-
def xx_define_tag_method tag_method, tag_name = nil
|
1038
|
-
#--{{{
|
1039
|
-
tag_method = tag_method.to_s
|
1040
|
-
tag_name ||= tag_method.gsub %r/_+$/, ""
|
1041
|
-
|
1042
|
-
remove_method tag_method if instance_methods.include? tag_method
|
1043
|
-
module_eval <<-code, __FILE__, __LINE__+1
|
1044
|
-
def #{ tag_method } *a, &b
|
1045
|
-
hashes, nothashes = a.partition{|x| Hash === x}
|
1046
|
-
|
1047
|
-
doc = xx_doc
|
1048
|
-
element = ::REXML::Element::new '#{ tag_name }'
|
1049
|
-
|
1050
|
-
hashes.each{|h| h.each{|k,v| element.add_attribute k.to_s, v}}
|
1051
|
-
nothashes.each{|nh| element << ::REXML::Text::new(nh.to_s)}
|
1052
|
-
|
1053
|
-
doc.create element, &b
|
1054
|
-
end
|
1055
|
-
code
|
1056
|
-
tag_method
|
1057
|
-
#--}}}
|
1058
|
-
end
|
1059
|
-
def xx_remove_tag_method tag_method
|
1060
|
-
#--{{{
|
1061
|
-
remove_method tag_method rescue nil
|
1062
|
-
#--}}}
|
1063
|
-
end
|
1064
|
-
def xx_ancestors xx_which = self
|
1065
|
-
#--{{{
|
1066
|
-
list = []
|
1067
|
-
ancestors.each do |a|
|
1068
|
-
list << a if a < xx_which
|
1069
|
-
end
|
1070
|
-
xx_which.ancestors.each do |a|
|
1071
|
-
list << a if a <= Markup
|
1072
|
-
end
|
1073
|
-
list
|
1074
|
-
#--}}}
|
1075
|
-
end
|
1076
|
-
def xx_config
|
1077
|
-
#--{{{
|
1078
|
-
@@xx_config ||= Hash::new{|h,k| h[k] = {}}
|
1079
|
-
#--}}}
|
1080
|
-
end
|
1081
|
-
def xx_config_for key, xx_which = nil
|
1082
|
-
#--{{{
|
1083
|
-
key = key.to_s
|
1084
|
-
xx_which ||= self
|
1085
|
-
xx_ancestors(xx_which).each do |a|
|
1086
|
-
if xx_config[a].has_key? key
|
1087
|
-
return xx_config[a][key]
|
1088
|
-
end
|
1089
|
-
end
|
1090
|
-
nil
|
1091
|
-
#--}}}
|
1092
|
-
end
|
1093
|
-
def xx_configure key, value, xx_which = nil
|
1094
|
-
#--{{{
|
1095
|
-
key = key.to_s
|
1096
|
-
xx_which ||= self
|
1097
|
-
xx_config[xx_which][key] = value
|
1098
|
-
#--}}}
|
1099
|
-
end
|
1100
|
-
#--}}}
|
1101
|
-
end
|
1102
|
-
|
1103
|
-
extend ClassMethods
|
1104
|
-
include InstanceMethods
|
1105
|
-
|
1106
|
-
def self::included other, *a, &b
|
1107
|
-
#--{{{
|
1108
|
-
ret = super
|
1109
|
-
other.module_eval do
|
1110
|
-
include Markup::InstanceMethods
|
1111
|
-
extend Markup::ClassMethods
|
1112
|
-
class << self
|
1113
|
-
define_method("included", Markup::XX_MARKUP_RECURSIVE_INCLUSION_PROC)
|
1114
|
-
end
|
1115
|
-
end
|
1116
|
-
ret
|
1117
|
-
#--}}}
|
1118
|
-
end
|
1119
|
-
XX_MARKUP_RECURSIVE_INCLUSION_PROC = method("included").to_proc
|
1120
|
-
|
1121
|
-
xx_configure "method_missing", XX::PERMISSIVE
|
1122
|
-
xx_configure "tags", []
|
1123
|
-
xx_configure "doctype", nil
|
1124
|
-
xx_configure "xmldecl", nil
|
1125
|
-
#--}}}
|
1126
|
-
end
|
1127
|
-
|
1128
|
-
module XHTML
|
1129
|
-
#--{{{
|
1130
|
-
include Markup
|
1131
|
-
xx_configure "doctype", %(html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd")
|
1132
|
-
|
1133
|
-
def xhtml_ which = XHTML, *a, &b
|
1134
|
-
#--{{{
|
1135
|
-
xx_which(which) do
|
1136
|
-
doc = xx_with_doc_in_effect(*a, &b)
|
1137
|
-
ddoc = doc.doc
|
1138
|
-
root = ddoc.root
|
1139
|
-
if root and root.name and root.name =~ %r/^html$/i
|
1140
|
-
if root.attribute("lang",nil).nil? or root.attribute("lang",nil).to_s.empty?
|
1141
|
-
root.add_attribute "lang", "en"
|
1142
|
-
end
|
1143
|
-
if root.attribute("xml:lang").nil? or root.attribute("xml:lang").to_s.empty?
|
1144
|
-
root.add_attribute "xml:lang", "en"
|
1145
|
-
end
|
1146
|
-
if root.namespace.nil? or root.namespace.to_s.empty?
|
1147
|
-
root.add_namespace "http://www.w3.org/1999/xhtml"
|
1148
|
-
end
|
1149
|
-
end
|
1150
|
-
doc
|
1151
|
-
end
|
1152
|
-
#--}}}
|
1153
|
-
end
|
1154
|
-
|
1155
|
-
module Strict
|
1156
|
-
#--{{{
|
1157
|
-
include XHTML
|
1158
|
-
xx_configure "doctype", %(html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd")
|
1159
|
-
xx_configure "tags", %w(
|
1160
|
-
html head body div span DOCTYPE title link meta style p
|
1161
|
-
h1 h2 h3 h4 h5 h6 strong em abbr acronym address bdo blockquote cite q code
|
1162
|
-
ins del dfn kbd pre samp var br a base img
|
1163
|
-
area map object param ul ol li dl dt dd table
|
1164
|
-
tr td th tbody thead tfoot col colgroup caption form input
|
1165
|
-
textarea select option optgroup button label fieldset legend script noscript b
|
1166
|
-
i tt sub sup big small hr
|
1167
|
-
)
|
1168
|
-
xx_configure "method_missing", ::XX::STRICT
|
1169
|
-
|
1170
|
-
def xhtml_ which = XHTML::Strict, *a, &b
|
1171
|
-
#--{{{
|
1172
|
-
super(which, *a, &b)
|
1173
|
-
#--}}}
|
1174
|
-
end
|
1175
|
-
#--}}}
|
1176
|
-
end
|
1177
|
-
|
1178
|
-
module Transitional
|
1179
|
-
#--{{{
|
1180
|
-
include XHTML
|
1181
|
-
xx_configure "doctype", %(html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd")
|
1182
|
-
def xhtml_ which = XHTML::Transitional, *a, &b
|
1183
|
-
#--{{{
|
1184
|
-
super(which, *a, &b)
|
1185
|
-
#--}}}
|
1186
|
-
end
|
1187
|
-
#--}}}
|
1188
|
-
end
|
1189
|
-
#--}}}
|
1190
|
-
end
|
1191
|
-
|
1192
|
-
module HTML4
|
1193
|
-
#--{{{
|
1194
|
-
include Markup
|
1195
|
-
xx_configure "doctype", %(html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN")
|
1196
|
-
|
1197
|
-
def html4_ which = HTML4, *a, &b
|
1198
|
-
#--{{{
|
1199
|
-
xx_which(which){ xx_with_doc_in_effect(*a, &b) }
|
1200
|
-
#--}}}
|
1201
|
-
end
|
1202
|
-
|
1203
|
-
module Strict
|
1204
|
-
#--{{{
|
1205
|
-
include HTML4
|
1206
|
-
xx_configure "doctype", %(html PUBLIC "-//W3C//DTD HTML 4.01 Strict//EN")
|
1207
|
-
xx_configure "tags", %w(
|
1208
|
-
html head body div span DOCTYPE title link meta style p
|
1209
|
-
h1 h2 h3 h4 h5 h6 strong em abbr acronym address bdo blockquote cite q code
|
1210
|
-
ins del dfn kbd pre samp var br a base img
|
1211
|
-
area map object param ul ol li dl dt dd table
|
1212
|
-
tr td th tbody thead tfoot col colgroup caption form input
|
1213
|
-
textarea select option optgroup button label fieldset legend script noscript b
|
1214
|
-
i tt sub sup big small hr
|
1215
|
-
)
|
1216
|
-
xx_configure "method_missing", ::XX::STRICT
|
1217
|
-
def html4_ which = HTML4::Strict, *a, &b
|
1218
|
-
#--{{{
|
1219
|
-
super(which, *a, &b)
|
1220
|
-
#--}}}
|
1221
|
-
end
|
1222
|
-
#--}}}
|
1223
|
-
end
|
1224
|
-
|
1225
|
-
module Transitional
|
1226
|
-
#--{{{
|
1227
|
-
include HTML4
|
1228
|
-
xx_configure "doctype", %(html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN")
|
1229
|
-
def html4_ which = HTML4::Transitional, *a, &b
|
1230
|
-
#--{{{
|
1231
|
-
super(which, *a, &b)
|
1232
|
-
#--}}}
|
1233
|
-
end
|
1234
|
-
#--}}}
|
1235
|
-
end
|
1236
|
-
#--}}}
|
1237
|
-
end
|
1238
|
-
HTML = HTML4
|
1239
|
-
|
1240
|
-
module XML
|
1241
|
-
#--{{{
|
1242
|
-
include Markup
|
1243
|
-
xx_configure "xmldecl", ::REXML::XMLDecl::new
|
1244
|
-
|
1245
|
-
def xml_ *a, &b
|
1246
|
-
#--{{{
|
1247
|
-
xx_which(XML){ xx_with_doc_in_effect(*a, &b)}
|
1248
|
-
#--}}}
|
1249
|
-
end
|
1250
|
-
#--}}}
|
1251
|
-
end
|
1252
|
-
#--}}}
|
1253
|
-
end
|
1254
|
-
|
1255
|
-
$__xx_rb__ = __FILE__
|
1256
|
-
end
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
#
|
1268
|
-
# simple examples - see samples/ dir for more complete examples
|
1269
|
-
#
|
1270
|
-
|
1271
|
-
if __FILE__ == $0
|
1272
|
-
|
1273
|
-
class Table < ::Array
|
1274
|
-
include XX::XHTML::Strict
|
1275
|
-
include XX::HTML4::Strict
|
1276
|
-
include XX::XML
|
1277
|
-
|
1278
|
-
def doc
|
1279
|
-
html_{
|
1280
|
-
head_{ title_{ "xhtml/html4/xml demo" } }
|
1281
|
-
|
1282
|
-
div_{
|
1283
|
-
h_{ "< malformed html & un-escaped symbols" }
|
1284
|
-
}
|
1285
|
-
|
1286
|
-
t_{ "escaped & text > <" }
|
1287
|
-
|
1288
|
-
x_{ "<any_valid> xml </any_valid>" }
|
1289
|
-
|
1290
|
-
div_(:style => :sweet){
|
1291
|
-
em_ "this is a table"
|
1292
|
-
|
1293
|
-
table_(:width => 42, :height => 42){
|
1294
|
-
each{|row| tr_{ row.each{|cell| td_ cell } } }
|
1295
|
-
}
|
1296
|
-
}
|
1297
|
-
|
1298
|
-
script_(:type => :dangerous){ cdata_{ "javascript" } }
|
1299
|
-
}
|
1300
|
-
end
|
1301
|
-
def to_xhtml
|
1302
|
-
xhtml_{ doc }
|
1303
|
-
end
|
1304
|
-
def to_html4
|
1305
|
-
html4_{ doc }
|
1306
|
-
end
|
1307
|
-
def to_xml
|
1308
|
-
xml_{ doc }
|
1309
|
-
end
|
1310
|
-
end
|
1311
|
-
|
1312
|
-
table = Table[ %w( 0 1 2 ), %w( a b c ) ]
|
1313
|
-
|
1314
|
-
methods = %w( to_xhtml to_html4 to_xml )
|
1315
|
-
|
1316
|
-
methods.each do |method|
|
1317
|
-
2.times{ puts "-" * 42 }
|
1318
|
-
puts(table.send(method).pretty)
|
1319
|
-
puts
|
1320
|
-
end
|
1321
|
-
|
1322
|
-
end
|
1323
|
-
# vi: set sw=4:
|
1324
|
-
# Here is Emacs setting. DO NOT REMOVE!
|
1325
|
-
# Local Variables:
|
1326
|
-
# ruby-indent-level: 4
|
1327
|
-
# End:
|