ripper_ruby_parser 1.3.0 → 1.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd7842da24ae8db93c8a0c397a7648469dd549734c4903a252c042a7a45ad967
4
- data.tar.gz: c6684342b972c5d5a021fc4e1848b460f57a5f471158da76f9255427b224c356
3
+ metadata.gz: 4a4cdc97eb0ffc630d78101fbd5ec056919c03bd91571a27d5972f6b67794dbf
4
+ data.tar.gz: 192aa89ab393bfaa24690b4db77368cd608dd44de41575e2223d8936628f95c2
5
5
  SHA512:
6
- metadata.gz: f067ec3069d0baa143ded82de049ae1baa5c8811cee88ff930494baf5bbcdfb83bee1656712120150ca0293c55da9237923a170fd463f261b1cd4f637abbcad7
7
- data.tar.gz: 76e945832ebcefab6df4ae6c3fc26c4b03e1a24dac1399ea5ac4b1f92c2c331d8d7f8dff365757f5450bed8d738d769bf398b02843bb9aebff8c1010be70439f
6
+ metadata.gz: 8c44761bbf0e73e5c37a14ed1744639938d1e0e50f100735937f6727677224ef3f065a81a711246375a31df55394e7f2e0dd7a996a474a8c24dc3e01319b05f1
7
+ data.tar.gz: 6fed83fa681eb454030522d362bc7d0b5904d061331b659f695f5b668cb5124f94ad5aafe1dfa7ee21387cf5d292e72403aab27aa9daa5d99b7003026e712896
@@ -1,4 +1,9 @@
1
- # Change log
1
+ # Changelog
2
+
3
+ ## 1.4.0 / 2018-03-30
4
+
5
+ * Handle begin..end blocks with postfix conditionals
6
+ * Correctly handle string variants that do not allow escape sequences
2
7
 
3
8
  ## 1.3.0 / 2018-02-17
4
9
 
@@ -1,5 +1,6 @@
1
1
  require 'ripper'
2
2
  require 'ripper_ruby_parser/syntax_error'
3
+ require 'ripper_ruby_parser/unescape'
3
4
 
4
5
  module RipperRubyParser
5
6
  # Variant of Ripper's SexpBuilder parser class that inserts comments as
@@ -11,6 +12,7 @@ module RipperRubyParser
11
12
  super
12
13
  @comment = nil
13
14
  @comment_stack = []
15
+ @delimiter_stack = []
14
16
  @in_symbol = false
15
17
  end
16
18
 
@@ -21,6 +23,11 @@ module RipperRubyParser
21
23
  Sexp.from_array(result)
22
24
  end
23
25
 
26
+ def on_backtick(delimiter)
27
+ @delimiter_stack.push delimiter
28
+ super
29
+ end
30
+
24
31
  def on_comment(tok)
25
32
  @comment ||= ''
26
33
  @comment += tok
@@ -66,6 +73,16 @@ module RipperRubyParser
66
73
  list << elem
67
74
  end
68
75
 
76
+ def on_heredoc_beg(delimiter)
77
+ @delimiter_stack.push delimiter
78
+ super
79
+ end
80
+
81
+ def on_heredoc_end(delimiter)
82
+ @delimiter_stack.pop
83
+ super
84
+ end
85
+
69
86
  def on_mlhs_new
70
87
  [:mlhs]
71
88
  end
@@ -86,6 +103,11 @@ module RipperRubyParser
86
103
  list << elem
87
104
  end
88
105
 
106
+ def on_qsymbols_beg(delimiter)
107
+ @delimiter_stack.push delimiter
108
+ super
109
+ end
110
+
89
111
  def on_qsymbols_new
90
112
  [:qsymbols]
91
113
  end
@@ -94,6 +116,11 @@ module RipperRubyParser
94
116
  list << elem
95
117
  end
96
118
 
119
+ def on_qwords_beg(delimiter)
120
+ @delimiter_stack.push delimiter
121
+ super
122
+ end
123
+
97
124
  def on_qwords_new
98
125
  [:qwords]
99
126
  end
@@ -102,6 +129,16 @@ module RipperRubyParser
102
129
  list << elem
103
130
  end
104
131
 
132
+ def on_regexp_beg(delimiter)
133
+ @delimiter_stack.push delimiter
134
+ super
135
+ end
136
+
137
+ def on_regexp_end(delimiter)
138
+ @delimiter_stack.pop
139
+ super
140
+ end
141
+
105
142
  def on_regexp_new
