ripper_ruby_parser 0.0.4 → 0.0.5

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/Rakefile CHANGED
@@ -5,13 +5,13 @@ namespace :test do
5
5
  Rake::TestTask.new(:unit) do |t|
6
6
  t.libs = ['lib']
7
7
  t.test_files = FileList['test/unit/*_test.rb']
8
- t.ruby_opts += ["-w"]
8
+ t.warning = true
9
9
  end
10
10
 
11
11
  Rake::TestTask.new(:end_to_end) do |t|
12
12
  t.libs = ['lib']
13
13
  t.test_files = FileList['test/end_to_end/*_test.rb']
14
- t.ruby_opts += ["-w"]
14
+ t.warning = true
15
15
  end
16
16
 
17
17
  task :run => [:unit, :end_to_end]
@@ -7,6 +7,7 @@ module RipperRubyParser
7
7
  super
8
8
  @comment = nil
9
9
  @comment_stack = []
10
+ @in_symbol = false
10
11
  end
11
12
 
12
13
  def on_comment tok
@@ -18,22 +19,42 @@ module RipperRubyParser
18
19
  def on_kw tok
19
20
  case tok
20
21
  when "class", "def", "module"
21
- @comment_stack.push @comment
22
- @comment = nil
22
+ unless @in_symbol
23
+ @comment_stack.push [tok.to_sym, @comment]
24
+ @comment = nil
25
+ end
23
26
  end
24
27
  super
25
28
  end
26
29
 
30
+ def on_module *args
31
+ commentize(:module, super)
32
+ end
33
+
27
34
  def on_class *args
28
- commentize(super)
35
+ commentize(:class, super)
36
+ end
37
+
38
+ def on_sclass *args
39
+ commentize(:class, super)
29
40
  end
30
41
 
31
42
  def on_def *args
32
- commentize(super)
43
+ commentize(:def, super)
33
44
  end
34
45
 
35
- def on_module *args
36
- commentize(super)
46
+ def on_defs *args
47
+ commentize(:def, super)
48
+ end
49
+
50
+ def on_symbeg *args
51
+ @in_symbol = true
52
+ super
53
+ end
54
+
55
+ def on_symbol *args
56
+ @in_symbol = false
57
+ super
37
58
  end
38
59
 
39
60
  def on_parse_error *args
@@ -58,8 +79,13 @@ module RipperRubyParser
58
79
 
59
80
  private
60
81
 
61
- def commentize exp
62
- comment = @comment_stack.pop
82
+ def commentize name, exp
83
+ tok, comment = @comment_stack.pop
84
+ unless tok == name
85
+ p @comment_stack
86
+ p [tok, comment]
87
+ raise "Expected on_#{tok} event, got on_#{name}"
88
+ end
63
89
  if comment.nil?
64
90
  [:comment, "", exp]
65
91
  else
@@ -13,14 +13,28 @@ module RipperRubyParser
13
13
  end
14
14
 
15
15
  def parse source, filename='(string)', lineno=1
16
+ # FIXME: Allow parser class to be passed to #initialize also.
16
17
  parser = CommentingSexpBuilder.new(source, filename, lineno)
17
- result = parser.parse
18
+
19
+ result = suppress_warnings { parser.parse }
18
20
  raise "Ripper parse failed." if result.nil?
21
+
19
22
  exp = Sexp.from_array(result)
23
+
20
24
  @processor.filename = filename
21
25
  @processor.extra_compatible = extra_compatible
22
26
  @processor.process exp
23
27
  end
28
+
29
+ private
30
+
31
+ def suppress_warnings
32
+ old_verbose = $VERBOSE
33
+ $VERBOSE = nil
34
+ result = yield
35
+ $VERBOSE = old_verbose
36
+ result
37
+ end
24
38
  end
25
39
  end
26
40
 
@@ -22,6 +22,11 @@ module RipperRubyParser
22
22
  end
23
23
  process(args)
24
24
  end
25
+
26
+ def process_rest_param exp
27
+ _, ident = exp.shift 2
28
+ s(:splat, process(ident))
29
+ end
25
30
  end
26
31
  end
27
32
  end
@@ -3,15 +3,7 @@ module RipperRubyParser
3
3
  module Arrays
4
4
  def process_array exp
5
5
  _, elems = exp.shift 2
6
- elems = handle_potentially_typeless_sexp(elems)
7
- elems.map! do |elem|
8
- if elem.first.is_a? Symbol
9
- elem
10
- else
11
- elem.first
12
- end
13
- end
14
- s(:array, *elems)
6
+ s(:array, *handle_array_elements(elems))
15
7
  end
16
8
 
17
9
  def process_aref exp
@@ -21,11 +21,11 @@ module RipperRubyParser
21
21
  left.shift
22
22
  end
23
23
 
24
- left = create_multiple_assignement_sub_types left
24
+ left = create_multiple_assignment_sub_types left
25
25
 
26
26
  right = process(right)
27
27
 
28
- unless right.sexp_type == :array
28
+ unless [:array, :splat].include? right.sexp_type
29
29
  right = s(:to_ary, right)
30
30
  end
31
31
 
@@ -35,21 +35,30 @@ module RipperRubyParser
35
35
  def process_mrhs_new_from_args exp
36
36
  _, inner, last = exp.shift 3
37
37
  inner.map! {|item| process(item)}
38
- inner.push process(last)
38
+ inner.push process(last) unless last.nil?
39
39
  s(:array, *inner)
40
40
  end
41
41
 
42
+ def process_mrhs_add_star exp
43
+ exp = generic_add_star exp
44
+ unless exp.first.is_a? Symbol
45
+ exp = exp.first
46
+ end
47
+ exp
48
+ end
49
+
42
50
  def process_mlhs_add_star exp
43
51
  generic_add_star exp
44
52
  end
45
53
 
