seeing_is_believing 0.0.23 → 0.0.24

Sign up to get free protection for your applications and to get access to all the features.
data/Readme.md CHANGED
@@ -92,6 +92,12 @@ See [sublime-text-2-seeing-is-believing](https://github.com/JoshCheek/sublime-te
92
92
  TextMate Integration
93
93
  ====================
94
94
 
95
+ Note: This assumes you've already set up Ruby to work with TextMate.
96
+ If not, you'll need to start there. [Here](https://rvm.io/integration/textmate/)
97
+ are instructions for RVM (I recommend the wrapper approach).
98
+ [Here](http://uberfork.com/post/12280974742/integrate-rbenv-with-textmate)
99
+ are instructions for rbenv.
100
+
95
101
  Go to the bundle editor, create this new command in the Ruby bundle:
96
102
 
97
103
  ```shell
@@ -140,8 +146,8 @@ Known Issues
140
146
  Todo
141
147
  ====
142
148
 
149
+ * Move as much of the SyntaxAnalyzer as possible over to Parser and ditch Ripper altogether
143
150
  * Refactor ExpressionList/SeeingIsBelieving to store lines in an array instead of as a string, so everyone doesn't magically need to know when to chomp
144
- * Make friends who actually know how to parse Ruby syntax (omg, teach me Ripper, pls, it will make this lib so much better, you have no idea O.o)
145
151
 
146
152
  License
147
153
  =======
@@ -235,7 +235,7 @@ Feature: Running the binary successfully
235
235
  """
236
236
 
237
237
  Scenario: Reading from stdin
238
- Given I have the stdin content "hi!"
238
+ Given the stdin content "hi!"
239
239
  And the file "reads_from_stdin.rb":
240
240
  """
241
241
  puts "You said: #{gets}"
@@ -251,7 +251,7 @@ Feature: Running the binary successfully
251
251
  """
252
252
 
253
253
  Scenario: Passing the file on stdin
254
- Given I have the stdin content "1 + 1"
254
+ Given the stdin content "1 + 1"
255
255
  When I run "seeing_is_believing"
256
256
  Then stderr is empty
257
257
  And the exit status is 0
@@ -223,7 +223,7 @@ Feature: Using flags
223
223
 
224
224
  Scenario: --as and stdin
225
225
  Given the file "example.rb" "1+1"
226
- Given I have the stdin content:
226
+ Given the stdin content:
227
227
  """
228
228
  1+1
229
229
  __FILE__
@@ -397,3 +397,43 @@ Feature: Using flags
397
397
  1 + 1 # => 2
398
398
  1 + 1 + 1 # => 3
399
399
  """
400
+
401
+ Scenario: --inherit-exit-status
402
+ Given the file "exit_status.rb" "exit 123"
403
+ When I run "seeing_is_believing exit_status.rb"
404
+ Then the exit status is 1
405
+ When I run "seeing_is_believing --inherit-exit-status exit_status.rb"
406
+ Then the exit status is 123
407
+
408
+ # Show that Ruby exceptions exit with 1, and --inherit-exit-status does as well
409
+ Scenario: --inherit-exit-status
410
+ Given the file "exception_exit_status.rb" "raise Exception"
411
+ When I run "ruby exception_exit_status.rb"
412
+ Then the exit status is 1
413
+ When I run "seeing_is_believing --inherit-exit-status exception_exit_status.rb"
414
+ Then the exit status is 1
415
+
416
+ Scenario: --inherit-exit-status in an at_exit block
417
+ Given the file "exit_status_in_at_exit_block.rb" "at_exit { exit 10 }"
418
+ When I run "seeing_is_believing exit_status_in_at_exit_block.rb"
419
+ Then the exit status is 0
420
+ When I run "seeing_is_believing --inherit-exit-status exit_status_in_at_exit_block.rb"
421
+ Then the exit status is 10
422
+
423
+ @wip
424
+ Scenario: --xmpfilter-style
425
+ Given the file "magic_comments.rb":
426
+ """
427
+ 1# =>
428
+ 1 # =>
429
+ 1
430
+ """
431
+ When I run "seeing_is_believing --xmpfilter-style magic_comments.rb"
432
+ Then stderr is empty
433
+ And the exit status is 0
434
+ And stdout is:
435
+ """
436
+ 1# => 1
437
+ 1 # => 1
438
+ 1
439
+ """
@@ -4,7 +4,7 @@ Feature:
4
4
  I want to have tests on those bugs that I found and could not have predicted
5
5
 
6
6
  Scenario: A program containing a single comment
7
- Given I have the stdin content "# single comment"
7
+ Given the stdin content "# single comment"
8
8
  When I run "seeing_is_believing"
9
9
  Then stderr is empty
10
10
  And the exit status is 0
@@ -23,7 +23,7 @@ Feature:
23
23
  a # ~> NameError: undefined local variable or method `a' for main:Object
24
24
  """
25
25
 
26
- Scenario:
26
+ Scenario: Errors being raised in the evaluated code that don't exist in the evaluating code
27
27
  Given the file "raising_custom_errors.rb":
28
28
  """
29
29
  MyError = Class.new StandardError
@@ -36,3 +36,27 @@ Feature:
36
36
  When I run "seeing_is_believing raising_custom_errors.rb"
37
37
  Then stderr is empty
38
38
  And the exit status is 1
39
+
40
+ Scenario: statements that inherit void value expressions
41
+ Given the file "statements_that_inherit_void_value_expressions.rb":
42
+ """
43
+ def m
44
+ if true
45
+ return 1
46
+ end
47
+ end
48
+ m
49
+ """
50
+ When I run "seeing_is_believing statements_that_inherit_void_value_expressions.rb"
51
+ Then stderr is empty
52
+ And the exit status is 0
53
+ Then stdout is:
54
+ """
55
+ def m
56
+ if true
57
+ return 1
58
+ end
59
+ end # => nil
60
+ m # => 1
61
+ """
62
+
@@ -1,78 +1,8 @@
1
- require 'fileutils'
2
- require 'open3'
3
1
  require_relative '../../lib/seeing_is_believing/version'
4
2
 
5
-
6
- module CommandLineHelpers
7
- Invocation = Struct.new :stdout, :stderr, :status do
8
- def exitstatus
9
- status.exitstatus
10
- end
11
- end
12
-
13
- extend self
14
-
15
- def write_file(filename, body)
16
- in_proving_grounds do
17
- FileUtils.mkdir_p File.dirname filename
18
- File.open(filename, 'w') { |file| file.write body }
19
- end
20
- end
21
-
22
- def execute(command, stdin_data=nil)
23
- stdin_data ||= ''
24
- in_proving_grounds do
25
- with_bin_in_path do
26
- Invocation.new *Open3.capture3(command, stdin_data: stdin_data)
27
- end
28
- end
29
- end
30
-
31
- def in_proving_grounds(&block)
32
- Dir.chdir proving_grounds_dir, &block
33
- end
34
-
35
- def proving_grounds_dir
36
- File.join root_dir, 'proving_grounds'
37
- end
38
-
39
- def root_dir
40
- @root_dir ||= begin
41
- dir = File.expand_path Dir.pwd
42
- dir = File.dirname dir until Dir["#{dir}/*"].map { |fn| File.basename fn }.include?('lib')
43
- dir
44
- end
45
- end
46
-
47
- def make_proving_grounds
48
- FileUtils.mkdir_p proving_grounds_dir
49
- end
50
-
51
- def bin_dir
52
- File.join root_dir, "bin"
53
- end
54
-
55
- def path_to(filename)
56
- in_proving_grounds { File.join proving_grounds_dir, filename }
57
- end
58
-
59
- # workaround for Ruby 2.0 bug where passing the new path as the first arg wasn't working
60
- # bug report submitted here: http://bugs.ruby-lang.org/issues/8004
61
- def with_bin_in_path
62
- original_path = ENV['PATH']
63
- ENV['PATH'] = "#{bin_dir}:#{ENV['PATH']}"
64
- yield
65
- ensure
66
- ENV['PATH'] = original_path
67
- end
68
- end
69
-
70
- CommandLineHelpers.make_proving_grounds
71
-
72
- module GeneralHelpers
73
- def eval_curlies(string)
74
- string.gsub(/{{(.*?)}}/) { eval $1 }
75
- end
3
+ require 'haiti'
4
+ Haiti.configure do |config|
5
+ config.proving_grounds_dir = File.expand_path '../../../proving_grounds', __FILE__
6
+ config.bin_dir = File.expand_path '../../../bin', __FILE__
76
7
  end
77
8
 
78
- World GeneralHelpers
@@ -108,6 +108,8 @@ class SeeingIsBelieving
108
108
  "rescue Exception;"\
109
109
  "line_number = $!.backtrace.grep(/\#{__FILE__}/).first[/:\\d+/][1..-1].to_i;"\
110
110
  "$seeing_is_believing_current_result.record_exception line_number, $!;"\
111
+ "$seeing_is_believing_current_result.exitstatus = 1;"\
112
+ "$seeing_is_believing_current_result.exitstatus = $!.status if $!.kind_of? SystemExit;"\
111
113
  "end"
112
114
  end
113
115
 
@@ -28,16 +28,25 @@ class SeeingIsBelieving
28
28
  elsif invalid_syntax? then print_syntax_error ; NONDISPLAYABLE_ERROR_STATUS
29
29
  elsif program_timedout? then print_timeout_error ; NONDISPLAYABLE_ERROR_STATUS
30
30
  elsif something_blew_up? then print_unexpected_error ; NONDISPLAYABLE_ERROR_STATUS
31
- else print_program ; (results.has_exception? ?
32
- DISPLAYABLE_ERROR_STATUS :
33
- SUCCESS_STATUS)
31
+ else print_program ; program_exit_status
34
32
  end
35
33
  end
36
34
 
35
+ # uhm, this is dumb
37
36
  alias exitstatus call
38
37
 
39
38
  private
40
39
 
40
+ def program_exit_status
41
+ if flags[:inherit_exit_status]
42
+ results.exitstatus
43
+ elsif results.has_exception?
44
+ DISPLAYABLE_ERROR_STATUS
45
+ else
46
+ SUCCESS_STATUS
47
+ end
48
+ end
49
+
41
50
  def has_filename?
42
51
  flags[:filename]
43
52
  end
@@ -21,22 +21,24 @@ class SeeingIsBelieving
21
21
  @result ||= begin
22
22
  until args.empty?
23
23
  case (arg = args.shift)
24
- when '-h', '--help' then options[:help] = self.class.help_screen
25
- when '-v', '--version' then options[:version] = true
26
- when '-c', '--clean' then options[:clean] = true
27
- when '-l', '--start-line' then extract_positive_int_for :start_line, arg
28
- when '-L', '--end-line' then extract_positive_int_for :end_line, arg
29
- when '-d', '--line-length' then extract_positive_int_for :line_length, arg
30
- when '-D', '--result-length' then extract_positive_int_for :result_length, arg
31
- when '-t', '--timeout' then extract_non_negative_float_for :timeout, arg
32
- when '-r', '--require' then next_arg("#{arg} expected a filename as the following argument but did not see one") { |filename| options[:require] << filename }
33
- when '-I', '--load-path' then next_arg("#{arg} expected a directory as the following argument but did not see one") { |dir| options[:load_path] << dir }
34
- when '-e', '--program' then next_arg("#{arg} expected a program as the following argument but did not see one") { |program| options[:program] = program }
35
- when '-a', '--as' then next_arg("#{arg} expected a filename as the following argument but did not see one") { |filename| options[:as] = filename }
36
- when '-s', '--alignment-strategy' then extract_alignment_strategy
37
- when /\A-K(.+)/ then options[:encoding] = $1
38
- when '-K', '--encoding' then next_arg("#{arg} expects an encoding, see `man ruby` for possibile values") { |encoding| options[:encoding] = encoding }
39
- when /^-/ then options[:errors] << "Unknown option: #{arg.inspect}" # unknown flags
24
+ when '-h', '--help' then options[:help] = self.class.help_screen
25
+ when '-v', '--version' then options[:version] = true
26
+ when '-c', '--clean' then options[:clean] = true
27
+ when '-x', '--xmpfilter-style' then options[:xmpfilter_style] = true
28
+ when '-i', '--inherit-exit-status' then options[:inherit_exit_status] = true
29
+ when '-l', '--start-line' then extract_positive_int_for :start_line, arg
30
+ when '-L', '--end-line' then extract_positive_int_for :end_line, arg
31
+ when '-d', '--line-length' then extract_positive_int_for :line_length, arg
32
+ when '-D', '--result-length' then extract_positive_int_for :result_length, arg
33
+ when '-t', '--timeout' then extract_non_negative_float_for :timeout, arg
34
+ when '-r', '--require' then next_arg("#{arg} expected a filename as the following argument but did not see one") { |filename| options[:require] << filename }
35
+ when '-I', '--load-path' then next_arg("#{arg} expected a directory as the following argument but did not see one") { |dir| options[:load_path] << dir }
36
+ when '-e', '--program' then next_arg("#{arg} expected a program as the following argument but did not see one") { |program| options[:program] = program }
37
+ when '-a', '--as' then next_arg("#{arg} expected a filename as the following argument but did not see one") { |filename| options[:as] = filename }
38
+ when '-s', '--alignment-strategy' then extract_alignment_strategy
39
+ when /\A-K(.+)/ then options[:encoding] = $1
40
+ when '-K', '--encoding' then next_arg("#{arg} expects an encoding, see `man ruby` for possibile values") { |encoding| options[:encoding] = encoding }
41
+ when /^-/ then options[:errors] << "Unknown option: #{arg.inspect}" # unknown flags
40
42
  else
41
43
  filenames << arg
42
44
  options[:filename] = arg
@@ -145,6 +147,7 @@ Usage: seeing_is_believing [options] [filename]
145
147
  -K, --encoding encoding # sets file encoding, equivalent to Ruby's -Kx (see `man ruby` for valid values)
146
148
  -a, --as filename # run the program as if it was the specified filename
147
149
  -c, --clean # remove annotations from previous runs of seeing_is_believing
150
+ -i, --inherit-exit-status # exit with the exit status of the program being eval
148
151
  -v, --version # print the version (#{VERSION})
149
152
  -h, --help # this help screen
150
153
  HELP_SCREEN
@@ -13,6 +13,7 @@
13
13
 
14
14
  require 'yaml'
15
15
  require 'open3'
16
+ require 'timeout'
16
17
  require 'stringio'
17
18
  require 'fileutils'
18
19
  require 'seeing_is_believing/error'
@@ -43,8 +44,7 @@ class SeeingIsBelieving
43
44
  write_program_to_file
44
45
  begin
45
46
  evaluate_file
46
- fail unless exitstatus.success?
47
- deserialize_result
47
+ deserialize_result.tap { |result| fail if result.bug_in_sib? }
48
48
  # Okay, really, I should wrap this in another exception and raise it on up,
49
49
  # but for now, I'm feeling a little lazy and am not going to do it
50
50
  rescue Exception
@@ -57,10 +57,6 @@ class SeeingIsBelieving
57
57
  }
58
58
  end
59
59
 
60
- def error_implies_bug_in_sib?(error)
61
- not error.kind_of? Timeout::Error
62
- end
63
-
64
60
  def file_directory
65
61
  File.dirname filename
66
62
  end
@@ -73,6 +69,10 @@ class SeeingIsBelieving
73
69
 
74
70
  attr_accessor :stdout, :stderr, :exitstatus
75
71
 
72
+ def error_implies_bug_in_sib?(error)
73
+ not error.kind_of? Timeout::Error
74
+ end
75
+
76
76
  def we_will_not_overwrite_existing_tempfile!
77
77
  raise TempFileAlreadyExists.new(filename, temp_filename) if File.exist? temp_filename
78
78
  end
@@ -8,7 +8,9 @@ class SeeingIsBelieving
8
8
  include TracksLineNumbersSeen
9
9
  include Enumerable
10
10
 
11
- attr_accessor :stdout, :stderr
11
+ attr_accessor :stdout, :stderr, :exitstatus, :bug_in_sib
12
+
13
+ alias bug_in_sib? bug_in_sib
12
14
 
13
15
  def has_stdout?
14
16
  stdout && !stdout.empty?
@@ -1,4 +1,5 @@
1
1
  require 'ripper'
2
+ require 'parser/current'
2
3
 
3
4
  class SeeingIsBelieving
4
5
  class SyntaxAnalyzer < Ripper::SexpBuilder
@@ -156,10 +157,22 @@ class SeeingIsBelieving
156
157
 
157
158
  # RETURNS
158
159
 
159
- # this is conspicuosuly inferior, but I can't figure out how to actually parse it
160
- # see: http://www.ruby-forum.com/topic/4409633
161
- def self.void_value_expression?(code)
162
- /(^|\s)(?:return|next|redo|retry|break)([^\w\n]|\n?\z).*?\n?\z/ =~ code
160
+ def self.void_value_expression?(code_or_ast)
161
+ ast = code_or_ast
162
+ ast = Parser::CurrentRuby.parse(code_or_ast) if code_or_ast.kind_of? String
163
+
164
+ case ast && ast.type
165
+ when :begin, :resbody
166
+ void_value_expression?(ast.children[-1])
167
+ when :rescue, :ensure
168
+ ast.children.any? { |child| void_value_expression? child }
169
+ when :if
170
+ void_value_expression?(ast.children[1]) || void_value_expression?(ast.children[2])
171
+ when :return, :next, :redo, :retry, :break
172
+ true
173
+ else
174
+ false
175
+ end
163
176
  end
164
177
 
165
178
  # HERE DOCS
@@ -15,5 +15,10 @@ at_exit do
15
15
  $seeing_is_believing_current_result.stdout = fake_stdout.string
16
16
  $seeing_is_believing_current_result.stderr = fake_stderr.string
17
17
 
18
+ $seeing_is_believing_current_result.exitstatus ||= 0
19
+ $seeing_is_believing_current_result.exitstatus = 1 if $!
20
+ $seeing_is_believing_current_result.exitstatus = $!.status if $!.kind_of? SystemExit
21
+ $seeing_is_believing_current_result.bug_in_sib = $! && ! $!.kind_of?(SystemExit)
22
+
18
23
  real_stdout.write YAML.dump $seeing_is_believing_current_result
19
24
  end
@@ -1,3 +1,3 @@
1
1
  class SeeingIsBelieving
2
- VERSION = '0.0.23'
2
+ VERSION = '0.0.24'
3
3
  end
@@ -19,6 +19,9 @@ Gem::Specification.new do |s|
19
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
20
  s.require_paths = ["lib"]
21
21
 
22
+ s.add_dependency "parser", "~> 1.4"
23
+
24
+ s.add_development_dependency "haiti", "~> 0.0.3"
22
25
  s.add_development_dependency "rake", "~> 10.0.3"
23
26
  s.add_development_dependency "rspec", "~> 2.12.0"
24
27
  s.add_development_dependency "cucumber", "~> 1.2.1"
@@ -57,8 +57,8 @@ describe SeeingIsBelieving::Binary::ArgParser do
57
57
 
58
58
  specify 'unknown options set an error' do
59
59
  parse(['--xyz']).should have_error 'Unknown option: "--xyz"'
60
- parse(['-x']).should have_error 'Unknown option: "-x"'
61
- parse(['-x', 'b']).should have_error 'Unknown option: "-x"'
60
+ parse(['-y']).should have_error 'Unknown option: "-y"'
61
+ parse(['-y', 'b']).should have_error 'Unknown option: "-y"'
62
62
  end
63
63
 
64
64
  example 'example: multiple args' do
@@ -311,5 +311,27 @@ describe SeeingIsBelieving::Binary::ArgParser do
311
311
  parse(['-s' ]).should have_error /alignment-strategy/
312
312
  end
313
313
  end
314
+
315
+ describe ':inherit_exit_status' do
316
+ it 'defaults to false' do
317
+ parse([])[:inherit_exit_status].should be_false
318
+ end
319
+
320
+ it 'can be set with --inherit-exit-status or -i' do
321
+ parse(['--inherit-exit-status'])[:inherit_exit_status].should be_true
322
+ parse(['-i'])[:inherit_exit_status].should be_true
323
+ end
324
+ end
325
+
326
+ describe ':xmpfilter_style' do
327
+ it 'defaults to false' do
328
+ parse([])[:xmpfilter_style].should be_false
329
+ end
330
+
331
+ it 'can be set with --xmpfilter-style or -x' do
332
+ parse(['--xmpfilter-style'])[:xmpfilter_style].should be_true
333
+ parse(['-x'])[:xmpfilter_style].should be_true
334
+ end
335
+ end
314
336
  end
315
337
 
@@ -284,6 +284,12 @@ describe SeeingIsBelieving do
284
284
  expect { invoke "sleep 0.2", timeout: 0.1 }.to raise_error Timeout::Error
285
285
  end
286
286
 
287
+ it 'records the exit status' do
288
+ invoke('raise "omg"').exitstatus.should == 1
289
+ invoke('exit 123').exitstatus.should == 123
290
+ invoke('at_exit { exit 121 }').exitstatus.should == 121
291
+ end
292
+
287
293
  it 'can record the middle of a chain of calls', not_implemented: true do
288
294
  values_for("[*1..5]
289
295
  .select(&:even?)
@@ -171,37 +171,175 @@ describe SeeingIsBelieving::SyntaxAnalyzer do
171
171
  end
172
172
  end
173
173
 
174
- shared_examples_for 'void_value_expression?' do |keyword|
175
- it "`#{keyword}` returns true when the expression ends in #{keyword}", t:true do
174
+ shared_examples_for 'single line void_value_expression?' do |keyword, options={}|
175
+ specify "`#{keyword}` returns true when the expression ends in #{keyword} without an argument" do
176
176
  described_class.void_value_expression?("#{keyword}").should be_true
177
- described_class.void_value_expression?("#{keyword}(1)").should be_true
178
- described_class.void_value_expression?("#{keyword} 1").should be_true
179
- described_class.void_value_expression?("#{keyword} 1\n").should be_true
180
- described_class.void_value_expression?("#{keyword} 1 if true").should be_true
181
- described_class.void_value_expression?("#{keyword} 1 if false").should be_true
177
+ described_class.void_value_expression?("#{keyword} if true").should be_true
182
178
  described_class.void_value_expression?("o.#{keyword}").should be_false
183
179
  described_class.void_value_expression?(":#{keyword}").should be_false
180
+ described_class.void_value_expression?(":'#{keyword}'").should be_false
184
181
  described_class.void_value_expression?("'#{keyword}'").should be_false
185
- described_class.void_value_expression?("def a\n#{keyword} 1\nend").should be_false
186
- described_class.void_value_expression?("-> {\n#{keyword} 1\n}").should be_false
187
- described_class.void_value_expression?("Proc.new {\n#{keyword} 1\n}").should be_false
188
- described_class.void_value_expression?("#{keyword}_something").should be_false
189
182
  described_class.void_value_expression?("def a\n#{keyword}\nend").should be_false
183
+ described_class.void_value_expression?("-> {\n#{keyword}\n}").should be_false
184
+ described_class.void_value_expression?("Proc.new {\n#{keyword}\n}").should be_false
185
+ described_class.void_value_expression?("#{keyword}_something").should be_false
186
+ described_class.void_value_expression?("'#{keyword}\n#{keyword}\n#{keyword}'").should be_false
187
+
188
+ unless options[:no_args]
189
+ described_class.void_value_expression?("#{keyword}(1)").should be_true
190
+ described_class.void_value_expression?("#{keyword} 1").should be_true
191
+ described_class.void_value_expression?("#{keyword} 1\n").should be_true
192
+ described_class.void_value_expression?("#{keyword} 1 if true").should be_true
193
+ described_class.void_value_expression?("#{keyword} 1 if false").should be_true
194
+ described_class.void_value_expression?("def a\n#{keyword} 1\nend").should be_false
195
+ described_class.void_value_expression?("-> {\n#{keyword} 1\n}").should be_false
196
+ described_class.void_value_expression?("Proc.new {\n#{keyword} 1\n}").should be_false
197
+ described_class.void_value_expression?("#{keyword} \\\n1").should be_true
198
+ end
199
+ end
200
+
201
+ it "knows when an if statement ends in `#{keyword}`" do
202
+ # if
203
+ described_class.void_value_expression?("if true\n#{keyword}\nend").should be_true
204
+ described_class.void_value_expression?("if true\n #{keyword}\nend").should be_true
205
+ described_class.void_value_expression?("if true\n 1+1\n #{keyword}\nend").should be_true
206
+ described_class.void_value_expression?("if true\n #{keyword}\n 1+1\n end").should be_false
207
+ described_class.void_value_expression?("123 && if true\n #{keyword}\nend").should be_false
208
+ described_class.void_value_expression?("def m\n if true\n #{keyword}\nend\n end").should be_false
209
+ described_class.void_value_expression?("if true; #{keyword}; end").should be_true
210
+ described_class.void_value_expression?("if true; 1; end").should be_false
211
+
212
+ # if .. elsif
213
+ described_class.void_value_expression?("if true\n #{keyword}\n elsif true\n 1\n end").should be_true
214
+ described_class.void_value_expression?("if true\n 1\n elsif true\n #{keyword}\n end").should be_true
215
+ described_class.void_value_expression?("if true\n #{keyword}\n 2\n elsif true\n 1\n end").should be_false
216
+ described_class.void_value_expression?("if true\n 1\n elsif true\n #{keyword}\n 2\n end").should be_false
217
+
218
+ # if .. else
219
+ described_class.void_value_expression?("if true\n #{keyword}\n else 1\n end").should be_true
220
+ described_class.void_value_expression?("if true\n 1\n else\n #{keyword}\n end").should be_true
221
+ described_class.void_value_expression?("if true\n #{keyword}\n 2\n else 1\n end").should be_false
222
+ described_class.void_value_expression?("if true\n 1\n else\n #{keyword}\n 2\n end").should be_false
223
+
224
+ # if .. elsif .. else .. end
225
+ described_class.void_value_expression?("if true\n #{keyword}\nelsif true\n 1 else 1\n end").should be_true
226
+ described_class.void_value_expression?("if true\n 1\n elsif true\n #{keyword}\n else\n 1\n end").should be_true
227
+ described_class.void_value_expression?("if true\n 1\n elsif true\n 1\n elsif true\n #{keyword}\n else\n 1\n end").should be_true
228
+ described_class.void_value_expression?("if true\n 1\n elsif true\n 1\n else\n #{keyword}\n end").should be_true
229
+ described_class.void_value_expression?("if true\n #{keyword}\n 2\nelsif true\n 1 else 1\n end").should be_false
230
+ described_class.void_value_expression?("if true\n 1\n elsif true\n #{keyword}\n 2\n else\n 1\n end").should be_false
231
+ described_class.void_value_expression?("if true\n 1\n elsif true\n 1\n elsif true\n #{keyword}\n 2\n else\n 1\n end").should be_false
232
+ described_class.void_value_expression?("if true\n 1\n elsif true\n 1\n else\n #{keyword}\n 2\n end").should be_false
233
+
234
+ unless options[:no_args]
235
+ # if
236
+ described_class.void_value_expression?("if true\n#{keyword} 1\nend").should be_true
237
+ described_class.void_value_expression?("if true\n #{keyword} 1\nend").should be_true
238
+ described_class.void_value_expression?("if true\n 1+1\n #{keyword} 1\nend").should be_true
239
+ described_class.void_value_expression?("if true\n #{keyword} 1\n 1+1\n end").should be_false
240
+ described_class.void_value_expression?("123 && if true\n #{keyword} 1\nend").should be_false
241
+ described_class.void_value_expression?("def m\n if true\n #{keyword} 1\nend\n end").should be_false
242
+ described_class.void_value_expression?("if true; #{keyword} 1; end").should be_true
243
+ described_class.void_value_expression?("if true; 1; end").should be_false
244
+
245
+ # if .. elsif
246
+ described_class.void_value_expression?("if true\n #{keyword} 1\n elsif true\n 1\n end").should be_true
247
+ described_class.void_value_expression?("if true\n 1\n elsif true\n #{keyword}\n end").should be_true
248
+ described_class.void_value_expression?("if true\n #{keyword} 1\n 2\n elsif true\n 1\n end").should be_false
249
+ described_class.void_value_expression?("if true\n 1\n elsif true\n #{keyword}\n 2\n end").should be_false
250
+
251
+ # if .. else
252
+ described_class.void_value_expression?("if true\n #{keyword} 1\n else 1\n end").should be_true
253
+ described_class.void_value_expression?("if true\n 1\n else\n #{keyword}\n end").should be_true
254
+ described_class.void_value_expression?("if true\n #{keyword} 1\n 2\n else 1\n end").should be_false
255
+ described_class.void_value_expression?("if true\n 1\n else\n #{keyword}\n 2\n end").should be_false
256
+
257
+ # if .. elsif .. else .. end
258
+ described_class.void_value_expression?("if true\n #{keyword} 1\nelsif true\n 1 else 1\n end").should be_true
259
+ described_class.void_value_expression?("if true\n 1\n elsif true\n #{keyword}\n else\n 1\n end").should be_true
260
+ described_class.void_value_expression?("if true\n 1\n elsif true\n 1\n elsif true\n #{keyword}\n else\n 1\n end").should be_true
261
+ described_class.void_value_expression?("if true\n 1\n elsif true\n 1\n else\n #{keyword}\n end").should be_true
262
+ described_class.void_value_expression?("if true\n #{keyword} 1\n 2\nelsif true\n 1 else 1\n end").should be_false
263
+ described_class.void_value_expression?("if true\n 1\n elsif true\n #{keyword}\n 2\n else\n 1\n end").should be_false
264
+ described_class.void_value_expression?("if true\n 1\n elsif true\n 1\n elsif true\n #{keyword}\n 2\n else\n 1\n end").should be_false
265
+ described_class.void_value_expression?("if true\n 1\n elsif true\n 1\n else\n #{keyword}\n 2\n end").should be_false
266
+ end
190
267
  end
191
268
 
192
- it "doesn't work because the return and next keyword evaluators are insufficient regexps" do
193
- pending "doesn't pass yet (and prob never will >.<)" do
194
- described_class.send(evalutor, "'#{keyword}\n#{keyword}\n#{keyword}'").should be_false
195
- described_class.send(evalutor, "#{keyword} \\\n1").should be_true
269
+ it "knows when a begin statement ends in `#{keyword}`" do
270
+ described_class.void_value_expression?("begin\n #{keyword}\n end").should be_true
271
+ described_class.void_value_expression?("begin\n 1\n #{keyword}\n end").should be_true
272
+ described_class.void_value_expression?("begin\n #{keyword}\n 1\n end").should be_false
273
+ described_class.void_value_expression?("begin\n 1\n #{keyword}\n 1\n end").should be_false
274
+
275
+ unless options[:no_args]
276
+ described_class.void_value_expression?("begin\n #{keyword} '123' \n end").should be_true
277
+ described_class.void_value_expression?("begin\n 1\n #{keyword} 456\n end").should be_true
278
+ described_class.void_value_expression?("begin\n #{keyword} :'789'\n 1\n end").should be_false
279
+ described_class.void_value_expression?("begin\n 1\n #{keyword} /101112/\n 1\n end").should be_false
280
+ end
281
+
282
+ # I don't know that the rest of these hold across all versions of Ruby since they make no fucking sense
283
+ # so even though some of them can technically be non-vve,
284
+ # I'm still going to call any one of them a vve
285
+ #
286
+ # e.g. (tested on 2.0)
287
+ # this is allowed
288
+ # -> { a = begin; return
289
+ # rescue; return
290
+ # ensure; return
291
+ # end }
292
+ # this is not
293
+ # -> { a = begin; return
294
+ # end }
295
+
296
+ # with rescue...
297
+ described_class.void_value_expression?("begin\n #{keyword}\n rescue\n #{keyword} end").should be_true
298
+ described_class.void_value_expression?("begin\n 1\n #{keyword}\n rescue RuntimeError => e\n end").should be_true
299
+ described_class.void_value_expression?("begin\n 1\n #{keyword}\n rescue RuntimeError\n end").should be_true
300
+ described_class.void_value_expression?("begin\n 1\n #{keyword}\n rescue\n end").should be_true
301
+ described_class.void_value_expression?("begin\n 1\n rescue\n end").should be_false
302
+ described_class.void_value_expression?("begin\n 1\n rescue\n #{keyword}\n end").should be_true
303
+ described_class.void_value_expression?("begin\n 1\n rescue\n #{keyword}\n 1\n end").should be_false
304
+
305
+ unless options[:no_args]
306
+ described_class.void_value_expression?("begin\n #{keyword}\n rescue\n #{keyword} 1 end").should be_true
307
+ described_class.void_value_expression?("begin\n 1\n #{keyword} 1\n rescue RuntimeError => e\n end").should be_true
308
+ described_class.void_value_expression?("begin\n 1\n #{keyword} 1\n rescue RuntimeError\n end").should be_true
309
+ described_class.void_value_expression?("begin\n 1\n #{keyword} :abc\n rescue\n end").should be_true
310
+ described_class.void_value_expression?("begin\n 1\n rescue\n #{keyword} 'abc'\n end").should be_true
311
+ described_class.void_value_expression?("begin\n 1\n rescue\n #{keyword} :abc\n 1\n end").should be_false
312
+ end
313
+
314
+ # with ensure
315
+ described_class.void_value_expression?("begin\n #{keyword}\n ensure\n #{keyword} end").should be_true
316
+ described_class.void_value_expression?("begin\n 1\n #{keyword}\n ensure\n end").should be_true
317
+ described_class.void_value_expression?("begin\n 1\n ensure\n end").should be_false
318
+ described_class.void_value_expression?("begin\n 1\n ensure\n #{keyword}\n end").should be_true
319
+ described_class.void_value_expression?("begin\n 1\n ensure\n #{keyword}\n 1\n end").should be_false
320
+
321
+ unless options[:no_args]
322
+ described_class.void_value_expression?("begin\n #{keyword}\n ensure\n #{keyword} 1 end").should be_true
323
+ described_class.void_value_expression?("begin\n 1\n #{keyword} 1\n ensure\n end").should be_true
324
+ described_class.void_value_expression?("begin\n 1\n #{keyword} :abc\n ensure\n end").should be_true
325
+ described_class.void_value_expression?("begin\n 1\n ensure\n #{keyword} 'abc'\n end").should be_true
326
+ described_class.void_value_expression?("begin\n 1\n ensure\n #{keyword} :abc\n 1\n end").should be_false
196
327
  end
328
+
329
+ # with ensure and rescue
330
+ described_class.void_value_expression?("begin\n 1\n rescue\n 2\n ensure\n 3\n end").should be_false
331
+ described_class.void_value_expression?("begin\n #{keyword}\n rescue\n 2\n ensure\n 3\n end").should be_true
332
+ described_class.void_value_expression?("begin\n 1\n rescue\n #{keyword}\n ensure\n 3\n end").should be_true
333
+ described_class.void_value_expression?("begin\n 1\n rescue\n 2\n ensure\n #{keyword}\n end").should be_true
197
334
  end
198
335
  end
199
336
 
200
- it_should_behave_like 'void_value_expression?', 'return'
201
- it_should_behave_like 'void_value_expression?', 'next'
202
- it_should_behave_like 'void_value_expression?', 'redo'
203
- it_should_behave_like 'void_value_expression?', 'retry'
204
- it_should_behave_like 'void_value_expression?', 'break'
337
+ it_should_behave_like 'single line void_value_expression?', 'return'
338
+ it_should_behave_like 'single line void_value_expression?', 'next'
339
+ it_should_behave_like 'single line void_value_expression?', 'break'
340
+
341
+ it_should_behave_like 'single line void_value_expression?', 'redo', no_args: true
342
+ it_should_behave_like 'single line void_value_expression?', 'retry', no_args: true
205
343
 
206
344
  it 'knows when a line opens the data segment' do
207
345
  described_class.begins_data_segment?('__END__').should be_true
metadata CHANGED
@@ -2,15 +2,47 @@
2
2
  name: seeing_is_believing
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.23
5
+ version: 0.0.24
6
6
  platform: ruby
7
7
  authors:
8
8
  - Josh Cheek
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-05-11 00:00:00.000000000 Z
12
+ date: 2013-06-21 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ version_requirements: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.4'
20
+ none: false
21
+ name: parser
22
+ type: :runtime
23
+ prerelease: false
24
+ requirement: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ version: '1.4'
29
+ none: false
30
+ - !ruby/object:Gem::Dependency
31
+ version_requirements: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: 0.0.3
36
+ none: false
37
+ name: haiti
38
+ type: :development
39
+ prerelease: false
40
+ requirement: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: 0.0.3
45
+ none: false
14
46
  - !ruby/object:Gem::Dependency
15
47
  version_requirements: !ruby/object:Gem::Requirement
16
48
  requirements:
@@ -95,7 +127,6 @@ files:
95
127
  - features/examples.feature
96
128
  - features/flags.feature
97
129
  - features/regression.feature
98
- - features/step_definitions/steps.rb
99
130
  - features/support/env.rb
100
131
  - lib/seeing_is_believing.rb
101
132
  - lib/seeing_is_believing/binary.rb
@@ -158,7 +189,6 @@ test_files:
158
189
  - features/examples.feature
159
190
  - features/flags.feature
160
191
  - features/regression.feature
161
- - features/step_definitions/steps.rb
162
192
  - features/support/env.rb
163
193
  - spec/arg_parser_spec.rb
164
194
  - spec/evaluate_by_moving_files_spec.rb
@@ -1,12 +0,0 @@
1
- Given('the file "$filename" "$body"') { |filename, body| CommandLineHelpers.write_file filename, eval_curlies(body) }
2
- Given('the file "$filename":') { |filename, body| CommandLineHelpers.write_file filename, eval_curlies(body) }
3
- Given('I have the stdin content "$content"') { |content| @stdin_data = eval_curlies(content) }
4
- Given('I have the stdin content:') { |content| @stdin_data = eval_curlies(content) }
5
- When('I run "$command"') { |command| @last_executed = CommandLineHelpers.execute command, @stdin_data }
6
- When("I run '$command'") { |command| @last_executed = CommandLineHelpers.execute command, @stdin_data }
7
- Then(/^(stderr|stdout) is:$/) { |stream_name, output| @last_executed.send(stream_name).chomp.should == eval_curlies(output) }
8
- Then(/^(stderr|stdout) is ["'](.*?)["']$/) { |stream_name, output| @last_executed.send(stream_name).chomp.should == eval_curlies(output) }
9
- Then(/^(stderr|stdout) is empty$/) { |stream_name| @last_executed.send(stream_name).should == '' }
10
- Then(/^(stderr|stdout) is not empty$/) { |stream_name| @last_executed.send(stream_name).chomp.should_not be_empty }
11
- Then(/^(stderr|stdout) includes "([^"]*)"$/) { |stream_name, content| @last_executed.send(stream_name).should include eval_curlies(content) }
12
- Then('the exit status is $status') { |status| @last_executed.exitstatus.to_s.should == status }