seeing_is_believing 3.0.0.beta.4 → 3.0.0.beta.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -8
- data/Rakefile +1 -1
- data/Readme.md +65 -25
- data/bin/seeing_is_believing +1 -0
- data/docs/sib-streaming.gif +0 -0
- data/features/deprecated-flags.feature +62 -2
- data/features/errors.feature +12 -7
- data/features/examples.feature +143 -4
- data/features/flags.feature +89 -29
- data/features/regression.feature +58 -14
- data/features/support/env.rb +4 -0
- data/features/xmpfilter-style.feature +181 -36
- data/lib/seeing_is_believing.rb +44 -33
- data/lib/seeing_is_believing/binary.rb +31 -88
- data/lib/seeing_is_believing/binary/align_chunk.rb +30 -11
- data/lib/seeing_is_believing/binary/annotate_end_of_file.rb +10 -16
- data/lib/seeing_is_believing/binary/annotate_every_line.rb +5 -25
- data/lib/seeing_is_believing/binary/annotate_marked_lines.rb +136 -0
- data/lib/seeing_is_believing/binary/comment_lines.rb +8 -10
- data/lib/seeing_is_believing/binary/commentable_lines.rb +20 -26
- data/lib/seeing_is_believing/binary/config.rb +392 -0
- data/lib/seeing_is_believing/binary/data_structures.rb +57 -0
- data/lib/seeing_is_believing/binary/engine.rb +104 -0
- data/lib/seeing_is_believing/binary/{comment_formatter.rb → format_comment.rb} +6 -6
- data/lib/seeing_is_believing/binary/remove_annotations.rb +29 -28
- data/lib/seeing_is_believing/binary/rewrite_comments.rb +42 -43
- data/lib/seeing_is_believing/code.rb +105 -49
- data/lib/seeing_is_believing/debugger.rb +6 -5
- data/lib/seeing_is_believing/error.rb +6 -17
- data/lib/seeing_is_believing/evaluate_by_moving_files.rb +78 -129
- data/lib/seeing_is_believing/event_stream/consumer.rb +114 -64
- data/lib/seeing_is_believing/event_stream/events.rb +169 -11
- data/lib/seeing_is_believing/event_stream/handlers/debug.rb +57 -0
- data/lib/seeing_is_believing/event_stream/handlers/record_exitstatus.rb +18 -0
- data/lib/seeing_is_believing/event_stream/handlers/stream_json_events.rb +45 -0
- data/lib/seeing_is_believing/event_stream/handlers/update_result.rb +39 -0
- data/lib/seeing_is_believing/event_stream/producer.rb +25 -24
- data/lib/seeing_is_believing/hash_struct.rb +206 -0
- data/lib/seeing_is_believing/result.rb +20 -3
- data/lib/seeing_is_believing/the_matrix.rb +20 -12
- data/lib/seeing_is_believing/version.rb +1 -1
- data/lib/seeing_is_believing/wrap_expressions.rb +55 -115
- data/lib/seeing_is_believing/wrap_expressions_with_inspect.rb +14 -0
- data/seeing_is_believing.gemspec +1 -1
- data/spec/binary/alignment_specs.rb +27 -0
- data/spec/binary/comment_lines_spec.rb +3 -2
- data/spec/binary/config_spec.rb +657 -0
- data/spec/binary/engine_spec.rb +97 -0
- data/spec/binary/{comment_formatter_spec.rb → format_comment_spec.rb} +2 -2
- data/spec/binary/marker_spec.rb +71 -0
- data/spec/binary/options_spec.rb +0 -0
- data/spec/binary/remove_annotations_spec.rb +31 -18
- data/spec/binary/rewrite_comments_spec.rb +26 -11
- data/spec/code_spec.rb +190 -6
- data/spec/debugger_spec.rb +4 -0
- data/spec/evaluate_by_moving_files_spec.rb +38 -20
- data/spec/event_stream_spec.rb +265 -116
- data/spec/hash_struct_spec.rb +514 -0
- data/spec/seeing_is_believing_spec.rb +108 -46
- data/spec/spec_helper.rb +9 -0
- data/spec/wrap_expressions_spec.rb +207 -172
- metadata +30 -18
- data/docs/for-presentations +0 -33
- data/lib/seeing_is_believing/binary/annotate_xmpfilter_style.rb +0 -128
- data/lib/seeing_is_believing/binary/interpret_flags.rb +0 -156
- data/lib/seeing_is_believing/binary/parse_args.rb +0 -263
- data/lib/seeing_is_believing/event_stream/update_result.rb +0 -24
- data/lib/seeing_is_believing/inspect_expressions.rb +0 -21
- data/lib/seeing_is_believing/parser_helpers.rb +0 -82
- data/spec/binary/interpret_flags_spec.rb +0 -332
- data/spec/binary/parse_args_spec.rb +0 -415
@@ -20,13 +20,18 @@ RSpec.describe SeeingIsBelieving do
|
|
20
20
|
options.delete :debug
|
21
21
|
options[:debugger] = SeeingIsBelieving::Debugger.new(stream: $stderr, colour: true)
|
22
22
|
end
|
23
|
-
described_class.new(input, options).call
|
23
|
+
described_class.new(input, options).call.result
|
24
24
|
end
|
25
25
|
|
26
26
|
def values_for(input, options={})
|
27
27
|
invoke(input, options).to_a
|
28
28
|
end
|
29
29
|
|
30
|
+
root_path = File.expand_path("../..", __FILE__)
|
31
|
+
proving_grounds = File.expand_path('proving_grounds', root_path)
|
32
|
+
before(:all) { Dir.mkdir proving_grounds unless Dir.exist? proving_grounds }
|
33
|
+
around { |spec| Dir.chdir proving_grounds, &spec }
|
34
|
+
|
30
35
|
let(:proving_grounds_dir) { File.expand_path '../../proving_grounds', __FILE__ }
|
31
36
|
|
32
37
|
it 'takes a string and returns a result of the line numbers (counting from 1) and each inspected result from that line' do
|
@@ -35,6 +40,10 @@ RSpec.describe SeeingIsBelieving do
|
|
35
40
|
expect(invoke(input)[2]).to eq ['"22"']
|
36
41
|
end
|
37
42
|
|
43
|
+
it 'blows up if given unknown options' do
|
44
|
+
expect { invoke '', not_an_option: 123 }.to raise_error KeyError, /not_an_option/
|
45
|
+
end
|
46
|
+
|
38
47
|
it 'only invokes inspect once' do
|
39
48
|
input = "class Fixnum; def inspect; 'NUM'\nend\nend\n1"
|
40
49
|
expect(invoke(input)[1]).to eq ['"NUM"']
|
@@ -45,10 +54,10 @@ RSpec.describe SeeingIsBelieving do
|
|
45
54
|
end
|
46
55
|
|
47
56
|
it 'records various useful information on the result' do
|
48
|
-
result = invoke '',
|
57
|
+
result = invoke '', max_line_captures: 10, filename: 'abc.rb'
|
49
58
|
expect(result.sib_version).to eq SeeingIsBelieving::VERSION
|
50
59
|
expect(result.ruby_version).to eq RUBY_VERSION
|
51
|
-
expect(result.
|
60
|
+
expect(result.max_line_captures).to eq 10
|
52
61
|
expect(result.num_lines).to eq 1
|
53
62
|
expect(result.filename).to eq 'abc.rb'
|
54
63
|
end
|
@@ -58,14 +67,12 @@ RSpec.describe SeeingIsBelieving do
|
|
58
67
|
end
|
59
68
|
|
60
69
|
it 'allows uers to pass in their own inspection recorder' do
|
61
|
-
wrapper = lambda { |program
|
62
|
-
SeeingIsBelieving::
|
63
|
-
|
64
|
-
|
65
|
-
num_captures,
|
66
|
-
after_each: -> line_number { ").tap { $SiB.record_result(:inspect, #{line_number}, 'zomg') }" }
|
70
|
+
wrapper = lambda { |program|
|
71
|
+
SeeingIsBelieving::WrapExpressions.call program,
|
72
|
+
before_each: -> * { '(' },
|
73
|
+
after_each: -> line_number { ").tap { $SiB.record_result(:inspect, #{line_number}, 'zomg') }" }
|
67
74
|
}
|
68
|
-
expect(invoke(':body',
|
75
|
+
expect(invoke(':body', rewrite_code: wrapper)[1]).to eq ['"zomg"']
|
69
76
|
end
|
70
77
|
|
71
78
|
it 'remembers context of previous lines' do
|
@@ -74,8 +81,8 @@ RSpec.describe SeeingIsBelieving do
|
|
74
81
|
|
75
82
|
it 'can be invoked multiple times, returning the same result' do
|
76
83
|
believer = described_class.new("$xyz||=1\n$xyz+=1")
|
77
|
-
expect(believer.call
|
78
|
-
expect(believer.call.to_a).to eq [['1'], ['2']]
|
84
|
+
expect(believer.call).to eq believer.call
|
85
|
+
expect(believer.call.result.to_a).to eq [['1'], ['2']]
|
79
86
|
end
|
80
87
|
|
81
88
|
it 'is evaluated at the toplevel' do
|
@@ -179,7 +186,24 @@ RSpec.describe SeeingIsBelieving do
|
|
179
186
|
end
|
180
187
|
end
|
181
188
|
|
189
|
+
it 'supports catch/throw' do
|
190
|
+
values = values_for("catch :zomg do\n"\
|
191
|
+
" 1\n"\
|
192
|
+
" throw :zomg\n"\
|
193
|
+
" 2\n"\
|
194
|
+
"end")
|
195
|
+
expect(values).to eq [[], ['1'], [], [], ['nil']]
|
182
196
|
|
197
|
+
result = invoke("throw :zomg")
|
198
|
+
expect(result.exception.message).to match /:zomg/
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'does not fuck up the __ENCODING__ macro' do
|
202
|
+
expect(values_for("# encoding: utf-8
|
203
|
+
__ENCODING__")).to eq [[], ["#<Encoding:UTF-8>"]]
|
204
|
+
expect(values_for("# encoding: ascii-8bit
|
205
|
+
__ENCODING__")).to eq [[], ["#<Encoding:ASCII-8BIT>"]]
|
206
|
+
end
|
183
207
|
|
184
208
|
it 'does not fuck up __LINE__ macro' do
|
185
209
|
expect(values_for( '__LINE__
|
@@ -314,7 +338,7 @@ RSpec.describe SeeingIsBelieving do
|
|
314
338
|
it 'can deal with methods that are invoked entirely on the next line' do
|
315
339
|
expect(values_for("a = 1\n.even?\na")).to eq [['1'], ['false'], ['false']]
|
316
340
|
expect(values_for("a = 1.\neven?\na")).to eq [['1'], ['false'], ['false']]
|
317
|
-
expect(values_for("1\n.even?\n__END__")).to eq [['1'], ['false'], []]
|
341
|
+
expect(values_for("1\n.even?\n__END__")).to eq [['1'], ['false'], []]
|
318
342
|
end
|
319
343
|
|
320
344
|
it 'does not record leading comments' do
|
@@ -325,15 +349,35 @@ RSpec.describe SeeingIsBelieving do
|
|
325
349
|
end
|
326
350
|
|
327
351
|
it 'times out if the timeout limit is exceeded' do
|
328
|
-
expect { invoke "sleep 0.2",
|
352
|
+
expect { invoke "sleep 0.2", timeout_seconds: 0.1 }.to raise_error Timeout::Error
|
329
353
|
end
|
330
354
|
|
331
355
|
it 'records the exit status' do
|
332
|
-
expect(invoke(
|
333
|
-
expect(invoke('
|
334
|
-
expect(invoke('
|
356
|
+
expect(invoke("" ).exitstatus).to eq 0 # happy path: no exceptions
|
357
|
+
expect(invoke('raise "omg"' ).exitstatus).to eq 1 # exceptions: status is 1
|
358
|
+
expect(invoke('exit' ).exitstatus).to eq 0 # call exit, but with no args
|
359
|
+
expect(invoke('exit 0' ).exitstatus).to eq 0 # set numeric status with exit
|
360
|
+
expect(invoke('exit 123' ).exitstatus).to eq 123
|
361
|
+
expect(invoke('exit true' ).exitstatus).to eq 0 # set boolean status with exit
|
362
|
+
expect(invoke('exit false' ).exitstatus).to eq 1
|
363
|
+
expect(invoke('at_exit { exit 121 }').exitstatus).to eq 121 # when status is set in an at_exit hook
|
364
|
+
|
365
|
+
# setting status with exit!
|
366
|
+
# since we might be overriding this (a questionable decision) we make sure it behaves as expected (no at_exit hooks are called)
|
367
|
+
result = invoke 'at_exit { puts "omg" }; exit!'
|
368
|
+
expect([result.exitstatus, result.stdout, result.stderr]).to eq [1, '', '']
|
369
|
+
|
370
|
+
result = invoke 'at_exit { puts "omg" }; exit! 100'
|
371
|
+
expect([result.exitstatus, result.stdout]).to eq [100, '']
|
372
|
+
|
373
|
+
result = invoke 'at_exit { puts "omg" }; Kernel.exit! 101'
|
374
|
+
expect([result.exitstatus, result.stdout]).to eq [101, '']
|
375
|
+
|
376
|
+
result = invoke 'at_exit { puts "omg" }; Kernel.exit! 102'
|
377
|
+
expect([result.exitstatus, result.stdout]).to eq [102, '']
|
335
378
|
end
|
336
379
|
|
380
|
+
|
337
381
|
it 'records lines that have comments on them' do
|
338
382
|
expect(values_for('1+1 # comment uno
|
339
383
|
#comment dos
|
@@ -373,23 +417,28 @@ RSpec.describe SeeingIsBelieving do
|
|
373
417
|
['[6, 12]']]
|
374
418
|
end
|
375
419
|
|
376
|
-
it 'can be limited to a specific number of captures' do
|
377
|
-
expect(values_for "2.times do\n1\nend",
|
420
|
+
it 'can be limited to a specific number of captures per line' do
|
421
|
+
expect(values_for "2.times do\n1\nend", max_line_captures: 1).to \
|
378
422
|
eq [['2'],
|
379
423
|
['1', '...'],
|
380
424
|
['2']]
|
381
425
|
end
|
382
426
|
|
383
427
|
describe 'BEGIN and END' do
|
428
|
+
it 'doesn\'t fuck up when the BEGIN block exits / raises' do
|
429
|
+
expect(invoke("BEGIN { exit 100 }").exitstatus).to eq 100
|
430
|
+
expect(invoke("BEGIN { exit! 100 }").exitstatus).to eq 100
|
431
|
+
expect(invoke("BEGIN { raise Exception, 'wat'}").exception.message).to eq 'wat'
|
432
|
+
end
|
433
|
+
|
384
434
|
it 'Executes in the appropriate order' do
|
385
|
-
|
386
|
-
expect(invoke <<-CODE).stdout.to eq "1\n2\n3\n4\n5\n6\n7\n8\n9\n"
|
435
|
+
expect(invoke(<<-CODE).stdout).to eq "1\n2\n3\n4\n5\n6\n7\n8\n9\n"
|
387
436
|
p 3
|
388
|
-
END { p
|
437
|
+
END { p 9 }
|
389
438
|
p 4
|
390
439
|
BEGIN { p 1 }
|
391
440
|
p 5
|
392
|
-
END { p
|
441
|
+
END { p 8 }
|
393
442
|
p 6
|
394
443
|
BEGIN { p 2 }
|
395
444
|
p 7
|
@@ -397,7 +446,6 @@ RSpec.describe SeeingIsBelieving do
|
|
397
446
|
end
|
398
447
|
|
399
448
|
it 'Maintains correct line numbers' do
|
400
|
-
pending 'not implemented'
|
401
449
|
expected_values = [
|
402
450
|
['1'],
|
403
451
|
[],
|
@@ -434,7 +482,7 @@ RSpec.describe SeeingIsBelieving do
|
|
434
482
|
result = invoke(%[def self.inspect
|
435
483
|
self
|
436
484
|
end
|
437
|
-
self], filename: 'blowsup.rb')
|
485
|
+
self], filename: 'blowsup.rb')
|
438
486
|
expect(result).to have_exception
|
439
487
|
expect(result.exception.class_name).to eq 'SystemStackError'
|
440
488
|
expect(result.exception.backtrace.grep(/blowsup.rb/)).to_not be_empty # backtrace includes a line that we can show
|
@@ -454,34 +502,48 @@ RSpec.describe SeeingIsBelieving do
|
|
454
502
|
let(:debugger) { SeeingIsBelieving::Debugger.new stream: stream }
|
455
503
|
|
456
504
|
def call
|
457
|
-
invoke "1", debugger: debugger
|
505
|
+
result = invoke "1", debugger: debugger
|
506
|
+
expect(result[1]).to eq ["1"]
|
507
|
+
result
|
458
508
|
end
|
459
509
|
|
460
510
|
it 'prints the pre-evaluated program' do
|
461
511
|
call
|
462
|
-
expect(stream.string).to include "
|
463
|
-
expect(stream.string).to include "$SiB.
|
512
|
+
expect(stream.string).to include "REWRITTEN PROGRAM:"
|
513
|
+
expect(stream.string).to include "$SiB.record_result" # there is more, but we're just interested in showing that it wound up in the stream
|
464
514
|
end
|
465
515
|
|
466
|
-
it '
|
516
|
+
it 'records eventstream information' do
|
467
517
|
call
|
468
|
-
expect(stream.string).to include "
|
469
|
-
|
470
|
-
|
518
|
+
expect(stream.string).to include "EVENTS"
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
describe 'exec' do
|
523
|
+
it 'passes stdin, stdout, stderr, and actually does exec the process' do
|
524
|
+
result = invoke \
|
525
|
+
"1+1\n"\
|
526
|
+
"$stdout.puts *1..1000\n"\
|
527
|
+
"$stderr.puts *1..1000\n"\
|
528
|
+
"exec %(ruby -e '$stdout.puts %{from stdin: } + gets.inspect
|
529
|
+
$stdout.puts %[out from exec]
|
530
|
+
$stderr.puts %[err from exec]')\n"\
|
531
|
+
"$stdout.puts 'this will never be executed'",
|
532
|
+
stdin: "the-stdin-dataz"
|
533
|
+
expect(result[1]).to eq ['2']
|
534
|
+
nums = (1..1000).map { |n| "#{n}\n" }.join('')
|
535
|
+
expect(result.stdout).to eq "#{nums}from stdin: \"the-stdin-dataz\"\nout from exec\n"
|
536
|
+
expect(result.stderr).to eq "#{nums}err from exec\n"
|
537
|
+
end
|
538
|
+
|
539
|
+
it 'works for Kernel#exec, Kernel.exec, Process.exec' do
|
540
|
+
expect(invoke('exec "ruby", "-e", "puts %(hello)"').stdout).to eq "hello\n"
|
541
|
+
expect(invoke('Kernel.exec "ruby", "-e", "puts %(hello)"').stdout).to eq "hello\n"
|
542
|
+
expect(invoke('Process.exec "ruby", "-e", "puts %(hello)"').stdout).to eq "hello\n"
|
543
|
+
end
|
544
|
+
|
545
|
+
it 'gets the exit status off of the child process' do
|
546
|
+
expect(invoke('exec "ruby", "-e", "exit 5"').exitstatus).to eq 5
|
471
547
|
end
|
472
|
-
# should ProgramRewriter have some debug options?
|
473
|
-
end
|
474
|
-
|
475
|
-
it 'can deal with exec' do
|
476
|
-
result = invoke \
|
477
|
-
"1+1\n"\
|
478
|
-
"$stdout.puts *1..1000\n"\
|
479
|
-
"$stderr.puts *1..1000\n"\
|
480
|
-
"exec %(ruby -e '$stdout.puts %[out from exec];
|
481
|
-
$stderr.puts %[err from exec]')"
|
482
|
-
expect(result[1]).to eq ['2']
|
483
|
-
nums = (1..1000).map { |n| "#{n}\n" }.join('')
|
484
|
-
expect(result.stdout).to eq "#{nums}out from exec\n"
|
485
|
-
expect(result.stderr).to eq "#{nums}err from exec\n"
|
486
548
|
end
|
487
549
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,12 +2,29 @@ require 'spec_helper'
|
|
2
2
|
require 'seeing_is_believing/wrap_expressions'
|
3
3
|
|
4
4
|
RSpec.describe SeeingIsBelieving::WrapExpressions do
|
5
|
-
def wrap(code)
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
def wrap(code, overrides={})
|
6
|
+
code = code + "\n" unless code.end_with? "\n"
|
7
|
+
described_class.call(code,
|
8
|
+
before_all: -> { overrides.fetch :before_all, '' },
|
9
|
+
after_all: -> { overrides.fetch :after_all, '' },
|
10
|
+
before_each: -> * { overrides.fetch :before_each, '<' },
|
11
|
+
after_each: -> * { overrides.fetch :after_each, '>' }
|
12
|
+
).chomp
|
9
13
|
end
|
10
14
|
|
15
|
+
def wrap_with_body(code, overrides={})
|
16
|
+
wrap code, { before_all: '[',
|
17
|
+
after_all: ']',
|
18
|
+
}.merge(overrides)
|
19
|
+
end
|
20
|
+
|
21
|
+
def heredoc_wrap(code, overrides={})
|
22
|
+
wrap_with_body code, { before_each: '{'.freeze,
|
23
|
+
after_each: '}'.freeze,
|
24
|
+
}.merge(overrides)
|
25
|
+
end
|
26
|
+
|
27
|
+
|
11
28
|
it 'raises a SyntaxError if the program is invalid' do
|
12
29
|
expect { wrap '+' }.to raise_error SyntaxError
|
13
30
|
end
|
@@ -17,34 +34,31 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
17
34
|
end
|
18
35
|
|
19
36
|
describe 'wrapping the body' do
|
20
|
-
let(:options) { { before_all: -> { "[".freeze },
|
21
|
-
after_all: -> { "]".freeze },
|
22
|
-
before_each: -> * { '<'.freeze },
|
23
|
-
after_each: -> * { '>'.freeze } } }
|
24
|
-
|
25
37
|
it 'wraps the entire body, ignoring leading comments and the data segment' do
|
26
|
-
expect(
|
38
|
+
expect(wrap_with_body "#comment\nA\n__END__\n1").to eq "#comment\n[<A>]\n__END__\n1"
|
39
|
+
expect(wrap_with_body "#comment\n__END__\n1").to eq "[]#comment\n__END__\n1"
|
27
40
|
end
|
28
41
|
|
29
|
-
it '
|
30
|
-
expect(
|
42
|
+
it 'wraps when code is an empty string' do
|
43
|
+
expect(wrap_with_body '').to eq '[]'
|
31
44
|
end
|
32
45
|
|
33
|
-
it '
|
34
|
-
expect(
|
46
|
+
it 'places body before first comment when there are only comments' do
|
47
|
+
expect(wrap_with_body "# abc").to eq "[]# abc"
|
35
48
|
end
|
36
49
|
|
37
|
-
it '
|
38
|
-
expect(
|
50
|
+
it 'places body before trailing comments, but still wraps code' do
|
51
|
+
expect(wrap_with_body "1# abc").to eq "[<1>]# abc"
|
39
52
|
end
|
40
53
|
|
41
54
|
# this changes the number of lines, annoyingly, though it shouldn't mess anything up,
|
42
55
|
# unless you were trying to reopen the file to read it, in which case, *surprise* the whole thing's been rewritten
|
43
56
|
it 'injects a newline if there is a data segment and the after block doesn\'t end in a newline' do
|
44
|
-
expect(
|
45
|
-
expect(
|
46
|
-
expect(
|
47
|
-
expect(
|
57
|
+
expect(wrap_with_body "__END__").to eq "[]\n__END__"
|
58
|
+
expect(wrap_with_body "\n__END__").to eq "[]\n__END__"
|
59
|
+
expect(wrap_with_body "\n\n__END__").to eq "[]\n\n__END__"
|
60
|
+
expect(wrap_with_body "__END__!").to eq "[<__END__!>]"
|
61
|
+
expect(wrap_with_body "%(\n__END__\n)").to eq "[<%(\n__END__\n)>]"
|
48
62
|
end
|
49
63
|
|
50
64
|
it 'wraps bodies that are wrapped in parentheses' do
|
@@ -54,35 +68,28 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
54
68
|
|
55
69
|
context 'fucking heredocs' do
|
56
70
|
example 'single heredoc' do
|
57
|
-
expect(
|
71
|
+
expect(heredoc_wrap "<<A\nA").to eq "[{<<A}]\nA"
|
58
72
|
end
|
59
73
|
|
60
74
|
example 'multiple heredocs' do
|
61
|
-
|
62
|
-
# causes the toplevel begin to wrap the whole file.
|
63
|
-
# It's fine b/c it is ultimately the same, but that's why it's
|
64
|
-
# "[<<<<A>\nA\n<<B>]\nB"
|
65
|
-
# instead of
|
66
|
-
# "[<<<A>\nA\n<<<B>]\nB"
|
67
|
-
expect(described_class.call("<<A\nA\n<<B\nB", options)).to eq "[<<<<A>\nA\n<<B>]\nB"
|
75
|
+
expect(heredoc_wrap "<<A\nA\n<<B\nB").to eq "[{<<A}\nA\n{<<B}]\nB"
|
68
76
|
end
|
69
77
|
|
70
78
|
example 'heredocs as targets and arguments to methods' do
|
71
|
-
expect(
|
72
|
-
expect(
|
73
|
-
expect(
|
74
|
-
expect(
|
75
|
-
expect(
|
76
|
-
expect(
|
79
|
+
expect(heredoc_wrap "<<A.size 1\nA").to eq "[{<<A.size 1}]\nA"
|
80
|
+
expect(heredoc_wrap "<<A.size\nA").to eq "[{<<A.size}]\nA"
|
81
|
+
expect(heredoc_wrap "<<A.size()\nA").to eq "[{<<A.size()}]\nA"
|
82
|
+
expect(heredoc_wrap "a.size <<A\nA").to eq "[{a.size <<A}]\nA"
|
83
|
+
expect(heredoc_wrap "<<A.size <<B\nA\nB").to eq "[{<<A.size <<B}]\nA\nB"
|
84
|
+
expect(heredoc_wrap "<<A.size(<<B)\nA\nB").to eq "[{<<A.size(<<B)}]\nA\nB"
|
77
85
|
end
|
78
86
|
end
|
79
87
|
|
80
88
|
it 'identifies the last line of the body' do
|
81
|
-
expect(
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
options)
|
89
|
+
expect(wrap_with_body "a\n"\
|
90
|
+
"def b\n"\
|
91
|
+
" c = 1\n"\
|
92
|
+
"end"
|
86
93
|
).to eq "[<a>\n"\
|
87
94
|
"<def b\n"\
|
88
95
|
" <c = 1>\n"\
|
@@ -92,7 +99,7 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
92
99
|
|
93
100
|
it 'passes the current line number to the before_each and after_each wrappers' do
|
94
101
|
pre_line_num = post_line_num = nil
|
95
|
-
described_class.call("\na",
|
102
|
+
described_class.call("\na\n",
|
96
103
|
before_each: -> _pre_line_num { pre_line_num = _pre_line_num; '<' },
|
97
104
|
after_each: -> _post_line_num { post_line_num = _post_line_num; '>' }
|
98
105
|
)
|
@@ -101,8 +108,7 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
101
108
|
end
|
102
109
|
|
103
110
|
it 'does nothing for an empty program' do
|
104
|
-
expect(wrap("")).to eq ""
|
105
|
-
expect(wrap("\n")).to eq "\n"
|
111
|
+
expect(wrap("")).to eq "" # note that code will fix the missing newline, and wrap will chomp it from the result for convenience
|
106
112
|
end
|
107
113
|
|
108
114
|
it 'ignores comments' do
|
@@ -112,79 +118,6 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
112
118
|
expect(wrap "=begin\n1\n=end\n2").to eq "=begin\n1\n=end\n<2>"
|
113
119
|
end
|
114
120
|
|
115
|
-
describe 'void value expressions' do
|
116
|
-
def void_value?(ast)
|
117
|
-
klass = described_class.new '', {}
|
118
|
-
klass.__send__(:void_value?, ast)
|
119
|
-
end
|
120
|
-
|
121
|
-
def ast_for(code)
|
122
|
-
Parser::CurrentRuby.parse code
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'knows a `return`, `next`, `redo`, `retry`, and `break` are void values' do
|
126
|
-
expect(void_value?(ast_for("def a; return; end").children.last)).to be true
|
127
|
-
expect(void_value?(ast_for("loop { next }" ).children.last)).to be true
|
128
|
-
expect(void_value?(ast_for("loop { redo }" ).children.last)).to be true
|
129
|
-
expect(void_value?(ast_for("loop { break }" ).children.last)).to be true
|
130
|
-
|
131
|
-
the_retry = ast_for("begin; rescue; retry; end").children.first.children[1].children.last
|
132
|
-
expect(the_retry.type).to eq :retry
|
133
|
-
expect(void_value? the_retry).to eq true
|
134
|
-
end
|
135
|
-
it 'knows an `if` is a void value if either side is a void value' do
|
136
|
-
the_if = ast_for("def a; if 1; return 2; else; 3; end; end").children.last
|
137
|
-
expect(the_if.type).to eq :if
|
138
|
-
expect(void_value?(the_if)).to be true
|
139
|
-
|
140
|
-
the_if = ast_for("def a; if 1; 2; else; return 3; end; end").children.last
|
141
|
-
expect(the_if.type).to eq :if
|
142
|
-
expect(void_value?(the_if)).to be true
|
143
|
-
|
144
|
-
the_if = ast_for("def a; if 1; 2; else; 3; end; end").children.last
|
145
|
-
expect(the_if.type).to eq :if
|
146
|
-
expect(void_value?(the_if)).to be false
|
147
|
-
end
|
148
|
-
it 'knows a begin is a void value if its last element is a void value' do
|
149
|
-
the_begin = ast_for("loop { begin; break; end }").children.last
|
150
|
-
expect([:begin, :kwbegin]).to include the_begin.type
|
151
|
-
expect(void_value?(the_begin)).to be true
|
152
|
-
|
153
|
-
the_begin = ast_for("loop { begin; 1; end }").children.last
|
154
|
-
expect([:begin, :kwbegin]).to include the_begin.type
|
155
|
-
expect(void_value?(the_begin)).to be false
|
156
|
-
end
|
157
|
-
it 'knows a rescue is a void value if its last child or its else is a void value' do
|
158
|
-
the_rescue = ast_for("begin; rescue; retry; end").children.first
|
159
|
-
expect(the_rescue.type).to eq :rescue
|
160
|
-
expect(void_value?(the_rescue)).to be true
|
161
|
-
|
162
|
-
the_rescue = ast_for("begin; rescue; 1; else; retry; end").children.first
|
163
|
-
expect(the_rescue.type).to eq :rescue
|
164
|
-
expect(void_value?(the_rescue)).to be true
|
165
|
-
|
166
|
-
the_rescue = ast_for("begin; rescue; 1; else; 2; end").children.first
|
167
|
-
expect(the_rescue.type).to eq :rescue
|
168
|
-
expect(void_value?(the_rescue)).to be false
|
169
|
-
end
|
170
|
-
it 'knows an ensure is a void value if its body or ensure portion are void values' do
|
171
|
-
the_ensure = ast_for("loop { begin; break; ensure; 1; end }").children.last.children.last
|
172
|
-
expect(the_ensure.type).to eq :ensure
|
173
|
-
expect(void_value?(the_ensure)).to be true
|
174
|
-
|
175
|
-
the_ensure = ast_for("loop { begin; 1; ensure; break; end }").children.last.children.last
|
176
|
-
expect(the_ensure.type).to eq :ensure
|
177
|
-
expect(void_value?(the_ensure)).to be true
|
178
|
-
|
179
|
-
the_ensure = ast_for("loop { begin; 1; ensure; 2; end }").children.last.children.last
|
180
|
-
expect(the_ensure.type).to eq :ensure
|
181
|
-
expect(void_value?(the_ensure)).to be false
|
182
|
-
end
|
183
|
-
it 'knows other things are not void values' do
|
184
|
-
expect(void_value?(ast_for "123")).to be false
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
121
|
describe 'basic expressions' do
|
189
122
|
it 'wraps an expression' do
|
190
123
|
expect(wrap("A")).to eq "<A>"
|
@@ -200,6 +133,10 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
200
133
|
it 'does not wrap multiple expressions when they constitute a void value' do
|
201
134
|
expect(wrap("def a\n1\nreturn 2\nend")).to eq "<def a\n<1>\nreturn <2>\nend>"
|
202
135
|
expect(wrap("def a\nreturn 1\n2\nend")).to eq "<def a\nreturn <1>\n<2>\nend>"
|
136
|
+
# BUG, but I'm skipping it, b/c it's borderline invalid.
|
137
|
+
# To the point that Parser doesn't even emit the else clause in the AST
|
138
|
+
# And Ruby will warn you that it's useless
|
139
|
+
# expect(wrap("begin\n1\nelse\nbreak\nend")).to eq "begin\n<1>\nelse\nbreak\nend"
|
203
140
|
end
|
204
141
|
|
205
142
|
it 'wraps nested expressions' do
|
@@ -212,9 +149,6 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
212
149
|
|
213
150
|
# many of these taken from http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Literals
|
214
151
|
it 'wraps simple literals' do
|
215
|
-
# should maybe also do %i[] and %I[] for symbols,
|
216
|
-
# but that's only Ruby 2.0, so I'm ignoring it for now
|
217
|
-
# (I expect it to handle them just fine)
|
218
152
|
%w|123
|
219
153
|
-123
|
220
154
|
1_123
|
@@ -236,6 +170,7 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
236
170
|
1...2
|
237
171
|
|
238
172
|
(true==true)..(1==2)
|
173
|
+
(true==true)...(1==2)
|
239
174
|
|
240
175
|
true
|
241
176
|
false
|
@@ -268,16 +203,16 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
268
203
|
end
|
269
204
|
|
270
205
|
it 'wraps macros' do
|
271
|
-
# should this actually replace __FILE__ and __LINE__ so as to avoid fucking up values with the rewrite?
|
272
|
-
# there is also __dir__, but it's only 2.0
|
273
206
|
expect(wrap("__FILE__")).to eq "<__FILE__>"
|
274
207
|
expect(wrap("__LINE__")).to eq "<__LINE__>"
|
208
|
+
expect(wrap("__ENCODING__")).to eq "<__ENCODING__>"
|
275
209
|
expect(wrap("defined? a")).to eq "<defined? a>"
|
276
210
|
end
|
277
211
|
|
278
212
|
it 'does not wrap alias, undef' do
|
279
213
|
expect(wrap("alias tos to_s")).to eq "alias tos to_s"
|
280
214
|
expect(wrap("undef tos")).to eq "undef tos"
|
215
|
+
expect(wrap("alias $a $b")).to eq "alias $a $b"
|
281
216
|
end
|
282
217
|
|
283
218
|
it 'wraps syscalls, but not code interpolated into them' do
|
@@ -290,6 +225,7 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
290
225
|
it 'wraps them' do
|
291
226
|
expect(wrap('a')).to eq "<a>"
|
292
227
|
expect(wrap("$a")).to eq "<$a>"
|
228
|
+
expect(wrap("$1")).to eq "<$1>"
|
293
229
|
expect(wrap("@a")).to eq "<@a>"
|
294
230
|
expect(wrap("@@a")).to eq "<@@a>"
|
295
231
|
end
|
@@ -311,6 +247,8 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
311
247
|
expect(wrap("a { }")).to eq "<a { }>"
|
312
248
|
expect(wrap("a {\n}")).to eq "<a {\n}>"
|
313
249
|
expect(wrap("a(b) {\n}")).to eq "<a(b) {\n}>"
|
250
|
+
expect(wrap("a(&b\n)")).to eq "<a(&<b>\n)>"
|
251
|
+
expect(wrap("a(&lambda { }\n)")).to eq "<a(&<lambda { }>\n)>"
|
314
252
|
end
|
315
253
|
|
316
254
|
it 'wraps method calls with an explicit receiver' do
|
@@ -345,9 +283,9 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
345
283
|
expect(wrap("a 1,\n2")).to eq "<a <1>,\n2>"
|
346
284
|
end
|
347
285
|
|
348
|
-
it 'does
|
349
|
-
expect(wrap("a(\n*a\n)")).to eq "<a(\n
|
350
|
-
expect(wrap("a(\n*1..2\n)")).to eq "<a(\n
|
286
|
+
it 'does wraps splat args' do
|
287
|
+
expect(wrap("a(\n*a\n)")).to eq "<a(\n*<a>\n)>"
|
288
|
+
expect(wrap("a(\n*1..2\n)")).to eq "<a(\n*<1..2>\n)>"
|
351
289
|
end
|
352
290
|
|
353
291
|
it 'does not wrap hash args' do
|
@@ -407,11 +345,13 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
407
345
|
expect(wrap("a -= 1")).to eq "<a -= 1>"
|
408
346
|
expect(wrap("a /= 1")).to eq "<a /= 1>"
|
409
347
|
expect(wrap("a **= 1")).to eq "<a **= 1>"
|
348
|
+
expect(wrap("a != 1")).to eq "<a != 1>"
|
410
349
|
expect(wrap("a |= 1")).to eq "<a |= 1>"
|
411
350
|
expect(wrap("a &= 1")).to eq "<a &= 1>"
|
412
351
|
expect(wrap("a ||= 1")).to eq "<a ||= 1>"
|
413
352
|
expect(wrap("a &&= 1")).to eq "<a &&= 1>"
|
414
353
|
expect(wrap("a[1] = 2")).to eq "<a[1] = 2>"
|
354
|
+
expect(wrap("a[1,2] = 3")).to eq "<a[1,2] = 3>"
|
415
355
|
expect(wrap("a[1] ||= 2")).to eq "<a[1] ||= 2>"
|
416
356
|
expect(wrap("@a ||= 123")).to eq "<@a ||= 123>"
|
417
357
|
expect(wrap("$a ||= 123")).to eq "<$a ||= 123>"
|
@@ -444,6 +384,7 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
444
384
|
expect(wrap("a,@b={\n},{\n}")).to eq "<a,@b=<{\n}>,{\n}>"
|
445
385
|
expect(wrap("a,@@b={\n},{\n}")).to eq "<a,@@b=<{\n}>,{\n}>"
|
446
386
|
expect(wrap("a,$b={\n},{\n}")).to eq "<a,$b=<{\n}>,{\n}>"
|
387
|
+
expect(wrap("a,$b={\n},{\n}")).to eq "<a,$b=<{\n}>,{\n}>"
|
447
388
|
|
448
389
|
# repeated assignments
|
449
390
|
expect(wrap("a=\nb={\n}")).to eq "<a=\nb={\n}>"
|
@@ -502,8 +443,9 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
502
443
|
expect(wrap("1 if 2")).to eq "<1 if 2>"
|
503
444
|
end
|
504
445
|
|
505
|
-
it '
|
506
|
-
expect(wrap("if /a/\n1\nend")).to eq "<if
|
446
|
+
it 'wraps implicit regexes, retaining their magic behaviour by prepending a ~' do
|
447
|
+
expect(wrap("if /a/\n1\nend")).to eq "<if <~/a/>\n<1>\nend>"
|
448
|
+
expect(wrap("/a/ &&\n1")).to eq "<</a/> &&\n1>"
|
507
449
|
end
|
508
450
|
|
509
451
|
it 'wraps ternaries' do
|
@@ -545,6 +487,8 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
545
487
|
# not sure if I actually want this, or if it's just easier b/c it falls out of the current implementation
|
546
488
|
it 'wraps the conditional from an inline if, when it cannot wrap the entire if' do
|
547
489
|
expect(wrap("def a\nreturn if 1\nend")).to eq "<def a\nreturn if <1>\nend>"
|
490
|
+
# could maybe do this:
|
491
|
+
# `return 1 if b` -> `return <1> if (b) || <nil>`
|
548
492
|
end
|
549
493
|
|
550
494
|
it 'does not wrap &&, and, ||, or, not' do
|
@@ -567,15 +511,15 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
567
511
|
expect(wrap("while 1\n2\nend")).to eq "<while <1>\n<2>\nend>"
|
568
512
|
expect(wrap("1 while 2")).to eq "<1 while 2>"
|
569
513
|
expect(wrap("begin\n1\nend while true")).to eq "<begin\n<1>\nend while true>"
|
514
|
+
expect(wrap("begin\n1\nend until true")).to eq "<begin\n<1>\nend until true>"
|
570
515
|
end
|
571
516
|
it 'wraps for/in loops collections and bodies' do
|
572
517
|
expect(wrap("for a in range;1;end")).to eq "<for a in range;1;end>"
|
573
518
|
expect(wrap("for a in range\n1\nend")).to eq "<for a in <range>\n<1>\nend>"
|
574
519
|
expect(wrap("for a in range do\n1\nend")).to eq "<for a in <range> do\n<1>\nend>"
|
575
520
|
expect(wrap("for a,b in whatev\n1\nend")).to eq "<for a,b in <whatev>\n<1>\nend>"
|
576
|
-
|
577
|
-
|
578
|
-
# "<for char in <<<HERE.each_char>\nabc\nHERE\n<puts char>\nend>"
|
521
|
+
expect(wrap("for char in <<HERE.each_char\nabc\nHERE\nputs char\nend"))
|
522
|
+
.to eq "<for char in <<<HERE.each_char>\nabc\nHERE\n<puts char>\nend>"
|
579
523
|
end
|
580
524
|
it 'does not wrap redo' do
|
581
525
|
expect(wrap("loop do\nredo\nend")).to eq "<loop do\nredo\nend>"
|
@@ -596,6 +540,7 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
596
540
|
it 'wraps namespaced constant access' do
|
597
541
|
expect(wrap("::A")).to eq "<::A>"
|
598
542
|
expect(wrap("A::B")).to eq "<A::B>"
|
543
|
+
expect(wrap("a::B")).to eq "<a::B>"
|
599
544
|
end
|
600
545
|
end
|
601
546
|
|
@@ -618,8 +563,8 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
618
563
|
expect(wrap("%w[\n1\n]")).to eq "<%w[\n1\n]>"
|
619
564
|
end
|
620
565
|
|
621
|
-
it 'does
|
622
|
-
expect(wrap("[1,\n*2..3,\n4\n]")).to eq "<[<1>,\n
|
566
|
+
it 'does wraps splat elements' do
|
567
|
+
expect(wrap("[1,\n*2..3,\n4\n]")).to eq "<[<1>,\n*<2..3>,\n<4>\n]>"
|
623
568
|
end
|
624
569
|
end
|
625
570
|
|
@@ -683,45 +628,46 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
683
628
|
end
|
684
629
|
|
685
630
|
it 'wraps heredocs with call defined on them (edge cases on edge cases *sigh*)' do
|
686
|
-
expect(
|
631
|
+
expect(heredoc_wrap "<<HERE.()\na\nHERE")
|
632
|
+
.to eq "[{<<HERE.()}]\na\nHERE"
|
687
633
|
end
|
688
634
|
end
|
689
635
|
|
690
636
|
describe 'heredocs' do
|
691
637
|
it 'wraps heredocs on their first line' do
|
692
|
-
expect(
|
693
|
-
expect(
|
694
|
-
expect(
|
695
|
-
expect(
|
696
|
-
expect(
|
697
|
-
expect(
|
698
|
-
expect(
|
699
|
-
expect(
|
638
|
+
expect(heredoc_wrap "<<A\nA").to eq "[{<<A}]\nA"
|
639
|
+
expect(heredoc_wrap "<<A\n123\nA").to eq "[{<<A}]\n123\nA"
|
640
|
+
expect(heredoc_wrap "<<-A\nA").to eq "[{<<-A}]\nA"
|
641
|
+
expect(heredoc_wrap "<<-A\n123\nA").to eq "[{<<-A}]\n123\nA"
|
642
|
+
expect(heredoc_wrap "1\n<<A\nA").to eq "[{1}\n{<<A}]\nA"
|
643
|
+
expect(heredoc_wrap "<<A + <<B\n1\nA\n2\nB").to eq "[{<<A + <<B}]\n1\nA\n2\nB"
|
644
|
+
expect(heredoc_wrap "<<A\n1\nA\n<<B\n2\nB").to eq "[{<<A}\n1\nA\n{<<B}]\n2\nB"
|
645
|
+
expect(heredoc_wrap "puts <<A\nA\nputs <<B\nB").to eq "[{puts <<A}\nA\n{puts <<B}]\nB"
|
700
646
|
end
|
701
647
|
|
702
648
|
it "wraps methods that wrap heredocs, even whent hey don't have parentheses" do
|
703
|
-
expect(
|
704
|
-
expect(
|
705
|
-
expect(
|
706
|
-
expect(
|
707
|
-
"
|
708
|
-
expect(
|
649
|
+
expect(heredoc_wrap "a(<<HERE)\nHERE").to eq "[{a(<<HERE)}]\nHERE"
|
650
|
+
expect(heredoc_wrap "a <<HERE\nHERE").to eq "[{a <<HERE}]\nHERE"
|
651
|
+
expect(heredoc_wrap "a 1, <<HERE\nHERE").to eq "[{a 1, <<HERE}]\nHERE"
|
652
|
+
expect(heredoc_wrap "a.b 1, 2, <<HERE1, <<-HERE2 \nHERE1\n HERE2").to eq\
|
653
|
+
"[{a.b 1, 2, <<HERE1, <<-HERE2}] \nHERE1\n HERE2"
|
654
|
+
expect(heredoc_wrap "a.b 1,\n2,\n<<HERE\nHERE").to eq "[{a.b {1},\n{2},\n<<HERE}]\nHERE"
|
709
655
|
end
|
710
656
|
|
711
657
|
it "wraps assignments whose value is a heredoc" do
|
712
|
-
expect(
|
713
|
-
expect(
|
714
|
-
expect(
|
715
|
-
expect(
|
658
|
+
expect(heredoc_wrap "a=<<A\nA").to eq "[{a=<<A}]\nA"
|
659
|
+
expect(heredoc_wrap "a,b=<<A,<<B\nA\nB").to eq "[{a,b=<<A,<<B}]\nA\nB"
|
660
|
+
expect(heredoc_wrap "a,b=1,<<B\nB").to eq "[{a,b=1,<<B}]\nB"
|
661
|
+
expect(heredoc_wrap "a,b=<<A,1\nA").to eq "[{a,b=<<A,1}]\nA"
|
716
662
|
end
|
717
663
|
|
718
664
|
it 'wraps methods tacked onto the end of heredocs' do
|
719
|
-
expect(
|
720
|
-
expect(
|
721
|
-
expect(
|
722
|
-
expect(
|
723
|
-
expect(
|
724
|
-
expect(
|
665
|
+
expect(heredoc_wrap "<<A.size\nA").to eq "[{<<A.size}]\nA"
|
666
|
+
expect(heredoc_wrap "<<A.size 1\nA").to eq "[{<<A.size 1}]\nA"
|
667
|
+
expect(heredoc_wrap "<<A.size(1)\nA").to eq "[{<<A.size(1)}]\nA"
|
668
|
+
expect(heredoc_wrap "<<A.whatever <<B\nA\nB").to eq "[{<<A.whatever <<B}]\nA\nB"
|
669
|
+
expect(heredoc_wrap "<<A.whatever(<<B)\nA\nB").to eq "[{<<A.whatever(<<B)}]\nA\nB"
|
670
|
+
expect(heredoc_wrap "<<A.size()\nA").to eq "[{<<A.size()}]\nA"
|
725
671
|
end
|
726
672
|
end
|
727
673
|
|
@@ -760,36 +706,30 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
760
706
|
end
|
761
707
|
end
|
762
708
|
|
763
|
-
# eventually, don't wrap these b/c they're spammy, but can be annoying since they can be accidentally wraped
|
764
|
-
# by e.g. a begin/end
|
765
|
-
# ignoring public/private/protected for now, b/c they're just methods, not keywords
|
766
709
|
describe 'class definitions' do
|
767
710
|
it 'does not wrap the class definition, does wrap the body' do
|
768
|
-
expect(wrap("class A\n1\nend")).to eq "class A\n<1>\nend"
|
711
|
+
expect(wrap("class A\n1\nend")).to eq "<class A\n<1>\nend>"
|
769
712
|
end
|
770
713
|
|
771
714
|
it 'does not wrap the superclass definition' do
|
772
|
-
expect(wrap("class A < B\nend")).to eq "class A < B
|
715
|
+
expect(wrap("class A < B\nend")).to eq "<class A < <B>\nend>"
|
773
716
|
end
|
774
717
|
|
775
718
|
it 'wraps the rescue body' do
|
776
|
-
expect(wrap("class A < B\n1\nrescue\n2\nend")).to eq "class A < B
|
719
|
+
expect(wrap("class A < B\n1\nrescue\n2\nend")).to eq "<class A < <B>\n<1>\nrescue\n<2>\nend>"
|
777
720
|
end
|
778
721
|
|
779
722
|
it 'does not wrap the singleton class' do
|
780
|
-
expect(wrap("class << self\n end")).to eq "class << self
|
723
|
+
expect(wrap("class << self\n end")).to eq "<class << <self>\n end>"
|
781
724
|
end
|
782
725
|
end
|
783
726
|
|
784
|
-
# eventually, don't wrap these b/c they're spammy, but can be annoying since they can be accidentally wraped
|
785
|
-
# by e.g. a begin/end
|
786
|
-
# ignoring public/private/protected for now, b/c they're just methods, not keywords
|
787
727
|
describe 'module definitions' do
|
788
728
|
it 'does not wrap the definition, does wrap the body' do
|
789
|
-
expect(wrap("module A\n1\nend")).to eq "module A\n<1>\nend"
|
729
|
+
expect(wrap("module A\n1\nend")).to eq "<module A\n<1>\nend>"
|
790
730
|
end
|
791
731
|
it 'wraps the rescue portion' do
|
792
|
-
expect(wrap("module A\n1\nrescue\n2\nend")).to eq "module A\n<1>\nrescue\n<2>\nend"
|
732
|
+
expect(wrap("module A\n1\nrescue\n2\nend")).to eq "<module A\n<1>\nrescue\n<2>\nend>"
|
793
733
|
end
|
794
734
|
end
|
795
735
|
|
@@ -812,11 +752,15 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
812
752
|
|
813
753
|
it 'wraps calls to yield' do
|
814
754
|
expect(wrap("def a\nyield\nend")).to eq "<def a\n<yield>\nend>"
|
755
|
+
expect(wrap("def a\nyield 1\nend")).to eq "<def a\n<yield 1>\nend>"
|
756
|
+
expect(wrap("def a\nyield(\n1\n)\nend")).to eq "<def a\n<yield(\n<1>\n)>\nend>"
|
815
757
|
end
|
816
758
|
|
817
759
|
it 'wraps calls to super' do
|
818
760
|
expect(wrap("def a\nsuper\nend")).to eq "<def a\n<super>\nend>"
|
819
761
|
expect(wrap("def a\nsuper 1\nend")).to eq "<def a\n<super 1>\nend>"
|
762
|
+
expect(wrap("def a\nsuper(1)\nend")).to eq "<def a\n<super(1)>\nend>"
|
763
|
+
expect(wrap("def a\nsuper(\n1\n)\nend")).to eq "<def a\n<super(\n<1>\n)>\nend>"
|
820
764
|
end
|
821
765
|
|
822
766
|
it 'wraps the bodies of returns' do
|
@@ -828,11 +772,17 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
828
772
|
expect(wrap("def a\n1\nrescue\n2\nensure\n3\nend")).to eq "<def a\n<1>\nrescue\n<2>\nensure\n<3>\nend>"
|
829
773
|
expect(wrap("def a\n1\nensure\n2\nend")).to eq "<def a\n<1>\nensure\n<2>\nend>"
|
830
774
|
end
|
775
|
+
|
776
|
+
it 'wrap a definition as a call to an invocation' do
|
777
|
+
expect(wrap("a def b\nc\nend,\nd")).to eq "<a <def b\n<c>\nend>,\nd>"
|
778
|
+
end
|
831
779
|
end
|
832
780
|
|
833
781
|
describe 'lambdas' do
|
834
782
|
it 'wraps the lambda' do
|
835
783
|
expect(wrap("lambda { }")).to eq "<lambda { }>"
|
784
|
+
expect(wrap("lambda { |;a| }")).to eq "<lambda { |;a| }>"
|
785
|
+
expect(wrap("lambda { |a,b=1,*c,&d| }")).to eq "<lambda { |a,b=1,*c,&d| }>"
|
836
786
|
expect(wrap("-> { }")).to eq "<-> { }>"
|
837
787
|
expect(wrap("-> a, b { }")).to eq "<-> a, b { }>"
|
838
788
|
expect(wrap("-> {\n1\n}")).to eq "<-> {\n<1>\n}>"
|
@@ -865,15 +815,100 @@ RSpec.describe SeeingIsBelieving::WrapExpressions do
|
|
865
815
|
# <2>
|
866
816
|
# <3>]
|
867
817
|
#
|
868
|
-
#
|
869
|
-
#
|
870
|
-
#
|
871
|
-
|
872
|
-
|
818
|
+
# Because not iw matters why you want to wrap it. Are you doing this because you want
|
819
|
+
# to catch an exception? then maybe your wrapping code needs to go around the inside of each begin block
|
820
|
+
# or maybe the begin blocks need to get consolidated into a single begin block.
|
821
|
+
# or maybe removed from the begin block and just stuck as normal fkn code at the top of the file?
|
822
|
+
# but we do need to rewrite __LINE__ expressions now, because they are changing.
|
823
|
+
# which... maybe that's fine.
|
824
|
+
#
|
825
|
+
# Or, you might just be interested in having your code execute first. In which case,
|
826
|
+
# it doesn't need to wrap the body, it just needs its own BEGIN block.
|
827
|
+
#
|
828
|
+
# note that there are also things line nested BEGINs and nested ENDs
|
829
|
+
# but you can't nest a BEGIN inside an END.
|
830
|
+
it 'does not record them' do
|
873
831
|
expect(wrap("BEGIN {}")).to eq "BEGIN {}"
|
874
832
|
expect(wrap("END {}")).to eq "END {}"
|
875
833
|
expect(wrap("BEGIN {\n123\n}")).to eq "BEGIN {\n<123>\n}"
|
876
834
|
expect(wrap("END {\n123\n}")).to eq "END {\n<123>\n}"
|
877
835
|
end
|
836
|
+
|
837
|
+
it 'moves them out of the body', not_implemented: true do
|
838
|
+
expect(wrap_with_body(<<-HERE)).to eq(<<-THERE)
|
839
|
+
# encoding: utf-8
|
840
|
+
p [1, __LINE__]
|
841
|
+
BEGIN {
|
842
|
+
p [2, __LINE__]
|
843
|
+
}
|
844
|
+
p [3, __LINE__]
|
845
|
+
END {
|
846
|
+
p [4, __LINE__]
|
847
|
+
}
|
848
|
+
p [5, __LINE__]
|
849
|
+
BEGIN { p [6, __LINE__] }
|
850
|
+
END { p [7, __LINE__] }
|
851
|
+
p [8, __LINE__]
|
852
|
+
HERE
|
853
|
+
# encoding: utf-8
|
854
|
+
BEGIN {
|
855
|
+
<p [2, 4]>
|
856
|
+
}
|
857
|
+
BEGIN { <p [6, 11]> }
|
858
|
+
[<p [1, 2]>
|
859
|
+
<p [3, 6]>
|
860
|
+
<p [5, 10]>
|
861
|
+
<p [8, 13]>]
|
862
|
+
END {
|
863
|
+
<p [4, 8]>
|
864
|
+
}
|
865
|
+
END { <p [7, 12]> }
|
866
|
+
THERE
|
867
|
+
end
|
868
|
+
end
|
869
|
+
|
870
|
+
# only checking on 2.2 b/c its hard to figure out when different pieces were introduced
|
871
|
+
# we'll assume that if it passes on 2.2, it will pass on 2.0 or 2.1, if the feature is available on that Ruby
|
872
|
+
major, minor, * = RUBY_VERSION.split(".").map(&:to_i)
|
873
|
+
if major > 2 || (major == 2 && minor >= 2)
|
874
|
+
describe 'Ruby 2 syntaxes', :'2.x' => true do
|
875
|
+
it 'respects __dir__ macro' do
|
876
|
+
expect(wrap('__dir__')).to eq '<__dir__>'
|
877
|
+
end
|
878
|
+
|
879
|
+
it 'does not wrap keyword/keywordrest arguments' do
|
880
|
+
expect(wrap("def a(b,c=1,*d,e:,f:1,**g, &h)\n1\nend"))
|
881
|
+
.to eq "<def a(b,c=1,*d,e:,f:1,**g, &h)\n<1>\nend>"
|
882
|
+
expect(wrap("def a b:\n1\nend")).to eq "<def a b:\n<1>\nend>"
|
883
|
+
expect(wrap("def a b:\nreturn 1\nend")).to eq "<def a b:\nreturn <1>\nend>"
|
884
|
+
expect(wrap("def a b:\nreturn\nend")).to eq "<def a b:\nreturn\nend>"
|
885
|
+
expect(wrap("a b:1, **c")).to eq "<a b:1, **c>"
|
886
|
+
expect(wrap("{\na:1,\n**b\n}")).to eq "<{\na:<1>,\n**<b>\n}>"
|
887
|
+
expect(wrap("a(b:1,\n **c\n)")).to eq "<a(b:<1>,\n **<c>\n)>"
|
888
|
+
pending 'Fixed this in Parser, but it\'s not released yet https://github.com/whitequark/parser/commit/aeb95c776d11e212ed95b92c69e96d1cccdb6424'
|
889
|
+
expect(wrap("def a(*, **)\n1\nend")).to eq "<def a(*, **)\n<1>\nend>"
|
890
|
+
end
|
891
|
+
|
892
|
+
it 'tags javascript style hashes' do
|
893
|
+
expect(wrap(%[{\na:1,\n'b':2,\n"c":3\n}])).to eq %[<{\na:<1>,\n'b':<2>,\n"c":<3>\n}>]
|
894
|
+
expect(wrap(%[a b: 1,\n'c': 2,\n"d": 3,\n:e => 4])).to eq %[<a b: <1>,\n'c': <2>,\n"d": <3>,\n:e => 4>]
|
895
|
+
end
|
896
|
+
|
897
|
+
it 'wraps symbol literals' do
|
898
|
+
expect(wrap("%i[abc]")).to eq "<%i[abc]>"
|
899
|
+
expect(wrap("%I[abc]")).to eq "<%I[abc]>"
|
900
|
+
expect(wrap("%I[a\nb\nc]")).to eq "<%I[a\nb\nc]>"
|
901
|
+
end
|
902
|
+
|
903
|
+
it 'wraps complex and rational' do
|
904
|
+
expect(wrap("1i")).to eq "<1i>"
|
905
|
+
expect(wrap("5+1i")).to eq "<5+1i>"
|
906
|
+
expect(wrap("1r")).to eq "<1r>"
|
907
|
+
expect(wrap("1.5r")).to eq "<1.5r>"
|
908
|
+
expect(wrap("1/2r")).to eq "<1/2r>"
|
909
|
+
expect(wrap("2/1r")).to eq "<2/1r>"
|
910
|
+
expect(wrap("1ri")).to eq "<1ri>"
|
911
|
+
end
|
912
|
+
end
|
878
913
|
end
|
879
914
|
end
|