106
143
  [:regexp]
107
144
  end
@@ -122,6 +159,11 @@ module RipperRubyParser
122
159
  list << elem
123
160
  end
124
161
 
162
+ def on_symbols_beg(delimiter)
163
+ @delimiter_stack.push delimiter
164
+ super
165
+ end
166
+
125
167
  def on_symbols_new
126
168
  [:symbols]
127
169
  end
@@ -130,6 +172,28 @@ module RipperRubyParser
130
172
  list << elem
131
173
  end
132
174
 
175
+ def on_tstring_beg(delimiter)
176
+ @delimiter_stack.push delimiter
177
+ super
178
+ end
179
+
180
+ def on_tstring_content(content)
181
+ content = case @delimiter_stack.last
182
+ when '"', '`', ':"', /^<</, /^%I/, /^%Q/, /^%W/
183
+ Unescape.unescape(content)
184
+ when "'", ":'"
185
+ Unescape.simple_unescape(content)
186
+ else
187
+ content
188
+ end
189
+ super(content)
190
+ end
191
+
192
+ def on_tstring_end(delimiter)
193
+ @delimiter_stack.pop
194
+ super
195
+ end
196
+
133
197
  def on_word_new
134
198
  [:word]
135
199
  end
@@ -138,6 +202,11 @@ module RipperRubyParser
138
202
  list << elem
139
203
  end
140
204
 
205
+ def on_words_beg(delimiter)
206
+ @delimiter_stack.push delimiter
207
+ super
208
+ end
209
+
141
210
  def on_words_new
142
211
  [:words]
143
212
  end
@@ -176,8 +245,8 @@ module RipperRubyParser
176
245
 
177
246
  NUMBER_LITERAL_TYPES = [:@int, :@float].freeze
178
247
 
179
- def on_unary(op, value)
180
- if !@space_before && op == :-@ && NUMBER_LITERAL_TYPES.include?(value.first)
248
+ def on_unary(operator, value)
249
+ if !@space_before && operator == :-@ && NUMBER_LITERAL_TYPES.include?(value.first)
181
250
  type, literal, lines = value
182
251
  if literal[0] == '-'
183
252
  super
@@ -189,7 +258,8 @@ module RipperRubyParser
189
258
  end
190
259
  end
191
260
 
192
- def on_symbeg(*args)
261
+ def on_symbeg(delimiter)
262
+ @delimiter_stack.push delimiter
193
263
  @in_symbol = true
194
264
  super
195
265
  end
@@ -199,7 +269,7 @@ module RipperRubyParser
199
269
  super
200
270
  end
201
271
 
202
- def on_embexpr_beg(*args)
272
+ def on_embexpr_beg(_delimiter)
203
273
  @in_symbol = false
204
274
  super
205
275
  end
@@ -23,7 +23,7 @@ module RipperRubyParser
23
23
  _, cond, truepart = exp.shift 3
24
24
 
25
25
  construct_conditional(handle_condition(cond),
26
- process(truepart),
26
+ handle_operator_argument(truepart),
27
27
  nil)
28
28
  end
29
29
 
@@ -40,7 +40,7 @@ module RipperRubyParser
40
40
 
41
41
  construct_conditional(handle_condition(cond),
42
42
  nil,
43
- process(truepart))
43
+ handle_operator_argument(truepart))
44
44
  end
45
45
 
46
46
  def process_case(exp)
@@ -8,7 +8,8 @@ module RipperRubyParser
8
8
  end
9
9
 
10
10
  def process_string_content(exp)
11
- string, rest = extract_unescaped_string_parts exp
11
+ _, *rest = shift_all exp
12
+ string, rest = extract_string_parts(rest)
12
13
 
13
14
  if rest.empty?
14
15
  s(:str, string)
@@ -55,7 +56,12 @@ module RipperRubyParser
55
56
 
56
57
  def process_xstring_literal(exp)
57
58
  _, content = exp.shift 2
58
- string, rest = extract_unescaped_string_parts content
59
+ process(content)
60
+ end
61
+
62
+ def process_xstring(exp)
63
+ _, *rest = shift_all exp
64
+ string, rest = extract_string_parts(rest)
59
65
  if rest.empty?
60
66
  s(:xstr, string)
61
67
  else