46
54
  def process_mlhs_paren exp
47
55
  _, contents = exp.shift 2
56
+
48
57
  items = handle_potentially_typeless_sexp(contents)
49
58
 
50
- items = create_multiple_assignement_sub_types items
59
+ return items if items.first.is_a? Symbol
51
60
 
52
- s(:masgn, s(:array, *items))
61
+ s(:masgn, s(:array, *create_multiple_assignment_sub_types(items)))
53
62
  end
54
63
 
55
64
  def process_opassign exp
@@ -64,10 +73,14 @@ module RipperRubyParser
64
73
 
65
74
  private
66
75
 
67
- def create_multiple_assignement_sub_types sexp_list
76
+ def create_multiple_assignment_sub_types sexp_list
68
77
  sexp_list.map! do |item|
69
78
  if item.sexp_type == :splat
70
- s(:splat, create_valueless_assignment_sub_type(item[1]))
79
+ if item[1].nil?
80
+ s(:splat)
81
+ else
82
+ s(:splat, create_valueless_assignment_sub_type(item[1]))
83
+ end
71
84
  else
72
85
  create_valueless_assignment_sub_type item
73
86
  end
@@ -88,9 +101,11 @@ module RipperRubyParser
88
101
  def create_operator_assignment_sub_type lvalue, value, operator
89
102
  case lvalue.sexp_type
90
103
  when :aref_field
91
- s(:op_asgn1, lvalue[1], s(:arglist, lvalue[2][1]), operator, value)
104
+ _, arr, arglist = lvalue
105
+ s(:op_asgn1, arr, arglist, operator, value)
92
106
  when :field
93
- s(:op_asgn2, lvalue[1], :"#{lvalue[3][1]}=", operator, value)
107
+ _, obj, _, (_, field) = lvalue
108
+ s(:op_asgn2, obj, :"#{field}=", operator, value)
94
109
  else
95
110
  if operator == :"||"
96
111
  s(:op_asgn_or, lvalue, create_assignment_sub_type(lvalue, value))
@@ -104,9 +119,12 @@ module RipperRubyParser
104
119
  def create_regular_assignment_sub_type lvalue, value
105
120
  case lvalue.sexp_type
106
121
  when :aref_field
107
- s(:attrasgn, lvalue[1], :[]=, s(:arglist, lvalue[2][1], value))
122
+ _, arr, arglist = lvalue
123
+ arglist << value
124
+ s(:attrasgn, arr, :[]=, arglist)
108
125
  when :field
109
- s(:attrasgn, lvalue[1], :"#{lvalue[3][1]}=", s(:arglist, value))
126
+ _, obj, _, (_, field) = lvalue
127
+ s(:attrasgn, obj, :"#{field}=", s(:arglist, value))
110
128
  else
111
129
  create_assignment_sub_type lvalue, value
112
130
  end
@@ -4,7 +4,7 @@ module RipperRubyParser
4
4
  def process_method_add_block exp
5
5
  _, call, block = exp.shift 3
6
6
  block = process(block)
7
- args = convert_block_args(block[1])
7
+ args = block[1]
8
8
  stmt = block[2].first
9
9
  if stmt.nil?
10
10
  s(:iter, process(call), args)
@@ -25,27 +25,36 @@ module RipperRubyParser
25
25
  _, normal, defaults, rest, _, block = exp.shift 6
26
26
 
27
27
  args = [*normal].map do |id|
28
- extract_node_symbol id
28
+ process(id)
29
29
  end
30
30
 
31
31
  assigns = [*defaults].map do |pair|
32
- sym = extract_node_symbol pair[0]
32
+ sym = process(pair[0])
33
33
  args << sym
34
- val = process pair[1]
35
- s(:lasgn, sym, val)
34
+ val = process(pair[1])
35
+ s(:lasgn, sym[1], val)
36
36
  end
37
37
 
38
- # FIXME: Delay conflating all arguments until later, so that
39
- # #convert_block_args doesn't need to tease this apart again.
40
- add_arg_unless_nil(rest, args) {|name| :"*#{name}" }
38
+ args << process(rest) unless rest.nil?
39
+ args << process(block) unless block.nil?
40
+ args << s(:block, *assigns) if assigns.length > 0
41
41
 
42
- add_arg_unless_nil(block, args) {|name| :"&#{name}" }
42
+ s(:args, *args)
43
+ end
43
44
 
44
- if assigns.length > 0
45
- args << s(:block, *assigns)
46
- end
45
+ def process_block_var exp
46
+ _, args, _ = exp.shift 3
47
47
 
48
- s(:args, *args)
48
+ names = process(args)
49
+ names.shift
50
+
51
+ if names.length == 1 and names.first.sexp_type == :lvar
52
+ s(:lasgn, names.first[1])
53
+ elsif names.length == 1 and names.first.sexp_type == :masgn
54
+ names.first
55
+ else
56
+ s(:masgn, s(:array, *names.map { |name| arg_name_to_lasgn(name) }))
57
+ end
49
58
  end
50
59
 
51
60
  def process_begin exp
@@ -57,7 +66,7 @@ module RipperRubyParser
57
66
  end
58
67
 
59
68
  def process_rescue exp
60
- _, eclass, evar, block, _ = exp.shift 5
69
+ _, eclass, evar, block, after = exp.shift 5
61
70
  rescue_block = map_body(block)
62
71
 
63
72
  arr = []
@@ -76,34 +85,46 @@ module RipperRubyParser
76
85
  arr << easgn
77
86
  end
78
87
 
79
- s(:resbody, s(:array, *arr),
80
- wrap_in_block(rescue_block))
88
+ s(
89
+ s(:resbody, s(:array, *arr), wrap_in_block(rescue_block)),
90
+ *process(after))
81
91
  end
82
92
 
83
93
  def process_bodystmt exp
