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.
Files changed (122) hide show
  1. checksums.yaml +7 -0
  2. data/.rdx +20 -0
  3. data/README +19 -0
  4. data/bin/rdx +7 -0
  5. data/examples/minimal/.rdx +8 -0
  6. data/examples/minimal/README +10 -0
  7. data/examples/minimal/lib/other_conventions.rb +64 -0
  8. data/examples/minimal/lib/the_basics.rb +94 -0
  9. data/examples/minimal/lib/using_directives.rb +66 -0
  10. data/examples/minimal/rakefile +27 -0
  11. data/examples/ruby-2.0.0-p0/README +7 -0
  12. data/examples/ruby-2.0.0-p0/install/core/.rdx +6 -0
  13. data/examples/ruby-2.0.0-p0/install/core/README +19 -0
  14. data/examples/ruby-2.0.0-p0/install/core/Rakefile +61 -0
  15. data/examples/ruby-2.0.0-p0/install/core/diffs/array.c.diff +166 -0
  16. data/examples/ruby-2.0.0-p0/install/core/diffs/bignum.c.diff +11 -0
  17. data/examples/ruby-2.0.0-p0/install/core/diffs/class.c.diff +36 -0
  18. data/examples/ruby-2.0.0-p0/install/core/diffs/compar.c.diff +11 -0
  19. data/examples/ruby-2.0.0-p0/install/core/diffs/complex.c.diff +301 -0
  20. data/examples/ruby-2.0.0-p0/install/core/diffs/cont.c.diff +65 -0
  21. data/examples/ruby-2.0.0-p0/install/core/diffs/dir.c.diff +147 -0
  22. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/re.rdoc.diff +328 -0
  23. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/security.rdoc.diff +8 -0
  24. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/standard_library.rdoc.diff +0 -0
  25. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax.rdoc.diff +0 -0
  26. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/assignment.rdoc.diff +160 -0
  27. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/calling_methods.rdoc.diff +130 -0
  28. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/control_expressions.rdoc.diff +254 -0
  29. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/exceptions.rdoc.diff +0 -0
  30. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/literals.rdoc.diff +54 -0
  31. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/methods.rdoc.diff +157 -0
  32. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/miscellaneous.rdoc.diff +91 -0
  33. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/modules_and_classes.rdoc.diff +161 -0
  34. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/precedence.rdoc.diff +8 -0
  35. data/examples/ruby-2.0.0-p0/install/core/diffs/doc/syntax/refinements.rdoc.diff +146 -0
  36. data/examples/ruby-2.0.0-p0/install/core/diffs/encoding.c.diff +276 -0
  37. data/examples/ruby-2.0.0-p0/install/core/diffs/enum.c.diff +281 -0
  38. data/examples/ruby-2.0.0-p0/install/core/diffs/enumerator.c.diff +479 -0
  39. data/examples/ruby-2.0.0-p0/install/core/diffs/error.c.diff +143 -0
  40. data/examples/ruby-2.0.0-p0/install/core/diffs/eval.c.diff +47 -0
  41. data/examples/ruby-2.0.0-p0/install/core/diffs/eval_jump.c.diff +23 -0
  42. data/examples/ruby-2.0.0-p0/install/core/diffs/file.c.diff +752 -0
  43. data/examples/ruby-2.0.0-p0/install/core/diffs/gc.c.diff +195 -0
  44. data/examples/ruby-2.0.0-p0/install/core/diffs/hash.c.diff +84 -0
  45. data/examples/ruby-2.0.0-p0/install/core/diffs/iseq.c.diff +354 -0
  46. data/examples/ruby-2.0.0-p0/install/core/diffs/load.c.diff +53 -0
  47. data/examples/ruby-2.0.0-p0/install/core/diffs/marshal.c.diff +98 -0
  48. data/examples/ruby-2.0.0-p0/install/core/diffs/math.c.diff +110 -0
  49. data/examples/ruby-2.0.0-p0/install/core/diffs/numeric.c.diff +103 -0
  50. data/examples/ruby-2.0.0-p0/install/core/diffs/object.c.diff +295 -0
  51. data/examples/ruby-2.0.0-p0/install/core/diffs/pack.c.diff +18 -0
  52. data/examples/ruby-2.0.0-p0/install/core/diffs/parse.y.diff +23 -0
  53. data/examples/ruby-2.0.0-p0/install/core/diffs/proc.c.diff +155 -0
  54. data/examples/ruby-2.0.0-p0/install/core/diffs/random.c.diff +126 -0
  55. data/examples/ruby-2.0.0-p0/install/core/diffs/range.c.diff +49 -0
  56. data/examples/ruby-2.0.0-p0/install/core/diffs/rational.c.diff +312 -0
  57. data/examples/ruby-2.0.0-p0/install/core/diffs/re.c.diff +207 -0
  58. data/examples/ruby-2.0.0-p0/install/core/diffs/ruby.c.diff +21 -0
  59. data/examples/ruby-2.0.0-p0/install/core/diffs/signal.c.diff +67 -0
  60. data/examples/ruby-2.0.0-p0/install/core/diffs/sprintf.c.diff +29 -0
  61. data/examples/ruby-2.0.0-p0/install/core/diffs/string.c.diff +73 -0
  62. data/examples/ruby-2.0.0-p0/install/core/diffs/struct.c.diff +20 -0
  63. data/examples/ruby-2.0.0-p0/install/core/diffs/time.c.diff +691 -0
  64. data/examples/ruby-2.0.0-p0/install/core/diffs/transcode.c.diff +435 -0
  65. data/examples/ruby-2.0.0-p0/install/core/diffs/variable.c.diff +62 -0
  66. data/examples/ruby-2.0.0-p0/install/core/diffs/vm_backtrace.c.diff +164 -0
  67. data/examples/ruby-2.0.0-p0/install/core/diffs/vm_eval.c.diff +99 -0
  68. data/examples/ruby-2.0.0-p0/install/core/diffs/vm_method.c.diff +17 -0
  69. data/examples/ruby-2.0.0-p0/install/core/diffs/vm_trace.c.diff +393 -0
  70. data/examples/ruby-2.0.0-p0/install/stdlib/.rdx +6 -0
  71. data/examples/ruby-2.0.0-p0/install/stdlib/README +19 -0
  72. data/examples/ruby-2.0.0-p0/install/stdlib/Rakefile +53 -0
  73. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/abbrev.rb.diff +77 -0
  74. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/base64.rb.diff +42 -0
  75. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/benchmark.rb.diff +144 -0
  76. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/cmath.rb.diff +52 -0
  77. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/forwardable.rb.diff +150 -0
  78. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/mathn.rb.diff +58 -0
  79. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/matrix.rb.diff +657 -0
  80. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/observer.rb.diff +31 -0
  81. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/optparse.rb.diff +147 -0
  82. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/ostruct.rb.diff +78 -0
  83. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/prime.rb.diff +52 -0
  84. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/pstore.rb.diff +110 -0
  85. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/scanf.rb.diff +100 -0
  86. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/securerandom.rb.diff +144 -0
  87. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/set.rb.diff +637 -0
  88. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/shellwords.rb.diff +66 -0
  89. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/singleton.rb.diff +37 -0
  90. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/tempfile.rb.diff +104 -0
  91. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/thread.rb.diff +38 -0
  92. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/time.rb.diff +140 -0
  93. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/tmpdir.rb.diff +52 -0
  94. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/uri.rb.diff +39 -0
  95. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/uri/common.rb.diff +237 -0
  96. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/weakref.rb.diff +36 -0
  97. data/examples/ruby-2.0.0-p0/install/stdlib/diffs/lib/yaml/store.rb.diff +27 -0
  98. data/examples/ruby-2.0.0-p0/rakefile +165 -0
  99. data/lib/rdx.rb +331 -0
  100. data/lib/rdx/assertions.rb +484 -0
  101. data/lib/rdx/binding.rb +151 -0
  102. data/lib/rdx/code_object.rb +598 -0
  103. data/lib/rdx/comment.rb +338 -0
  104. data/lib/rdx/convention.rb +1174 -0
  105. data/lib/rdx/directive.rb +1432 -0
  106. data/lib/rdx/example.rb +679 -0
  107. data/lib/rdx/generator.rb +112 -0
  108. data/lib/rdx/generator/rdoc.rb +1006 -0
  109. data/lib/rdx/options.rb +359 -0
  110. data/lib/rdx/plain_text.rb +65 -0
  111. data/lib/rdx/reporter.rb +421 -0
  112. data/lib/rdx/ruby_lex.rb +324 -0
  113. data/lib/rdx/runner.rb +309 -0
  114. data/lib/rdx/source_file.rb +94 -0
  115. data/lib/rdx/specification.rb +194 -0
  116. data/lib/rdx/statement.rb +248 -0
  117. data/lib/rdx/store.rb +119 -0
  118. data/lib/rdx/task.rb +361 -0
  119. data/lib/rdx/text.rb +688 -0
  120. data/lib/rdx/version.rb +15 -0
  121. data/rakefile +64 -0
  122. metadata +203 -0