@@ -66,7 +72,7 @@ module RipperRubyParser
66
72
  def process_regexp_literal(exp)
67
73
  _, content, (_, flags,) = exp.shift 3
68
74
 
69
- string, rest = extract_string_parts content
75
+ string, rest = process(content).sexp_body
70
76
  numflags = character_flags_to_numerical flags
71
77
 
72
78
  if rest.empty?
@@ -82,6 +88,12 @@ module RipperRubyParser
82
88
  end
83
89
  end
84
90
 
91
+ def process_regexp(exp)
92
+ _, *rest = shift_all exp
93
+ string, rest = extract_string_parts(rest)
94
+ s(:regexp, string, rest)
95
+ end
96
+
85
97
  def process_symbol_literal(exp)
86
98
  _, symbol = exp.shift 2
87
99
  process(symbol)
@@ -116,8 +128,8 @@ module RipperRubyParser
116
128
 
117
129
  private
118
130
 
119
- def extract_string_parts(exp)
120
- parts = internal_process_string_parts(exp)
131
+ def extract_string_parts(list)
132
+ parts = map_process_list list
121
133
 
122
134
  string = ''
123
135
  while !parts.empty? && parts.first.sexp_type == :str
@@ -130,74 +142,6 @@ module RipperRubyParser
130
142
  return string, rest
131
143
  end
132
144
 
133
- def internal_process_string_parts(exp)
134
- _, *rest = shift_all exp
135
- map_process_list rest
136
- end
137
-
138
- def extract_unescaped_string_parts(exp)
139
- string, rest = extract_string_parts exp
140
-
141
- string = unescape(string)
142
-
143
- rest.each do |sub_exp|
144
- sub_exp[1] = unescape(sub_exp[1]) if sub_exp.sexp_type == :str
145
- end
146
-
147
- return string, rest
148
- end
149
-
150
- SINGLE_LETTER_ESCAPES = {
151
- 'a' => "\a",
152
- 'b' => "\b",
153
- 'e' => "\e",
154
- 'f' => "\f",
155
- 'n' => "\n",
156
- 'r' => "\r",
157
- 's' => "\s",
158
- 't' => "\t",
159
- 'v' => "\v"
160
- }.freeze
161
-
162
- SINGLE_LETTER_ESCAPES_REGEXP =
163
- Regexp.new("^[#{SINGLE_LETTER_ESCAPES.keys.join}]$")
164
-
165
- def unescape(string)
166
- string.gsub(/\\(
167
- [0-7]{1,3} | # octal character
168
- x[0-9a-fA-F]{1,2} | # hex byte
169
- u[0-9a-fA-F]{4} | # unicode character
170
- M-\\C-. | # meta-ctrl
171
- C-\\M-. | # ctrl-meta
172
- M-\\c. | # meta-ctrl (shorthand)
173
- c\\M-. | # ctrl-meta (shorthand)
174
- C-. | # control (regular)
175
- c. | # control (shorthand)
176
- M-. | # meta
177
- . # single-character
178
- )/x) do
179
- bare = Regexp.last_match[1]
180
- case bare
181
- when SINGLE_LETTER_ESCAPES_REGEXP
182
- SINGLE_LETTER_ESCAPES[bare]
183
- when /^x/
184
- bare[1..-1].to_i(16).chr
185
- when /^u/
186
- bare[1..-1].to_i(16).chr(Encoding::UTF_8)
187
- when /^(c|C-).$/
188
- (bare[-1].ord & 0b1001_1111).chr
189
- when /^M-.$/
190
- (bare[-1].ord | 0b1000_0000).chr
191
- when /^(M-\\C-|C-\\M-|M-\\c|c\\M-).$/
192
- (bare[-1].ord & 0b1001_1111 | 0b1000_0000).chr
193
- when /^[0-7]+/
194
- bare.to_i(8).chr
195
- else
196
- bare
197
- end
198
- end
199
- end
200
-
201
145
  def character_flags_to_numerical(flags)
202
146
  numflags = 0
203
147
 
@@ -211,12 +155,15 @@ module RipperRubyParser
211
155
  numflags
212
156
  end
213
157
 
214
- def handle_dyna_symbol_content(list)
215
- string, rest = extract_unescaped_string_parts list
216
- if rest.empty?
217
- s(:lit, string.to_sym)
158
+ def handle_dyna_symbol_content(node)
159
+ type, *body = *process(node)
160
+ case type
161
+ when :str, :xstr
162
+ s(:lit, body.first.to_sym)
163
+ when :dstr, :dxstr
164
+ s(:dsym, *body)
218
165
  else