84
- _, body, rescue_block, _, ensure_block = exp.shift 5
94
+ _, body, rescue_block, else_block, ensure_block = exp.shift 5
85
95
 
86
96
  body = map_body body
87
97
 
88
- unless rescue_block or ensure_block
89
- return s(:scope, s(:block, *body))
90
- end
98
+ #unless rescue_block or ensure_block
99
+ # return s(:scope, s(:block, *body))
100
+ #end
91
101
 
92
102
  body = wrap_in_block(body)
93
103
 
104
+ body = if body.nil?
105
+ s()
106
+ else
107
+ s(body)
108
+ end
109
+
94
110
  if rescue_block
95
- if body.nil?
96
- body = s(:rescue, process(rescue_block))
97
- else
98
- body = s(:rescue, body, process(rescue_block))
99
- end
111
+ body.push(*process(rescue_block))
112
+ body << process(else_block) if else_block
113
+ body = s(s(:rescue, *body))
114
+ elsif else_block
115
+ body << process(else_block)
100
116
  end
101
117
 
102
118
  if ensure_block
103
- body = s(:ensure, body, process(ensure_block))
119
+ body << process(ensure_block)
120
+ body = s(s(:ensure, *body))
104
121
  end
105
122
 
106
- s(:scope, s(:block, body))
123
+ if body.length == 1 and body.first.sexp_type == :block
124
+ s(:scope, *body)
125
+ else
126
+ s(:scope, s(:block, *body))
127
+ end
107
128
  end
108
129
 
109
130
  def process_rescue_mod exp
@@ -154,12 +175,21 @@ module RipperRubyParser
154
175
  end
155
176
  end
156
177
 
157
- def add_arg_unless_nil(item, args)
158
- unless item.nil?
159
- name = extract_node_symbol item[1]
160
- args << yield(name)
178
+ def arg_name_to_lasgn(name)
179
+ case name.sexp_type
180
+ when :lvar
181
+ s(:lasgn, name[1])
182
+ when :splat
183
+ if name[1].nil?
184
+ s(:splat)
185
+ else
186
+ s(:splat, s(:lasgn, name[1][1]))
187
+ end
188
+ else
189
+ name
161
190
  end
162
191
  end
192
+
163
193
  end
164
194
  end
165
195
  end
@@ -26,7 +26,7 @@ module RipperRubyParser
26
26
 
27
27
  def process_if_mod exp
28
28
  _, cond, truepart = exp.shift 3
29
- s(:if, process(cond), process(truepart), nil)
29
+ process_if s(:if, cond, s(truepart), nil)
30
30
  end
31
31
 
32
32
  def process_unless_mod exp
@@ -59,8 +59,16 @@ module RipperRubyParser
59
59
  end
60
60
  end
61
61
 
62
- s(s(:when,
63
- process(s(:array, values)),
62
+ values = handle_array_elements values
63
+ values = values.map do |val|
64
+ if val.sexp_type == :splat
65
+ s(:when, val[1], nil)
66
+ else
67
+ val
68
+ end
69
+ end
70
+
71
+ s(s(:when, s(:array, *values),
64
72
  handle_statement_list(truepart)),
65
73
  *falsepart)
66
74
  end
@@ -23,25 +23,6 @@ module RipperRubyParser
23
23
  end
24
24
  end
25
25
 
26
- def convert_block_args(args)
27
- if args
28
- names = args[1][1..-1]
29
- if names.length > 1 or names.first =~ /^\*/
30
- s(:masgn, s(:array, *names.map { |name| arg_name_to_lasgn(name) }))
31
- else
32
- s(:lasgn, names.first)
33
- end
34
- end
35
- end
36
-
37
- def arg_name_to_lasgn(name)
38
- if name =~ /^\*(.*)/
39
- s(:splat, s(:lasgn, $1.to_sym))
40
- else
41
- s(:lasgn, name)
42
- end
43
- end
44
-
45
26
  def handle_statement_list exp
46
27
  statements = map_body exp
47
28
 
@@ -60,8 +41,9 @@ module RipperRubyParser
60
41
  ident.to_sym
61
42
  end
62
43
 
63
- def with_position pos, exp
44
+ def with_position pos, exp=nil
64
45
  (line, _) = pos
46
+ exp = yield if exp.nil?
65
47
  with_line_number line, exp
66
48
  end
67
49
 
@@ -77,9 +59,9 @@ module RipperRubyParser
77
59
 
78
60
  def generic_add_star exp
79
61
  _, args, splatarg = exp.shift 3
80
- items = args.map { |sub| process(sub) }
62
+ items = handle_potentially_typeless_sexp args
81
63
  items << s(:splat, process(splatarg))
82
- s(*items)
64
+ items
83
65
  end
84
66
 
85
67
  def is_literal? exp
@@ -118,6 +100,17 @@ module RipperRubyParser
118
100
  s(:array, *args)
119
101
  end
120
102
  end
103
+
104
+ def handle_array_elements elems
105
+ elems = handle_potentially_typeless_sexp(elems)
106
+ elems.map do |elem|
107
+ if elem.first.is_a? Symbol
108
+ elem
109
+ else
110
+ elem.first
111
+ end
112
+ end
113
+ end
121
114
  end
122
115
  end
123
116
  end
@@ -41,6 +41,13 @@ module RipperRubyParser
41
41
  with_position_from_node_symbol(ident) {|method|
42
42
  s(:call, nil, method, s(:arglist)) }
43
43
  end
44
+
45
+ def process_super exp
46
+ _, args = exp.shift 2
47
+ args = process(args)
48
+ args.shift
49
+ s(:super, *args)
50
+ end
44
51
  end
45
52
  end
46
53
  end
@@ -4,15 +4,17 @@ module RipperRubyParser
4
4
  def process_def exp
5
5
  _, ident, params, body = exp.shift 4
6
6
  ident, pos = extract_node_symbol_with_position ident
7
+ params = convert_special_args(process(params))
7
8
  with_position(pos,
8
- s(:defn, ident, process(params), method_body(body)))
9
+ s(:defn, ident, params, method_body(body)))
9
10
  end
10
11
 
11
12
  def process_defs exp
12
- _, receiver, _, method, args, body = exp.shift 6
13
+ _, receiver, _, method, params, body = exp.shift 6
14
+ params = convert_special_args(process(params))
13
15
  s(:defs, process(receiver),
14
16
  extract_node_symbol(method),
15
- process(args), in_method { process(body) })
17
+ params, in_method { process(body) })
16
18
  end
