seeing_is_believing 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|