rdx 0.9.0.pre
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.
- checksums.yaml +7 -0
- data/.rdx +20 -0
- data/README +19 -0
- data/bin/rdx +7 -0
- data/examples/minimal/.rdx +8 -0
- data/examples/minimal/README +10 -0
- data/examples/minimal/lib/other_conventions.rb +64 -0
- data/examples/minimal/lib/the_basics.rb +94 -0
- data/examples/minimal/lib/using_directives.rb +66 -0
- data/examples/minimal/rakefile +27 -0
- data/examples/ruby-2.0.0-p0/README +7 -0
- data/examples/ruby-2.0.0-p0/install/core/.rdx +6 -0
- data/examples/ruby-2.0.0-p0/install/core/README +19 -0
- data/examples/ruby-2.0.0-p0/install/core/Rakefile +61 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/array.c.diff +166 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/bignum.c.diff +11 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/class.c.diff +36 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/compar.c.diff +11 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/complex.c.diff +301 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/cont.c.diff +65 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/dir.c.diff +147 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/doc/re.rdoc.diff +328 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/doc/security.rdoc.diff +8 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/doc/standard_library.rdoc.diff +0 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax.rdoc.diff +0 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/assignment.rdoc.diff +160 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/calling_methods.rdoc.diff +130 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/control_expressions.rdoc.diff +254 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/exceptions.rdoc.diff +0 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/literals.rdoc.diff +54 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/methods.rdoc.diff +157 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/miscellaneous.rdoc.diff +91 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/modules_and_classes.rdoc.diff +161 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/precedence.rdoc.diff +8 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/refinements.rdoc.diff +146 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/encoding.c.diff +276 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/enum.c.diff +281 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/enumerator.c.diff +479 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/error.c.diff +143 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/eval.c.diff +47 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/eval_jump.c.diff +23 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/file.c.diff +752 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/gc.c.diff +195 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/hash.c.diff +84 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/iseq.c.diff +354 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/load.c.diff +53 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/marshal.c.diff +98 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/math.c.diff +110 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/numeric.c.diff +103 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/object.c.diff +295 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/pack.c.diff +18 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/parse.y.diff +23 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/proc.c.diff +155 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/random.c.diff +126 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/range.c.diff +49 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/rational.c.diff +312 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/re.c.diff +207 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/ruby.c.diff +21 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/signal.c.diff +67 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/sprintf.c.diff +29 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/string.c.diff +73 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/struct.c.diff +20 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/time.c.diff +691 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/transcode.c.diff +435 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/variable.c.diff +62 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/vm_backtrace.c.diff +164 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/vm_eval.c.diff +99 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/vm_method.c.diff +17 -0
- data/examples/ruby-2.0.0-p0/install/core/diffs/vm_trace.c.diff +393 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/.rdx +6 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/README +19 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/Rakefile +53 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/abbrev.rb.diff +77 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/base64.rb.diff +42 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/benchmark.rb.diff +144 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/cmath.rb.diff +52 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/forwardable.rb.diff +150 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/mathn.rb.diff +58 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/matrix.rb.diff +657 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/observer.rb.diff +31 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/optparse.rb.diff +147 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/ostruct.rb.diff +78 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/prime.rb.diff +52 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/pstore.rb.diff +110 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/scanf.rb.diff +100 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/securerandom.rb.diff +144 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/set.rb.diff +637 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/shellwords.rb.diff +66 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/singleton.rb.diff +37 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/tempfile.rb.diff +104 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/thread.rb.diff +38 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/time.rb.diff +140 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/tmpdir.rb.diff +52 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/uri.rb.diff +39 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/uri/common.rb.diff +237 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/weakref.rb.diff +36 -0
- data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/yaml/store.rb.diff +27 -0
- data/examples/ruby-2.0.0-p0/rakefile +165 -0
- data/lib/rdx.rb +331 -0
- data/lib/rdx/assertions.rb +484 -0
- data/lib/rdx/binding.rb +151 -0
- data/lib/rdx/code_object.rb +598 -0
- data/lib/rdx/comment.rb +338 -0
- data/lib/rdx/convention.rb +1174 -0
- data/lib/rdx/directive.rb +1432 -0
- data/lib/rdx/example.rb +679 -0
- data/lib/rdx/generator.rb +112 -0
- data/lib/rdx/generator/rdoc.rb +1006 -0
- data/lib/rdx/options.rb +359 -0
- data/lib/rdx/plain_text.rb +65 -0
- data/lib/rdx/reporter.rb +421 -0
- data/lib/rdx/ruby_lex.rb +324 -0
- data/lib/rdx/runner.rb +309 -0
- data/lib/rdx/source_file.rb +94 -0
- data/lib/rdx/specification.rb +194 -0
- data/lib/rdx/statement.rb +248 -0
- data/lib/rdx/store.rb +119 -0
- data/lib/rdx/task.rb +361 -0
- data/lib/rdx/text.rb +688 -0
- data/lib/rdx/version.rb +15 -0
- data/rakefile +64 -0
- metadata +203 -0
@@ -0,0 +1,1432 @@
|
|
1
|
+
|
2
|
+
module RDX
|
3
|
+
|
4
|
+
#
|
5
|
+
# == When to use directives?
|
6
|
+
#
|
7
|
+
# Conventions work fine when all the processing steps are no longer than a single statement,
|
8
|
+
# but what if we want to interact with other examples, or in general with other sections of the comment?
|
9
|
+
#
|
10
|
+
# Perhaps we may want to not execute an example, to interpret one as the output of the
|
11
|
+
# previous, to locally change some of the assertions methods, to run it in a temporary directory,
|
12
|
+
# to simulate a bash environment, and so on...
|
13
|
+
#
|
14
|
+
# *Directives* allow all of this: they <b>work on a larger scale</b> (usually operate on other examples and
|
15
|
+
# the comment, but can also influence different comments and even other directives!),
|
16
|
+
# <b>making possible to treat your comments, text sections and examples differently from the standard way</b>.
|
17
|
+
#
|
18
|
+
# == Which directives are available?
|
19
|
+
#
|
20
|
+
# There are many directives, subdivided for functionality:
|
21
|
+
# * Activation/Deactivation: like ::on, ::off, ::skip, ::if, ::lazy;
|
22
|
+
# * Input/Output/Error: the most useful is ::stdout;
|
23
|
+
# * Context change: they can change the binding, current directory, execution in time
|
24
|
+
# (like ::setup and ::teardown), simulate a ::bash session;
|
25
|
+
# * Assertion customization: to mention ::float
|
26
|
+
# * Miscellanous: insert comments, ::disable_warnings, ...
|
27
|
+
# All the directives already defined are documented as Directive's class methods
|
28
|
+
# (even if technically they aren't) in the relative sections.
|
29
|
+
#
|
30
|
+
# If these aren't enough, you can *edit* them or even *define* your own directives
|
31
|
+
# in the Specification.
|
32
|
+
#
|
33
|
+
# But before this you'll need to know other few things...
|
34
|
+
#
|
35
|
+
# == How to use directives?
|
36
|
+
#
|
37
|
+
# Directives come in two flavours: _explicit_ and _implicit_.
|
38
|
+
#
|
39
|
+
# We can insert an <b>explicit directive</b> in a comment through the <b>documentation generator tool</b>.
|
40
|
+
# First we have to tell it - using its directive syntax - that we have an RDX directive;
|
41
|
+
# the rest (parameter for the generator tool) is parsed by Directive.split, that returns a directive
|
42
|
+
# name and optionally its parameter.
|
43
|
+
# For an example with the +rdoc+ generator see the "Directives" section in ::RDoc.
|
44
|
+
#
|
45
|
+
# There is also the nice way to insert them *implicitly* in the comment, <b>without the need
|
46
|
+
# of the user to use the specific generator tool</b>. This is done recognizing specific patterns
|
47
|
+
# in plain text sections or examples. For instance ::stdout is automatically inserted if a plain text
|
48
|
+
# section consists - simplifying a bit - of the string 'produces:' (this pattern was so common in the
|
49
|
+
# Ruby Core that I thought implicit directives were a fundamental feature), while ::bash can detect an
|
50
|
+
# example starting with the bash prompt "<tt>$ </tt>" (since it isn't valid ruby syntax).
|
51
|
+
#
|
52
|
+
# == What are directives?
|
53
|
+
#
|
54
|
+
# Directives are classes (subclassing Directive), and each appearance in the comments generates
|
55
|
+
# a corresponding instance.
|
56
|
+
#
|
57
|
+
# For this reason the class methods are used to define the behaviour of the directive
|
58
|
+
# (the most important is ::define), while the instance ones allow to query
|
59
|
+
# informations about their status (the #parameter, if it's #implicit?, some stored #metadata)
|
60
|
+
# and retrive neighbour sections in the comment (the most used is #next_example).
|
61
|
+
#
|
62
|
+
class Directive < CodeObject
|
63
|
+
|
64
|
+
#
|
65
|
+
# :category: Internal
|
66
|
+
#
|
67
|
+
# Splits _string_ (which is the parameter of the +rdx+ directive for the generator)
|
68
|
+
# into a directive name and its parameter.
|
69
|
+
#
|
70
|
+
# The name consists of the first sequence of printable (non-space) characters -
|
71
|
+
# may even be the empty string -; the parameter is anything that follows after the
|
72
|
+
# first spaces - even this may be empty too.
|
73
|
+
#
|
74
|
+
def Directive.split string
|
75
|
+
string.to_str.strip.match(/\A\s*(\S*)\s*(.*)\z/m).captures
|
76
|
+
end
|
77
|
+
|
78
|
+
# :stopdoc:
|
79
|
+
|
80
|
+
def Directive.validate_name name
|
81
|
+
name = name.to_str
|
82
|
+
raise "Invalid directive name: `#{name}'" if name =~ /\s/
|
83
|
+
name.downcase
|
84
|
+
end
|
85
|
+
|
86
|
+
def Directive.join dir, param
|
87
|
+
dir = validate_name dir
|
88
|
+
param = param.to_str
|
89
|
+
return param.empty? ? dir : "#{dir} #{param}"
|
90
|
+
end
|
91
|
+
|
92
|
+
# :startdoc:
|
93
|
+
|
94
|
+
class << self
|
95
|
+
|
96
|
+
# The first name which with the directive is defined (not influenced by aliases).
|
97
|
+
attr_reader :name
|
98
|
+
|
99
|
+
# Hash of arbitrary metadata. This will be copied into each instance.
|
100
|
+
attr_reader :metadata
|
101
|
+
|
102
|
+
# :stopdoc:
|
103
|
+
|
104
|
+
def to_s
|
105
|
+
"RDX::Directive:#{name}"
|
106
|
+
end
|
107
|
+
alias inspect to_s
|
108
|
+
|
109
|
+
def verify_status
|
110
|
+
public_instance_methods(false).include?(:execute) or
|
111
|
+
raise "Directive behaviour not defined (use `define')"
|
112
|
+
end
|
113
|
+
private :verify_status
|
114
|
+
|
115
|
+
def has_implicit?
|
116
|
+
!@implicit[:text].empty? or !@implicit[:example].empty?
|
117
|
+
end
|
118
|
+
|
119
|
+
def find_implicit_in type, text
|
120
|
+
text = text.to_str
|
121
|
+
@implicit[type].each do |pattern|
|
122
|
+
md = text.match(pattern)
|
123
|
+
next unless md
|
124
|
+
param = md[1]
|
125
|
+
l_no = 1 + md.pre_match.count("\n") + md[0][/\A\s*/].count("\n")
|
126
|
+
result = [param, l_no]
|
127
|
+
yield(*result) if block_given?
|
128
|
+
return result
|
129
|
+
end
|
130
|
+
return false
|
131
|
+
end
|
132
|
+
|
133
|
+
# :startdoc:
|
134
|
+
|
135
|
+
#
|
136
|
+
# :call-seq:
|
137
|
+
# define{ || ... }
|
138
|
+
# define{ |dir| ... }
|
139
|
+
#
|
140
|
+
# Defines the action of the directive: the block will be called from each instance generated from
|
141
|
+
# an occurrence of this directive in a comment.
|
142
|
+
#
|
143
|
+
# If the block takes no arguments, it directly becomes the body of that instance method
|
144
|
+
# (so that +self+ is that directive instance in the block).
|
145
|
+
# Otherwise it will be yielded the directive instance as a parameter,
|
146
|
+
# without changing the block's context.
|
147
|
+
#
|
148
|
+
# In both ways, you should use the instance methods of Directive to access its
|
149
|
+
# its status and retrive neighbour sections. At this point you will need the API
|
150
|
+
# provided by the CodeObject class and its descendants - mainly the Example one -
|
151
|
+
# to shape their behaviour to your needs.
|
152
|
+
#
|
153
|
+
def define &execution
|
154
|
+
if execution.arity == 0
|
155
|
+
define_method :execute do
|
156
|
+
trace_execution{ instance_eval(&execution) }
|
157
|
+
end
|
158
|
+
else
|
159
|
+
define_method :execute do
|
160
|
+
trace_execution{ execution.call(self) }
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
#
|
166
|
+
# :category: Internal
|
167
|
+
#
|
168
|
+
# Registers the given block as a configuration for the implicit recognization:
|
169
|
+
# this centralizes the building procedure, allowing the user to supply
|
170
|
+
# (through ::use_implicit_with) only the desired parameters - often some particular
|
171
|
+
# pattern or word. The block should call ::find_in_text or ::find_in_example.
|
172
|
+
#
|
173
|
+
# After this ::default_implicit_configuration is called.
|
174
|
+
#
|
175
|
+
# This configuration can be defined for built-in directives;
|
176
|
+
# user-defined ones often do not need this step.
|
177
|
+
#
|
178
|
+
def configure_implicit &implicit_configuration
|
179
|
+
@implicit_configuration = implicit_configuration
|
180
|
+
default_implicit_configuration
|
181
|
+
end
|
182
|
+
|
183
|
+
#
|
184
|
+
# Calls the configuration +Proc+ (if registered through ::configure_implicit)
|
185
|
+
# with the given arguments. In this way you can add new behaviour according to
|
186
|
+
# an existing scheme.
|
187
|
+
#
|
188
|
+
# This method can be called from the Specification.
|
189
|
+
#
|
190
|
+
# Returns +self+, allowing to chain other methods.
|
191
|
+
#
|
192
|
+
def use_implicit_with(*args,&blk)
|
193
|
+
if @implicit_configuration
|
194
|
+
@implicit_configuration.call(*args,&blk)
|
195
|
+
elsif !args.empty? || blk
|
196
|
+
raise "#{self} does not accept an implicit configuration"
|
197
|
+
end
|
198
|
+
return self
|
199
|
+
end
|
200
|
+
|
201
|
+
# Clears the patterns for the implicit search.
|
202
|
+
def clear_implicit_patterns
|
203
|
+
@implicit = { :text=>[], :example=>[] }
|
204
|
+
end
|
205
|
+
|
206
|
+
#
|
207
|
+
# Restores the default configuration for the implicit recognization of this
|
208
|
+
# directive. First calls ::clear_implicit_patterns, then
|
209
|
+
# calls the block supplied to ::configure_implicit without parameters
|
210
|
+
# (so its arity should allow this).
|
211
|
+
#
|
212
|
+
def default_implicit_configuration
|
213
|
+
clear_implicit_patterns
|
214
|
+
use_implicit_with()
|
215
|
+
end
|
216
|
+
|
217
|
+
#
|
218
|
+
# Registers the Regexp to match the text of a non-example section.
|
219
|
+
# If there is a match, the directive is implicitly added in the comment
|
220
|
+
# without consuming any text.
|
221
|
+
#
|
222
|
+
def find_in_text regexp
|
223
|
+
raise 'Invalid Regexp pattern' unless regexp.is_a?(Regexp)
|
224
|
+
@implicit[:text] << regexp
|
225
|
+
end
|
226
|
+
|
227
|
+
#
|
228
|
+
# Registers the Regexp to match the code of an example.
|
229
|
+
# If there is a match, the directive is implicitly added in the comment
|
230
|
+
# without consuming any text.
|
231
|
+
#
|
232
|
+
def find_in_example regexp
|
233
|
+
raise 'Invalid Regexp pattern' unless regexp.is_a?(Regexp)
|
234
|
+
@implicit[:example] << regexp
|
235
|
+
end
|
236
|
+
|
237
|
+
end
|
238
|
+
|
239
|
+
#
|
240
|
+
# This module is included into the Specification and allows the interaction
|
241
|
+
# with the Directive objects in use: you can define new ones, create aliases,
|
242
|
+
# remove those already in use or simply modify some of their features.
|
243
|
+
#
|
244
|
+
# It also extends the Directive class, so that the built-in directives
|
245
|
+
# are defined in the same way.
|
246
|
+
# This provides a good starting point: just look at the core definitions
|
247
|
+
# to learn something very quickly. Anyway in the Directive class
|
248
|
+
# you can find the details on how directive work.
|
249
|
+
#
|
250
|
+
module SpecificationHelper
|
251
|
+
|
252
|
+
# :stopdoc:
|
253
|
+
|
254
|
+
attr_reader :directives
|
255
|
+
private :directives
|
256
|
+
|
257
|
+
def known_directives
|
258
|
+
directives.dup
|
259
|
+
end
|
260
|
+
|
261
|
+
# :startdoc:
|
262
|
+
|
263
|
+
# Returns the Directive with the given _name_ or +nil+ if it isn't defined.
|
264
|
+
def directive_defined? name
|
265
|
+
name = Directive.validate_name name
|
266
|
+
directives[name]
|
267
|
+
end
|
268
|
+
|
269
|
+
#
|
270
|
+
# Returns the Directive with the given _name_ or raises an exception if it isn't defined.
|
271
|
+
# You can now use class methods of Directive to modify its features.
|
272
|
+
#
|
273
|
+
def directive name
|
274
|
+
directive_defined?(name) or
|
275
|
+
raise Error, "Undefined directive `#{name}'"
|
276
|
+
end
|
277
|
+
|
278
|
+
#
|
279
|
+
# :call-seq:
|
280
|
+
# define_directive(name){ || action } -> directive
|
281
|
+
# define_directive(name){ |dir_class| setup } -> directive
|
282
|
+
# define_directive(name,directive) -> directive
|
283
|
+
#
|
284
|
+
# Defines a directive class (subclass of Directive) with the given _name_.
|
285
|
+
#
|
286
|
+
# In the first form the block (that takes no argument) will be sent to ::define,
|
287
|
+
# thus it directly becomes the action of the directive.
|
288
|
+
# In the second form the block is yielded the directive class itself, allowing
|
289
|
+
# other methods to be called on it (the user must explicitly call +define+).
|
290
|
+
# In the last form associates _name_ to _directive_.
|
291
|
+
#
|
292
|
+
# In all cases the directive class is returned.
|
293
|
+
#
|
294
|
+
# If the defined directive name ends with "<tt>!</tt>", and if the corresponding
|
295
|
+
# directive without the trailing bang is already defined these two classes will
|
296
|
+
# share the same #metadata. This strategy is used when the actions they perform
|
297
|
+
# are the same, differing only in the targets on which they operate.
|
298
|
+
#
|
299
|
+
def define_directive name, dir=nil, &definition
|
300
|
+
defined = directive_defined?(name) and
|
301
|
+
raise "Directive `#{defined.name}' already defined!"
|
302
|
+
if definition.nil?
|
303
|
+
raise "Invalid directive: #{dir.inspect}" unless dir.is_a?(Class) && dir < Directive
|
304
|
+
else
|
305
|
+
if name.end_with?('!') && simil_dir=directive_defined?(name.chomp '!')
|
306
|
+
metadata = simil_dir.metadata
|
307
|
+
else
|
308
|
+
metadata = {}
|
309
|
+
end
|
310
|
+
dir = Class.new(Directive) do
|
311
|
+
@name = name.freeze
|
312
|
+
@metadata = metadata # Of the class itself
|
313
|
+
clear_implicit_patterns
|
314
|
+
if definition.arity == 0
|
315
|
+
define &definition
|
316
|
+
else
|
317
|
+
definition.call(self)
|
318
|
+
end
|
319
|
+
verify_status
|
320
|
+
end
|
321
|
+
end
|
322
|
+
return directives[name] = dir
|
323
|
+
end
|
324
|
+
|
325
|
+
# Creates an alias _new_name_ for the directive named _old_name_.
|
326
|
+
def alias_directive new_name, old_name
|
327
|
+
define_directive new_name, directive(old_name)
|
328
|
+
end
|
329
|
+
|
330
|
+
# Removes the given _name_ from the list of known directives.
|
331
|
+
def undefine_directive name
|
332
|
+
name = Directive.validate_name name
|
333
|
+
!!directives.delete(name)
|
334
|
+
end
|
335
|
+
|
336
|
+
# Removes the directive _dir_ (or the one associated to that name) from the list of directives.
|
337
|
+
def remove_directive dir
|
338
|
+
dir = directive(dir) unless dir.is_a?(Class) && dir < Directive
|
339
|
+
!!directives.delete_if{ |_,d| d == dir }
|
340
|
+
end
|
341
|
+
|
342
|
+
end
|
343
|
+
|
344
|
+
@directives = {}
|
345
|
+
extend SpecificationHelper
|
346
|
+
class << self # :nodoc:
|
347
|
+
alias known known_directives
|
348
|
+
alias get directive
|
349
|
+
alias [] directive
|
350
|
+
end
|
351
|
+
|
352
|
+
def initialize comment, text='', relative_line_no=1 # :nodoc:
|
353
|
+
@comment = comment
|
354
|
+
super(text,relative_line_no) # initializes metadata
|
355
|
+
@metadata.update self.class.metadata
|
356
|
+
end
|
357
|
+
|
358
|
+
# The +name+ of the class.
|
359
|
+
def name
|
360
|
+
self.class.name
|
361
|
+
end
|
362
|
+
|
363
|
+
# The SourceFile this directive is into.
|
364
|
+
def source_file
|
365
|
+
comment.source_file
|
366
|
+
end
|
367
|
+
|
368
|
+
# The Comment this directive is into.
|
369
|
+
attr_reader :comment
|
370
|
+
alias parent comment
|
371
|
+
|
372
|
+
# Returns +self+
|
373
|
+
def directive
|
374
|
+
self
|
375
|
+
end
|
376
|
+
|
377
|
+
# Returns +nil+ if it wasn't given, the +String+ otherwise.
|
378
|
+
def parameter
|
379
|
+
text.empty? ? nil : text
|
380
|
+
end
|
381
|
+
alias param parameter
|
382
|
+
|
383
|
+
#
|
384
|
+
# Split #parameter on spaces, returning an +Array+ of them.
|
385
|
+
# If _remove_commas_ is true, from each parameter is removed the trailing comma
|
386
|
+
# (so that this resembles a list of parameters in a method call).
|
387
|
+
#
|
388
|
+
def parameters remove_commas=true
|
389
|
+
return [] unless parameter
|
390
|
+
result = parameter.split(/\s+/)
|
391
|
+
result.map!{ |param| param.chomp(',') } if remove_commas
|
392
|
+
result
|
393
|
+
end
|
394
|
+
alias params parameters
|
395
|
+
|
396
|
+
#
|
397
|
+
# Has this directive been detected implicitly?
|
398
|
+
# If _in_sections_ is given, it specifies the sections in which the search takes place.
|
399
|
+
#
|
400
|
+
def implicit?(*in_sections)
|
401
|
+
in_sections = comment.sections if in_sections.empty?
|
402
|
+
# An implicit directive is "over" some other section
|
403
|
+
in_sections.find{ |sec| sec.line_range.cover?(self.line_no) }
|
404
|
+
end
|
405
|
+
|
406
|
+
#
|
407
|
+
# :section: API
|
408
|
+
#
|
409
|
+
|
410
|
+
# Uses +:directive+ as the default type of warning.
|
411
|
+
def warn msg=nil, type=:directive, frame=nil
|
412
|
+
super
|
413
|
+
end
|
414
|
+
|
415
|
+
# Meaningful default values are provided.
|
416
|
+
def eval code, binding=Binding.pseudo_toplevel, filename=file_name, lineno=line_no # :doc:
|
417
|
+
pwd = Dir.pwd
|
418
|
+
Kernel.eval(code,binding,filename,lineno)
|
419
|
+
ensure
|
420
|
+
Dir.chdir(pwd) unless Dir.pwd==pwd
|
421
|
+
end
|
422
|
+
private :eval
|
423
|
+
|
424
|
+
# Deactivate this directive so that it won't have any effect.
|
425
|
+
def deactivate!
|
426
|
+
define_singleton_method(:execute){}
|
427
|
+
end
|
428
|
+
alias deactivate deactivate!
|
429
|
+
|
430
|
+
#
|
431
|
+
# :section: Accessing related sections
|
432
|
+
#
|
433
|
+
|
434
|
+
def section_index # :nodoc:
|
435
|
+
@section_index ||= comment.sections.find_index{ |sec| sec.line_no >= self.line_no } ||
|
436
|
+
comment.sections.size-1
|
437
|
+
end
|
438
|
+
private :section_index
|
439
|
+
|
440
|
+
# Returns the Comment#enclosed_comments for the #comment.
|
441
|
+
# If a block is given, it's yielded each of them in turn.
|
442
|
+
def all_enclosed_comments(&blk)
|
443
|
+
ary = comment.enclosed_comments
|
444
|
+
ary.each(&blk) if blk
|
445
|
+
ary
|
446
|
+
end
|
447
|
+
|
448
|
+
# Returns the Comment#sections of the #comment.
|
449
|
+
# If a block is given, it's yielded each of them in turn.
|
450
|
+
def all_sections(&blk)
|
451
|
+
ary = comment.sections
|
452
|
+
if blk
|
453
|
+
warn 'This directive affects also sections before' unless prev_sections.empty?
|
454
|
+
ary.each(&blk)
|
455
|
+
end
|
456
|
+
ary
|
457
|
+
end
|
458
|
+
|
459
|
+
# Returns the Comment#examples of the #comment.
|
460
|
+
# If a block is given, it's yielded each of them in turn.
|
461
|
+
def all_examples &blk
|
462
|
+
ary = all_sections.select(&:example?)
|
463
|
+
if blk
|
464
|
+
warn 'This directive affects also examples before' unless prev_examples.empty?
|
465
|
+
ary.each(&blk)
|
466
|
+
end
|
467
|
+
ary
|
468
|
+
end
|
469
|
+
|
470
|
+
# Returns the Comment#plain_texts of the #comment.
|
471
|
+
# If a block is given, it's yielded each of them in turn.
|
472
|
+
def all_texts &blk
|
473
|
+
ary = all_sections.select(&:text?)
|
474
|
+
if blk
|
475
|
+
warn 'This directive affects also texts before' unless prev_texts.empty?
|
476
|
+
ary.each(&blk)
|
477
|
+
end
|
478
|
+
ary
|
479
|
+
end
|
480
|
+
|
481
|
+
# Returns the +sections+ of the #comment that are before this directive.
|
482
|
+
# If a block is given, it's yielded each of them in turn.
|
483
|
+
def prev_sections(&blk)
|
484
|
+
ary = all_sections.take(section_index)
|
485
|
+
if blk
|
486
|
+
warn 'No sections before this directive' if ary.empty?
|
487
|
+
ary.each(&blk)
|
488
|
+
end
|
489
|
+
ary
|
490
|
+
end
|
491
|
+
|
492
|
+
# Returns the +examples+ of the #comment that are before this directive.
|
493
|
+
# If a block is given, it's yielded each of them in turn.
|
494
|
+
def prev_examples &blk
|
495
|
+
ary = prev_sections.select(&:example?)
|
496
|
+
if blk
|
497
|
+
warn 'No examples before this directive' if ary.empty?
|
498
|
+
ary.each(&blk)
|
499
|
+
end
|
500
|
+
ary
|
501
|
+
end
|
502
|
+
|
503
|
+
# Returns the +plain_texts+ of the #comment that are before this directive.
|
504
|
+
# If a block is given, it's yielded each of them in turn.
|
505
|
+
def prev_texts &blk
|
506
|
+
ary = prev_sections.select(&:text?)
|
507
|
+
if blk
|
508
|
+
warn 'No texts before this directive' if ary.empty?
|
509
|
+
ary.each(&blk)
|
510
|
+
end
|
511
|
+
ary
|
512
|
+
end
|
513
|
+
|
514
|
+
# Returns the +sections+ of the #comment that are after this directive.
|
515
|
+
# If a block is given, it's yielded each of them in turn.
|
516
|
+
def next_sections(&blk)
|
517
|
+
ary = all_sections.drop(section_index)
|
518
|
+
if blk
|
519
|
+
warn 'No sections after this directive' if ary.empty?
|
520
|
+
ary.each(&blk)
|
521
|
+
end
|
522
|
+
return ary
|
523
|
+
end
|
524
|
+
|
525
|
+
# Returns the +examples+ of the #comment that are after this directive.
|
526
|
+
# If a block is given, it's yielded each of them in turn.
|
527
|
+
def next_examples &blk
|
528
|
+
ary = next_sections.select(&:example?)
|
529
|
+
if blk
|
530
|
+
warn 'No examples after this directive' if ary.empty?
|
531
|
+
ary.each(&blk)
|
532
|
+
end
|
533
|
+
ary
|
534
|
+
end
|
535
|
+
|
536
|
+
# Returns the +plain_texts+ of the #comment that are after this directive.
|
537
|
+
# If a block is given, it's yielded each of them in turn.
|
538
|
+
def next_texts &blk
|
539
|
+
ary = next_sections.select(&:text?)
|
540
|
+
if blk
|
541
|
+
warn 'No texts after this directive' if ary.empty?
|
542
|
+
ary.each(&blk)
|
543
|
+
end
|
544
|
+
ary
|
545
|
+
end
|
546
|
+
|
547
|
+
# Returns the +section+ of the #comment just after this directive.
|
548
|
+
def next_section
|
549
|
+
next_sections.first
|
550
|
+
end
|
551
|
+
|
552
|
+
# Returns the +example+ of the #comment just after this directive.
|
553
|
+
def next_example
|
554
|
+
next_examples.first or
|
555
|
+
raise "Couldn't apply directive, missing example after"
|
556
|
+
end
|
557
|
+
|
558
|
+
# Returns the +plain_text+ of the #comment just after this directive.
|
559
|
+
def next_text
|
560
|
+
next_texts.first or
|
561
|
+
raise "Couldn't apply directive, missing text after"
|
562
|
+
end
|
563
|
+
|
564
|
+
# Returns the +section+ of the #comment just before this directive.
|
565
|
+
def prev_section
|
566
|
+
prev_sections.last
|
567
|
+
end
|
568
|
+
|
569
|
+
# Returns the +example+ of the #comment just before this directive.
|
570
|
+
def prev_example
|
571
|
+
prev_examples.last or
|
572
|
+
raise "Couldn't apply directive, missing example before"
|
573
|
+
end
|
574
|
+
|
575
|
+
# Returns the +plain_text+ of the #comment just after this directive.
|
576
|
+
def prev_text
|
577
|
+
prev_texts.last or
|
578
|
+
raise "Couldn't apply directive, missing text before"
|
579
|
+
end
|
580
|
+
|
581
|
+
#
|
582
|
+
# :section: Directives: Activation/Deactivation
|
583
|
+
#
|
584
|
+
|
585
|
+
##
|
586
|
+
# :singleton-method:
|
587
|
+
# :call-seq:
|
588
|
+
# on
|
589
|
+
# "" (empty string)
|
590
|
+
#
|
591
|
+
# Turns on execution of examples. Often used after an ::off directive.
|
592
|
+
#
|
593
|
+
# An example (from <tt>array.c</tt>):
|
594
|
+
# :rdx: off
|
595
|
+
# /*
|
596
|
+
# * [...]
|
597
|
+
# * a = ["a", "b", "c"]
|
598
|
+
# * :rdx: off
|
599
|
+
# * a.cycle { |x| print x } # prints abcabcabc... forever
|
600
|
+
# * :rdx:
|
601
|
+
# * a.cycle(2) { |x| print x } # prints abcabc
|
602
|
+
# * [...]
|
603
|
+
# */
|
604
|
+
# static VALUE
|
605
|
+
# rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
|
606
|
+
#
|
607
|
+
# Note::
|
608
|
+
# This may also be used in a non-documenting comment (see Comment#documenting),
|
609
|
+
# with the purpouse of executing additional examples other than the ones in the documentation output.
|
610
|
+
#
|
611
|
+
define_directive 'on' do
|
612
|
+
next_examples{ |ex| ex.activate true }
|
613
|
+
end
|
614
|
+
alias_directive '', 'on'
|
615
|
+
|
616
|
+
##
|
617
|
+
# :singleton-method:
|
618
|
+
# :call-seq:
|
619
|
+
# off [-]
|
620
|
+
#
|
621
|
+
# Turns off execution of examples (see the ::on directive for an example).
|
622
|
+
#
|
623
|
+
# Note::
|
624
|
+
# If the parameter is (or starts with) a hypen, only the immediately following
|
625
|
+
# example is deactivated; the execution will continue regularly,
|
626
|
+
# according to the effect of other directives after it.
|
627
|
+
#
|
628
|
+
define_directive 'off' do
|
629
|
+
if param && param[0] == '-'
|
630
|
+
next_example.deactivate true
|
631
|
+
else
|
632
|
+
next_examples{ |ex| ex.deactivate true }
|
633
|
+
end
|
634
|
+
end
|
635
|
+
|
636
|
+
##
|
637
|
+
# :singleton-method:
|
638
|
+
# :call-seq:
|
639
|
+
# skip [motivation]
|
640
|
+
#
|
641
|
+
# Skips the execution of the immediately following example (through Example#whole_skip)
|
642
|
+
# reporting the optional _motivation_.
|
643
|
+
#
|
644
|
+
# The cause (and type) of this skip is a simple +TODO+ in RDX,
|
645
|
+
# in a lighter way than an explicit failure.
|
646
|
+
#
|
647
|
+
# An example:
|
648
|
+
# # Sorts a collection in descending order.
|
649
|
+
# # :rdx: skip write an example
|
650
|
+
# def reverse_sort enum
|
651
|
+
# enum.sort.reverse
|
652
|
+
# end
|
653
|
+
#
|
654
|
+
# Note::
|
655
|
+
# This directive may even be used before a text section: in this case nothing is
|
656
|
+
# really skipped, but it will anyhow be showed in the report.
|
657
|
+
#
|
658
|
+
define_directive 'skip' do
|
659
|
+
sect = next_section
|
660
|
+
msg,type = param,:TODO
|
661
|
+
if sect && sect.example?
|
662
|
+
next_example.whole_skip(msg, type, relative_line_no)
|
663
|
+
else
|
664
|
+
skip msg, type
|
665
|
+
end
|
666
|
+
end
|
667
|
+
|
668
|
+
##
|
669
|
+
# :singleton-method:
|
670
|
+
# :call-seq:
|
671
|
+
# bug [details]
|
672
|
+
# buggy [details]
|
673
|
+
# is_buggy [details]
|
674
|
+
#
|
675
|
+
# Signals a bug in the library reporting _details_: use this directive above an example
|
676
|
+
# that _should_ work as declared.
|
677
|
+
# Use this only if you can't fix it, otherwise the explicit failure is better.
|
678
|
+
#
|
679
|
+
# An example (from <tt>encoding.c</tt>):
|
680
|
+
# :rdx: off
|
681
|
+
# /*
|
682
|
+
# * Search the encoding with specified <i>name</i>.
|
683
|
+
# * <i>name</i> should be a string or symbol.
|
684
|
+
# * Encoding.find("US-ASCII") #=> Encoding::US_ASCII
|
685
|
+
# * :rdx: bug symbols aren't accepted
|
686
|
+
# * Encoding.find(:Shift_JIS) #=> Encoding::Shift_JIS
|
687
|
+
# * [...]
|
688
|
+
# */
|
689
|
+
# static VALUE
|
690
|
+
# enc_find(VALUE klass, VALUE enc)
|
691
|
+
#
|
692
|
+
# Note::
|
693
|
+
# This works in a way similar to ::skip, but used +BUG+ as the skip type.
|
694
|
+
#
|
695
|
+
define_directive 'bug' do
|
696
|
+
next_example.whole_skip param, :BUG, relative_line_no
|
697
|
+
end
|
698
|
+
alias_directive 'buggy', 'bug'
|
699
|
+
alias_directive 'is_buggy', 'buggy'
|
700
|
+
|
701
|
+
##
|
702
|
+
# :singleton-method:
|
703
|
+
# :call-seq:
|
704
|
+
# if condition
|
705
|
+
#
|
706
|
+
# If _condition_ evals to a true value the next example is executed regularly,
|
707
|
+
# otherwise it's skipped.
|
708
|
+
#
|
709
|
+
# An example:
|
710
|
+
# # The code will show a demonstration of +fork+:
|
711
|
+
# # :rdx: if Process.respond_to? :fork
|
712
|
+
# # puts 'In parent'
|
713
|
+
# # fork do
|
714
|
+
# # puts 'In child'
|
715
|
+
# # end
|
716
|
+
# # puts 'Back in parent'
|
717
|
+
# module Kernel; end
|
718
|
+
#
|
719
|
+
# Note::
|
720
|
+
# The condition is often platform-dependent,
|
721
|
+
# in order to make tests portable between different operating systems
|
722
|
+
# (hence the type of this skip is +LACKING+).
|
723
|
+
#
|
724
|
+
define_directive 'if' do
|
725
|
+
if eval(param)
|
726
|
+
next_example.activate
|
727
|
+
else
|
728
|
+
next_example.whole_skip param, :LACKING, relative_line_no
|
729
|
+
end
|
730
|
+
end
|
731
|
+
|
732
|
+
##
|
733
|
+
# :singleton-method:
|
734
|
+
# :call-seq:
|
735
|
+
# lazy
|
736
|
+
# is_slow
|
737
|
+
#
|
738
|
+
# Run the next example only when necessary (see Example#lazy).
|
739
|
+
# This directive is often used when the example shows performance penalities.
|
740
|
+
#
|
741
|
+
# An example (from <tt>re.rdoc</tt>):
|
742
|
+
# :rdx: off
|
743
|
+
# == Performance
|
744
|
+
# Certain pathological combinations of constructs can lead to abysmally bad
|
745
|
+
# performance.
|
746
|
+
# [...]
|
747
|
+
# s = 'a' * 25 + 'd' + 'a' * 4 + 'c'
|
748
|
+
# #=> "aaaaaaaaaaaaaaaaaaaaaaaaadaaaac"
|
749
|
+
# [...]
|
750
|
+
# However, the following pattern takes appreciably longer:
|
751
|
+
# \:rdx: is_slow
|
752
|
+
# /(b|a+)*c/ =~ s #=> 26
|
753
|
+
#
|
754
|
+
define_directive 'lazy' do
|
755
|
+
next_example.lazy relative_line_no
|
756
|
+
end
|
757
|
+
alias_directive 'is_slow', 'lazy'
|
758
|
+
|
759
|
+
#
|
760
|
+
# :section: Directives: Input/Output/Error
|
761
|
+
#
|
762
|
+
|
763
|
+
##
|
764
|
+
# :singleton-method:
|
765
|
+
# :call-seq:
|
766
|
+
# stdout
|
767
|
+
# output
|
768
|
+
#
|
769
|
+
# Interprets the next example as the expected output of the previuos one
|
770
|
+
# (see Example#produces_on_stdout).
|
771
|
+
#
|
772
|
+
# Implicit detection::
|
773
|
+
# Recognized in a text section containing only <tt>produces:</tt>
|
774
|
+
# (html emphasized tags are allowed).
|
775
|
+
#
|
776
|
+
# An example:
|
777
|
+
# # Kernel#puts writes to <tt>$stdout</tt> its arguments.
|
778
|
+
# # puts 'one', 'two', 'three...'
|
779
|
+
# # produces:
|
780
|
+
# # one
|
781
|
+
# # two
|
782
|
+
# # three...
|
783
|
+
# module Kernel; end
|
784
|
+
#
|
785
|
+
# Note::
|
786
|
+
# If the output is only one line it can be passed as a parameter to this directive
|
787
|
+
# (and it's probably described in a text section)
|
788
|
+
#
|
789
|
+
define_directive 'stdout' do |dir|
|
790
|
+
dir.define do
|
791
|
+
output = param || next_example
|
792
|
+
prev_example.produces_on_stdout output, relative_line_no
|
793
|
+
end
|
794
|
+
dir.configure_implicit do |base=/[Pp]roduces:?/, allow_emphatized=true|
|
795
|
+
pat = Regexp.union(base)
|
796
|
+
pat = Text.add_html_tags pat, nil, 'em', 'i' if allow_emphatized
|
797
|
+
dir.find_in_text /\A\s*#{pat}\s*\z/
|
798
|
+
end
|
799
|
+
end
|
800
|
+
alias_directive 'output', 'stdout'
|
801
|
+
|
802
|
+
##
|
803
|
+
# :singleton-method:
|
804
|
+
# :call-seq:
|
805
|
+
# indicative_output
|
806
|
+
#
|
807
|
+
# Ignores the next example and the output produced by the previuos one.
|
808
|
+
#
|
809
|
+
# An example:
|
810
|
+
# #
|
811
|
+
# # The following code will output the first 1000 prime numbers.
|
812
|
+
# # require 'Prime'
|
813
|
+
# # Prime.first(1000).each{ |prime| puts prime }
|
814
|
+
# # The result:
|
815
|
+
# # :rdx: indicative_output
|
816
|
+
# # 2
|
817
|
+
# # 3
|
818
|
+
# # 5
|
819
|
+
# # 7
|
820
|
+
# # ... other 994 prime numbers ...
|
821
|
+
# # 7907
|
822
|
+
# # 7919
|
823
|
+
# module Prime; end
|
824
|
+
#
|
825
|
+
define_directive 'indicative_output' do
|
826
|
+
next_example.deactivate!
|
827
|
+
prev_example.outputs //
|
828
|
+
end
|
829
|
+
|
830
|
+
##
|
831
|
+
# :singleton-method:
|
832
|
+
# :call-seq:
|
833
|
+
# stderr
|
834
|
+
#
|
835
|
+
# Interprets the next example as the expected output of the previuos one
|
836
|
+
# (see Example#produces_on_stderr).
|
837
|
+
#
|
838
|
+
# An example (from <tt>enumerator.c</tt>):
|
839
|
+
# :rdx: off
|
840
|
+
# /*
|
841
|
+
# * [...]
|
842
|
+
# * Use of this form is discouraged. Use Kernel#enum_for or Kernel#to_enum
|
843
|
+
# * instead.
|
844
|
+
# * e = Enumerator.new(ObjectSpace, :each_object)
|
845
|
+
# * #-> ObjectSpace.enum_for(:each_object)
|
846
|
+
# * produces on stderr:
|
847
|
+
# * :rdx: stderr
|
848
|
+
# * warning: Enumerator.new without a block is deprecated; use Object#to_enum
|
849
|
+
# * [...]
|
850
|
+
# */
|
851
|
+
# static VALUE
|
852
|
+
# enumerator_initialize(int argc, VALUE *argv, VALUE obj)
|
853
|
+
#
|
854
|
+
define_directive 'stderr' do
|
855
|
+
output = param || next_example
|
856
|
+
prev_example.produces_on_stderr output, relative_line_no
|
857
|
+
end
|
858
|
+
|
859
|
+
##
|
860
|
+
# :singleton-method:
|
861
|
+
# :call-seq:
|
862
|
+
# stdin
|
863
|
+
# input
|
864
|
+
#
|
865
|
+
# Interprets the previous example as the input for the next one.
|
866
|
+
#
|
867
|
+
# An example (from <tt>vm_eval.c</tt>):
|
868
|
+
# :rdx: off
|
869
|
+
# /*
|
870
|
+
# * [...]
|
871
|
+
# * When the following input
|
872
|
+
# * First line given
|
873
|
+
# * Second line given
|
874
|
+
# * Last line given
|
875
|
+
# * Quit!
|
876
|
+
# * is given into this program
|
877
|
+
# * :rdx: stdin
|
878
|
+
# * loop do
|
879
|
+
# * line = gets
|
880
|
+
# * break if !line or line =~ /^[qQ]/
|
881
|
+
# * puts "Got: #{line}"
|
882
|
+
# * end
|
883
|
+
# * produces:
|
884
|
+
# * Got: First line given
|
885
|
+
# * Got: Second line given
|
886
|
+
# * Got: Last line given
|
887
|
+
# * [...]
|
888
|
+
# */
|
889
|
+
# static VALUE
|
890
|
+
# rb_f_loop(VALUE self)
|
891
|
+
#
|
892
|
+
define_directive 'stdin' do
|
893
|
+
input = param || prev_example
|
894
|
+
next_example.take_input_from input
|
895
|
+
end
|
896
|
+
alias_directive 'input', 'stdin'
|
897
|
+
|
898
|
+
##
|
899
|
+
# :singleton-method:
|
900
|
+
# :call-seq:
|
901
|
+
# exception
|
902
|
+
# error
|
903
|
+
#
|
904
|
+
# :rdx: no_warnings conventions
|
905
|
+
# Interprets the next example as the description of the exception
|
906
|
+
# raised by previous one (see Example#raises).
|
907
|
+
#
|
908
|
+
# Implicit detection::
|
909
|
+
# Recognized in a text section containing only <tt>raises the exception:</tt>
|
910
|
+
# (or simply <tt>raises:</tt>).
|
911
|
+
#
|
912
|
+
# An example:
|
913
|
+
# # Kernel#raise will raise a RuntimeError with the given message:
|
914
|
+
# # raise 'Boom!'
|
915
|
+
# # raises the exception:
|
916
|
+
# # Boom! (RuntimeError)
|
917
|
+
# module Kernel; end
|
918
|
+
#
|
919
|
+
# Note::
|
920
|
+
# If the parameter is given it's treated as the exception's class name.
|
921
|
+
# This can be useful if the message is negligible, but we don't want to
|
922
|
+
# rely on an error convention.
|
923
|
+
#
|
924
|
+
define_directive 'exception' do |dir|
|
925
|
+
dir.define do
|
926
|
+
error = param || next_example
|
927
|
+
prev_example.raises error, relative_line_no
|
928
|
+
end
|
929
|
+
dir.configure_implicit do |base=/[Rr]aises?(?: the exception)?:?/, allow_emphatized=true|
|
930
|
+
pat = Regexp.union base
|
931
|
+
pat = Text.add_html_tags pat, nil, 'em', 'i' if allow_emphatized
|
932
|
+
dir.find_in_text /\A\s*#{pat}\s*\z/
|
933
|
+
end
|
934
|
+
end
|
935
|
+
alias_directive 'error', 'exception'
|
936
|
+
|
937
|
+
##
|
938
|
+
# :singleton-method:
|
939
|
+
# :call-seq:
|
940
|
+
# write_file relative_name
|
941
|
+
#
|
942
|
+
# Writes the content of the next example to the specified file _relative_name_
|
943
|
+
# (see Example#write_to_file).
|
944
|
+
#
|
945
|
+
# Implicit detection::
|
946
|
+
# Recognized in an example beginning with a comment <tt># File: </tt> _relative_name_.
|
947
|
+
#
|
948
|
+
# An example:
|
949
|
+
# # IO.foreach iterates over the lines (according to <tt>$/</tt>) of the given file.
|
950
|
+
# # # File: lines.txt
|
951
|
+
# # This is line 1
|
952
|
+
# # this is line 2
|
953
|
+
# # and so on...
|
954
|
+
# # From the application:
|
955
|
+
# # enum = IO.foreach 'lines.txt'
|
956
|
+
# # enum.next.chomp #=> "This is line 1"
|
957
|
+
# # enum.next.chomp #=> "This is line 2"
|
958
|
+
# # enum.next.chomp #=> "and so on..."
|
959
|
+
# class IO; end
|
960
|
+
#
|
961
|
+
define_directive 'write_file' do |dir|
|
962
|
+
dir.define do
|
963
|
+
next_example.write_to_file param, relative_line_no do |content|
|
964
|
+
content.slice! /\A.*\n/ if implicit?
|
965
|
+
content
|
966
|
+
end
|
967
|
+
end
|
968
|
+
dir.configure_implicit do |base=/(?:[Ii]n +)?[Ff]ile[: ]/, fname=/\S+/|
|
969
|
+
dir.find_in_example /\A\s*#[ \t]*#{base}[ \t]*(#{fname})[ \t]*$/
|
970
|
+
end
|
971
|
+
end
|
972
|
+
|
973
|
+
##
|
974
|
+
# :singleton-method:
|
975
|
+
# :call-seq:
|
976
|
+
# check_file relative_name
|
977
|
+
#
|
978
|
+
# Compares the next example against the content of the specified file _relative_name_
|
979
|
+
# (see Example#check_file_content).
|
980
|
+
#
|
981
|
+
# An example:
|
982
|
+
# # IO#puts writes the given argument to +ios+ along with a record separator.
|
983
|
+
# # f = File.new 'out', 'w'
|
984
|
+
# # f.puts 'line 1'
|
985
|
+
# # f.puts 'line 2'
|
986
|
+
# # f.puts 'line 1000' # 1,2,3 was boring...
|
987
|
+
# # Now the file +out+ will contian:
|
988
|
+
# # :rdx: check_file out
|
989
|
+
# # line 1
|
990
|
+
# # line 2
|
991
|
+
# # line 1000
|
992
|
+
# class IO; end
|
993
|
+
#
|
994
|
+
define_directive 'check_file' do
|
995
|
+
next_example.check_file_content param, relative_line_no
|
996
|
+
end
|
997
|
+
|
998
|
+
#
|
999
|
+
# :section: Directives: Context change
|
1000
|
+
#
|
1001
|
+
|
1002
|
+
##
|
1003
|
+
# :singleton-method:
|
1004
|
+
# :call-seq:
|
1005
|
+
# new_binding
|
1006
|
+
#
|
1007
|
+
# Changes the binding of the following examples to a new empty one
|
1008
|
+
# (specifically to Binding.pseudo_toplevel).
|
1009
|
+
#
|
1010
|
+
# An example (from <tt>re.c</tt>):
|
1011
|
+
# :rdx: off
|
1012
|
+
# /*
|
1013
|
+
# * [...]
|
1014
|
+
# * If <code>=~</code> is used with a regexp literal with named captures,
|
1015
|
+
# * captured strings (or nil) is assigned to local variables named by
|
1016
|
+
# * the capture names.
|
1017
|
+
# * /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/ =~ " x = y "
|
1018
|
+
# * lhs #=> "x"
|
1019
|
+
# * rhs #=> "y"
|
1020
|
+
# * [...]
|
1021
|
+
# * :rdx: new_binding
|
1022
|
+
# * :rdx: # Without this directive those local variables are already defined
|
1023
|
+
# * The assignment does not occur if the regexp is not a literal.
|
1024
|
+
# * re = /(?<lhs>\w+)\s*=\s*(?<rhs>\w+)/
|
1025
|
+
# * re =~ " x = y "
|
1026
|
+
# * lhs # error: undefined local variable
|
1027
|
+
# * rhs # error: undefined local variable
|
1028
|
+
# * [...]
|
1029
|
+
# */
|
1030
|
+
# VALUE
|
1031
|
+
# rb_reg_match(VALUE re, VALUE str)
|
1032
|
+
#
|
1033
|
+
define_directive 'new_binding' do
|
1034
|
+
new_binding = Binding.pseudo_toplevel
|
1035
|
+
next_examples{ |ex| ex.set_binding new_binding }
|
1036
|
+
end
|
1037
|
+
|
1038
|
+
##
|
1039
|
+
# :singleton-method:
|
1040
|
+
# :call-seq:
|
1041
|
+
# toplevel
|
1042
|
+
#
|
1043
|
+
# The default binding for the execution isn't the true toplevel one
|
1044
|
+
# (see CodeObject::Runnable::Startable#prepare_binding),
|
1045
|
+
# however some examples don't have sense under this condition.
|
1046
|
+
# This directive changes the binding of the following examples to a copy
|
1047
|
+
# of the toplevel one (specifically to Binding.toplevel).
|
1048
|
+
#
|
1049
|
+
# An example (from <tt>struct.c</tt>):
|
1050
|
+
# :rdx: off
|
1051
|
+
# /*
|
1052
|
+
# * [...]
|
1053
|
+
# * <code>Struct::new</code> returns a new <code>Class</code> object,
|
1054
|
+
# * which can then be used to create specific instances of the new
|
1055
|
+
# * structure.
|
1056
|
+
# * [...]
|
1057
|
+
# * :rdx: toplevel
|
1058
|
+
# * # Create a structure named by its constant
|
1059
|
+
# * Customer = Struct.new(:name, :address) #=> Customer
|
1060
|
+
# * Customer.new("Dave", "123 Main") # > #<struct Customer name="Dave", address="123 Main">
|
1061
|
+
# *-- rdx
|
1062
|
+
# * Without this directive we should write <tt>::Customer</tt> instead of <tt>Customer</tt>;
|
1063
|
+
# * this can confuse the reader, bacause normally it's not necessary.
|
1064
|
+
# * Now clean-up step:
|
1065
|
+
# * Object.send :remove_const, :Customer
|
1066
|
+
# *++
|
1067
|
+
# */
|
1068
|
+
# static VALUE
|
1069
|
+
# rb_struct_s_def(int argc, VALUE *argv, VALUE klass)
|
1070
|
+
#
|
1071
|
+
# Note::
|
1072
|
+
# It's user's responsibilty to clean up all the necessary
|
1073
|
+
# (usually using private rdx sections).
|
1074
|
+
#
|
1075
|
+
define_directive 'toplevel' do
|
1076
|
+
toplevel_binding = Binding.toplevel
|
1077
|
+
next_examples{ |ex| ex.set_binding toplevel_binding }
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
##
|
1081
|
+
# :singleton-method:
|
1082
|
+
# :call-seq:
|
1083
|
+
# before_require
|
1084
|
+
#
|
1085
|
+
# Runs the next example before requiring the full set of libraries.
|
1086
|
+
# This turns handy if you are modifying the core and you want
|
1087
|
+
# to show the differences provided by your patch.
|
1088
|
+
#
|
1089
|
+
# An example (from <tt>mathn.rb</tt>):
|
1090
|
+
# # [...]
|
1091
|
+
# # mathn features late rounding and lacks truncation of intermediate results:
|
1092
|
+
# # Without mathn:
|
1093
|
+
# # :rdx: before_require
|
1094
|
+
# # 20 / 9 * 3 * 14 / 7 * 3 / 2 # => 18
|
1095
|
+
# # With mathn:
|
1096
|
+
# # 20 / 9 * 3 * 14 / 7 * 3 / 2 # => 20
|
1097
|
+
# # [...]
|
1098
|
+
# class Numeric; end
|
1099
|
+
#
|
1100
|
+
define_directive 'before_require' do
|
1101
|
+
next_example.run_before_require
|
1102
|
+
end
|
1103
|
+
|
1104
|
+
##
|
1105
|
+
# :singleton-method:
|
1106
|
+
# :call-seq:
|
1107
|
+
# setup
|
1108
|
+
#
|
1109
|
+
# Uses the next example as a setup for the comment, that will run
|
1110
|
+
# before every Comment#enclosed_comments.
|
1111
|
+
#
|
1112
|
+
# An example (from <tt>cmath.rb</tt>):
|
1113
|
+
# # [...]
|
1114
|
+
# # In the following examples we assume that CMath is included at toplevel for the sake of clarity:
|
1115
|
+
# # :rdx: setup
|
1116
|
+
# # include CMath
|
1117
|
+
# # Square root of a negative number is a complex number.
|
1118
|
+
# # sqrt(-9) #=> 0+3.0i
|
1119
|
+
# # [...]
|
1120
|
+
# module CMath
|
1121
|
+
# ##
|
1122
|
+
# # Returns the natural logarithm of Complex. If a second argument is given,
|
1123
|
+
# # it will be the base of logarithm.
|
1124
|
+
# # log(Complex(0,0)) # > (-Infinity+0.0i)
|
1125
|
+
# #--
|
1126
|
+
# # This works thanks to the above setup
|
1127
|
+
# def log(*args)
|
1128
|
+
# #[...]
|
1129
|
+
# end
|
1130
|
+
# end
|
1131
|
+
#
|
1132
|
+
define_directive 'setup' do
|
1133
|
+
next_example.use_as_setup
|
1134
|
+
end
|
1135
|
+
|
1136
|
+
##
|
1137
|
+
# :singleton-method:
|
1138
|
+
# :call-seq:
|
1139
|
+
# teardown
|
1140
|
+
#
|
1141
|
+
# Uses the next example as a teardown for the comment, that will run
|
1142
|
+
# after every Comment#enclosed_comments.
|
1143
|
+
#
|
1144
|
+
# See +setup+ for an example.
|
1145
|
+
#
|
1146
|
+
define_directive 'teardown' do
|
1147
|
+
next_example.use_as_teardown
|
1148
|
+
end
|
1149
|
+
|
1150
|
+
##
|
1151
|
+
# :singleton-method:
|
1152
|
+
# :call-seq:
|
1153
|
+
# in_tmpdir
|
1154
|
+
#
|
1155
|
+
# Runs the next example in a temporary directory (see Example#run_in_tmpdir).
|
1156
|
+
#
|
1157
|
+
# An example (from <tt>encoding.c</tt>):
|
1158
|
+
# :rdx: off
|
1159
|
+
# /*
|
1160
|
+
# * [...]
|
1161
|
+
# * While writing the file, the internal encoding is not specified as it is
|
1162
|
+
# * only necessary for reading. While reading the file both the internal and
|
1163
|
+
# * external encoding must be specified to obtain the correct result:
|
1164
|
+
# * :rdx: in_tmpdir
|
1165
|
+
# * string = "R\u00E9sum\u00E9"
|
1166
|
+
# * open("transcoded.txt", "w:ISO-8859-1") do |io|
|
1167
|
+
# * io.write(string)
|
1168
|
+
# * end
|
1169
|
+
# * puts File.binread("transcoded.txt").dump
|
1170
|
+
# * [...]
|
1171
|
+
# * produces:
|
1172
|
+
# * "R\xE9sum\xE9"
|
1173
|
+
# * [...]
|
1174
|
+
# */
|
1175
|
+
# void
|
1176
|
+
# Init_Encoding(void)
|
1177
|
+
#
|
1178
|
+
define_directive 'in_tmpdir' do
|
1179
|
+
next_example.run_in_tmpdir
|
1180
|
+
end
|
1181
|
+
|
1182
|
+
##
|
1183
|
+
# :singleton-method:
|
1184
|
+
# :call-seq:
|
1185
|
+
# in_tmpdir!
|
1186
|
+
#
|
1187
|
+
# Same as ::in_tmpdir, but applies to the whole comment.
|
1188
|
+
#
|
1189
|
+
define_directive 'in_tmpdir!' do
|
1190
|
+
comment.run_in_tmpdir
|
1191
|
+
end
|
1192
|
+
|
1193
|
+
##
|
1194
|
+
# :singleton-method:
|
1195
|
+
# :call-seq:
|
1196
|
+
# in_tmpdir!!
|
1197
|
+
#
|
1198
|
+
# Same as ::in_tmpdir, but applies to #all_enclosed_comments
|
1199
|
+
# (on which operate +setup+ and +teardown+).
|
1200
|
+
#
|
1201
|
+
define_directive 'in_tmpdir!!' do
|
1202
|
+
all_enclosed_comments(&:run_in_tmpdir)
|
1203
|
+
end
|
1204
|
+
|
1205
|
+
##
|
1206
|
+
# :singleton-method:
|
1207
|
+
# :call-seq:
|
1208
|
+
# bash default_prompt=/\$\s/, continuation_prompt=/>\s/
|
1209
|
+
#
|
1210
|
+
# Interprets the next example as a bash command-line session
|
1211
|
+
# (see Example#on_bash_mode).
|
1212
|
+
#
|
1213
|
+
# Implicit detection::
|
1214
|
+
# Recognized in an example that begins with the default prompt (the predefined
|
1215
|
+
# isn't syntattically correct in Ruby, so we can safely avoid ambiguous situations).
|
1216
|
+
#
|
1217
|
+
# An example (from <tt>optparse.rb</tt>):
|
1218
|
+
# # [...]
|
1219
|
+
# # We give options from the command line:
|
1220
|
+
# # $ ruby example.rb -h
|
1221
|
+
# # Usage: example.rb [options] [arguments...]
|
1222
|
+
# # -v, --[no-]verbose Run verbosely
|
1223
|
+
# # $ ruby example.rb -v
|
1224
|
+
# # options = {:verbose=>true}
|
1225
|
+
# # ARGV = []
|
1226
|
+
# # [...]
|
1227
|
+
# class OptionParser; end
|
1228
|
+
#
|
1229
|
+
# Note::
|
1230
|
+
# If the output includes the default or continuation prompt you should change
|
1231
|
+
# them (or supply +nil+ if you don't want) with the explicit directive:
|
1232
|
+
# :rdx: off
|
1233
|
+
# # This is the result in the command line (<tt>" </tt> is the continuation prompt):
|
1234
|
+
# # :rdx: bash nil, '" '
|
1235
|
+
# # $ ruby <<EOS
|
1236
|
+
# # " puts "> Hello world!"
|
1237
|
+
# # " EOS
|
1238
|
+
# # > Hello world!
|
1239
|
+
# class Shell; end
|
1240
|
+
#
|
1241
|
+
define_directive 'bash' do |dir|
|
1242
|
+
dir.metadata[:default_prompt] = /\$\s/
|
1243
|
+
dir.metadata[:continuation_prompt] = />\s/
|
1244
|
+
dir.define do
|
1245
|
+
default_prompt,continuation_prompt = param && eval("[#{param}]")
|
1246
|
+
default_prompt ||= metadata[:default_prompt]
|
1247
|
+
continuation_prompt ||= metadata[:continuation_prompt]
|
1248
|
+
next_example.on_bash_mode default_prompt, continuation_prompt
|
1249
|
+
end
|
1250
|
+
dir.configure_implicit do |prompt=dir.metadata[:default_prompt]|
|
1251
|
+
prompt = prompt.is_a?(Regexp) ? prompt.to_s : Regexp.escape(prompt.to_str)
|
1252
|
+
dir.find_in_example /\A\s*^#{prompt}/
|
1253
|
+
end
|
1254
|
+
end
|
1255
|
+
|
1256
|
+
#
|
1257
|
+
# :section: Directives: Assertions customization
|
1258
|
+
#
|
1259
|
+
|
1260
|
+
##
|
1261
|
+
# :singleton-method:
|
1262
|
+
# :call-seq:
|
1263
|
+
# float digits=3
|
1264
|
+
#
|
1265
|
+
# Sets the next example on floating-point mode (see Example#on_float_mode)
|
1266
|
+
# passing _digits_ (default to 3, value stored in the #metadata as +:digits+).
|
1267
|
+
#
|
1268
|
+
# An example (from <tt>math.c</tt>):
|
1269
|
+
# :rdx: off
|
1270
|
+
# /*
|
1271
|
+
# * [...]
|
1272
|
+
# * If +x+ isn't too large we have that:
|
1273
|
+
# * :rdx: float
|
1274
|
+
# * log_gamma,sgn_gamma = Math.lgamma(x)
|
1275
|
+
# * log_gamma #=> Math.log(Math.gamma(x).abs)
|
1276
|
+
# * sgn_gamma #=> Math.gamma(x) < 0 ? -1 : 1
|
1277
|
+
# * otherwise Math.gamma(x) will overflow (yielding Infinity),
|
1278
|
+
# * while Math.lgamma(x) does not
|
1279
|
+
# */
|
1280
|
+
# static VALUE
|
1281
|
+
# math_lgamma(VALUE obj, VALUE x)
|
1282
|
+
#
|
1283
|
+
# Note::
|
1284
|
+
# This directive covers the holes leaved by Convention::result_numeric.
|
1285
|
+
#
|
1286
|
+
define_directive 'float' do |dir_class|
|
1287
|
+
dir_class.metadata[:digits] = 3
|
1288
|
+
dir_class.define do
|
1289
|
+
digits = param ? Integer(param) : metadata[:digits]
|
1290
|
+
next_example.on_float_mode(digits)
|
1291
|
+
end
|
1292
|
+
end
|
1293
|
+
|
1294
|
+
##
|
1295
|
+
# :singleton-method:
|
1296
|
+
# :call-seq:
|
1297
|
+
# float! digits=3
|
1298
|
+
#
|
1299
|
+
# Same as ::float but applies to the whole comment.
|
1300
|
+
#
|
1301
|
+
define_directive 'float!' do
|
1302
|
+
digits = param ? Integer(param) : metadata[:digits]
|
1303
|
+
all_examples{ |ex| ex.on_float_mode(digits) }
|
1304
|
+
end
|
1305
|
+
|
1306
|
+
##
|
1307
|
+
# :singleton-method:
|
1308
|
+
# :call-seq:
|
1309
|
+
# indicative_numbers
|
1310
|
+
#
|
1311
|
+
# Sets the next example on indicative numbers mode
|
1312
|
+
# (see Example#on_indicative_numbers_mode).
|
1313
|
+
#
|
1314
|
+
# An example (from <tt>benchmark.rb</tt>):
|
1315
|
+
# :rdx: off
|
1316
|
+
# # :rdx: indicative_numbers
|
1317
|
+
# # n = 50000
|
1318
|
+
# # Benchmark.bm(7) do |x|
|
1319
|
+
# # x.report("for:") { for i in 1..n; a = "1"; end }
|
1320
|
+
# # x.report("times:") { n.times do ; a = "1"; end }
|
1321
|
+
# # x.report("upto:") { 1.upto(n) do ; a = "1"; end }
|
1322
|
+
# # end
|
1323
|
+
# # Produces:
|
1324
|
+
# # user system total real
|
1325
|
+
# # for: 1.050000 0.000000 1.050000 ( 0.503462)
|
1326
|
+
# # times: 1.533333 0.016667 1.550000 ( 0.735473)
|
1327
|
+
# # upto: 1.500000 0.016667 1.516667 ( 0.711239)
|
1328
|
+
# module Benchmark; end
|
1329
|
+
#
|
1330
|
+
define_directive 'indicative_numbers' do
|
1331
|
+
next_example.on_indicative_numbers_mode
|
1332
|
+
end
|
1333
|
+
|
1334
|
+
##
|
1335
|
+
# :singleton-method:
|
1336
|
+
# :call-seq:
|
1337
|
+
# indicative_numbers!
|
1338
|
+
#
|
1339
|
+
# Same as ::indicative_numbers, but applies to the whole comment.
|
1340
|
+
#
|
1341
|
+
define_directive 'indicative_numbers!' do
|
1342
|
+
all_examples(&:on_indicative_numbers_mode)
|
1343
|
+
end
|
1344
|
+
|
1345
|
+
#
|
1346
|
+
# :section: Directives: Miscellaneous
|
1347
|
+
#
|
1348
|
+
|
1349
|
+
##
|
1350
|
+
# :singleton-method:
|
1351
|
+
# :call-seq:
|
1352
|
+
# # comment
|
1353
|
+
#
|
1354
|
+
# Insert a comment (probably about some RDX detail).
|
1355
|
+
#
|
1356
|
+
# Note::
|
1357
|
+
# For the directive syntax at least one space is required after the hash,
|
1358
|
+
# which happens to be the directive name.
|
1359
|
+
#
|
1360
|
+
define_directive '#' do end
|
1361
|
+
|
1362
|
+
##
|
1363
|
+
# :singleton-method:
|
1364
|
+
# :call-seq:
|
1365
|
+
# disable_warnings *types
|
1366
|
+
# no_warnings *types
|
1367
|
+
#
|
1368
|
+
# Disables the given _types_ of warnings for the next section
|
1369
|
+
# (see CodeObject#disable_warnings).
|
1370
|
+
#
|
1371
|
+
# An example:
|
1372
|
+
# :rdx: off
|
1373
|
+
# # :rdx: no_warnings convention
|
1374
|
+
# # The hash-rocket notation, <tt>#=></tt>, indicates the result of a statement:
|
1375
|
+
# # 1+1 #=> 2
|
1376
|
+
# class Convention; end
|
1377
|
+
#
|
1378
|
+
define_directive 'disable_warnings' do
|
1379
|
+
next_section.disable_warnings *params
|
1380
|
+
end
|
1381
|
+
alias_directive 'no_warnings', 'disable_warnings'
|
1382
|
+
|
1383
|
+
##
|
1384
|
+
# :singleton-method:
|
1385
|
+
# :call-seq:
|
1386
|
+
# disable_warnings! *types
|
1387
|
+
# no_warnings! *types
|
1388
|
+
#
|
1389
|
+
# Same as ::disable_warnings, but applies to the whole comment.
|
1390
|
+
#
|
1391
|
+
define_directive 'disable_warnings!' do
|
1392
|
+
comment.disable_warnings *params
|
1393
|
+
end
|
1394
|
+
alias_directive 'no_warnings!', 'disable_warnings!'
|
1395
|
+
|
1396
|
+
##
|
1397
|
+
# :singleton-method:
|
1398
|
+
# :call-seq:
|
1399
|
+
# discard_output
|
1400
|
+
#
|
1401
|
+
# Ignores the uncaptured output produced by the next example - otherwise a warning will be generated.
|
1402
|
+
#
|
1403
|
+
# An example:
|
1404
|
+
# :rdx: off
|
1405
|
+
# # The following code will output the first 1000 prime numbers:
|
1406
|
+
# # :rdx: discard_output
|
1407
|
+
# # require 'Prime'
|
1408
|
+
# # Prime.first(1000).each{ |prime| puts prime }
|
1409
|
+
# module Prime; end
|
1410
|
+
#
|
1411
|
+
# Note::
|
1412
|
+
# This directive actually suppresses the +stdout+ type of warning.
|
1413
|
+
#
|
1414
|
+
define_directive 'discard_output' do
|
1415
|
+
next_example.disable_warnings 'stdout'
|
1416
|
+
end
|
1417
|
+
|
1418
|
+
##
|
1419
|
+
# :singleton-method:
|
1420
|
+
# :call-seq:
|
1421
|
+
# disable_implicit *names
|
1422
|
+
#
|
1423
|
+
# Disables the given _names_ of implicit directives in the next section
|
1424
|
+
# (see Comment#disable_implicit_directives_in).
|
1425
|
+
#
|
1426
|
+
define_directive 'disable_implicit' do
|
1427
|
+
comment.disable_implicit_directives_in next_section, *params
|
1428
|
+
end
|
1429
|
+
|
1430
|
+
end
|
1431
|
+
|
1432
|
+
end
|