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
data/lib/rdx/ruby_lex.rb
ADDED
@@ -0,0 +1,324 @@
|
|
1
|
+
|
2
|
+
module RDX
|
3
|
+
|
4
|
+
require 'rdoc'
|
5
|
+
require 'rdoc/ruby_token'
|
6
|
+
require 'rdoc/ruby_lex'
|
7
|
+
|
8
|
+
#
|
9
|
+
# Interface to the +RDoc::RubyLex+ tokenizer and parser.
|
10
|
+
#
|
11
|
+
module RubyLex
|
12
|
+
|
13
|
+
extend self
|
14
|
+
|
15
|
+
# :stopdoc:
|
16
|
+
|
17
|
+
# Matches a Ruby inline comment
|
18
|
+
RE_CMT = /#.*+\n/
|
19
|
+
|
20
|
+
# Matches a Ruby inline comment optionally preceded by spaces
|
21
|
+
RE_SP_CMT = /[^\S\n]*+#{RE_CMT.source}/o
|
22
|
+
|
23
|
+
# Matches trailing spaces of a line
|
24
|
+
RE_SP_NL = /[^\S\n]*+\n/
|
25
|
+
|
26
|
+
TkCOMMENT = RDoc::Parser::Ruby::TkCOMMENT
|
27
|
+
TkSPACE = RDoc::Parser::Ruby::TkSPACE
|
28
|
+
TkNL = RDoc::Parser::Ruby::TkNL
|
29
|
+
ERROR = RDoc::RubyLex::Error
|
30
|
+
|
31
|
+
# +tab_width+ does not matter in evaluation...
|
32
|
+
RDOC_OPTIONS = RDoc::Options.new
|
33
|
+
|
34
|
+
# :startdoc:
|
35
|
+
|
36
|
+
# Raises a +ParseError+ from the given exception and internal line number.
|
37
|
+
def raise_parse_error err, line_no=nil
|
38
|
+
msg = "Invalid ruby code"
|
39
|
+
error = ParseError.new msg
|
40
|
+
if err.is_a?(ERROR)
|
41
|
+
msg << ":\n" << err.message
|
42
|
+
error.line_no = line_no
|
43
|
+
end
|
44
|
+
raise error # this caller: assuming not debugging RDoc::RubyLex itself
|
45
|
+
end
|
46
|
+
private :raise_parse_error
|
47
|
+
|
48
|
+
# Generates a new +RDoc::RubyLex+ with the given _ruby_ as input.
|
49
|
+
def new_rdoc_scanner ruby
|
50
|
+
scanner = RDoc::RubyLex.new ruby, RDOC_OPTIONS
|
51
|
+
scanner.exception_on_syntax_error = true
|
52
|
+
scanner
|
53
|
+
end
|
54
|
+
private :new_rdoc_scanner
|
55
|
+
|
56
|
+
# Through <tt>RDoc::RubyLex.tokenize</tt> tokenizes the _ruby_ string and
|
57
|
+
# retunrs an array of +RDoc::RubyToken+.
|
58
|
+
# These are processed with #adjust_tokens if _adjust_tokens_ is +true+ (default).
|
59
|
+
# May raise a +ParseError+ if the input is invalid enough.
|
60
|
+
def tokenize ruby, adjust_tokens=true
|
61
|
+
ruby = ruby.to_str
|
62
|
+
scanner = new_rdoc_scanner ruby
|
63
|
+
tokens = []
|
64
|
+
begin
|
65
|
+
while token = scanner.token do
|
66
|
+
tokens << token
|
67
|
+
end
|
68
|
+
rescue => err
|
69
|
+
raise_parse_error err, scanner.line_no
|
70
|
+
end
|
71
|
+
tokens = adjust_tokens tokens if adjust_tokens
|
72
|
+
tokens.each{ |tk| yield tk } if block_given?
|
73
|
+
return tokens
|
74
|
+
end
|
75
|
+
private :tokenize
|
76
|
+
|
77
|
+
# The comments also include the trailing newline and any comment on
|
78
|
+
# successives lines until a blank one.
|
79
|
+
def adjust_tokens orig_tokens
|
80
|
+
tokens = []
|
81
|
+
current_tkcomment = comment_on_current_line = nil
|
82
|
+
space_tokens = []
|
83
|
+
orig_tokens.each do |tk|
|
84
|
+
if tk.instance_of?(TkCOMMENT) # Don't consider embedded documents
|
85
|
+
comment_on_current_line = true
|
86
|
+
next tokens.push(current_tkcomment = tk) unless current_tkcomment
|
87
|
+
current_tkcomment.text << space_tokens.map(&:text).join('') << tk.text
|
88
|
+
space_tokens.clear
|
89
|
+
elsif tk.is_a?(TkSPACE)
|
90
|
+
next tokens << tk unless current_tkcomment
|
91
|
+
# comment_on_current_line is false
|
92
|
+
space_tokens << tk
|
93
|
+
elsif tk.is_a?(TkNL) # there is for sure at the end of the tokens
|
94
|
+
next tokens << tk unless current_tkcomment
|
95
|
+
if comment_on_current_line
|
96
|
+
current_tkcomment.text << tk.text
|
97
|
+
comment_on_current_line = false
|
98
|
+
else
|
99
|
+
tokens.concat space_tokens
|
100
|
+
space_tokens.clear
|
101
|
+
current_tkcomment = nil
|
102
|
+
end
|
103
|
+
else
|
104
|
+
tokens << tk
|
105
|
+
current_tkcomment = nil
|
106
|
+
end
|
107
|
+
end
|
108
|
+
return tokens
|
109
|
+
end
|
110
|
+
private :adjust_tokens
|
111
|
+
|
112
|
+
#
|
113
|
+
# Doesn't interpret _string_ as ruby code and extracts
|
114
|
+
# potential ruby comments.
|
115
|
+
# The result is an array <tt>[ [comment,line_no],... ]</tt>.
|
116
|
+
#
|
117
|
+
# RDX::RubyLex.extract_potential_comments <<EOS
|
118
|
+
# This is not ruby :-( # potential comment
|
119
|
+
# # ...continuing... #
|
120
|
+
# other text
|
121
|
+
# # another comment
|
122
|
+
# EOS
|
123
|
+
# # => [
|
124
|
+
# # ["# potential comment\n# ...continuing... #\n", 1],
|
125
|
+
# # ["# another comment\n", 4]
|
126
|
+
# # ]
|
127
|
+
#
|
128
|
+
# If a block is supplied, it is yielded those results.
|
129
|
+
#
|
130
|
+
# This method never raises a +ParseError+.
|
131
|
+
#
|
132
|
+
def extract_potential_comments string
|
133
|
+
string = string.to_str
|
134
|
+
string = string.dup << "\n" unless string.end_with?("\n")
|
135
|
+
comments = []
|
136
|
+
string.scan /#{RE_CMT}#{RE_SP_CMT}*+/o do |comment|
|
137
|
+
md = Regexp.last_match
|
138
|
+
l_no = md.pre_match.count("\n") + 1
|
139
|
+
comments << [comment,l_no]
|
140
|
+
end
|
141
|
+
comments.each{ |(comment,line_no)| yield comment, line_no } if block_given?
|
142
|
+
return comments
|
143
|
+
end
|
144
|
+
|
145
|
+
#
|
146
|
+
# Extracts the comments in _ruby_ string and returns an
|
147
|
+
# array of arrays <tt>[ [comment,line_no],... ]</tt>.
|
148
|
+
# The comments also include the trailing newline and any comment
|
149
|
+
# on successives lines until a blank one.
|
150
|
+
#
|
151
|
+
# RDX::RubyLex.extract_comments <<EOS
|
152
|
+
# # This is Ruby!
|
153
|
+
#
|
154
|
+
# # This method simply returns the +Fixnum+ 2.
|
155
|
+
# def return_two
|
156
|
+
# 2 # of course
|
157
|
+
# # it returns two
|
158
|
+
# end
|
159
|
+
# EOS
|
160
|
+
# # => [
|
161
|
+
# # ["# This is Ruby!\n", 1],
|
162
|
+
# # ["# This method simply returns the +Fixnum+ 2.\n", 3],
|
163
|
+
# # ["# of course\n # it returns two\n", 5]
|
164
|
+
# # ]
|
165
|
+
#
|
166
|
+
# If a block is given, it is yielded those results.
|
167
|
+
#
|
168
|
+
# May raise a +ParseError+ if the input is invalid enough.
|
169
|
+
#
|
170
|
+
def extract_comments ruby
|
171
|
+
comments = []
|
172
|
+
tokenize ruby do |tk|
|
173
|
+
next unless tk.instance_of?(TkCOMMENT) # Don't capture embedded documents
|
174
|
+
comments << [tk.text,tk.line_no]
|
175
|
+
end
|
176
|
+
comments.each{ |(comment,line_no)| yield comment, line_no } if block_given?
|
177
|
+
return comments
|
178
|
+
end
|
179
|
+
|
180
|
+
# Subdivides the _ruby_ string into toplevel statements and returns an array
|
181
|
+
# <tt>[ [statement,line_no] ]</tt>.
|
182
|
+
# These are processed with #adjust_statements if _adjust_statements_ is +true+ (default).
|
183
|
+
# May raise a +ParseError+ if the input invalid enough.
|
184
|
+
def statementize ruby, adjust_statements=true
|
185
|
+
ruby = ruby.to_str
|
186
|
+
statements = []
|
187
|
+
scanner = new_rdoc_scanner ruby
|
188
|
+
begin
|
189
|
+
scanner.each_top_level_statement do |stmnt,l_no|
|
190
|
+
statements << [stmnt,l_no]
|
191
|
+
end
|
192
|
+
rescue => err
|
193
|
+
raise_parse_error err, scanner.line_no
|
194
|
+
end
|
195
|
+
statements = adjust_statements statements if adjust_statements
|
196
|
+
statements.each{ |stmnt| yield stmnt } if block_given?
|
197
|
+
return statements
|
198
|
+
end
|
199
|
+
private :statementize
|
200
|
+
|
201
|
+
# The statements also includes trailing comments until a blank line.
|
202
|
+
def adjust_statements orig_statements
|
203
|
+
statements = []
|
204
|
+
return statements if orig_statements.empty?
|
205
|
+
# The first statement is unchanged
|
206
|
+
statements.push(orig_statements.shift)
|
207
|
+
previous_statement = statements.first[0]
|
208
|
+
orig_statements.each do |stmnt,l_no|
|
209
|
+
if stmnt =~ /\A[^\S\n]*\./ # statement concatenation
|
210
|
+
previous_statement.concat stmnt
|
211
|
+
next
|
212
|
+
end
|
213
|
+
# For all the other statements move the leading spaces and comment to the previous statement
|
214
|
+
leading = stmnt.slice! /\A#{RE_SP_CMT}*+#{RE_SP_NL}*+/o
|
215
|
+
previous_statement.concat leading
|
216
|
+
l_no += leading.count("\n")
|
217
|
+
statements << [stmnt,l_no]
|
218
|
+
previous_statement = stmnt
|
219
|
+
end
|
220
|
+
return statements
|
221
|
+
end
|
222
|
+
private :adjust_statements
|
223
|
+
|
224
|
+
#
|
225
|
+
# Collects all top-level statements for _ruby_ string into an array
|
226
|
+
# <tt>[ [statement,line_no], ... ]</tt>. Each statement also includes
|
227
|
+
# trailing comments until a blank line.
|
228
|
+
#
|
229
|
+
# RDX::RubyLex.extract_statements <<EOS
|
230
|
+
# # beginning comment
|
231
|
+
# statement_1 # => result_1
|
232
|
+
# # other stuff...
|
233
|
+
# statement_2
|
234
|
+
# statement_3
|
235
|
+
# # => result_3
|
236
|
+
#
|
237
|
+
# # new block
|
238
|
+
# statement_4
|
239
|
+
# # => result_4
|
240
|
+
# EOS
|
241
|
+
# # => [
|
242
|
+
# # ["# beginning comment\nstatement_1 # => result_1\n# other stuff...\n", 1],
|
243
|
+
# # ["statement_2\n", 4],
|
244
|
+
# # ["statement_3\n # => result_3\n\n", 5],
|
245
|
+
# # ["# new block\nstatement_4\n# => result_4\n", 8]
|
246
|
+
# # ]
|
247
|
+
#
|
248
|
+
# If a block is given, it is yielded those results.
|
249
|
+
#
|
250
|
+
# May raise a +ParseError+ if the input is invalid enough.
|
251
|
+
#
|
252
|
+
def extract_statements ruby
|
253
|
+
statements = statementize ruby
|
254
|
+
statements.delete_if{ |stmnt,_| stmnt !~ /\S/ }
|
255
|
+
statements.each{ |(statement,line_no)| yield statement, line_no } if block_given?
|
256
|
+
return statements
|
257
|
+
end
|
258
|
+
|
259
|
+
#
|
260
|
+
# Returns the first statement for _ruby_ code.
|
261
|
+
# Until it's found may raise a +ParseError+ if the input is invalid enough.
|
262
|
+
#
|
263
|
+
# RDX::RubyLex.extract_first_statement <<EOS
|
264
|
+
# 'A ' +
|
265
|
+
# 'string'
|
266
|
+
# # statement ended succesfully!
|
267
|
+
# 0xqwerty: invalid input, but who cares now?
|
268
|
+
# EOS
|
269
|
+
# # => "'A ' +\n'string'\n# statement ended succesfully!\n"
|
270
|
+
#
|
271
|
+
def extract_first_statement ruby
|
272
|
+
ruby = ruby.to_str
|
273
|
+
scanner = new_rdoc_scanner ruby
|
274
|
+
begin
|
275
|
+
stmnt = scanner.each_top_level_statement{ |stmnt| break stmnt }
|
276
|
+
rescue => err
|
277
|
+
raise_parse_error err, scanner.line_no
|
278
|
+
end
|
279
|
+
while line = scanner.gets
|
280
|
+
break unless line =~ /\A#{RE_SP_CMT}/o
|
281
|
+
stmnt << line
|
282
|
+
end
|
283
|
+
stmnt
|
284
|
+
end
|
285
|
+
|
286
|
+
#
|
287
|
+
# Tokenizes _ruby_statement_ and returns an array of arrays <tt>[ [comment,line_no],... ]</tt>.
|
288
|
+
# The last element will always contain the comment at the end of the statement (an empty
|
289
|
+
# String if there isn't); all the others are indeed at positions of incomplete statement.
|
290
|
+
# RDX::RubyLex.extract_comments_from_statement <<EOS
|
291
|
+
# class AClass
|
292
|
+
# self # => AClass
|
293
|
+
# # Right, but the statement isn't yet complete!
|
294
|
+
# end
|
295
|
+
# # => AClass # Now it's ok!
|
296
|
+
# # other metadata...
|
297
|
+
# EOS
|
298
|
+
# # => [
|
299
|
+
# # ["# => AClass\n # Right, but the statement isn't yet complete!\n", 2],
|
300
|
+
# # ["# => AClass # Now it's ok!\n# other metadata...\n", 5]
|
301
|
+
# # ]
|
302
|
+
# RDX::RubyLex.extract_comments_from_statement <<EOS
|
303
|
+
# a_statement +
|
304
|
+
# without_comment\n
|
305
|
+
# EOS
|
306
|
+
# # => [ ["",2] ]
|
307
|
+
#
|
308
|
+
def extract_comments_from_statement ruby_statement
|
309
|
+
ruby_statement = ruby_statement.to_str.rstrip
|
310
|
+
tokens = tokenize ruby_statement
|
311
|
+
comments = []
|
312
|
+
tokens.each do |tk|
|
313
|
+
next unless tk.instance_of?(TkCOMMENT) # Don't capture embedded documents
|
314
|
+
comments << [tk.text,tk.line_no]
|
315
|
+
end
|
316
|
+
last_tk = tokens.last
|
317
|
+
comments << ['',last_tk.line_no] unless last_tk.instance_of?(TkCOMMENT)
|
318
|
+
comments.each{ |(comment,line_no)| yield comment, line_no } if block_given?
|
319
|
+
return comments
|
320
|
+
end
|
321
|
+
|
322
|
+
end
|
323
|
+
|
324
|
+
end
|
data/lib/rdx/runner.rb
ADDED
@@ -0,0 +1,309 @@
|
|
1
|
+
|
2
|
+
require 'rdx'
|
3
|
+
|
4
|
+
require 'rdx/code_object'
|
5
|
+
require 'rdx/reporter'
|
6
|
+
|
7
|
+
module RDX
|
8
|
+
|
9
|
+
#
|
10
|
+
# Coordinates all moving parts of RDX.
|
11
|
+
#
|
12
|
+
class Runner
|
13
|
+
|
14
|
+
# :stopdoc:
|
15
|
+
|
16
|
+
#
|
17
|
+
# Start and run RDX with the given _argv_
|
18
|
+
#
|
19
|
+
def self.run(argv)
|
20
|
+
new(argv).run
|
21
|
+
end
|
22
|
+
|
23
|
+
# Is RDX running?
|
24
|
+
def self.active?
|
25
|
+
!current.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
@current = nil
|
29
|
+
class << self
|
30
|
+
attr_reader :current
|
31
|
+
def current= runner
|
32
|
+
if runner && @current
|
33
|
+
raise Error, 'Only one instance of RDX is allowed to run'
|
34
|
+
end
|
35
|
+
@current = runner
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
ACTIONS = {
|
40
|
+
:initializing => [],
|
41
|
+
:ready => [:run],
|
42
|
+
:documenting => [:signal_start_parsing,
|
43
|
+
:signal_do_testing, :signal_start_generating],
|
44
|
+
:parsing => [:signal_end_parsing, :signal_start_parsing_file,
|
45
|
+
:signal_found_comment],
|
46
|
+
:parsing_file => [:signal_end_parsing_file, :signal_found_comment],
|
47
|
+
:testing => [],
|
48
|
+
:building => [],
|
49
|
+
:running_pre_tests => [],
|
50
|
+
:requiring_libs => [],
|
51
|
+
:running_post_tests => [],
|
52
|
+
:generating => [:signal_end_generating],
|
53
|
+
:reporting => [],
|
54
|
+
:finished => [],
|
55
|
+
}
|
56
|
+
|
57
|
+
def check_action action
|
58
|
+
actions = ACTIONS[@status]
|
59
|
+
return if actions && actions.include?(action.to_sym)
|
60
|
+
raise Error, "action #{action} request in #{@status.to_s}"
|
61
|
+
end
|
62
|
+
private :check_action
|
63
|
+
|
64
|
+
attr_reader :options
|
65
|
+
|
66
|
+
attr_reader :reporter
|
67
|
+
|
68
|
+
attr_reader :store
|
69
|
+
|
70
|
+
def initialize(argv)
|
71
|
+
@status = :initializing
|
72
|
+
setup_options(argv)
|
73
|
+
setup_reporter
|
74
|
+
setup_store
|
75
|
+
@status = :ready
|
76
|
+
end
|
77
|
+
|
78
|
+
def passed?
|
79
|
+
store.passed?
|
80
|
+
end
|
81
|
+
def self.passed?
|
82
|
+
active? && current.passed?
|
83
|
+
end
|
84
|
+
|
85
|
+
def verbose
|
86
|
+
options.verbose
|
87
|
+
end
|
88
|
+
def debug
|
89
|
+
options.debug
|
90
|
+
end
|
91
|
+
|
92
|
+
def puts *args # :nodoc:
|
93
|
+
reporter.puts *args
|
94
|
+
end
|
95
|
+
def print *args # :nodoc:
|
96
|
+
reporter.print *args
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def setup_options(options)
|
102
|
+
options = Options.new(options) unless options.is_a?(Options)
|
103
|
+
@options = options
|
104
|
+
end
|
105
|
+
|
106
|
+
def setup_reporter
|
107
|
+
@reporter = Reporter[options.reporter].new(self)
|
108
|
+
end
|
109
|
+
|
110
|
+
def setup_store
|
111
|
+
rdx_file = File.expand_path('.rdx')
|
112
|
+
spec = Specification.load(rdx_file) || Specification.default
|
113
|
+
unless spec.original?
|
114
|
+
puts 'Conventions and/or directives changed according to the .rdx file'
|
115
|
+
@options.files.delete rdx_file # TODO: include in doc
|
116
|
+
end
|
117
|
+
@store = Store.new spec
|
118
|
+
end
|
119
|
+
|
120
|
+
def run
|
121
|
+
check_action __method__
|
122
|
+
Runner.current = self
|
123
|
+
generator = Generator[options.generator].new
|
124
|
+
documenting_hook do
|
125
|
+
generator.generate(options.generator_options,options.files)
|
126
|
+
end
|
127
|
+
reporting_hook
|
128
|
+
rescue Exception => exc
|
129
|
+
exc.set_backtrace RDX.filter_backtrace(exc.backtrace)
|
130
|
+
raise exc
|
131
|
+
ensure
|
132
|
+
Runner.current = nil
|
133
|
+
end
|
134
|
+
public :run
|
135
|
+
|
136
|
+
#
|
137
|
+
# === Singal and Hooks ===
|
138
|
+
#
|
139
|
+
# Must be called elsewhere -> public -> checks @status
|
140
|
+
#
|
141
|
+
|
142
|
+
def start_documenting_hook
|
143
|
+
puts
|
144
|
+
puts "This is RDX, version #{RDX::VERSION}"
|
145
|
+
puts
|
146
|
+
puts "Start documenting with #{options.generator}"
|
147
|
+
@status = :documenting
|
148
|
+
end
|
149
|
+
|
150
|
+
def signal_start_parsing
|
151
|
+
check_action __method__
|
152
|
+
puts 'Parsing files...'
|
153
|
+
@status = :parsing
|
154
|
+
end
|
155
|
+
|
156
|
+
def signal_start_parsing_file(filename)
|
157
|
+
check_action __method__
|
158
|
+
@status = :parsing_file
|
159
|
+
end
|
160
|
+
|
161
|
+
def signal_end_parsing_file filename, success=true
|
162
|
+
check_action __method__
|
163
|
+
@status = :parsing
|
164
|
+
end
|
165
|
+
|
166
|
+
def signal_end_parsing success=true, testing=success
|
167
|
+
check_action __method__
|
168
|
+
@status = :documenting
|
169
|
+
signal_do_testing if testing
|
170
|
+
end
|
171
|
+
|
172
|
+
def signal_do_testing
|
173
|
+
check_action __method__
|
174
|
+
prev_status = @status
|
175
|
+
@status = :testing
|
176
|
+
tmpdir = Dir.mktmpdir ['rdx', Time.now.strftime("-%H%M")]
|
177
|
+
begin
|
178
|
+
Dir.chdir tmpdir do
|
179
|
+
build_tests_hook
|
180
|
+
handle_dry_run_option
|
181
|
+
run_tests_hook
|
182
|
+
dispose_store # clear bindings and run GC, so that tmpdir is empty and can be safely deleted
|
183
|
+
end
|
184
|
+
ensure
|
185
|
+
FileUtils.remove_entry tmpdir, !debug
|
186
|
+
end
|
187
|
+
puts "Tests finished!"
|
188
|
+
@status = prev_status
|
189
|
+
end
|
190
|
+
|
191
|
+
def build_tests_hook
|
192
|
+
puts 'Building tests...'
|
193
|
+
@status = :building
|
194
|
+
store.build options.seed
|
195
|
+
end
|
196
|
+
|
197
|
+
def run_tests_hook
|
198
|
+
puts
|
199
|
+
reporter.on_testing do
|
200
|
+
reporter.puts "Running tests (seed=#{options.seed})", ''
|
201
|
+
run_pre_tests_hook
|
202
|
+
require_libs_hook
|
203
|
+
run_post_tests_hook
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def handle_dry_run_option
|
208
|
+
return unless options.dry_run
|
209
|
+
CodeObject::Runnable.class_eval do
|
210
|
+
def trace_execution(*); end
|
211
|
+
def trace_assertion conv_name=nil, frame=location
|
212
|
+
register Detection.new(conv_name,frame)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def run_pre_tests_hook
|
218
|
+
@status = :running_pre_tests
|
219
|
+
reporter.run_pre_tests store.tests_before_require
|
220
|
+
end
|
221
|
+
|
222
|
+
def require_libs_hook
|
223
|
+
@status = :requiring_libs
|
224
|
+
lib_dirs = options.lib_dirs.reverse
|
225
|
+
$LOAD_PATH.unshift(*lib_dirs)
|
226
|
+
libs = options.libs
|
227
|
+
reporter.require_libs do
|
228
|
+
libs.each do |file|
|
229
|
+
reporter.require_lib(file){ require file }
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def run_post_tests_hook
|
235
|
+
@status = :running_post_tests
|
236
|
+
reporter.run_post_tests store.tests_after_require
|
237
|
+
end
|
238
|
+
|
239
|
+
def dispose_store
|
240
|
+
store.dispose_bindings
|
241
|
+
GC.start
|
242
|
+
end
|
243
|
+
|
244
|
+
def signal_start_generating
|
245
|
+
check_action __method__
|
246
|
+
@status = :generating
|
247
|
+
puts "Generating documentation output..."
|
248
|
+
end
|
249
|
+
|
250
|
+
def signal_end_generating success=true
|
251
|
+
check_action __method__
|
252
|
+
@status = :documenting
|
253
|
+
end
|
254
|
+
|
255
|
+
def end_documenting_hook
|
256
|
+
puts "Documentation finished!"
|
257
|
+
end
|
258
|
+
|
259
|
+
def reporting_hook
|
260
|
+
@status = :reporting
|
261
|
+
reporter.show_report
|
262
|
+
end
|
263
|
+
|
264
|
+
# reset => :ready ???
|
265
|
+
|
266
|
+
# Block hooks & signals
|
267
|
+
|
268
|
+
def documenting_hook
|
269
|
+
reporter.on_documenting do
|
270
|
+
start_documenting_hook
|
271
|
+
yield
|
272
|
+
end_documenting_hook
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def signal_parsing
|
277
|
+
signal_start_parsing
|
278
|
+
result = yield
|
279
|
+
signal_end_parsing
|
280
|
+
result
|
281
|
+
end
|
282
|
+
|
283
|
+
def signal_generating
|
284
|
+
unless options.doc_output
|
285
|
+
puts 'Generation of documentation output is disabled'
|
286
|
+
return
|
287
|
+
end
|
288
|
+
signal_start_generating
|
289
|
+
result = yield
|
290
|
+
signal_end_generating
|
291
|
+
result
|
292
|
+
end
|
293
|
+
|
294
|
+
# Define these as public signals and also in RDX::Runner and RDX.
|
295
|
+
# This methods do nothing if RDX isn't running.
|
296
|
+
private_instance_methods(false)
|
297
|
+
.concat(public_instance_methods(false))
|
298
|
+
.grep(/^signal_/) do |name|
|
299
|
+
public name
|
300
|
+
define_singleton_method name do |*args,&blk|
|
301
|
+
current && current.public_send(name,*args,&blk)
|
302
|
+
end
|
303
|
+
RDX.define_singleton_method name do |*args,&blk|
|
304
|
+
Runner.public_send(name,*args,&blk)
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
end
|