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.
Files changed (68) hide show
  1. data/BLURB +2 -40
  2. data/LICENSE +2 -5
  3. data/Rakefile +32 -106
  4. data/THANKS +14 -0
  5. data/bin/rcov +277 -1090
  6. data/doc/readme_for_api.markdown +22 -0
  7. data/doc/readme_for_emacs.markdown +52 -0
  8. data/doc/readme_for_rake.markdown +51 -0
  9. data/doc/readme_for_vim.markdown +34 -0
  10. data/{rcov.el → editor-extensions/rcov.el} +0 -0
  11. data/{rcov.vim → editor-extensions/rcov.vim} +0 -0
  12. data/ext/rcovrt/1.8/callsite.c +216 -0
  13. data/ext/rcovrt/1.8/rcovrt.c +287 -0
  14. data/ext/rcovrt/1.9/callsite.c +234 -0
  15. data/ext/rcovrt/1.9/rcovrt.c +264 -0
  16. data/ext/rcovrt/extconf.rb +12 -2
  17. data/lib/rcov.rb +13 -968
  18. data/lib/rcov/call_site_analyzer.rb +225 -0
  19. data/lib/rcov/code_coverage_analyzer.rb +268 -0
  20. data/lib/rcov/coverage_info.rb +36 -0
  21. data/lib/rcov/differential_analyzer.rb +116 -0
  22. data/lib/rcov/file_statistics.rb +334 -0
  23. data/lib/rcov/formatters.rb +13 -0
  24. data/lib/rcov/formatters/base_formatter.rb +173 -0
  25. data/lib/rcov/formatters/failure_report.rb +15 -0
  26. data/lib/rcov/formatters/full_text_report.rb +48 -0
  27. data/lib/rcov/formatters/html_coverage.rb +274 -0
  28. data/lib/rcov/formatters/html_erb_template.rb +62 -0
  29. data/lib/rcov/formatters/text_coverage_diff.rb +193 -0
  30. data/lib/rcov/formatters/text_report.rb +32 -0
  31. data/lib/rcov/formatters/text_summary.rb +11 -0
  32. data/lib/rcov/lowlevel.rb +16 -17
  33. data/lib/rcov/rcovtask.rb +21 -22
  34. data/lib/rcov/templates/detail.html.erb +64 -0
  35. data/lib/rcov/templates/index.html.erb +93 -0
  36. data/lib/rcov/templates/jquery-1.3.2.min.js +19 -0
  37. data/lib/rcov/templates/jquery.tablesorter.min.js +15 -0
  38. data/lib/rcov/templates/print.css +12 -0
  39. data/lib/rcov/templates/rcov.js +42 -0
  40. data/lib/rcov/templates/screen.css +270 -0
  41. data/lib/rcov/version.rb +5 -8
  42. data/setup.rb +5 -2
  43. data/test/{sample_01.rb → assets/sample_01.rb} +0 -0
  44. data/test/{sample_02.rb → assets/sample_02.rb} +0 -0
  45. data/test/{sample_03.rb → assets/sample_03.rb} +0 -0
  46. data/test/{sample_04.rb → assets/sample_04.rb} +0 -0
  47. data/test/{sample_05-new.rb → assets/sample_05-new.rb} +0 -0
  48. data/test/{sample_05-old.rb → assets/sample_05-old.rb} +0 -0
  49. data/test/{sample_05.rb → assets/sample_05.rb} +0 -0
  50. data/test/{test_CallSiteAnalyzer.rb → call_site_analyzer_test.rb} +57 -81
  51. data/test/{test_CodeCoverageAnalyzer.rb → code_coverage_analyzer_test.rb} +71 -35
  52. data/test/{test_FileStatistics.rb → file_statistics_test.rb} +34 -36
  53. data/test/{test_functional.rb → functional_test.rb} +21 -35
  54. metadata +91 -69
  55. data/CHANGES +0 -177
  56. data/LEGAL +0 -36
  57. data/README.API +0 -42
  58. data/README.emacs +0 -64
  59. data/README.en +0 -130
  60. data/README.rake +0 -62
  61. data/README.rant +0 -68
  62. data/README.vim +0 -47
  63. data/Rantfile +0 -76
  64. data/ext/rcovrt/callsite.c +0 -242
  65. data/ext/rcovrt/rcovrt.c +0 -329
  66. data/lib/rcov/rant.rb +0 -87
  67. data/lib/rcov/report.rb +0 -1236
  68. 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 and Rant
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 README.rake or the RDoc documentation
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
- (see the file GPL), or the conditions below:
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
- # Rcov::RcovTask.new
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/test*.rb']
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/test_FileStatistics.rb']
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/test_CodeCoverageAnalyzer.rb']
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
- Rake::TestTask.new(:test_rcovrt => ["ext/rcovrt/rcovrt.so"]) do |t|
46
- t.libs << "ext/rcovrt"
47
- t.test_files = FileList['test/test*.rb']
48
- t.verbose = true
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/test*.rb']
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/report'
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::Formatter::DEFAULT_OPTS[:ignore]
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
- opts.separator ""
90
- opts.separator "Options:"
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
- opts.on("-T", "--text-report", "Dump detailed plain-text report to stdout.",
173
- "(filename, LoC, total lines, coverage)") do
174
- options.textmode = :report
175
- end
176
- opts.on("-t", "--text-summary", "Dump plain-text summary to stdout.") do
177
- options.textmode = :summary
178
- end
179
- opts.on("--text-counts", "Dump execution counts in plaintext.") do
180
- options.textmode = :counts
181
- end
182
- opts.on("--text-coverage", "Dump coverage info to stdout, using",
183
- "ANSI color sequences unless -n.") do
184
- options.textmode = :coverage
185
- end
186
- opts.on("--gcc", "Dump uncovered line in GCC error format.") do
187
- options.gcc_output = true
188
- end
189
- opts.on("--aggregate FILE", "Aggregate data from previous runs",
190
- "in FILE. Overwrites FILE with the",
191
- "merged data. FILE is created if",
192
- "necessary.") do |file|
193
- options.aggregate_file = file
194
- end
195
- opts.on("-D [FILE]", "--text-coverage-diff [FILE]",
196
- "Compare code coverage with saved state",
197
- "in FILE, defaults to coverage.info.",
198
- "Implies --comments.") do |file|
199
- options.textmode = :coverage_diff
200
- options.comments_run_by_default = true
201
- if options.coverage_diff_save
202
- raise "You shouldn't use --save and --text-coverage-diff at a time."
203
- end
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
- opts.on("--replace-progname", "Replace $0 when loading the .rb files.") do
251
- options.replace_prog_name = true
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
- opts.on("-w", "Turn warnings on (like ruby).") do
254
- $VERBOSE = true
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
- opts.on("--no-rcovrt", "Do not use the optimized C runtime.",
257
- "(will run 30-300 times slower)") do
258
- $rcov_do_not_use_rcovrt = true
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
- opts.on("--diff-cmd PROGNAME", "Use PROGNAME for --text-coverage-diff.",
261
- "(default: diff)") do |cmd|
262
- options.diff_cmd = cmd
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
- opts.separator ""
265
- opts.on_tail("-h", "--help", "Show extended help message") do
266
- require 'pp'
267
- puts opts
268
- puts <<EOF
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
- puts EXTRA_HELP
274
- exit
275
- end
276
- opts.on_tail("--report-cov-bug SELECTOR",
277
- "Report coverage analysis bug for the",
278
- "method specified by SELECTOR",
279
- "(format: Foo::Bar#method, A::B.method)") do |selector|
280
- case selector
281
- when /([^.]+)(#|\.)(.*)/: options.report_cov_bug_for = selector
282
- else
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
- extra_args = ARGV[idx+1..-1]
298
- ARGV.replace(ARGV[0,idx])
304
+ extra_args = ARGV[idx+1..-1]
305
+ ARGV.replace(ARGV[0,idx])
299
306
  else
300
- extra_args = []
307
+ extra_args = []
301
308
  end
302
309
 
303
310
  begin
304
- opts.parse! ARGV
305
- rescue OptionParser::InvalidOption, OptionParser::InvalidArgument,
306
- OptionParser::MissingArgument => e
307
- puts opts
308
- puts
309
- puts e.message
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
- puts opts
315
- exit
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
- require 'zlib'
331
- begin
332
- old_data = nil
333
- Zlib::GzipReader.open(file){|gz| old_data = Marshal.load(gz) }
334
- rescue
335
- old_data = {}
336
- end
337
- old_data || {}
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
- require 'zlib'
342
- Zlib::GzipWriter.open(file) do |f|
343
- Marshal.dump({:callsites => $rcov_callsite_analyzer,
344
- :coverage => $rcov_code_coverage_analyzer}, f)
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
- if options.aggregate_file
350
- saved_aggregate_data = rcov_load_aggregate_data(options.aggregate_file)
351
- if saved_aggregate_data[:callsites]
352
- $rcov_callsite_analyzer = saved_aggregate_data[:callsites]
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
- $rcov_callsite_analyzer ||= Rcov::CallSiteAnalyzer.new
356
- $rcov_callsite_analyzer.install_hook
360
+ end
361
+ $rcov_callsite_analyzer ||= Rcov::CallSiteAnalyzer.new
362
+ $rcov_callsite_analyzer.install_hook
357
363
  else
358
- $rcov_callsite_analyzer = nil
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
- :validator_links => options.show_validator_links,
379
- :charset => options.charset
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
- if options.profiling
385
- formatters << make_formatter[Rcov::HTMLProfiling]
386
- else
387
- formatters << make_formatter[Rcov::HTMLCoverage]
388
- end
391
+ if options.profiling
392
+ formatters << make_formatter[Rcov::HTMLProfiling]
393
+ else
394
+ formatters << make_formatter[Rcov::HTMLCoverage]
395
+ end
389
396
  end
390
- textual_formatters = {:counts => Rcov::FullTextReport,
391
- :coverage => Rcov::FullTextReport,
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
- formatters << make_formatter[textual_formatters[options.textmode]]
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
- saved_aggregate_data ||= rcov_load_aggregate_data(options.aggregate_file)
405
- if saved_aggregate_data[:coverage]
406
- $rcov_code_coverage_analyzer = saved_aggregate_data[:coverage]
407
- end
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
- You can report the bug via the Ruby-Talk ML, send it directly to
437
- <mfp at acm dot org> (include "rcov" in the subject to get past the spam filters),
438
- or post it to
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
- if formatters.all?{|formatter| formatter.sorted_file_pairs.empty? }
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
- if options.test_unit_only
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
- $0 = File.basename(File.expand_path(prog))
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: