seeing_is_believing 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +3 -1
- data/Readme.md +28 -6
- data/bin/seeing_is_believing +2 -3
- data/features/binary.feature +89 -0
- data/features/step_definitions/steps.rb +2 -2
- data/features/support/env.rb +15 -2
- data/lib/seeing_is_believing/error.rb +7 -0
- data/lib/seeing_is_believing/evaluate_by_moving_files.rb +118 -0
- data/lib/seeing_is_believing/example_use.rb +64 -18
- data/lib/seeing_is_believing/expression_list.rb +35 -23
- data/lib/seeing_is_believing/hard_core_ensure.rb +52 -0
- data/lib/seeing_is_believing/has_exception.rb +6 -0
- data/lib/seeing_is_believing/result.rb +26 -20
- data/lib/seeing_is_believing/syntax_analyzer.rb +119 -37
- data/lib/seeing_is_believing/the_matrix.rb +19 -0
- data/lib/seeing_is_believing/tracks_line_numbers_seen.rb +18 -0
- data/lib/seeing_is_believing/version.rb +1 -1
- data/lib/seeing_is_believing.rb +54 -13
- data/seeing_is_believing.gemspec +1 -0
- data/spec/evaluate_by_moving_files_spec.rb +68 -0
- data/spec/expression_list_spec.rb +22 -4
- data/spec/hard_core_ensure_spec.rb +73 -0
- data/spec/seeing_is_believing_spec.rb +94 -11
- data/spec/syntax_analyzer_spec.rb +112 -1
- metadata +27 -6
@@ -14,6 +14,8 @@ describe SeeingIsBelieving do
|
|
14
14
|
StringIO.new string
|
15
15
|
end
|
16
16
|
|
17
|
+
let(:proving_grounds_dir) { File.expand_path '../../proving_grounds', __FILE__ }
|
18
|
+
|
17
19
|
it 'takes a string or stream and returns a result of the line numbers (counting from 1) and each inspected result from that line' do
|
18
20
|
input = "1+1\n'2'+'2'"
|
19
21
|
output = [[1, ["2"]], [2, ['"22"']]]
|
@@ -88,6 +90,12 @@ describe SeeingIsBelieving do
|
|
88
90
|
|
89
91
|
values_for("1 +
|
90
92
|
2").should == [[], ['3']]
|
93
|
+
|
94
|
+
values_for("'\n1\n'").should == [[], [], ['"\n1\n"']]
|
95
|
+
|
96
|
+
# fails b/c parens should go around line 1, not around entire expression -.^
|
97
|
+
# values_for("<<HEREDOC\n1\nHEREDOC").should == [[], [], ['"\n1\n"']]
|
98
|
+
# values_for("<<-HEREDOC\n1\nHEREDOC").should == [[], [], ['"\n1\n"']]
|
91
99
|
end
|
92
100
|
|
93
101
|
it 'does not record expressions that end in a comment' do
|
@@ -98,26 +106,101 @@ describe SeeingIsBelieving do
|
|
98
106
|
|
99
107
|
it 'has no output for empty lines' do
|
100
108
|
values_for('').should == [[]]
|
109
|
+
values_for(' ').should == [[]]
|
110
|
+
values_for(" \n").should == [[]]
|
101
111
|
values_for("1\n\n2").should == [['1'],[],['2']]
|
102
112
|
end
|
103
113
|
|
104
114
|
it 'stops executing on errors and reports them' do
|
105
|
-
|
106
|
-
result[0].should == ['12']
|
115
|
+
invoke("'no exception'").should_not have_exception
|
107
116
|
|
108
|
-
result
|
109
|
-
|
110
|
-
exception.
|
111
|
-
|
117
|
+
result = invoke("12\nraise Exception, 'omg!'\n12")
|
118
|
+
result.should have_exception
|
119
|
+
result.exception.message.should == 'omg!'
|
120
|
+
|
121
|
+
result[1].should == ['12']
|
112
122
|
|
113
123
|
result[2].should == []
|
114
|
-
result.
|
124
|
+
result[2].exception.should == result.exception
|
125
|
+
|
126
|
+
result[3].should == []
|
127
|
+
result.to_a.size.should == 3
|
128
|
+
|
129
|
+
pending 'Not sure how to force the backtrace to render' do
|
130
|
+
result.exception.backtrace.should be_a_kind_of Array
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
it 'does not fuck up __LINE__ macro' do
|
135
|
+
values_for('__LINE__
|
136
|
+
__LINE__
|
137
|
+
|
138
|
+
def meth
|
139
|
+
__LINE__
|
140
|
+
end
|
141
|
+
meth
|
142
|
+
|
143
|
+
# comment
|
144
|
+
__LINE__').should == [['1'], ['2'], [], [], ['5'], ['nil'], ['5'], [], [], ['10']]
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'does not try to record a return statement when that will break it' do
|
148
|
+
values_for("def meth \n return 1 \n end \n meth").should == [[], [], ['nil'], ['1']]
|
149
|
+
values_for("def meth \n return 1 if true \n end \n meth").should == [[], [], ['nil'], ['1']]
|
150
|
+
values_for("def meth \n return 1 if false \n end \n meth").should == [[], [], ['nil'], ['nil']]
|
151
|
+
values_for("-> { \n return 1 \n }.call" ).should == [[], [], ['1']]
|
152
|
+
pending "this doesn't work because the return detecting code is a very conservative regexp" do
|
153
|
+
values_for("-> { return 1 }.call" ).should == [['1']]
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'does not affect its environment' do
|
158
|
+
invoke 'def Object.abc() end'
|
159
|
+
Object.should_not respond_to :abc
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'captures the standard output and error' do
|
163
|
+
result = invoke "2.times { puts 'a', 'b' }
|
164
|
+
STDOUT.puts 'c'
|
165
|
+
$stdout.puts 'd'
|
166
|
+
STDERR.puts '1', '2'
|
167
|
+
$stderr.puts '3'
|
168
|
+
$stdout = $stderr
|
169
|
+
puts '4'"
|
170
|
+
result.stdout.should == "a\nb\n" "a\nb\n" "c\n" "d\n"
|
171
|
+
result.stderr.should == "1\n2\n" "3\n" "4\n"
|
172
|
+
result.should have_stdout
|
173
|
+
result.should have_stderr
|
174
|
+
|
175
|
+
result = invoke '1+1'
|
176
|
+
result.should_not have_stdout
|
177
|
+
result.should_not have_stderr
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'defaults the filename to temp_dir/program.rb' do
|
181
|
+
result = invoke('print File.expand_path __FILE__')
|
182
|
+
File.basename(result.stdout).should == 'program.rb'
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'can be told to run as a given file (in a given dir/with a given filename)' do
|
186
|
+
filename = File.join proving_grounds_dir, 'mah_file.rb'
|
187
|
+
FileUtils.rm_f filename
|
188
|
+
result = described_class.new('print File.expand_path __FILE__', filename: filename).call
|
189
|
+
result.stdout.should == filename
|
190
|
+
end
|
191
|
+
|
192
|
+
specify 'cwd is the directory of the file' do
|
193
|
+
filename = File.join proving_grounds_dir, 'mah_file.rb'
|
194
|
+
FileUtils.rm_f filename
|
195
|
+
result = described_class.new('print File.expand_path __FILE__', filename: filename).call
|
196
|
+
result = described_class.new('print File.expand_path(Dir.pwd)', filename: filename).call
|
197
|
+
result.stdout.should == proving_grounds_dir
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'does not capture output from __END__ onward' do
|
201
|
+
values_for("1+1\nDATA.read\n__END__\n....").should == [['2'], ['"...."']]
|
115
202
|
end
|
116
203
|
|
117
|
-
# it ignores lines that end in comments
|
118
|
-
# something about printing to stdout
|
119
|
-
# something about printing to stderr
|
120
204
|
# something about when the whole input is invalid
|
121
205
|
# something about multi-line strings
|
122
|
-
# does not fuck up __LINE__ macro
|
123
206
|
end
|
@@ -3,8 +3,13 @@ require 'seeing_is_believing'
|
|
3
3
|
describe SeeingIsBelieving::SyntaxAnalyzer do
|
4
4
|
it 'knows if syntax is valid' do
|
5
5
|
is_valid = lambda { |code| described_class.valid_ruby? code }
|
6
|
-
is_valid['+'].should be_false
|
7
6
|
is_valid['1+2'].should be_true
|
7
|
+
is_valid['+'].should be_false
|
8
|
+
|
9
|
+
# due to what are possibly bugs in Ripper
|
10
|
+
# these don't raise any errors, so have to check them explicitly
|
11
|
+
is_valid["'"].should be_false
|
12
|
+
is_valid["/"].should be_false
|
8
13
|
end
|
9
14
|
|
10
15
|
it 'knows if the last line is a comment' do
|
@@ -16,4 +21,110 @@ describe SeeingIsBelieving::SyntaxAnalyzer do
|
|
16
21
|
is_comment["a # whatev \n b"].should be_false
|
17
22
|
is_comment[""].should be_false
|
18
23
|
end
|
24
|
+
|
25
|
+
# probably don't really need this many tests, but I'm unfamiliar with how thorough Ripper is
|
26
|
+
# and already found areas where it doesn't behave correctly
|
27
|
+
it 'knows if the code contains an unclosed string' do
|
28
|
+
unclosed_string = lambda { |code| described_class.unclosed_string? code }
|
29
|
+
[%(a),
|
30
|
+
%("a"),
|
31
|
+
%("a \n"),
|
32
|
+
%("a \n a"),
|
33
|
+
%(a \n" a"),
|
34
|
+
%(a \n' a'),
|
35
|
+
%('a' "b"),
|
36
|
+
%('a"b'),
|
37
|
+
%("a'b"),
|
38
|
+
%("a\\""),
|
39
|
+
%(%()),
|
40
|
+
%(%<>),
|
41
|
+
%(%[]),
|
42
|
+
%(%{}),
|
43
|
+
%(%Q()),
|
44
|
+
%(%q()),
|
45
|
+
%("\#{""}"),
|
46
|
+
%("\#{''}"),
|
47
|
+
%("\#{%(\#{%[\#{%[]}]})}"),
|
48
|
+
%(%{}),
|
49
|
+
%(%<>),
|
50
|
+
%(%..),
|
51
|
+
].each do |string|
|
52
|
+
unclosed_string[string].should be_false, "Expected #{string.inspect} to be closed"
|
53
|
+
end
|
54
|
+
|
55
|
+
[%(a "),
|
56
|
+
%(a '),
|
57
|
+
%("a \n),
|
58
|
+
%(a \n 'a\n),
|
59
|
+
%("a"\n"b),
|
60
|
+
%("a" "b),
|
61
|
+
%("a" "b'),
|
62
|
+
%("a\\"),
|
63
|
+
%('a\\'),
|
64
|
+
%(%\(),
|
65
|
+
%(%<),
|
66
|
+
%(%[),
|
67
|
+
%(%{),
|
68
|
+
%(%Q[),
|
69
|
+
%(%q[),
|
70
|
+
%(%Q(\#{)),
|
71
|
+
%("\#{),
|
72
|
+
%("\#{'}"),
|
73
|
+
%("\#{"}"),
|
74
|
+
%("\#{%(\#{%[\#{%[}]})}"),
|
75
|
+
].each do |string|
|
76
|
+
unclosed_string[string].should be_true, "Expected #{string.inspect} to be unclosed"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'knows if the code contains an unclosed regexp' do
|
81
|
+
unclosed_regexp = lambda { |code| described_class.unclosed_regexp? code }
|
82
|
+
[%(a),
|
83
|
+
%(/a/),
|
84
|
+
%(/a \n/),
|
85
|
+
%(/a \n a/),
|
86
|
+
%(a \n/ a/),
|
87
|
+
%(/a\\//),
|
88
|
+
%(/\#{//}/),
|
89
|
+
%(%r()),
|
90
|
+
%(%r{}),
|
91
|
+
%(%r<>),
|
92
|
+
%(%r..),
|
93
|
+
].each do |code|
|
94
|
+
unclosed_regexp[code].should be_false, "Expected #{code.inspect} to be closed"
|
95
|
+
end
|
96
|
+
|
97
|
+
[%(a + /),
|
98
|
+
%(/a \n),
|
99
|
+
%(a \n /a\n),
|
100
|
+
%(/a/\n/b),
|
101
|
+
%(/a\\/),
|
102
|
+
%(%r\(),
|
103
|
+
%(%r<),
|
104
|
+
%(%r[),
|
105
|
+
%(%r{),
|
106
|
+
%(%r(\#{)),
|
107
|
+
%(%r[\#{),
|
108
|
+
%("\#{%r[}"),
|
109
|
+
].each do |code|
|
110
|
+
unclosed_regexp[code].should be_true, "Expected #{code.inspect} to be unclosed"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# the commented out ones will require actual parsing to solve
|
115
|
+
it "knows if the code contains a return (can't capture a void value)" do
|
116
|
+
will_return = -> code { described_class.will_return? code }
|
117
|
+
will_return["return 1"].should be_true
|
118
|
+
will_return["return 1\n"].should be_true
|
119
|
+
will_return["return 1 if true"].should be_true
|
120
|
+
will_return["return 1 if false"].should be_true
|
121
|
+
will_return["o.return"].should be_false
|
122
|
+
will_return[":return"].should be_false
|
123
|
+
will_return["'return'"].should be_false
|
124
|
+
# will_return["'return\nreturn\nreturn'"].should be_false
|
125
|
+
will_return["def a\nreturn 1\nend"].should be_false
|
126
|
+
will_return["-> {\nreturn 1\n}"].should be_false
|
127
|
+
will_return["Proc.new {\nreturn 1\n}"].should be_false
|
128
|
+
# will_return["return \\\n1"].should be_true
|
129
|
+
end
|
19
130
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: seeing_is_believing
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-01-
|
12
|
+
date: 2013-01-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement: &
|
16
|
+
requirement: &70133565808080 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 2.12.0
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70133565808080
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: cucumber
|
27
|
-
requirement: &
|
27
|
+
requirement: &70133565807280 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,7 +32,18 @@ dependencies:
|
|
32
32
|
version: 1.2.1
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70133565807280
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: ichannel
|
38
|
+
requirement: &70133565806600 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 5.1.1
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70133565806600
|
36
47
|
description: Records the results of every line of code in your file (intended to be
|
37
48
|
like xmpfilter), inspired by Bret Victor's JavaScript example in his talk "Inventing
|
38
49
|
on Principle"
|
@@ -52,13 +63,21 @@ files:
|
|
52
63
|
- features/step_definitions/steps.rb
|
53
64
|
- features/support/env.rb
|
54
65
|
- lib/seeing_is_believing.rb
|
66
|
+
- lib/seeing_is_believing/error.rb
|
67
|
+
- lib/seeing_is_believing/evaluate_by_moving_files.rb
|
55
68
|
- lib/seeing_is_believing/example_use.rb
|
56
69
|
- lib/seeing_is_believing/expression_list.rb
|
70
|
+
- lib/seeing_is_believing/hard_core_ensure.rb
|
71
|
+
- lib/seeing_is_believing/has_exception.rb
|
57
72
|
- lib/seeing_is_believing/result.rb
|
58
73
|
- lib/seeing_is_believing/syntax_analyzer.rb
|
74
|
+
- lib/seeing_is_believing/the_matrix.rb
|
75
|
+
- lib/seeing_is_believing/tracks_line_numbers_seen.rb
|
59
76
|
- lib/seeing_is_believing/version.rb
|
60
77
|
- seeing_is_believing.gemspec
|
78
|
+
- spec/evaluate_by_moving_files_spec.rb
|
61
79
|
- spec/expression_list_spec.rb
|
80
|
+
- spec/hard_core_ensure_spec.rb
|
62
81
|
- spec/seeing_is_believing_spec.rb
|
63
82
|
- spec/syntax_analyzer_spec.rb
|
64
83
|
homepage: https://github.com/JoshCheek/seeing_is_believing
|
@@ -89,6 +108,8 @@ test_files:
|
|
89
108
|
- features/binary.feature
|
90
109
|
- features/step_definitions/steps.rb
|
91
110
|
- features/support/env.rb
|
111
|
+
- spec/evaluate_by_moving_files_spec.rb
|
92
112
|
- spec/expression_list_spec.rb
|
113
|
+
- spec/hard_core_ensure_spec.rb
|
93
114
|
- spec/seeing_is_believing_spec.rb
|
94
115
|
- spec/syntax_analyzer_spec.rb
|