rcov 0.8.1.2.0 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/BLURB +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:
|