219
- s(:dsym, string, *rest)
166
+ raise type.to_s
220
167
  end
221
168
  end
222
169
 
@@ -74,18 +74,18 @@ module RipperRubyParser
74
74
 
75
75
  private
76
76
 
77
- def make_boolean_operator(op, left, right)
78
- _, left, _, right = rebalance_binary(s(:binary, left, op, right))
79
- s(op, process(left), handle_operator_argument(right))
77
+ def make_boolean_operator(operator, left, right)
78
+ _, left, _, right = rebalance_binary(s(:binary, left, operator, right))
79
+ s(operator, process(left), handle_operator_argument(right))
80
80
  end
81
81
 
82
- def make_regexp_match_operator(op, left, right)
82
+ def make_regexp_match_operator(operator, left, right)
83
83
  if left.sexp_type == :regexp_literal
84
84
  s(:match2, process(left), process(right))
85
85
  elsif right.sexp_type == :regexp_literal
86
86
  s(:match3, process(right), process(left))
87
87
  else
88
- s(:call, process(left), op, process(right))
88
+ s(:call, process(left), operator, process(right))
89
89
  end
90
90
  end
91
91
 
@@ -1,5 +1,6 @@
1
1
  require 'sexp_processor'
2
2
  require 'ripper_ruby_parser/sexp_handlers'
3
+ require 'ripper_ruby_parser/unescape'
3
4
 
4
5
  module RipperRubyParser
5
6
  # Processes the sexp created by Ripper to what RubyParser would produce.
@@ -160,7 +161,7 @@ module RipperRubyParser
160
161
  # character literals
161
162
  def process_at_CHAR(exp)
162
163
  _, val, pos = exp.shift 3
163
- with_position(pos, s(:str, unescape(val[1..-1])))
164
+ with_position(pos, s(:str, Unescape.unescape(val[1..-1])))
164
165
  end
165
166
 
166
167
  def process_at_label(exp)
@@ -0,0 +1,68 @@
1
+ module RipperRubyParser
2
+ # Implements string unescaping
3
+ #
4
+ # @api private
5
+ module Unescape
6
+ module_function
7
+
8
+ SINGLE_LETTER_ESCAPES = {
9
+ 'a' => "\a",
10
+ 'b' => "\b",
11
+ 'e' => "\e",
12
+ 'f' => "\f",
13
+ 'n' => "\n",
14
+ 'r' => "\r",
15
+ 's' => "\s",
16
+ 't' => "\t",
17
+ 'v' => "\v"
18
+ }.freeze
19
+
20
+ SINGLE_LETTER_ESCAPES_REGEXP =
21
+ Regexp.new("^[#{SINGLE_LETTER_ESCAPES.keys.join}]$")
22
+
23
+ def simple_unescape(string)
24
+ string.gsub(/\\(
25
+ ' | # single quote
26
+ \\ # backslash
27
+ )/x) do
28
+ Regexp.last_match[1]
29
+ end
30
+ end
31
+
32
+ def unescape(string)
33
+ string.gsub(/\\(
34
+ [0-7]{1,3} | # octal character
35
+ x[0-9a-fA-F]{1,2} | # hex byte
36
+ u[0-9a-fA-F]{4} | # unicode character
37
+ M-\\C-. | # meta-ctrl
38
+ C-\\M-. | # ctrl-meta
39
+ M-\\c. | # meta-ctrl (shorthand)
40
+ c\\M-. | # ctrl-meta (shorthand)
41
+ C-. | # control (regular)
42
+ c. | # control (shorthand)
43
+ M-. | # meta
44
+ . # single-character
45
+ )/x) do
46
+ bare = Regexp.last_match[1]
47
+ case bare
48
+ when SINGLE_LETTER_ESCAPES_REGEXP
49
+ SINGLE_LETTER_ESCAPES[bare]
50
+ when /^x/
51
+ bare[1..-1].to_i(16).chr
52
+ when /^u/
53
+ bare[1..-1].to_i(16).chr(Encoding::UTF_8)
54
+ when /^(c|C-).$/
55
+ (bare[-1].ord & 0b1001_1111).chr
56
+ when /^M-.$/
57
+ (bare[-1].ord | 0b1000_0000).chr
58
+ when /^(M-\\C-|C-\\M-|M-\\c|c\\M-).$/
59
+ (bare[-1].ord & 0b1001_1111 | 0b1000_0000).chr
60
+ when /^[0-7]+/
61
+ bare.to_i(8).chr
62
+ else
63
+ bare
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -1,3 +1,3 @@
1
1
  module RipperRubyParser
