ripper_ruby_parser 1.6.1 → 1.7.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +4 -23
- data/Rakefile +12 -12
- data/lib/ripper_ruby_parser.rb +2 -2
- data/lib/ripper_ruby_parser/commenting_ripper_parser.rb +9 -9
- data/lib/ripper_ruby_parser/parser.rb +3 -3
- data/lib/ripper_ruby_parser/sexp_handlers.rb +9 -9
- data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +3 -9
- data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +19 -24
- data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +14 -18
- data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +3 -3
- data/lib/ripper_ruby_parser/sexp_processor.rb +4 -4
- data/lib/ripper_ruby_parser/unescape.rb +11 -11
- data/lib/ripper_ruby_parser/version.rb +1 -1
- data/test/end_to_end/comments_test.rb +10 -10
- data/test/end_to_end/comparison_test.rb +28 -28
- data/test/end_to_end/lib_comparison_test.rb +6 -6
- data/test/end_to_end/line_numbering_test.rb +10 -10
- data/test/end_to_end/samples_comparison_test.rb +5 -5
- data/test/end_to_end/test_comparison_test.rb +6 -6
- data/test/pt_testcase/pt_test.rb +7 -7
- data/test/ripper_ruby_parser/commenting_ripper_parser_test.rb +163 -169
- data/test/ripper_ruby_parser/parser_test.rb +338 -338
- data/test/ripper_ruby_parser/sexp_handlers/assignment_test.rb +475 -511
- data/test/ripper_ruby_parser/sexp_handlers/blocks_test.rb +582 -564
- data/test/ripper_ruby_parser/sexp_handlers/conditionals_test.rb +469 -469
- data/test/ripper_ruby_parser/sexp_handlers/literals_test.rb +713 -724
- data/test/ripper_ruby_parser/sexp_handlers/loops_test.rb +155 -155
- data/test/ripper_ruby_parser/sexp_handlers/method_calls_test.rb +181 -181
- data/test/ripper_ruby_parser/sexp_handlers/methods_test.rb +337 -352
- data/test/ripper_ruby_parser/sexp_handlers/operators_test.rb +298 -298
- data/test/ripper_ruby_parser/sexp_processor_test.rb +119 -119
- data/test/ripper_ruby_parser/version_test.rb +2 -2
- data/test/samples/lambdas.rb +5 -0
- data/test/samples/misc.rb +3 -0
- data/test/samples/strings.rb +7 -0
- data/test/test_helper.rb +8 -6
- metadata +12 -10
@@ -1,306 +1,306 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require File.expand_path(
|
3
|
+
require File.expand_path("../test_helper.rb", File.dirname(__FILE__))
|
4
4
|
|
5
5
|
describe RipperRubyParser::Parser do
|
6
6
|
let(:parser) { RipperRubyParser::Parser.new }
|
7
|
-
describe
|
8
|
-
it
|
9
|
-
result = parser.parse
|
10
|
-
result.must_be_instance_of Sexp
|
7
|
+
describe "#parse" do
|
8
|
+
it "returns an s-expression" do
|
9
|
+
result = parser.parse "foo"
|
10
|
+
_(result).must_be_instance_of Sexp
|
11
11
|
end
|
12
12
|
|
13
|
-
describe
|
14
|
-
it
|
15
|
-
|
13
|
+
describe "for an empty program" do
|
14
|
+
it "returns nil" do
|
15
|
+
_("").must_be_parsed_as nil
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
describe
|
20
|
-
it
|
21
|
-
|
22
|
-
must_be_parsed_as s(:class,
|
23
|
-
|
24
|
-
|
19
|
+
describe "for a class declaration" do
|
20
|
+
it "works with a namespaced class name" do
|
21
|
+
_("class Foo::Bar; end")
|
22
|
+
.must_be_parsed_as s(:class,
|
23
|
+
s(:colon2, s(:const, :Foo), :Bar),
|
24
|
+
nil)
|
25
25
|
end
|
26
26
|
|
27
|
-
it
|
28
|
-
|
27
|
+
it "works for singleton classes" do
|
28
|
+
_("class << self; end").must_be_parsed_as s(:sclass, s(:self))
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
describe
|
33
|
-
it
|
34
|
-
|
35
|
-
must_be_parsed_as s(:module, :Foo)
|
32
|
+
describe "for a module declaration" do
|
33
|
+
it "works with a simple module name" do
|
34
|
+
_("module Foo; end")
|
35
|
+
.must_be_parsed_as s(:module, :Foo)
|
36
36
|
end
|
37
37
|
|
38
|
-
it
|
39
|
-
|
40
|
-
must_be_parsed_as s(:module,
|
41
|
-
|
38
|
+
it "works with a namespaced module name" do
|
39
|
+
_("module Foo::Bar; end")
|
40
|
+
.must_be_parsed_as s(:module,
|
41
|
+
s(:colon2, s(:const, :Foo), :Bar))
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
-
describe
|
46
|
-
it
|
47
|
-
|
45
|
+
describe "for empty parentheses" do
|
46
|
+
it "works with lone ()" do
|
47
|
+
_("()").must_be_parsed_as s(:nil)
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
describe
|
52
|
-
it
|
53
|
-
|
54
|
-
must_be_parsed_as s(:nil)
|
51
|
+
describe "for a begin..end block" do
|
52
|
+
it "works with no statements" do
|
53
|
+
_("begin; end")
|
54
|
+
.must_be_parsed_as s(:nil)
|
55
55
|
end
|
56
56
|
|
57
|
-
it
|
58
|
-
|
59
|
-
must_be_parsed_as s(:call, nil, :foo)
|
57
|
+
it "works with one statement" do
|
58
|
+
_("begin; foo; end")
|
59
|
+
.must_be_parsed_as s(:call, nil, :foo)
|
60
60
|
end
|
61
61
|
|
62
|
-
it
|
63
|
-
|
64
|
-
must_be_parsed_as s(:block,
|
65
|
-
|
66
|
-
|
62
|
+
it "works with multiple statements" do
|
63
|
+
_("begin; foo; bar; end")
|
64
|
+
.must_be_parsed_as s(:block,
|
65
|
+
s(:call, nil, :foo),
|
66
|
+
s(:call, nil, :bar))
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
-
describe
|
71
|
-
it
|
72
|
-
|
73
|
-
must_be_parsed_as s(:call,
|
74
|
-
|
75
|
-
|
76
|
-
|
70
|
+
describe "for arguments" do
|
71
|
+
it "works for a simple case with splat" do
|
72
|
+
_("foo *bar")
|
73
|
+
.must_be_parsed_as s(:call,
|
74
|
+
nil,
|
75
|
+
:foo,
|
76
|
+
s(:splat, s(:call, nil, :bar)))
|
77
77
|
end
|
78
78
|
|
79
|
-
it
|
80
|
-
|
81
|
-
must_be_parsed_as s(:call,
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
79
|
+
it "works for a multi-argument case with splat" do
|
80
|
+
_("foo bar, *baz")
|
81
|
+
.must_be_parsed_as s(:call,
|
82
|
+
nil,
|
83
|
+
:foo,
|
84
|
+
s(:call, nil, :bar),
|
85
|
+
s(:splat, s(:call, nil, :baz)))
|
86
86
|
end
|
87
87
|
|
88
|
-
it
|
89
|
-
|
90
|
-
must_be_parsed_as s(:call, nil, :foo,
|
91
|
-
|
92
|
-
|
88
|
+
it "works for a simple case passing a block" do
|
89
|
+
_("foo &bar")
|
90
|
+
.must_be_parsed_as s(:call, nil, :foo,
|
91
|
+
s(:block_pass,
|
92
|
+
s(:call, nil, :bar)))
|
93
93
|
end
|
94
94
|
|
95
|
-
it
|
96
|
-
|
97
|
-
must_be_parsed_as s(:call, nil, :foo,
|
98
|
-
|
99
|
-
|
100
|
-
|
95
|
+
it "works for a bare hash" do
|
96
|
+
_("foo bar => baz")
|
97
|
+
.must_be_parsed_as s(:call, nil, :foo,
|
98
|
+
s(:hash,
|
99
|
+
s(:call, nil, :bar),
|
100
|
+
s(:call, nil, :baz)))
|
101
101
|
end
|
102
102
|
end
|
103
103
|
|
104
|
-
describe
|
105
|
-
it
|
106
|
-
|
107
|
-
must_be_parsed_as s(:colon2, s(:const, :Encoding), :UTF_8)
|
104
|
+
describe "for the __ENCODING__ keyword" do
|
105
|
+
it "evaluates to the equivalent of Encoding::UTF_8" do
|
106
|
+
_("__ENCODING__")
|
107
|
+
.must_be_parsed_as s(:colon2, s(:const, :Encoding), :UTF_8)
|
108
108
|
end
|
109
109
|
end
|
110
110
|
|
111
|
-
describe
|
112
|
-
describe
|
111
|
+
describe "for the __FILE__ keyword" do
|
112
|
+
describe "when not passing a file name" do
|
113
113
|
it "creates a string sexp with value '(string)'" do
|
114
|
-
|
115
|
-
must_be_parsed_as s(:str,
|
114
|
+
_("__FILE__")
|
115
|
+
.must_be_parsed_as s(:str, "(string)")
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
119
|
-
describe
|
120
|
-
it
|
121
|
-
result = parser.parse
|
122
|
-
result.must_equal s(:str,
|
119
|
+
describe "when passing a file name" do
|
120
|
+
it "creates a string sexp with the file name" do
|
121
|
+
result = parser.parse "__FILE__", "foo"
|
122
|
+
_(result).must_equal s(:str, "foo")
|
123
123
|
end
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
127
|
-
describe
|
128
|
-
it
|
129
|
-
|
130
|
-
must_be_parsed_as s(:lit, 1)
|
131
|
-
"\n__LINE__"
|
132
|
-
must_be_parsed_as s(:lit, 2)
|
127
|
+
describe "for the __LINE__ keyword" do
|
128
|
+
it "creates a literal sexp with value of the line number" do
|
129
|
+
_("__LINE__")
|
130
|
+
.must_be_parsed_as s(:lit, 1)
|
131
|
+
_("\n__LINE__")
|
132
|
+
.must_be_parsed_as s(:lit, 2)
|
133
133
|
end
|
134
134
|
end
|
135
135
|
|
136
|
-
describe
|
137
|
-
it
|
138
|
-
|
139
|
-
must_be_parsed_as s(:iter, s(:postexe), 0, s(:call, nil, :foo))
|
136
|
+
describe "for the END keyword" do
|
137
|
+
it "converts to a :postexe iterator" do
|
138
|
+
_("END { foo }")
|
139
|
+
.must_be_parsed_as s(:iter, s(:postexe), 0, s(:call, nil, :foo))
|
140
140
|
end
|
141
141
|
|
142
|
-
it
|
143
|
-
|
144
|
-
must_be_parsed_as s(:iter, s(:postexe), 0)
|
142
|
+
it "works with an empty block" do
|
143
|
+
_("END { }")
|
144
|
+
.must_be_parsed_as s(:iter, s(:postexe), 0)
|
145
145
|
end
|
146
146
|
|
147
|
-
it
|
148
|
-
"END {\nfoo\n}"
|
149
|
-
must_be_parsed_as s(:iter,
|
150
|
-
|
151
|
-
|
152
|
-
|
147
|
+
it "assigns correct line numbers" do
|
148
|
+
_("END {\nfoo\n}")
|
149
|
+
.must_be_parsed_as s(:iter,
|
150
|
+
s(:postexe).line(1), 0,
|
151
|
+
s(:call, nil, :foo).line(2)).line(1),
|
152
|
+
with_line_numbers: true
|
153
153
|
end
|
154
154
|
|
155
|
-
it
|
156
|
-
"END {\nbegin\nfoo\nend\n}"
|
157
|
-
must_be_parsed_as s(:iter,
|
158
|
-
|
159
|
-
|
160
|
-
|
155
|
+
it "assigns correct line numbers to a embedded begin block" do
|
156
|
+
_("END {\nbegin\nfoo\nend\n}")
|
157
|
+
.must_be_parsed_as s(:iter,
|
158
|
+
s(:postexe).line(1), 0,
|
159
|
+
s(:call, nil, :foo).line(3)).line(1),
|
160
|
+
with_line_numbers: true
|
161
161
|
end
|
162
162
|
end
|
163
163
|
|
164
|
-
describe
|
165
|
-
it
|
166
|
-
|
167
|
-
must_be_parsed_as s(:iter, s(:preexe), 0, s(:call, nil, :foo))
|
164
|
+
describe "for the BEGIN keyword" do
|
165
|
+
it "converts to a :preexe iterator" do
|
166
|
+
_("BEGIN { foo }")
|
167
|
+
.must_be_parsed_as s(:iter, s(:preexe), 0, s(:call, nil, :foo))
|
168
168
|
end
|
169
169
|
|
170
|
-
it
|
171
|
-
|
172
|
-
must_be_parsed_as s(:iter, s(:preexe), 0)
|
170
|
+
it "works with an empty block" do
|
171
|
+
_("BEGIN { }")
|
172
|
+
.must_be_parsed_as s(:iter, s(:preexe), 0)
|
173
173
|
end
|
174
174
|
|
175
|
-
it
|
176
|
-
"BEGIN {\nfoo\n}"
|
177
|
-
must_be_parsed_as s(:iter,
|
178
|
-
|
179
|
-
|
180
|
-
|
175
|
+
it "assigns correct line numbers" do
|
176
|
+
_("BEGIN {\nfoo\n}")
|
177
|
+
.must_be_parsed_as s(:iter,
|
178
|
+
s(:preexe).line(1), 0,
|
179
|
+
s(:call, nil, :foo).line(2)).line(1),
|
180
|
+
with_line_numbers: true
|
181
181
|
end
|
182
182
|
|
183
|
-
it
|
184
|
-
"BEGIN {\nbegin\nfoo\nend\n}"
|
185
|
-
must_be_parsed_as s(:iter,
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
183
|
+
it "assigns correct line numbers to a embedded begin block" do
|
184
|
+
_("BEGIN {\nbegin\nfoo\nend\n}")
|
185
|
+
.must_be_parsed_as s(:iter,
|
186
|
+
s(:preexe).line(1), 0,
|
187
|
+
s(:begin,
|
188
|
+
s(:call, nil, :foo).line(3)).line(2)).line(1),
|
189
|
+
with_line_numbers: true
|
190
190
|
end
|
191
191
|
end
|
192
192
|
|
193
|
-
describe
|
194
|
-
it
|
195
|
-
|
196
|
-
must_be_parsed_as s(:colon3, :Foo)
|
193
|
+
describe "for constant lookups" do
|
194
|
+
it "works when explicitely starting from the root namespace" do
|
195
|
+
_("::Foo")
|
196
|
+
.must_be_parsed_as s(:colon3, :Foo)
|
197
197
|
end
|
198
198
|
|
199
|
-
it
|
200
|
-
|
201
|
-
must_be_parsed_as s(:colon2,
|
202
|
-
|
203
|
-
|
199
|
+
it "works with a three-level constant lookup" do
|
200
|
+
_("Foo::Bar::Baz")
|
201
|
+
.must_be_parsed_as s(:colon2,
|
202
|
+
s(:colon2, s(:const, :Foo), :Bar),
|
203
|
+
:Baz)
|
204
204
|
end
|
205
205
|
|
206
|
-
it
|
207
|
-
|
208
|
-
|
209
|
-
|
206
|
+
it "works looking up a constant in a non-constant" do
|
207
|
+
_("foo::Bar").must_be_parsed_as s(:colon2,
|
208
|
+
s(:call, nil, :foo),
|
209
|
+
:Bar)
|
210
210
|
end
|
211
211
|
end
|
212
212
|
|
213
|
-
describe
|
214
|
-
it
|
215
|
-
|
216
|
-
must_be_parsed_as s(:self)
|
213
|
+
describe "for variable references" do
|
214
|
+
it "works for self" do
|
215
|
+
_("self")
|
216
|
+
.must_be_parsed_as s(:self)
|
217
217
|
end
|
218
218
|
|
219
|
-
it
|
220
|
-
|
221
|
-
must_be_parsed_as s(:ivar, :@foo)
|
219
|
+
it "works for instance variables" do
|
220
|
+
_("@foo")
|
221
|
+
.must_be_parsed_as s(:ivar, :@foo)
|
222
222
|
end
|
223
223
|
|
224
|
-
it
|
225
|
-
|
226
|
-
must_be_parsed_as s(:gvar, :$foo)
|
224
|
+
it "works for global variables" do
|
225
|
+
_("$foo")
|
226
|
+
.must_be_parsed_as s(:gvar, :$foo)
|
227
227
|
end
|
228
228
|
|
229
|
-
it
|
230
|
-
|
231
|
-
must_be_parsed_as s(:nth_ref, 1)
|
229
|
+
it "works for regexp match references" do
|
230
|
+
_("$1")
|
231
|
+
.must_be_parsed_as s(:nth_ref, 1)
|
232
232
|
end
|
233
233
|
|
234
|
-
specify { "$'".must_be_parsed_as s(:back_ref, :"'") }
|
235
|
-
specify {
|
234
|
+
specify { _("$'").must_be_parsed_as s(:back_ref, :"'") }
|
235
|
+
specify { _("$&").must_be_parsed_as s(:back_ref, :"&") }
|
236
236
|
|
237
|
-
it
|
238
|
-
|
239
|
-
must_be_parsed_as s(:cvar, :@@foo)
|
237
|
+
it "works for class variables" do
|
238
|
+
_("@@foo")
|
239
|
+
.must_be_parsed_as s(:cvar, :@@foo)
|
240
240
|
end
|
241
241
|
end
|
242
242
|
|
243
|
-
describe
|
244
|
-
it
|
245
|
-
|
246
|
-
must_be_parsed_as s(:call,
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
243
|
+
describe "for expressions" do
|
244
|
+
it "handles assignment inside binary operator expressions" do
|
245
|
+
_("foo + (bar = baz)")
|
246
|
+
.must_be_parsed_as s(:call,
|
247
|
+
s(:call, nil, :foo),
|
248
|
+
:+,
|
249
|
+
s(:lasgn,
|
250
|
+
:bar,
|
251
|
+
s(:call, nil, :baz)))
|
252
252
|
end
|
253
253
|
|
254
|
-
it
|
255
|
-
|
256
|
-
must_be_parsed_as s(:call,
|
257
|
-
|
258
|
-
|
254
|
+
it "handles assignment inside unary operator expressions" do
|
255
|
+
_("+(foo = bar)")
|
256
|
+
.must_be_parsed_as s(:call,
|
257
|
+
s(:lasgn, :foo, s(:call, nil, :bar)),
|
258
|
+
:+@)
|
259
259
|
end
|
260
260
|
end
|
261
261
|
|
262
262
|
# Note: differences in the handling of comments are not caught by Sexp's
|
263
263
|
# implementation of equality.
|
264
|
-
describe
|
265
|
-
it
|
264
|
+
describe "for comments" do
|
265
|
+
it "handles method comments" do
|
266
266
|
result = parser.parse "# Foo\ndef foo; end"
|
267
|
-
result.must_equal s(:defn,
|
268
|
-
|
269
|
-
|
270
|
-
result.comments.must_equal "# Foo\n"
|
267
|
+
_(result).must_equal s(:defn,
|
268
|
+
:foo,
|
269
|
+
s(:args), s(:nil))
|
270
|
+
_(result.comments).must_equal "# Foo\n"
|
271
271
|
end
|
272
272
|
|
273
|
-
it
|
273
|
+
it "handles comments for methods with explicit receiver" do
|
274
274
|
result = parser.parse "# Foo\ndef foo.bar; end"
|
275
|
-
result.must_equal s(:defs,
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
result.comments.must_equal "# Foo\n"
|
275
|
+
_(result).must_equal s(:defs,
|
276
|
+
s(:call, nil, :foo),
|
277
|
+
:bar,
|
278
|
+
s(:args),
|
279
|
+
s(:nil))
|
280
|
+
_(result.comments).must_equal "# Foo\n"
|
281
281
|
end
|
282
282
|
|
283
|
-
it
|
283
|
+
it "matches comments to the correct entity" do
|
284
284
|
result = parser.parse "# Foo\nclass Foo\n# Bar\ndef bar\nend\nend"
|
285
|
-
result.must_equal s(:class, :Foo, nil,
|
286
|
-
|
287
|
-
|
288
|
-
result.comments.must_equal "# Foo\n"
|
285
|
+
_(result).must_equal s(:class, :Foo, nil,
|
286
|
+
s(:defn, :bar,
|
287
|
+
s(:args), s(:nil)))
|
288
|
+
_(result.comments).must_equal "# Foo\n"
|
289
289
|
defn = result[3]
|
290
|
-
defn.sexp_type.must_equal :defn
|
291
|
-
defn.comments.must_equal "# Bar\n"
|
290
|
+
_(defn.sexp_type).must_equal :defn
|
291
|
+
_(defn.comments).must_equal "# Bar\n"
|
292
292
|
end
|
293
293
|
|
294
|
-
it
|
294
|
+
it "combines multi-line comments" do
|
295
295
|
result = parser.parse "# Foo\n# Bar\ndef foo; end"
|
296
|
-
result.must_equal s(:defn,
|
297
|
-
|
298
|
-
|
299
|
-
result.comments.must_equal "# Foo\n# Bar\n"
|
296
|
+
_(result).must_equal s(:defn,
|
297
|
+
:foo,
|
298
|
+
s(:args), s(:nil))
|
299
|
+
_(result.comments).must_equal "# Foo\n# Bar\n"
|
300
300
|
end
|
301
301
|
|
302
|
-
it
|
303
|
-
result = parser.parse <<-
|
302
|
+
it "drops comments inside method bodies" do
|
303
|
+
result = parser.parse <<-RUBY
|
304
304
|
# Foo
|
305
305
|
class Foo
|
306
306
|
# foo
|
@@ -313,241 +313,241 @@ describe RipperRubyParser::Parser do
|
|
313
313
|
baz
|
314
314
|
end
|
315
315
|
end
|
316
|
-
|
317
|
-
result.must_equal s(:class,
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
result.comments.must_equal "# Foo\n"
|
323
|
-
result[3].comments.must_equal "# foo\n"
|
324
|
-
result[4].comments.must_equal "# bar\n"
|
325
|
-
end
|
326
|
-
|
327
|
-
it
|
316
|
+
RUBY
|
317
|
+
_(result).must_equal s(:class,
|
318
|
+
:Foo,
|
319
|
+
nil,
|
320
|
+
s(:defn, :foo, s(:args), s(:call, nil, :bar)),
|
321
|
+
s(:defn, :bar, s(:args), s(:call, nil, :baz)))
|
322
|
+
_(result.comments).must_equal "# Foo\n"
|
323
|
+
_(result[3].comments).must_equal "# foo\n"
|
324
|
+
_(result[4].comments).must_equal "# bar\n"
|
325
|
+
end
|
326
|
+
|
327
|
+
it "handles use of singleton class inside methods" do
|
328
328
|
result = parser.parse "# Foo\ndef bar\nclass << self\nbaz\nend\nend"
|
329
|
-
result.must_equal s(:defn,
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
result.comments.must_equal "# Foo\n"
|
329
|
+
_(result).must_equal s(:defn,
|
330
|
+
:bar,
|
331
|
+
s(:args),
|
332
|
+
s(:sclass, s(:self),
|
333
|
+
s(:call, nil, :baz)))
|
334
|
+
_(result.comments).must_equal "# Foo\n"
|
335
335
|
end
|
336
336
|
|
337
337
|
# TODO: Prefer assigning comment to the BEGIN instead
|
338
|
-
it
|
338
|
+
it "assigns comments on BEGIN blocks to the following item" do
|
339
339
|
result = parser.parse "# Bar\nBEGIN { }\n# Foo\nclass Bar\n# foo\ndef foo; end\nend"
|
340
|
-
result.must_equal s(:block,
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
result[2].comments.must_equal "# Bar\n# Foo\n"
|
345
|
-
result[2][3].comments.must_equal "# foo\n"
|
340
|
+
_(result).must_equal s(:block,
|
341
|
+
s(:iter, s(:preexe), 0),
|
342
|
+
s(:class, :Bar, nil,
|
343
|
+
s(:defn, :foo, s(:args), s(:nil))))
|
344
|
+
_(result[2].comments).must_equal "# Bar\n# Foo\n"
|
345
|
+
_(result[2][3].comments).must_equal "# foo\n"
|
346
346
|
end
|
347
347
|
|
348
|
-
it
|
348
|
+
it "assigns comments on multiple BEGIN blocks to the following item" do
|
349
349
|
result = parser.parse "# Bar\nBEGIN { }\n# Baz\nBEGIN { }\n# Foo\ndef foo; end"
|
350
|
-
result.must_equal s(:block,
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
result[3].comments.must_equal "# Bar\n# Baz\n# Foo\n"
|
350
|
+
_(result).must_equal s(:block,
|
351
|
+
s(:iter, s(:preexe), 0),
|
352
|
+
s(:iter, s(:preexe), 0),
|
353
|
+
s(:defn, :foo, s(:args), s(:nil)))
|
354
|
+
_(result[3].comments).must_equal "# Bar\n# Baz\n# Foo\n"
|
355
355
|
end
|
356
356
|
|
357
|
-
it
|
357
|
+
it "assigns comments on BEGIN blocks to the first following item" do
|
358
358
|
result = parser.parse "# Bar\nBEGIN { }\n# Baz\nBEGIN { }\n# Foo\ndef foo; end"
|
359
|
-
result.must_equal s(:block,
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
result[3].comments.must_equal "# Bar\n# Baz\n# Foo\n"
|
359
|
+
_(result).must_equal s(:block,
|
360
|
+
s(:iter, s(:preexe), 0),
|
361
|
+
s(:iter, s(:preexe), 0),
|
362
|
+
s(:defn, :foo, s(:args), s(:nil)))
|
363
|
+
_(result[3].comments).must_equal "# Bar\n# Baz\n# Foo\n"
|
364
364
|
end
|
365
365
|
end
|
366
366
|
|
367
367
|
# Note: differences in the handling of line numbers are not caught by
|
368
368
|
# Sexp's implementation of equality.
|
369
|
-
describe
|
370
|
-
it
|
371
|
-
result = parser.parse
|
372
|
-
result.line.must_equal 1
|
369
|
+
describe "assigning line numbers" do
|
370
|
+
it "works for a plain method call" do
|
371
|
+
result = parser.parse "foo"
|
372
|
+
_(result.line).must_equal 1
|
373
373
|
end
|
374
374
|
|
375
|
-
it
|
376
|
-
result = parser.parse
|
377
|
-
result.line.must_equal 1
|
375
|
+
it "works for a method call with parentheses" do
|
376
|
+
result = parser.parse "foo()"
|
377
|
+
_(result.line).must_equal 1
|
378
378
|
end
|
379
379
|
|
380
|
-
it
|
381
|
-
result = parser.parse
|
382
|
-
result.line.must_equal 1
|
380
|
+
it "works for a method call with receiver" do
|
381
|
+
result = parser.parse "foo.bar"
|
382
|
+
_(result.line).must_equal 1
|
383
383
|
end
|
384
384
|
|
385
|
-
it
|
386
|
-
result = parser.parse
|
387
|
-
result.line.must_equal 1
|
385
|
+
it "works for a method call with receiver and arguments" do
|
386
|
+
result = parser.parse "foo.bar baz"
|
387
|
+
_(result.line).must_equal 1
|
388
388
|
end
|
389
389
|
|
390
|
-
it
|
391
|
-
result = parser.parse
|
392
|
-
result.line.must_equal 1
|
390
|
+
it "works for a method call with arguments" do
|
391
|
+
result = parser.parse "foo bar"
|
392
|
+
_(result.line).must_equal 1
|
393
393
|
end
|
394
394
|
|
395
|
-
it
|
395
|
+
it "works for a block with two lines" do
|
396
396
|
result = parser.parse "foo\nbar\n"
|
397
|
-
result.sexp_type.must_equal :block
|
398
|
-
result[1].line.must_equal 1
|
399
|
-
result[2].line.must_equal 2
|
400
|
-
result.line.must_equal 1
|
397
|
+
_(result.sexp_type).must_equal :block
|
398
|
+
_(result[1].line).must_equal 1
|
399
|
+
_(result[2].line).must_equal 2
|
400
|
+
_(result.line).must_equal 1
|
401
401
|
end
|
402
402
|
|
403
|
-
it
|
404
|
-
result = parser.parse
|
405
|
-
result.line.must_equal 1
|
403
|
+
it "works for a constant reference" do
|
404
|
+
result = parser.parse "Foo"
|
405
|
+
_(result.line).must_equal 1
|
406
406
|
end
|
407
407
|
|
408
|
-
it
|
409
|
-
result = parser.parse
|
410
|
-
result.line.must_equal 1
|
408
|
+
it "works for an instance variable" do
|
409
|
+
result = parser.parse "@foo"
|
410
|
+
_(result.line).must_equal 1
|
411
411
|
end
|
412
412
|
|
413
|
-
it
|
414
|
-
result = parser.parse
|
415
|
-
result.line.must_equal 1
|
413
|
+
it "works for a global variable" do
|
414
|
+
result = parser.parse "$foo"
|
415
|
+
_(result.line).must_equal 1
|
416
416
|
end
|
417
417
|
|
418
|
-
it
|
419
|
-
result = parser.parse
|
420
|
-
result.line.must_equal 1
|
418
|
+
it "works for a class variable" do
|
419
|
+
result = parser.parse "@@foo"
|
420
|
+
_(result.line).must_equal 1
|
421
421
|
end
|
422
422
|
|
423
|
-
it
|
424
|
-
"foo = bar\nfoo\n"
|
425
|
-
must_be_parsed_as s(:block,
|
426
|
-
|
427
|
-
|
428
|
-
|
423
|
+
it "works for a local variable" do
|
424
|
+
_("foo = bar\nfoo\n")
|
425
|
+
.must_be_parsed_as s(:block,
|
426
|
+
s(:lasgn, :foo, s(:call, nil, :bar).line(1)).line(1),
|
427
|
+
s(:lvar, :foo).line(2)).line(1),
|
428
|
+
with_line_numbers: true
|
429
429
|
end
|
430
430
|
|
431
|
-
it
|
432
|
-
result = parser.parse
|
433
|
-
result.line.must_equal 1
|
431
|
+
it "works for an integer literal" do
|
432
|
+
result = parser.parse "42"
|
433
|
+
_(result.line).must_equal 1
|
434
434
|
end
|
435
435
|
|
436
|
-
it
|
437
|
-
result = parser.parse
|
438
|
-
result.line.must_equal 1
|
436
|
+
it "works for a float literal" do
|
437
|
+
result = parser.parse "3.14"
|
438
|
+
_(result.line).must_equal 1
|
439
439
|
end
|
440
440
|
|
441
|
-
it
|
442
|
-
result = parser.parse
|
443
|
-
result.line.must_equal 1
|
441
|
+
it "works for a range literal" do
|
442
|
+
result = parser.parse "0..4"
|
443
|
+
_(result.line).must_equal 1
|
444
444
|
end
|
445
445
|
|
446
|
-
it
|
447
|
-
result = parser.parse
|
448
|
-
result.line.must_equal 1
|
446
|
+
it "works for an exclusive range literal" do
|
447
|
+
result = parser.parse "0...4"
|
448
|
+
_(result.line).must_equal 1
|
449
449
|
end
|
450
450
|
|
451
|
-
it
|
452
|
-
result = parser.parse
|
453
|
-
result.line.must_equal 1
|
451
|
+
it "works for a symbol literal" do
|
452
|
+
result = parser.parse ":foo"
|
453
|
+
_(result.line).must_equal 1
|
454
454
|
end
|
455
455
|
|
456
|
-
it
|
457
|
-
result = parser.parse
|
458
|
-
result.line.must_equal 1
|
456
|
+
it "works for a keyword-like symbol literal" do
|
457
|
+
result = parser.parse ":and"
|
458
|
+
_(result.line).must_equal 1
|
459
459
|
end
|
460
460
|
|
461
|
-
it
|
461
|
+
it "works for a string literal" do
|
462
462
|
result = parser.parse '"foo"'
|
463
|
-
result.line.must_equal 1
|
463
|
+
_(result.line).must_equal 1
|
464
464
|
end
|
465
465
|
|
466
|
-
it
|
467
|
-
result = parser.parse
|
468
|
-
result.line.must_equal 1
|
466
|
+
it "works for a backtick string literal" do
|
467
|
+
result = parser.parse "`foo`"
|
468
|
+
_(result.line).must_equal 1
|
469
469
|
end
|
470
470
|
|
471
|
-
it
|
472
|
-
result = parser.parse
|
473
|
-
result.line.must_equal 1
|
471
|
+
it "works for a plain regexp literal" do
|
472
|
+
result = parser.parse "/foo/"
|
473
|
+
_(result.line).must_equal 1
|
474
474
|
end
|
475
475
|
|
476
|
-
it
|
477
|
-
result = parser.parse
|
478
|
-
result.line.must_equal 1
|
476
|
+
it "works for a regular expression back reference" do
|
477
|
+
result = parser.parse "$1"
|
478
|
+
_(result.line).must_equal 1
|
479
479
|
end
|
480
480
|
|
481
|
-
it
|
482
|
-
result = parser.parse
|
483
|
-
result.line.must_equal 1
|
481
|
+
it "works for self" do
|
482
|
+
result = parser.parse "self"
|
483
|
+
_(result.line).must_equal 1
|
484
484
|
end
|
485
485
|
|
486
|
-
it
|
487
|
-
result = parser.parse
|
488
|
-
result.line.must_equal 1
|
486
|
+
it "works for __FILE__" do
|
487
|
+
result = parser.parse "__FILE__"
|
488
|
+
_(result.line).must_equal 1
|
489
489
|
end
|
490
490
|
|
491
|
-
it
|
492
|
-
result = parser.parse
|
493
|
-
result.line.must_equal 1
|
491
|
+
it "works for nil" do
|
492
|
+
result = parser.parse "nil"
|
493
|
+
_(result.line).must_equal 1
|
494
494
|
end
|
495
495
|
|
496
|
-
it
|
497
|
-
result = parser.parse
|
498
|
-
result.line.must_equal 1
|
496
|
+
it "works for a class definition" do
|
497
|
+
result = parser.parse "class Foo; end"
|
498
|
+
_(result.line).must_equal 1
|
499
499
|
end
|
500
500
|
|
501
|
-
it
|
502
|
-
result = parser.parse
|
503
|
-
result.line.must_equal 1
|
501
|
+
it "works for a module definition" do
|
502
|
+
result = parser.parse "module Foo; end"
|
503
|
+
_(result.line).must_equal 1
|
504
504
|
end
|
505
505
|
|
506
|
-
it
|
507
|
-
result = parser.parse
|
508
|
-
result.line.must_equal 1
|
506
|
+
it "works for a method definition" do
|
507
|
+
result = parser.parse "def foo; end"
|
508
|
+
_(result.line).must_equal 1
|
509
509
|
end
|
510
510
|
|
511
|
-
it
|
512
|
-
"foo(bar) do\nnext baz\nend\n"
|
513
|
-
must_be_parsed_as s(:iter,
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
511
|
+
it "assigns line numbers to nested sexps without their own line numbers" do
|
512
|
+
_("foo(bar) do\nnext baz\nend\n")
|
513
|
+
.must_be_parsed_as s(:iter,
|
514
|
+
s(:call, nil, :foo, s(:call, nil, :bar).line(1)).line(1),
|
515
|
+
0,
|
516
|
+
s(:next, s(:call, nil, :baz).line(2)).line(2)).line(1),
|
517
|
+
with_line_numbers: true
|
518
518
|
end
|
519
519
|
|
520
|
-
describe
|
521
|
-
it
|
522
|
-
result = parser.parse "foo\nbar\n",
|
523
|
-
result.must_equal s(:block,
|
524
|
-
|
525
|
-
|
526
|
-
result.line.must_equal 3
|
527
|
-
result[1].line.must_equal 3
|
528
|
-
result[2].line.must_equal 4
|
520
|
+
describe "when a line number is passed" do
|
521
|
+
it "shifts all line numbers as appropriate" do
|
522
|
+
result = parser.parse "foo\nbar\n", "(string)", 3
|
523
|
+
_(result).must_equal s(:block,
|
524
|
+
s(:call, nil, :foo),
|
525
|
+
s(:call, nil, :bar))
|
526
|
+
_(result.line).must_equal 3
|
527
|
+
_(result[1].line).must_equal 3
|
528
|
+
_(result[2].line).must_equal 4
|
529
529
|
end
|
530
530
|
end
|
531
531
|
end
|
532
532
|
end
|
533
533
|
|
534
|
-
describe
|
535
|
-
it
|
534
|
+
describe "#trickle_up_line_numbers" do
|
535
|
+
it "works through several nested levels" do
|
536
536
|
inner = s(:foo)
|
537
537
|
outer = s(:bar, s(:baz, s(:qux, inner)))
|
538
538
|
outer.line = 42
|
539
539
|
parser.send :trickle_down_line_numbers, outer
|
540
|
-
inner.line.must_equal 42
|
540
|
+
_(inner.line).must_equal 42
|
541
541
|
end
|
542
542
|
end
|
543
543
|
|
544
|
-
describe
|
545
|
-
it
|
544
|
+
describe "#trickle_down_line_numbers" do
|
545
|
+
it "works through several nested levels" do
|
546
546
|
inner = s(:foo)
|
547
547
|
inner.line = 42
|
548
548
|
outer = s(:bar, s(:baz, s(:qux, inner)))
|
549
549
|
parser.send :trickle_up_line_numbers, outer
|
550
|
-
outer.line.must_equal 42
|
550
|
+
_(outer.line).must_equal 42
|
551
551
|
end
|
552
552
|
end
|
553
553
|
end
|