@@ -0,0 +1,94 @@
1
+
2
+ module RDX
3
+
4
+ #
5
+ # Represents a parsed source file.
6
+ #
7
+ class SourceFile < CodeObject
8
+
9
+ # Absolute path for file
10
+ attr_reader :absolute_path
11
+ alias file_name absolute_path
12
+
13
+ # Conventionally the line number is <tt>1</tt>.
14
+ def line_no
15
+ 1
16
+ end
17
+
18
+ # The +Array+ of contained Comments.
19
+ attr_reader :comments
20
+ alias children comments
21
+
22
+ # :stopdoc:
23
+
24
+ attr_reader :reportables
25
+
26
+ def initialize(absolute_path)
27
+ super(nil)
28
+ @absolute_path = absolute_path
29
+ @comments = []
30
+ @reportables = nil
31
+ @reportables_hash = Hash.new{ |hash,cmt| hash[cmt] = [] } # comment => reportables_ary
32
+ end
33
+
34
+ def <=> other
35
+ return nil unless self.class == other.class
36
+ self.absolute_path <=> other.absolute_path
37
+ end
38
+
39
+ def add_comment comment
40
+ @comments << comment
41
+ return self
42
+ end
43
+ def remove_comment comment
44
+ @comments.delete comment
45
+ return self
46
+ end
47
+
48
+ def register reportable, code_object
49
+ @reportables_hash[code_object.comment] << reportable
50
+ end
51
+
52
+ def collect_reportables
53
+ return @reportables if @reportables
54
+ @reportables = []
55
+ @reportables_hash.to_a.sort_by(&:first).each do |comment,reportables|
56
+ @reportables.concat reportables.sort_by(&:line_no)
57
+ end
58
+ @reportables_hash = nil
59
+ @reportables
60
+ end
61
+
62
+ private
63
+
64
+ def build_self
65
+ uniq_comments
66
+ end
67
+
68
+ # Remove RDX comments pointing at the same location
69
+ # (for example RDoc creates more comments for ruby methods pointing at the same c-function)
70
+ # TODO: move to generator/rdoc
71
+ def uniq_comments
72
+ result = []
73
+ map = @comments.group_by(&:line_no)
74
+ map.delete(nil) # line number not set
75
+ map.each_value do |cmts|
76
+ if cmts.size == 1 # no conflict
77
+ result << cmts.first
78
+ else
79
+ doc,ndoc = cmts.partition(&:documenting)
80
+ if doc.empty?
81
+ result << ndoc.first
82
+ elsif ndoc.empty? || doc.size==1
83
+ result << doc.first
84
+ else # ambiguous situation
85
+ result << doc.first
86
+ end
87
+ end
88
+ end
89
+ @comments.replace result
90
+ end
91
+
92
+ end
93
+
94
+ end
@@ -0,0 +1,194 @@
1
+
2
+ module RDX
3
+
4
+ #
5
+ # Allows you to specify the conventions and directives used in your files.
6
+ #
7
+ # If the root directory of your project has an <tt>.rdx</tt> file,
8
+ # it's evalued as ruby code: this should return a Specification.
9
+ # Otherwise (or if there isn't such file) the ::default will be used and
10
+ # this class falls in the background.
11
+ #
12
+ # In that file you should indeed use <tt>RDX::Specification.new</tt> passing
13
+ # a block, that is allowed to modify its state (see ::new).
14
+ #
15
+ class Specification
16
+
17
+ include Convention::SpecificationHelper
18
+
19
+ include Directive::SpecificationHelper
20
+
21
+ #
22
+ # :category: Internal
23
+ #
24
+ # Loads the Specification from the given _file_ name.
25
+ # This is by default the <tt>.rdx</tt> file at the top level in the project directory.
26
+ #
27
+ def self.load file
28
+ file &&= file.dup.untaint
29
+ if file && File.file?(file)
30
+ opts = Object.const_defined?(:Encoding) ? { :mode => 'r:UTF-8:-' } : {}
31
+ code = File.read(file,opts).untaint
32
+ begin
33
+ spec = eval code, binding, file
34
+ if Specification === spec
35
+ spec.file = file.to_s
36
+ return spec
37
+ end
38
+ warn "[#{file}] isn't a #{self} (#{spec.class} instead).\nUsing default settings."
39
+ rescue SignalException, SystemExit
40
+ raise
41
+ rescue SyntaxError, Exception => e
42
+ warn "Invalid #{self} in [#{file}]: #{e}\nUsing default settings."
43
+ end
44
+ end
45
+ return nil
46
+ end
47
+
48
+ #
49
+ # :category: Internal
50
+ #
51
+ # Returns a new specification containing only the default initialization.
52
+ #
53
+ def self.default
54
+ new()
55
+ end
56
+
57
+ #
58
+ # :call-seq:
59
+ # new{ || ... }
60
+ # new{ |spec| ... }
61
+ #
62
+ # Creates a new Specification initialized with #default_conventions
63
+ # and #default_directives.
64
+ #
65
+ # If the block takes no argument it will be executed in the context
66
+ # of the specification instance, otherwise this will simply be yielded.
67
+ #
68
+ # The instance methods of the Specification allow its customization
69
+ # (but only during the execution of the block).
70
+ # These facilities are provided by the included modules
71
+ # Convention::SpecificationHelper (with a few enhancements) and
72
+ # Directive::SpecificationHelper.
73
+ #
74
+ def initialize(&blk)
75
+ @file = nil
76
+ @known_conventions = Convention.list
77
+ @used_conventions = []
78
+ default_conventions
79
+ default_directives
80
+ if blk
81
+ if blk.arity == 0
82
+ instance_eval(&blk)
83
+ else
84
+ blk.call(self)
85
+ end
86
+ end
87
+ finalize
88
+ end
89
+
90
+ def conventions # :nodoc:
91
+ @known_conventions
92
+ end
93
+ private :conventions
94
+
95
+ #
96
+ # :category: Internal
97
+ #
98
+ # Sets up the list of the default conventions.
99
+ # It's as if the content of this method would be
100
+ # at the beginning of each specification.
101
+ #
102
+ def default_conventions # :doc:
103
+ use_convention :eval
104
+ use_convention :result_eval
105
+ use_convention :result_same
106
+ use_convention :result_numeric
107
+ use_convention :result_string
108
+ use_convention :result_instance_of
109
+ use_convention :output_literal
110
+ use_convention :error_literal
111
+ use_convention :throws
112
+ end
113
+ private :default_conventions
114
+
115
+ #
116
+ # :category: Internal
117
+ #
118
+ # Sets up the list of the default directives.
119
+ # All the directives defined are automatically used.
120
+ #
121
+ def default_directives # :doc:
122
+ @directives = Directive.known
123
+ end
124
+ private :default_directives
125
+
126
+ #
127
+ # Returns _conv_ if it's already a Convention; otherwise calls +super+.
128
+ # You can now use instance methods of Convention to modify its features.
129
+ #
130
+ def convention conv
131
+ conv.is_a?(Convention) ? conv : super
132
+ end
133
+
134
+ #
135
+ # Uses the #convention _conv_ during the run, returning this convention.
136
+ #
137
+ # You can than chain some methods to modify its behaviour, such as
138
+ # Convention#use_with (or better its alias +with+) or
139
+ # Convention#edit.
140
+ #
141
+ # For example this line in the specification
142
+ # :rdx: off
143
+ # use_convention(:result_eval).with '->'
144
+ # will associate the <tt>-></tt> prompt to Convention::result_eval.
145
+ #
146
+ def use_convention conv
147
+ conv = convention(conv)
148
+ @used_conventions << conv unless @used_conventions.include?(conv)
149
+ return conv
150
+ end
151
+
152
+ #
153
+ # Removes the #convention _conv_ during the run.
154
+ # The convention is still defined and may be restored through #use_convention.
155
+ #
156
+ def dont_use_convention conv
157
+ @used_conventions.delete convention(conv)
158
+ return nil
159
+ end
160
+
161
+ # Use this convention once it's defined through +super+.
162
+ def define_convention(*)
163
+ use_convention super
164
+ end
165
+
166
+ # Don't use this convention once it's undefined through +super+.
167
+ def undefine_convention(*)
168
+ dont_use_convention super
169
+ end
170
+ alias remove_convention undefine_convention
171
+
172
+ # :stopdoc:
173
+
174
+ def original?
175
+ file.nil?
176
+ end
177
+
178
+ def finalize
179
+ return self if @used_conventions.frozen?
180
+ @known_conventions.replace @used_conventions
181
+ sort_conventions
182
+ @known_conventions.each(&:freeze).freeze
183
+ @directives.each(&:freeze).freeze
184
+ # Now (public) methods available
185
+ class << self # :nodoc:
186
+ public :conventions
187
+ attr_reader :directives
188
+ attr_accessor :file
189
+ end
190
+ end
191
+
192
+ end
193
+
194
+ end
@@ -0,0 +1,248 @@
1
+
2
+ module RDX
3
+
4
+ #
5
+ # Represents a toplevel statement in an example.
6
+ #
7
+ # For instance the following Example is composed by three +Statement+ objects:
8
+ #
9
+ # :rdx: off
10
+ #
11
+ # statement_1
12
+ # statement +
13
+ # 2
14
+ # if true
15
+ # else
16
+ # statement
17
+ # 3
18
+ # end # ends here
19
+ #
20
+ class Statement < CodeObject::Runnable
21
+
22
+ # The SourceFile this statement is into.
23
+ def source_file
24
+ comment.source_file
25
+ end
26
+
27
+ # The Comment this statement belongs to.
28
+ def comment
29
+ example.comment
30
+ end
31
+
32
+ # The Example this statement belongs to.
33
+ attr_reader :example
34
+ alias parent example
35
+
36
+ # Returns +self+.
37
+ def statement
38
+ self
39
+ end
40
+
41
+ # The Expectation of this stetement (may be +nil+ if invalid).
42
+ attr_reader :expectation
43
+
44
+ # Contains only the expectation.
45
+ def children
46
+ [expectation].compact
47
+ end
48
+
49
+ # The code of this statement.
50
+ def code
51
+ text
52
+ end
53
+
54
+ def initialize(example,text,relative_line_no=1) # :nodoc:
55
+ @example = example
56
+ super(text,relative_line_no)
57
+ remove_magic_comment # encoding handled in example
58
+ @expectation = nil
59
+ end
60
+
61
+ # The Convention associated with the expectation.
62
+ def convention
63
+ expectation && expectation.convention
64
+ end
65
+
66
+ # Does the expectation an #assertion?
67
+ def assertion?
68
+ expectation && expectation.assertion?
69
+ end
70
+
71
+ # Adds the label "top_level_statement" to +super+
72
+ def location l_no=nil
73
+ super(l_no,'top_level_statement')
74
+ end
75
+
76
+ #
77
+ # :section: Internal
78
+ #
79
+
80
+ # Computes the #actual_value and passes it to Expectation#run.
81
+ def run
82
+ expectation && expectation.run(actual_value)
83
+ end
84
+
85
+ # Wraps the original method into #capture_exceptions.
86
+ def whole_run
87
+ capture_exceptions{ super }
88
+ end
89
+
90
+ private
91
+
92
+ #
93
+ # First RubyLex#extract_comments_from_statement is used to extract the comments.
94
+ # The final one is kept for #build_expectation, while those before are sent to #check_inner_conventions.
95
+ #
96
+ def build_self # :doc:
97
+ comments = RubyLex.extract_comments_from_statement(code)
98
+ # code must be valid since it was determined through RubyLex.statementize
99
+ last_comment = comments.pop
100
+ check_inner_conventions comments
101
+ build_expectation *last_comment
102
+ end
103
+
104
+ #
105
+ # If a convention is determined inside the statement (while it isn't yet complete)
106
+ # a +ParseError+ will be raised.
107
+ #
108
+ def check_inner_conventions comments # :doc:
109
+ comments.find do |cmt,line_no|
110
+ cmt = Text.normalize_comment cmt
111
+ store.find_convention_in cmt do
112
+ raise ParseError.new 'Incomplete statement', line_no
113
+ end
114
+ end
115
+ end
116
+
117
+ #
118
+ # First the last comment is normalized through Text#normalize_comment,
119
+ # then tries to find a convention that can accept this comment
120
+ # calling Convention#process_comment for the conventions in use.
121
+ #
122
+ # When one convention is found, an Expectation will be associated to this statement;
123
+ # the result of +process_comment+ will be stored into Expectation#expected_data.
124
+ #
125
+ # If the search fails, Convention.eval will be used
126
+ # (with the whole normalized comment as +expected_data+).
127
+ #
128
+ def build_expectation last_comment, line_no # :doc:
129
+ last_comment = Text.normalize_comment last_comment
130
+ conv,processed = store.find_convention_in(last_comment)
131
+ conv,processed = store.eval_convention,last_comment unless conv
132
+ @expectation = Expectation.new(self,conv,processed,line_no)
133
+ end
134
+
135
+ # This is obtained processing the #code through Convention#process_statement.
136
+ def actual_value # :doc:
137
+ trace_execution do
138
+ convention.call_process_statement(self,code)
139
+ end
140
+ end
141
+
142
+ #
143
+ # Rescues the +StandardError+ and subclasses raised during the execution of the statement.
144
+ # If there is an #assertion? the error is reported
145
+ # (and it will not propagate, so that other statements of this examples can run).
146
+ # Otherwise it's re-raised and will be handled by Example#capture_exceptions.
147
+ #
148
+ def capture_exceptions # :doc:
149
+ yield
150
+ rescue => err
151
+ raise err unless assertion?
152
+ register_error err
153
+ end
154
+
155
+ end
156
+
157
+
158
+
159
+ #
160
+ # Represent an expectation of a statement.
161
+ # This is written as a comment at its end that has been accepted by one of defined conventions.
162
+ #
163
+ # For instance the statement in the next example
164
+ # 1 + 1 #=> 2
165
+ # has the expectation associated with the Convention::result_eval.
166
+ #
167
+ class Expectation < CodeObject::Runnable
168
+
169
+ # The SourceFile this expectation is into.
170
+ def source_file
171
+ comment.source_file
172
+ end
173
+
174
+ # The Comment this expectation is into.
175
+ def comment
176
+ example.comment
177
+ end
178
+
179
+ # The Example this expectation is into.
180
+ def example
181
+ statement.example
182
+ end
183
+
184
+ # The Statement of this expectation.
185
+ attr_reader :statement
186
+ alias parent statement
187
+
188
+ # Returns +self+.
189
+ def expectation
190
+ self
191
+ end
192
+
193
+ #
194
+ # Does the convention process an assertion?
195
+ # For example Convention.eval doesn't assert anything.
196
+ #
197
+ def assertion?
198
+ !!convention.process_assertion
199
+ end
200
+
201
+ # The Convention of this expectation.
202
+ attr_reader :convention
203
+
204
+ # The result of Convention#process_comment.
205
+ attr_reader :expected_data
206
+
207
+ def initialize statement, convention, expected_data, relative_line_no=1 # :nodoc:
208
+ @statement = statement
209
+ @convention = convention
210
+ @expected_data = expected_data
211
+ super(nil,relative_line_no)
212
+ end
213
+
214
+ #
215
+ # :section: API
216
+ #
217
+
218
+ # The default type is the #convention's name.
219
+ def warn msg, type=convention.name, frame=nil
220
+ super
221
+ end
222
+
223
+ #
224
+ # :section: Internal
225
+ #
226
+
227
+ #
228
+ # Receives Statement#actual_value as _actual_value_, computes #expected_value
229
+ # and process the assertion through Convention#process_assertion.
230
+ #
231
+ def run actual_value
232
+ act,exp = actual_value,expected_value # compute expected now
233
+ trace_assertion convention.name do # then do the assertion
234
+ convention.call_process_assertion example, act, exp
235
+ end
236
+ end
237
+
238
+ # This is obtained processing the #expected_data through Convention#process_expectation.
239
+ def expected_value # :doc:
240
+ trace_execution do
241
+ convention.call_process_expectation(self,expected_data)
242
+ end
243
+ end
244
+ private :expected_value
245
+
246
+ end
247
+
248
+ end