2
- VERSION = '1.3.0'.freeze
2
+ VERSION = '1.4.0'.freeze
3
3
  end
@@ -2,24 +2,13 @@ require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
2
2
  require 'ruby_parser'
3
3
 
4
4
  describe 'Using RipperRubyParser and RubyParser' do
5
- let :newparser do
6
- RipperRubyParser::Parser.new
7
- end
8
-
9
- let :oldparser do
10
- RubyParser.new
11
- end
12
-
13
5
  describe 'for a simple well known program' do
14
6
  let :program do
15
7
  "puts 'Hello World'"
16
8
  end
17
9
 
18
10
  it 'gives the same result' do
19
- original = oldparser.parse program
20
- imitation = newparser.parse program
21
-
22
- imitation.must_equal original
11
+ program.must_be_parsed_as_before
23
12
  end
24
13
  end
25
14
 
@@ -45,10 +34,7 @@ describe 'Using RipperRubyParser and RubyParser' do
45
34
  end
46
35
 
47
36
  it 'gives the same result' do
48
- original = oldparser.parse program
49
- imitation = newparser.parse program
50
-
51
- imitation.must_equal original
37
+ program.must_be_parsed_as_before
52
38
  end
53
39
  end
54
40
 
@@ -58,10 +44,7 @@ describe 'Using RipperRubyParser and RubyParser' do
58
44
  end
59
45
 
60
46
  it 'gives the same result' do
61
- original = oldparser.parse program
62
- imitation = newparser.parse program
63
-
64
- imitation.must_equal original
47
+ program.must_be_parsed_as_before
65
48
  end
66
49
  end
67
50
 
@@ -79,10 +62,7 @@ describe 'Using RipperRubyParser and RubyParser' do
79
62
  end
80
63
 
81
64
  it 'gives the same result' do
82
- original = oldparser.parse program
83
- imitation = newparser.parse program
84
-
85
- formatted(imitation).must_equal formatted(original)
65
+ program.must_be_parsed_as_before
86
66
  end
87
67
  end
88
68
 
@@ -106,10 +86,7 @@ describe 'Using RipperRubyParser and RubyParser' do
106
86
  end
107
87
 
108
88
  it 'gives the same result' do
109
- original = oldparser.parse program
110
- imitation = newparser.parse program
111
-
112
- formatted(imitation).must_equal formatted(original)
89
+ program.must_be_parsed_as_before
113
90
  end
114
91
  end
115
92
 
@@ -119,10 +96,7 @@ describe 'Using RipperRubyParser and RubyParser' do
119
96
  end
120
97
 
121
98
  it 'gives the same result' do
122
- original = oldparser.parse program
123
- imitation = newparser.parse program
124
-
125
- formatted(imitation).must_equal formatted(original)
99
+ program.must_be_parsed_as_before
126
100
  end
127
101
  end
128
102
 
@@ -145,4 +119,58 @@ describe 'Using RipperRubyParser and RubyParser' do
145
119
  program.must_be_parsed_as_before
146
120
  end
147
121
  end
122
+
123
+ describe 'for an example with __ENCODING__' do
124
+ it 'gives the same result' do
125
+ program = 'foo = __ENCODING__'
126
+ program.must_be_parsed_as_before
127
+ end
128
+ end
129
+
130
+ describe 'for an example with self[]' do
131
+ # https://github.com/seattlerb/ruby_parser/issues/250
132
+ it 'gives the same result' do
133
+ program = 'self[:foo]'
134
+ program.must_be_parsed_as_before
135
+ end
136
+ end
137
+
138
+ describe 'for an example with required keyword arguments and no parentheses' do
139
+ # https://github.com/seattlerb/ruby_parser/pull/254
140
+ let(:program) do
141
+ <<-END
142
+ def foo a:, b:
143
+ # body
144
+ end
145
+ END
146
+ end
147
+
148
+ it 'gives the same result' do
149
+ program.must_be_parsed_as_before
150
+ end
151
+ end
152
+
153
+ describe 'for an example combining begin..end and diverse operators' do
154
+ let(:program) do
155
+ <<-END
156
+ begin end
157
+ begin; foo; end
158
+ begin; foo; bar; end
159
+ - begin; foo; end
160
+ begin; bar; end + foo
161
+ foo + begin; bar; end
162
+ begin; foo; end ? bar : baz
163
+ foo ? begin; bar; end : baz
164
+ foo ? bar : begin; baz; end
165
+ begin; bar; end and foo
166
+ foo and begin; bar; end
167
+ begin; foo; end if bar
168
+ begin; foo; end unless bar
169
+ END
170
+ end
171
+
172
+ it 'gives the same result' do
173
+ program.must_be_parsed_as_before
174
+ end
175
+ end
148
176
  end