17
19
 
18
20
  def process_return exp
@@ -81,6 +83,28 @@ module RipperRubyParser
81
83
  end
82
84
  scope
83
85
  end
86
+
87
+ SPECIAL_ARG_MARKER = {
88
+ :splat => "*",
89
+ :blockarg => "&"
90
+ }
91
+
92
+ def convert_special_args args
93
+ args.map! do |item|
94
+ if item.is_a? Symbol
95
+ item
96
+ else
97
+ if (marker = SPECIAL_ARG_MARKER[item.sexp_type])
98
+ name = extract_node_symbol item[1]
99
+ :"#{marker}#{name}"
100
+ elsif item.sexp_type == :lvar
101
+ item[1]
102
+ else
103
+ item
104
+ end
105
+ end
106
+ end
107
+ end
84
108
  end
85
109
  end
86
110
  end
@@ -1,7 +1,7 @@
1
1
  module RipperRubyParser
2
2
  module SexpHandlers
3
3
  module Operators
4
- BINARY_OPERTOR_MAP = {
4
+ BINARY_OPERATOR_MAP = {
5
5
  "&&".to_sym => :and,
6
6
  "||".to_sym => :or,
7
7
  :and => :and,
@@ -13,6 +13,11 @@ module RipperRubyParser
13
13
  :not => :not
14
14
  }
15
15
 
16
+ NEGATED_BINARY_OPERATOR_MAP = {
17
+ :"!~" => :=~,
18
+ :"!=" => :==
19
+ }
20
+
16
21
  def process_binary exp
17
22
  _, left, op, right = exp.shift 4
18
23
  if op == :=~
@@ -23,21 +28,18 @@ module RipperRubyParser
23
28
  else
24
29
  s(:call, process(left), op, s(:arglist, process(right)))
25
30
  end
26
- elsif op == :"!="
27
- s(:not, s(:call, process(left), :==, s(:arglist, process(right))))
28
- else
29
- mapped = BINARY_OPERTOR_MAP[op]
30
- if mapped
31
- left = process(left)
32
- right = process(right)
33
- if mapped == left.sexp_type
34
- s(left.sexp_type, left[1], s(mapped, left[2], right))
35
- else
36
- s(mapped, left, right)
37
- end
31
+ elsif (mapped = NEGATED_BINARY_OPERATOR_MAP[op])
32
+ s(:not, process(s(:binary, left, mapped, right)))
33
+ elsif (mapped = BINARY_OPERATOR_MAP[op])
34
+ left = process(left)
35
+ right = process(right)
36
+ if mapped == left.sexp_type
37
+ s(left.sexp_type, left[1], s(mapped, left[2], right))
38
38
  else
39
- s(:call, process(left), op, s(:arglist, process(right)))
39
+ s(mapped, left, right)
40
40
  end
41
+ else
42
+ s(:call, process(left), op, s(:arglist, process(right)))
41
43
  end
42
44
  end
43
45
 
@@ -71,6 +71,11 @@ module RipperRubyParser
71
71
  s(:class, const, parent, class_or_module_body(body)))
72
72
  end
73
73
 
74
+ def process_sclass exp
75
+ _, klass, block = exp.shift 3
76
+ s(:sclass, process(klass), class_or_module_body(block))
77
+ end
78
+
74
79
  def process_var_ref exp
75
80
  _, contents = exp.shift 2
76
81
  process(contents)
@@ -178,7 +183,14 @@ module RipperRubyParser
178
183
 
179
184
  def process_at_backref exp
180
185
  _, str, pos = exp.shift 3
181
- with_position(pos, s(:nth_ref, str[1..-1].to_i))
186
+ name = str[1..-1]
187
+ with_position pos do
188
+ if name =~ /[0-9]/
189
+ s(:nth_ref, name.to_i)
190
+ else
191
+ s(:back_ref, name.to_sym)
192
+ end
193
+ end
182
194
  end
183
195
 
184
196
  private
@@ -1,3 +1,3 @@
1
1
  module RipperRubyParser
2
- VERSION = '0.0.4'
2
+ VERSION = '0.0.5'
3
3
  end
@@ -2,22 +2,6 @@ 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
- def to_comments exp
6
- inner = exp.map do |sub_exp|
7
- if sub_exp.is_a? Sexp
8
- to_comments sub_exp
9
- else
10
- sub_exp
11
- end
12
- end
13
-
14
- if exp.comments.nil?
15
- s(*inner)
16
- else
17
- s(:comment, exp.comments, s(*inner))
18
- end
19
- end
20
-
21
5
  let :newparser do
22
6
  RipperRubyParser::Parser.new
23
7
  end
@@ -16,13 +16,23 @@ describe "Using RipperRubyParser and RubyParser" do
16
16
  File.read file
17
17
  end
18
18
 
19
- it "gives the same result" do
19
+ let :original do
20
+ oldparser.parse program
21
+ end
22
+
23
+ let :imitation do
20
24
  newparser.extra_compatible = true
21
- original = oldparser.parse program
22
- imitation = newparser.parse program
25
+ newparser.parse program
26
+ end
23
27
 
28
+ it "gives the same result" do
24
29
  formatted(imitation).must_equal formatted(original)