@@ -201,6 +201,22 @@ describe RipperRubyParser::Parser do
201
201
  s(:call, nil, :bar),
202
202
  s(:begin, s(:call, nil, :baz)))
203
203
  end
204
+
205
+ it 'keeps :begin for the truepart of a postfix if' do
206
+ 'begin; foo; end if bar'.
207
+ must_be_parsed_as s(:if,
208
+ s(:call, nil, :bar),
209
+ s(:begin, s(:call, nil, :foo)),
210
+ nil)
211
+ end
212
+
213
+ it 'keeps :begin for the falsepart of a postfix unless' do
214
+ 'begin; foo; end unless bar'.
215
+ must_be_parsed_as s(:if,
216
+ s(:call, nil, :bar),
217
+ nil,
218
+ s(:begin, s(:call, nil, :foo)))
219
+ end
204
220
  end
205
221
 
206
222
  describe 'for rescue/else' do
@@ -302,6 +302,40 @@ describe RipperRubyParser::Parser do
302
302
  end
303
303
  end
304
304
 
305
+ describe 'with single quoted strings' do
306
+ it 'works with escaped single quotes' do
307
+ "'foo\\'bar'".
308
+ must_be_parsed_as s(:str, "foo'bar")
309
+ end
310
+
311
+ it 'works with embedded backslashes' do
312
+ "'foo\\abar'".
313
+ must_be_parsed_as s(:str, 'foo\abar')
314
+ end
315
+
316
+ it 'works with escaped embedded backslashes' do
317
+ "'foo\\\\abar'".
318
+ must_be_parsed_as s(:str, 'foo\abar')
319
+ end
320
+
321
+ it 'works with sequences of backslashes' do
322
+ "'foo\\\\\\abar'".
323
+ must_be_parsed_as s(:str, 'foo\\\\abar')
324
+ end
325
+ end
326
+
327
+ describe 'with %Q-delimited strings' do
328
+ it 'works for the simple case' do
329
+ '%Q[bar]'.
330
+ must_be_parsed_as s(:str, 'bar')
331
+ end
332
+
333
+ it 'works for escape sequences' do
334
+ '%Q[foo\\nbar]'.
335
+ must_be_parsed_as s(:str, "foo\nbar")
336
+ end
337
+ end
338
+
305
339
  describe 'with string concatenation' do
306
340
  it 'performs the concatenation in the case of two simple literal strings' do
307
341
  '"foo" "bar"'.must_be_parsed_as s(:str, 'foobar')
@@ -351,6 +385,18 @@ describe RipperRubyParser::Parser do
351
385
  end
352
386
  end
353
387
  end
388
+
389
+ describe 'for heredocs' do
390
+ it 'works for the simple case' do
391
+ "<<FOO\nbar\nFOO".
392
+ must_be_parsed_as s(:str, "bar\n")
393
+ end
394
+
395
+ it 'works for escape sequences' do
396
+ "<<FOO\nbar\\tbaz\nFOO".
397
+ must_be_parsed_as s(:str, "bar\tbaz\n")
398
+ end
399
+ end
354
400
  end
355
401
 
356
402
  describe 'for word list literals' do
@@ -389,19 +435,35 @@ describe RipperRubyParser::Parser do
389
435
  s(:evstr, s(:call, nil, :bar)),
390
436
  s(:str, 'baz')))
391
437
  end
438
+
439
+ it 'correctly handles escape sequences' do
440
+ '%W(foo\nbar baz)'.
441
+ must_be_parsed_as s(:array,
442
+ s(:str, "foo\nbar"),
443
+ s(:str, 'baz'))
444
+ end
392
445
  end