25
30
  end
31
+
32
+ it "gives the same result with comments" do
33
+ formatted(to_comments(imitation)).
34
+ must_equal formatted(to_comments(original))
35
+ end
26
36
  end
27
37
  end
28
38
  end
data/test/test_helper.rb CHANGED
@@ -9,16 +9,36 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
9
9
 
10
10
  require 'ripper_ruby_parser'
11
11
 
12
- class MiniTest::Unit::TestCase
12
+ class MiniTest::Spec
13
13
  def formatted exp
14
14
  exp.to_s.gsub(/\), /, "),\n")
15
15
  end
16
16
 
17
- def suppress_warnings
18
- old_verbose = $VERBOSE
19
- $VERBOSE = nil
20
- result = yield
21
- $VERBOSE = old_verbose
22
- result
17
+ def to_comments exp
18
+ inner = exp.map do |sub_exp|
19
+ if sub_exp.is_a? Sexp
20
+ to_comments sub_exp
21
+ else
22
+ sub_exp
23
+ end
24
+ end
25
+
26
+ comments = exp.comments.to_s.gsub(/\n\s*\n/, "\n")
27
+ if comments.empty?
28
+ s(*inner)
29
+ else
30
+ s(:comment, comments, s(*inner))
31
+ end
32
+ end
33
+
34
+ def assert_parsed_as sexp, code
35
+ parser = RipperRubyParser::Parser.new
36
+ result = parser.parse code
37
+ assert_equal sexp, result
23
38
  end
24
39
  end
40
+
41
+ module MiniTest::Expectations
42
+ infect_an_assertion :assert_parsed_as, :must_be_parsed_as
43
+ end
44
+
@@ -0,0 +1,70 @@
1
+ require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
2
+
3
+ describe RipperRubyParser::Parser do
4
+ describe "#parse" do
5
+ describe "for multiple assignment" do
6
+ specify do
7
+ "foo, * = bar".
8
+ must_be_parsed_as s(:masgn,
9
+ s(:array, s(:lasgn, :foo), s(:splat)),
10
+ s(:to_ary, s(:call, nil, :bar, s(:arglist))))
11
+ end
12
+
13
+ specify do
14
+ "(foo, *bar) = baz".
15
+ must_be_parsed_as s(:masgn,
16
+ s(:array,
17
+ s(:lasgn, :foo),
18
+ s(:splat, s(:lasgn, :bar))),
19
+ s(:to_ary, s(:call, nil, :baz, s(:arglist))))
20
+ end
21
+ end
22
+
23
+ describe "for assignment to a collection element" do
24
+ it "handles multiple indices" do
25
+ "foo[bar, baz] = qux".
26
+ must_be_parsed_as s(:attrasgn,
27
+ s(:call, nil, :foo, s(:arglist)),
28
+ :[]=,
29
+ s(:arglist,
30
+ s(:call, nil, :bar, s(:arglist)),
31
+ s(:call, nil, :baz, s(:arglist)),
32
+ s(:call, nil, :qux, s(:arglist))))
33
+ end
34
+ end
35
+
36
+ describe "for operator assignment" do
37
+ describe "assigning to a collection element" do
38
+ it "handles multiple indices" do
39
+ "foo[bar, baz] += qux".
40
+ must_be_parsed_as s(:op_asgn1,
41
+ s(:call, nil, :foo, s(:arglist)),
42
+ s(:arglist,
43
+ s(:call, nil, :bar, s(:arglist)),
44
+ s(:call, nil, :baz, s(:arglist))),
45
+ :+,
46
+ s(:call, nil, :qux, s(:arglist)))
47
+ end
48
+ end
49
+ end
50
+
51
+ describe "for multiple assignment" do
52
+ describe "with a right-hand splat" do
53
+ specify do
54
+ "foo, bar = *baz".
55
+ must_be_parsed_as s(:masgn,
56
+ s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
57
+ s(:splat, s(:call, nil, :baz, s(:arglist))))
58
+ end
59
+ specify do
60
+ "foo, bar = baz, *qux".
61
+ must_be_parsed_as s(:masgn,
62
+ s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
63
+ s(:array,
64
+ s(:call, nil, :baz, s(:arglist)),
65
+ s(:splat, s(:call, nil, :qux, s(:arglist)))))
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,72 @@
1
+ require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
2
+
3
+ describe RipperRubyParser::Parser do
4
+ describe "#parse" do
5
+ describe "for block parameters" do
6
+ specify do
7
+ "foo do |(bar, baz)| end".
8
+ must_be_parsed_as s(:iter,
9
+ s(:call, nil, :foo, s(:arglist)),
10
+ s(:masgn,
11
+ s(:array,
12
+ s(:lasgn, :bar),
13
+ s(:lasgn, :baz))))
14
+ end
15
+
16
+ specify do
17
+ "foo do |(bar, *baz)| end".
18
+ must_be_parsed_as s(:iter,
19
+ s(:call, nil, :foo, s(:arglist)),
20
+ s(:masgn,
21
+ s(:array,
22
+ s(:lasgn, :bar),
23
+ s(:splat, s(:lasgn, :baz)))))
24
+ end
25
+
26
+ specify do
27
+ "foo do |bar,*| end".
28
+ must_be_parsed_as s(:iter,
29
+ s(:call, nil, :foo, s(:arglist)),
30
+ s(:masgn, s(:array, s(:lasgn, :bar), s(:splat))))
31
+ end
32
+
33
+ it "behaves differently from RubyParser with a trailing comma in the block parameters" do
34
+ "foo do |bar, | end".
35
+ must_be_parsed_as s(:iter,
36
+ s(:call, nil, :foo, s(:arglist)),
37
+ s(:lasgn, :bar))
38
+ end
39
+ end
40
+
41
+ describe "for rescue/else/ensure" do
42
+ it "works for a block with multiple rescue statements" do
43
+ "begin foo; rescue; bar; rescue; baz; end".
44
+ must_be_parsed_as s(:rescue,
45
+ s(:call, nil, :foo, s(:arglist)),
46
+ s(:resbody,
47
+ s(:array),
48
+ s(:call, nil, :bar, s(:arglist))),
49
+ s(:resbody,
50
+ s(:array),
51
+ s(:call, nil, :baz, s(:arglist))))
52
+ end
53
+
54
+ it "works for a block with rescue and else" do
55
+ "begin; foo; rescue; bar; else; baz; end".
56
+ must_be_parsed_as s(:rescue,
57
+ s(:call, nil, :foo, s(:arglist)),
58
+ s(:resbody,
59
+ s(:array),
60
+ s(:call, nil, :bar, s(:arglist))),
61
+ s(:call, nil, :baz, s(:arglist)))
62
+ end
63
+
64
+ it "works for a block with only else" do
65
+ "begin; foo; else; bar; end".
66
+ must_be_parsed_as s(:block,
67
+ s(:call, nil, :foo, s(:arglist)),
68
+ s(:call, nil, :bar, s(:arglist)))
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
2
+
3
+ describe RipperRubyParser::Parser do
4
+ describe "#parse" do
5
+ describe "for postfix if" do
6
+ it "normalizes negative conditions" do
7
+ "foo if not bar".
8
+ must_be_parsed_as s(:if,
9
+ s(:call, nil, :bar, s(:arglist)),
10
+ nil,
11
+ s(:call, nil, :foo, s(:arglist)))
12
+ end
13
+ end
14
+
15
+ describe "for case" do
16
+ it "emulates RubyParser's strange handling of splat" do
17
+ "case foo; when *bar; baz; end".
18
+ must_be_parsed_as s(:case, s(:call, nil, :foo, s(:arglist)),
19
+ s(:when,
20
+ s(:array,
21
+ s(:when, s(:call, nil, :bar, s(:arglist)),
22
+ nil)),
23
+ s(:call, nil, :baz, s(:arglist))),
24
+ nil)
25
+
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,27 @@
1
+ require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
2
+
3
+ describe RipperRubyParser::Parser do
4
+ describe "#parse" do
5
+ describe "for calls to super" do
6
+ specify { "super".must_be_parsed_as s(:zsuper) }
7
+ specify { "super foo".must_be_parsed_as s(:super,
8
+ s(:call, nil, :foo, s(:arglist))) }
9
+ specify {
10
+ "super foo, bar".must_be_parsed_as s(:super,
11
+ s(:call, nil, :foo, s(:arglist)),
12
+ s(:call, nil, :bar, s(:arglist))) }
13
+ specify {
14
+ "super foo, *bar".must_be_parsed_as s(:super,
15
+ s(:call, nil, :foo, s(:arglist)),
16
+ s(:splat,
17
+ s(:call, nil, :bar, s(:arglist)))) }
18
+ specify {
19
+ "super foo, *bar, &baz".
20
+ must_be_parsed_as s(:super,
21
+ s(:call, nil, :foo, s(:arglist)),
22
+ s(:splat, s(:call, nil, :bar, s(:arglist))),
23
+ s(:block_pass, s(:call, nil, :baz, s(:arglist)))) }
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,16 @@
1
+ require File.expand_path('../test_helper.rb', File.dirname(__FILE__))
2
+
3
+ describe RipperRubyParser::Parser do
4
+ describe "#parse" do
5
+ describe "for negated operators" do
6
+ specify do
7
+ "foo !~ bar".must_be_parsed_as s(:not,
8
+ s(:call,
9
+ s(:call, nil, :foo, s(:arglist)),
10
+ :=~,
11
+ s(:arglist,
12
+ s(:call, nil, :bar, s(:arglist)))))
13
+ end
14
+ end
15
+ end
16
+ end
@@ -29,6 +29,10 @@ describe RipperRubyParser::Parser do
29
29
  nil,
30
30
  s(:scope))
31
31
  end
32
+
33
+ it "works for singleton classes" do
34
+ "class << self; end".must_be_parsed_as s(:sclass, s(:self), s(:scope))
35
+ end
32
36
  end
33
37
 
34
38
  describe "for a module declaration" do
@@ -254,8 +258,7 @@ describe RipperRubyParser::Parser do
254
258
 
255
259
  describe "for the for statement" do
256
260
  it "works with do" do
257
- result = suppress_warnings {
258
- parser.parse "for foo in bar do; baz; end" }
261
+ result = parser.parse "for foo in bar do; baz; end"
259
262
  result.must_equal s(:for,
260
263
  s(:call, nil, :bar, s(:arglist)),
261
264
  s(:lasgn, :foo),
@@ -263,8 +266,7 @@ describe RipperRubyParser::Parser do
263
266
  end
264
267
 
265
268
  it "works without do" do
266
- result = suppress_warnings {
267
- parser.parse "for foo in bar; baz; end" }
269
+ result = parser.parse "for foo in bar; baz; end"
268
270
  result.must_equal s(:for,
269
271
  s(:call, nil, :bar, s(:arglist)),
270
272
  s(:lasgn, :foo),
@@ -321,8 +323,7 @@ describe RipperRubyParser::Parser do
321
323
  end
322
324
 
323
325
  it "works with assignment to an error variable" do
324
- result = suppress_warnings {
325
- parser.parse "begin; foo; rescue => e; bar; end" }
326
+ result = parser.parse "begin; foo; rescue => e; bar; end"
326
327
  result.must_equal s(:rescue,
327
328
  s(:call, nil, :foo, s(:arglist)),
328
329
  s(:resbody,
@@ -340,8 +341,7 @@ describe RipperRubyParser::Parser do
340
341
  end
341
342
 
342
343
  it "works with filtering of the exception type and assignment to an error variable" do
343
- result = suppress_warnings {
344
- parser.parse "begin; foo; rescue Bar => e; baz; end" }
344
+ result = parser.parse "begin; foo; rescue Bar => e; baz; end"
345
345
  result.must_equal s(:rescue,
346
346
  s(:call, nil, :foo, s(:arglist)),
347
347
  s(:resbody,
@@ -1188,6 +1188,9 @@ describe RipperRubyParser::Parser do
1188
1188
  result.must_equal s(:nth_ref, 1)
1189
1189
  end
1190
1190
 
1191
+ specify { "$'".must_be_parsed_as s(:back_ref, :"'") }
1192
+ specify { "$&".must_be_parsed_as s(:back_ref, :"&") }
1193
+
1191
1194
  it "works for class variables" do
1192
1195
  result = parser.parse "@@foo"
1193
1196
  result.must_equal s(:cvar, :@@foo)
@@ -1263,7 +1266,7 @@ describe RipperRubyParser::Parser do
1263
1266
 
1264
1267
  describe "for operator assignment" do
1265
1268
  it "works with +=" do
1266
- result = suppress_warnings { parser.parse "foo += bar" }
1269
+ result = parser.parse "foo += bar"
1267
1270
  result.must_equal s(:lasgn,
1268
1271
  :foo,
1269
1272
  s(:call,
@@ -1273,7 +1276,7 @@ describe RipperRubyParser::Parser do
1273
1276
  end
1274
1277
 
1275
1278
  it "works with -=" do
1276
- result = suppress_warnings { parser.parse "foo -= bar" }
1279
+ result = parser.parse "foo -= bar"
1277
1280
  result.must_equal s(:lasgn,
1278
1281
  :foo,
1279
1282
  s(:call,
@@ -1283,7 +1286,7 @@ describe RipperRubyParser::Parser do
1283
1286
  end
1284
1287
 
1285
1288
  it "works with ||=" do
1286
- result = suppress_warnings { parser.parse "foo ||= bar" }
1289
+ result = parser.parse "foo ||= bar"
1287
1290
  result.must_equal s(:op_asgn_or,
1288
1291
  s(:lvar, :foo),
1289
1292
  s(:lasgn, :foo,
@@ -1339,7 +1342,7 @@ describe RipperRubyParser::Parser do
1339
1342
 
1340
1343
  describe "for multiple assignment" do
1341
1344
  it "works the same number of items on each side" do
1342
- result = suppress_warnings { parser.parse "foo, bar = baz, qux" }
1345
+ result = parser.parse "foo, bar = baz, qux"
1343
1346
  result.must_equal s(:masgn,
1344
1347
  s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
1345
1348
  s(:array,
@@ -1348,7 +1351,7 @@ describe RipperRubyParser::Parser do
1348
1351
  end
1349
1352
 
1350
1353
  it "works with a single item on the right-hand side" do
1351
- result = suppress_warnings { parser.parse "foo, bar = baz" }
1354
+ result = parser.parse "foo, bar = baz"
1352
1355
  result.must_equal s(:masgn,
1353
1356
  s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
1354
1357
  s(:to_ary,
@@ -1356,7 +1359,7 @@ describe RipperRubyParser::Parser do
1356
1359
  end
1357
1360
 
1358
1361
  it "works with left-hand splat" do
1359
- result = suppress_warnings { parser.parse "foo, *bar = baz, qux" }
1362
+ result = parser.parse "foo, *bar = baz, qux"
1360
1363
  result.must_equal s(:masgn,
1361
1364
  s(:array, s(:lasgn, :foo), s(:splat, s(:lasgn, :bar))),
1362
1365
  s(:array,
@@ -1365,7 +1368,7 @@ describe RipperRubyParser::Parser do
1365
1368
  end
1366
1369
 
1367
1370
  it "works with brackets around the left-hand side" do
1368
- result = suppress_warnings { parser.parse "(foo, bar) = baz" }
1371
+ result = parser.parse "(foo, bar) = baz"
1369
1372
  result.must_equal s(:masgn,
1370
1373
  s(:array, s(:lasgn, :foo), s(:lasgn, :bar)),
1371
1374
  s(:to_ary,
@@ -1373,7 +1376,7 @@ describe RipperRubyParser::Parser do
1373
1376
  end
1374
1377
 
1375
1378
  it "works with complex destructuring" do
1376
- result = suppress_warnings { parser.parse "foo, (bar, baz) = qux" }
1379
+ result = parser.parse "foo, (bar, baz) = qux"
1377
1380
  result.must_equal s(:masgn,
1378
1381
  s(:array,
1379
1382
  s(:lasgn, :foo),
@@ -1620,7 +1623,7 @@ describe RipperRubyParser::Parser do
1620
1623
 
1621
1624
  describe "for expressions" do
1622
1625
  it "handles assignment inside binary operator expressions" do
1623
- result = suppress_warnings { parser.parse "foo + (bar = baz)" }
1626
+ result = parser.parse "foo + (bar = baz)"
1624
1627
  result.must_equal s(:call,
1625
1628
  s(:call, nil, :foo, s(:arglist)),
1626
1629
  :+,
@@ -1631,7 +1634,7 @@ describe RipperRubyParser::Parser do
1631
1634
  end
1632
1635
 
1633
1636
  it "handles assignment inside unary operator expressions" do
1634
- result = suppress_warnings { parser.parse "+(foo = bar)" }
1637
+ result = parser.parse "+(foo = bar)"
1635
1638
  result.must_equal s(:call,
1636
1639
  s(:lasgn, :foo, s(:call, nil, :bar, s(:arglist))),
1637
1640
  :+@,
@@ -1650,6 +1653,15 @@ describe RipperRubyParser::Parser do
1650
1653
  result.comments.must_equal "# Foo\n"
1651
1654
  end
1652
1655
 
1656
+ it "handles comments for methods with explicit receiver" do
1657
+ result = parser.parse "# Foo\ndef foo.bar; end"
1658
+ result.must_equal s(:defs,
1659
+ s(:call, nil, :foo, s(:arglist)),
1660
+ :bar,
1661
+ s(:args), s(:scope, s(:block)))
1662
+ result.comments.must_equal "# Foo\n"
1663
+ end
1664
+
1653
1665
  it "matches comments to the correct entity" do
1654
1666
  result = parser.parse "# Foo\nclass Foo\n# Bar\ndef bar\nend\nend"
1655
1667
  result.must_equal s(:class, :Foo, nil,
@@ -1669,6 +1681,27 @@ describe RipperRubyParser::Parser do
1669
1681
  s(:args), s(:scope, s(:block, s(:nil))))
1670
1682
  result.comments.must_equal "# Foo\n# Bar\n"
1671
1683
  end
1684
+
1685
+ it "handles the use of symbols that are keywords" do
1686
+ result = parser.parse "# Foo\ndef bar\n:class\nend"
1687
+ result.must_equal s(:defn,
1688
+ :bar,
1689
+ s(:args),
1690
+ s(:scope, s(:block, s(:lit, :class))))
1691
+ result.comments.must_equal "# Foo\n"
1692
+ end
1693
+
1694
+ it "handles use of singleton class inside methods" do
1695
+ result = parser.parse "# Foo\ndef bar\nclass << self\nbaz\nend\nend"
1696
+ result.must_equal s(:defn,
1697
+ :bar,
1698
+ s(:args),
1699
+ s(:scope,
1700
+ s(:block,
1701
+ s(:sclass, s(:self),
1702
+ s(:scope, s(:call, nil, :baz, s(:arglist)))))))
1703
+ result.comments.must_equal "# Foo\n"
1704
+ end
1672
1705
  end
1673
1706
 
1674
1707
  # Note: differences in the handling of line numbers are not caught by
@@ -1786,12 +1819,12 @@ describe RipperRubyParser::Parser do
1786
1819
  end
1787
1820
 
1788
1821
  it "works for assignment of the empty hash" do
1789
- result = suppress_warnings { parser.parse "foo = {}" }
1822
+ result = parser.parse "foo = {}"
1790
1823
  result.line.must_equal 1
1791
1824
  end
1792
1825
 
1793
1826
  it "works for multiple assignment of empty hashes" do
1794
- result = suppress_warnings { parser.parse "foo, bar = {}, {}" }
1827
+ result = parser.parse "foo, bar = {}, {}"
1795
1828
  result.line.must_equal 1
1796
1829
  end
1797
1830
 
@@ -185,11 +185,11 @@ describe RipperRubyParser::SexpProcessor do
185
185
  end
186
186
 
187
187
  describe "for a :params sexp" do
188
- describe "with a normal argument" do
189
- it "uses the bare argument names" do
188
+ describe "with a normal arguments" do
189
+ it "creates :lvar sexps" do
190
190
  sexp = s(:params, s(s(:@ident, "bar", s(1, 8))), nil, nil, nil, nil)
191
191
  result = processor.process sexp
192
- result.must_equal s(:args, :bar)
192
+ result.must_equal s(:args, s(:lvar, :bar))
193
193
  end
194
194
  end
195
195
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ripper_ruby_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
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: 2012-03-31 00:00:00.000000000 Z
12
+ date: 2012-04-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sexp_processor
16
- requirement: &22929360 !ruby/object:Gem::Requirement
16
+ requirement: &18762580 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3.0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *22929360
24
+ version_requirements: *18762580
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: minitest
27
- requirement: &22928840 !ruby/object:Gem::Requirement
27
+ requirement: &18762060 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 2.11.2
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *22928840
35
+ version_requirements: *18762060
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rake
38
- requirement: &22928360 !ruby/object:Gem::Requirement
38
+ requirement: &18761580 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.9.2
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *22928360
46
+ version_requirements: *18761580
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: ruby_parser
49
- requirement: &22927880 !ruby/object:Gem::Requirement
49
+ requirement: &18761100 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 2.3.1
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *22927880
57
+ version_requirements: *18761100
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: simplecov
60
- requirement: &22927500 !ruby/object:Gem::Requirement
60
+ requirement: &18760720 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,7 +65,7 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *22927500
68
+ version_requirements: *18760720
69
69
  description:
70
70
  email:
71
71
  - matijs@matijs.net
@@ -103,8 +103,13 @@ files:
103
103
  - test/end_to_end/line_numbering_test.rb
104
104
  - test/end_to_end/error_conditions_test.rb
105
105
  - test/unit/parser_test.rb
106
+ - test/unit/parser_blocks_test.rb
106
107
  - test/unit/sexp_processor_test.rb
108
+ - test/unit/parser_operators_test.rb
109
+ - test/unit/parser_conditionals_test.rb
107
110
  - test/unit/version_test.rb
111
+ - test/unit/parser_assignment_test.rb
112
+ - test/unit/parser_method_calls_test.rb
108
113
  - test/unit/commenting_sexp_builder_test.rb
109
114
  - README.rdoc
110
115
  - Rakefile
@@ -144,6 +149,11 @@ test_files:
144
149
  - test/end_to_end/test_comparison_test.rb
145
150
  - test/test_helper.rb
146
151
  - test/unit/commenting_sexp_builder_test.rb
152
+ - test/unit/parser_assignment_test.rb
153
+ - test/unit/parser_blocks_test.rb
154
+ - test/unit/parser_conditionals_test.rb
155
+ - test/unit/parser_method_calls_test.rb
156
+ - test/unit/parser_operators_test.rb
147
157
  - test/unit/parser_test.rb
148
158
  - test/unit/sexp_processor_test.rb
149
159
  - test/unit/version_test.rb