393
446
 
394
- describe 'for symbol list literals' do
395
- it 'works for an array created with %i' do
447
+ describe 'for symbol list literals with %i delimiter' do
448
+ it 'works for the simple case' do
396
449
  '%i(foo bar)'.
397
450
  must_be_parsed_as s(:array, s(:lit, :foo), s(:lit, :bar))
398
451
  end
452
+ end
399
453
 
400
- it 'works for an array created with %I' do
454
+ describe 'for symbol list literals with %I delimiter' do
455
+ it 'works for the simple case' do
401
456
  '%I(foo bar)'.
402
457
  must_be_parsed_as s(:array, s(:lit, :foo), s(:lit, :bar))
403
458
  end
404
459
 
460
+ it 'correctly handles escape sequences' do
461
+ '%I(foo\nbar baz)'.
462
+ must_be_parsed_as s(:array,
463
+ s(:lit, :"foo\nbar"),
464
+ s(:lit, :baz))
465
+ end
466
+
405
467
  it 'correctly handles interpolation' do
406
468
  "%I(foo \#{bar} baz)".
407
469
  must_be_parsed_as s(:array,
@@ -485,6 +547,26 @@ describe RipperRubyParser::Parser do
485
547
  'foo',
486
548
  s(:evstr, s(:call, nil, :bar)))
487
549
  end
550
+
551
+ it 'works for dsyms with escape sequences' do
552
+ ':"foo\nbar"'.
553
+ must_be_parsed_as s(:lit, :"foo\nbar")
554
+ end
555
+
556
+ it 'works with single quoted dsyms' do
557
+ ":'foo'".
558
+ must_be_parsed_as s(:lit, :foo)
559
+ end
560
+
561
+ it 'works with single quoted dsyms with escaped single quotes' do
562
+ ":'foo\\'bar'".
563
+ must_be_parsed_as s(:lit, :'foo\'bar')
564
+ end
565
+
566
+ it 'works with single quoted dsyms with embedded backslashes' do
567
+ ":'foo\\abar'".
568
+ must_be_parsed_as s(:lit, :"foo\\abar")
569
+ end
488
570
  end
489
571
 
490
572
  describe 'for backtick string literals' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ripper_ruby_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matijs van Zuijlen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-02-17 00:00:00.000000000 Z
11
+ date: 2018-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sexp_processor
@@ -111,6 +111,7 @@ files:
111
111
  - lib/ripper_ruby_parser/sexp_handlers/operators.rb
112
112
  - lib/ripper_ruby_parser/sexp_processor.rb
113
113
  - lib/ripper_ruby_parser/syntax_error.rb
114
+ - lib/ripper_ruby_parser/unescape.rb
114
115
  - lib/ripper_ruby_parser/version.rb
115
116
  - test/end_to_end/comments_test.rb
116
117
  - test/end_to_end/comparison_test.rb
@@ -131,7 +132,6 @@ files:
131
132
  - test/ripper_ruby_parser/sexp_processor_test.rb
132
133
  - test/ripper_ruby_parser/version_test.rb
133
134
  - test/samples/inline.rb
134
- - test/samples/misc.rb
135
135
  - test/test_helper.rb
136
136
  homepage: http://www.github.com/mvz/ripper_ruby_parser
137
137
  licenses:
@@ -155,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
155
  version: '0'
156
156
  requirements: []
157
157
  rubyforge_project:
158
- rubygems_version: 2.7.3
158
+ rubygems_version: 2.7.6
159
159
  signing_key:
160
160
  specification_version: 4
161
161
  summary: Parse with Ripper, produce sexps that are compatible with RubyParser.
@@ -179,5 +179,4 @@ test_files:
179
179
  - test/ripper_ruby_parser/sexp_processor_test.rb
180
180
  - test/ripper_ruby_parser/version_test.rb
181
181
  - test/samples/inline.rb
182
- - test/samples/misc.rb
183
182
  - test/test_helper.rb
@@ -1,12 +0,0 @@
1
- # Collect diverse tricky pieces of code here
2
- #
3
-
4
- enc = __ENCODING__
5
-
6
- # https://github.com/seattlerb/ruby_parser/issues/250
7
- self[:x]
8
-
9
- # https://github.com/seattlerb/ruby_parser/pull/254
10
- def foo a:, b:
11
- # body
12
- end