jruby-parser 0.3 → 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.
Binary file
@@ -1,3 +1,3 @@
1
1
  module JRubyParser
2
- VERSION = "0.3"
2
+ VERSION = "0.4"
3
3
  end
@@ -110,11 +110,123 @@ module HaveArgCounts
110
110
  ArgCountsMatcher.new(*args)
111
111
  end
112
112
  end
113
-
113
+
114
+ class HaveParametersMatcher
115
+ def initialize(*list)
116
+ @with_decorations = []
117
+ @without_decorations = []
118
+ list.each do |e1, e2|
119
+ @without_decorations << e1
120
+ @with_decorations << (e2 || e1)
121
+ end
122
+ end
123
+
124
+ def matches?(args)
125
+ @actual_with = args.get_normative_parameter_name_list(false).to_a
126
+ @actual_without = args.get_normative_parameter_name_list(true).to_a
127
+ @with_decorations == @actual_with && @without_decorations == @actual_without
128
+ end
129
+
130
+ def failure_message
131
+ error = ""
132
+ if @with_decorations != @actual_with
133
+ error << %[expected #{@actual_with.inspect} to have #{@with_decorations.inspect}.]
134
+ end
135
+
136
+ if @without_decorations != @actual_without
137
+ error << %[ expected #{@actual_without.inspect} to have #{@without_decorations.inspect}.]
138
+ end
139
+ error
140
+ end
141
+
142
+ def negative_failure_message
143
+ error = ""
144
+ if @with_decorations != @actual_with
145
+ error << %[expected #{@actual_with.inspect} to not have #{@with_decorations.inspect}.]
146
+ end
147
+
148
+ if @without_decorations != @actual_without
149
+ error << %[ expected #{@actual_without.inspect} to not have #{@without_decorations.inspect}.]
150
+ end
151
+ error
152
+ end
153
+ end
154
+
155
+ module HaveParameters
156
+ def have_parameters(*args)
157
+ HaveParametersMatcher.new(*args)
158
+ end
159
+ end
160
+
161
+ class HaveStaticAssignmentsMatcher
162
+ java_import org.jrubyparser.ast.FixnumNode
163
+ java_import org.jrubyparser.ast.ListNode
164
+
165
+ def initialize(list)
166
+ @list = list
167
+ end
168
+
169
+ def matches?(args)
170
+ @actual_list = args.calculateStaticAssignments.to_a
171
+ @failures_var_names = []
172
+ @failures_var_values = []
173
+
174
+ @list.each_with_index do |arr, i|
175
+ node_pair = @actual_list[i]
176
+ expected_var, expected_value = arr[0].to_s, arr[1]
177
+ actual_var, actual_value = node_pair.first.name, value_for(node_pair.second)
178
+
179
+ @failures_var_names << [expected_var, actual_var] if expected_var != actual_var
180
+ @failures_var_values << [expected_value, actual_value] if expected_value != actual_value
181
+
182
+ end
183
+
184
+ @failures_var_names.size == 0 && @failures_var_values.size == 0
185
+ end
186
+
187
+ def value_for(node)
188
+ if node.kind_of? FixnumNode
189
+ node.value
190
+ elsif node.kind_of? ListNode
191
+ node.child_nodes.map {|e| value_for(e)}
192
+ else
193
+ node
194
+ end
195
+ end
196
+
197
+ def failure_message
198
+ names = @failures_var_names.inject("names: ") do |s, e|
199
+ s << "#{e[0]} != #{e[1]} "
200
+ end
201
+
202
+ @failures_var_values.inject(names + "\nvalues: ") do |s, e|
203
+ s << "#{e[0]} != #{e[1]} "
204
+ end
205
+ end
206
+
207
+ def negative_failure_message
208
+ names = @failures_var_names.inject("names: ") do |s, e|
209
+ s << "#{e[0]} !!= #{e[1]}"
210
+ end
211
+
212
+ @failures_var_values.inject(names + "\nvalues: ") do |s, e|
213
+ s << "#{e[0]} !!= #{e[1]} "
214
+ end
215
+ end
216
+ end
217
+
218
+ module HaveStaticAssignments
219
+ def have_static_assignments(*args)
220
+ HaveStaticAssignmentsMatcher.new(*args)
221
+ end
222
+ end
223
+
114
224
  #module Spec::Example::ExampleMethods
115
225
  class Object
116
226
  include HavePosition
117
227
  include HaveName
118
228
  include HaveNameAndPosition
119
229
  include HaveArgCounts
230
+ include HaveParameters
231
+ include HaveStaticAssignments
120
232
  end
@@ -20,4 +20,17 @@ class Object
20
20
  config = version == 1.8 ? CONFIG_18 : CONFIG_19
21
21
  PARSER.parse "<code>", source(code), config
22
22
  end
23
+
24
+ ##
25
+ # parse code but record first '^' and return the node which
26
+ # that offset represents. If you are testing source which contains
27
+ # a caret already you can substitute the value with a delimeter which
28
+ # will work.
29
+ def caret_parse(code, version=1.8, caret='^')
30
+ caret_index = code.index(caret)
31
+ raise ArgumentError.new("Caret '^' missing: #{code}") unless caret_index
32
+
33
+ root = parse(code.sub(caret, ''), version)
34
+ [root, root.node_at(caret_index)]
35
+ end
23
36
  end
@@ -0,0 +1,31 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../../lib"
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../helpers"
3
+ require 'java'
4
+ require 'jruby-parser'
5
+ require 'parser_helpers'
6
+
7
+ describe JRubyParser do
8
+ [JRubyParser::Compat::RUBY1_8, JRubyParser::Compat::RUBY1_9].each do |v|
9
+ it "children can ask for the method it is contained in [#{v}]" do
10
+ parse("def foo; true if false; end").find_node(:defn) do |defn|
11
+ defn.find_node(:true).method_for.should == defn
12
+ defn.find_node(:false).method_for.should == defn
13
+ defn.find_node(:if).method_for.should == defn
14
+ end
15
+ end
16
+
17
+ it "children can ask for the iter/block it is contained in [#{v}]" do
18
+ parse("proc { |a| proc { |b| true } }").find_node(:iter) do |iter1|
19
+ iter1.find_node(:true).innermost_iter.should_not == iter1
20
+ iter1.find_node(:true).outermost_iter.should == iter1
21
+ end
22
+ end
23
+
24
+ it "should not find an innermost block if method is inside block" do
25
+ parse("proc { def foo; true; end }").find_node(:true) do |tru|
26
+ tru.innermost_iter.should == nil
27
+ tru.outermost_iter.should == nil
28
+ end
29
+ end
30
+ end
31
+ end
@@ -1,25 +1,27 @@
1
1
  $LOAD_PATH.unshift File.dirname(__FILE__) + "/../../lib"
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../helpers"
2
3
  require 'java'
3
4
  require 'jruby-parser'
5
+ require 'parser_helpers'
4
6
 
5
7
  describe JRubyParser do
6
- [JRubyParser::Compat::RUBY1_8, JRubyParser::Compat::RUBY1_9].each do |v|
7
- it "finds fcall via simple symbol search" do
8
- JRubyParser.parse("b = foo(1)").tap do |root|
8
+ [1.8, 1.9].each do |v|
9
+ it "finds fcall via simple symbol search [#{v}]" do
10
+ parse("b = foo(1)").tap do |root|
9
11
  fcall = root.find_type(:fcall)
10
12
  fcall.should_not == nil
11
13
  end
12
14
  end
13
15
 
14
- it "finds specific fcall by block and simple symbol" do
15
- JRubyParser.parse("foo(1); bar(2)").tap do |root|
16
+ it "finds specific fcall by block and simple symbol [#{v}]" do
17
+ parse("foo(1); bar(2)").tap do |root|
16
18
  fcall = root.find_type(:fcall) { |n| n.name == "bar" }
17
19
  fcall.name.should == "bar"
18
20
  end
19
21
  end
20
22
 
21
- it "finds type and method named based on Enumerable find" do
22
- JRubyParser.parse("foo(1); bar(2)").tap do |root|
23
+ it "finds type and method named based on Enumerable find [#{v}]" do
24
+ parse("foo(1); bar(2)").tap do |root|
23
25
  fcall = root.find { |n| n.short_name == "fcall" && n.name == "bar"}
24
26
  fcall.name.should == "bar"
25
27
  fcalls = root.find_all { |n| n.short_name == "fcall" }
@@ -0,0 +1,18 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../../lib"
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../helpers"
3
+ require 'java'
4
+ require 'jruby-parser'
5
+ require 'parser_helpers'
6
+
7
+ describe JRubyParser do
8
+ [1.8, 1.9].each do |v|
9
+ it "finds fcall via simple getNodeAt search [#{v}]" do
10
+ caret_parse("b = fo^o(1)", v).tap do |root, caret_node|
11
+ root.find_node(:fcall).should == caret_node
12
+ end
13
+ caret_parse("b = foo(^1)", v).tap do |root, caret_node|
14
+ root.find_node(:fixnum).should == caret_node
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,38 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../../lib"
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../helpers"
3
+ require 'java'
4
+ require 'jruby-parser'
5
+ require 'parser_helpers'
6
+
7
+ describe JRubyParser do
8
+ [1.8, 1.9].each do |v|
9
+ it "finds parameter via is_block_parameter [#{v}]" do
10
+ caret_parse("proc { |^a| }", v).tap do |root, caret_node|
11
+ caret_node.block_parameter?.should == true
12
+ end
13
+ caret_parse("proc { |^a,b| }", v).tap do |root, caret_node|
14
+ caret_node.block_parameter?.should == true
15
+ end
16
+ caret_parse("proc { |*^a| }", v).tap do |root, caret_node|
17
+ caret_node.block_parameter?.should == true
18
+ end
19
+ caret_parse("proc { |a, (b, ^c)| }", v).tap do |root, caret_node|
20
+ caret_node.block_parameter?.should == true
21
+ end
22
+ caret_parse("proc { |&^a| }", v).tap do |root, caret_node|
23
+ caret_node.block_parameter?.should == true
24
+ end
25
+
26
+ if v == 1.9
27
+ caret_parse("proc { |a, ^b=1| }", v).tap do |root, caret_node|
28
+ caret_node.block_parameter?.should == true
29
+ end
30
+
31
+ caret_parse("proc { |c| proc { |a, b=^c| } }", v).tap do |root, caret_node|
32
+ caret_node.block_parameter?.should == false
33
+ end
34
+
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,35 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../../lib"
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../helpers"
3
+ require 'java'
4
+ require 'jruby-parser'
5
+ require 'parser_helpers'
6
+
7
+ describe JRubyParser do
8
+ [1.8, 1.9].each do |v|
9
+ it "finds parameter via is_method_parameter [#{v}]" do
10
+ caret_parse("def foo(^a); end", v).tap do |root, caret_node|
11
+ caret_node.method_parameter?.should == true
12
+ end
13
+ caret_parse("def foo(^a,b); end", v).tap do |root, caret_node|
14
+ caret_node.method_parameter?.should == true
15
+ end
16
+ caret_parse("def foo(*^a); end", v).tap do |root, caret_node|
17
+ caret_node.method_parameter?.should == true
18
+ end
19
+ caret_parse("def foo(&^a); end", v).tap do |root, caret_node|
20
+ caret_node.method_parameter?.should == true
21
+ end
22
+ caret_parse("def foo(a, ^b=1); end", v).tap do |root, caret_node|
23
+ caret_node.method_parameter?.should == true
24
+ end
25
+ if v == 1.9
26
+ caret_parse("def foo(a, (b, ^c)); end", v).tap do |root, caret_node|
27
+ caret_node.method_parameter?.should == true
28
+ end
29
+ caret_parse("def foo(a, b=1, ^c); end", v).tap do |root, caret_node|
30
+ caret_node.method_parameter?.should == true
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -2,51 +2,51 @@ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../../lib"
2
2
  require 'jruby-parser'
3
3
 
4
4
  describe JRubyParser do
5
- [JRubyParser::Compat::RUBY1_8, JRubyParser::Compat::RUBY1_9].each do |v|
6
- it "rewrites method name from foo to bar" do
7
- JRubyParser.parse("b = foo(1)").tap do |root|
5
+ [1.8, 1.9].each do |v|
6
+ it "rewrites method name from foo to bar [#{v}]" do
7
+ parse("b = foo(1)").tap do |root|
8
8
  fcall = root.find_node(:fcall)
9
9
  fcall.name = 'bar'
10
10
  end.to_source.should == "b = bar(1)"
11
11
 
12
- JRubyParser.parse("b = foo 1").tap do |root|
12
+ parse("b = foo 1").tap do |root|
13
13
  fcall = root.find_node(:fcall)
14
14
  fcall.name = 'bar'
15
15
  end.to_source.should == "b = bar 1"
16
16
  end
17
17
 
18
- it "rewrites between different coercible ruby types" do
18
+ it "rewrites between different coercible ruby types [#{v}]" do
19
19
  [1, 1.0, true, false, nil, "a"].each do |replace|
20
- JRubyParser.parse("foo 1").tap do |root|
20
+ parse("foo 1").tap do |root|
21
21
  fcall = root.find_node(:fcall)
22
22
  fcall.args[0] = replace
23
23
  end.to_source.should == "foo #{replace.inspect}"
24
24
  end
25
25
  end
26
26
 
27
- it "rewrites receiver of a call" do
28
- JRubyParser.parse("1.to_f(1)").tap do |root|
27
+ it "rewrites receiver of a call [#{v}]" do
28
+ parse("1.to_f(1)").tap do |root|
29
29
  call = root.find_node(:call)
30
30
  call.receiver = 2
31
31
  end.to_source.should == "2.to_f(1)"
32
32
  end
33
33
 
34
- it "rewrites can add to simple args" do
35
- JRubyParser.parse("foo(1)").tap do |root|
34
+ it "rewrites can add to simple args [#{v}]" do
35
+ parse("foo(1)").tap do |root|
36
36
  call = root.find_node(:fcall)
37
37
  call.args << 2
38
38
  end.to_source.should == "foo(1, 2)"
39
39
  end
40
40
 
41
- it "rewrites can add to simple args" do
42
- JRubyParser.parse("foo(1)").tap do |root|
41
+ it "rewrites can add to simple args [#{v}]" do
42
+ parse("foo(1)").tap do |root|
43
43
  call = root.find_node(:fcall)
44
44
  call.args = [3, 4]
45
45
  end.to_source.should == "foo(3, 4)"
46
46
  end
47
47
 
48
- it "rewrites op element assignment" do
49
- JRubyParser.parse("a[3] += 5").tap do |root|
48
+ it "rewrites op element assignment [#{v}]" do
49
+ parse("a[3] += 5").tap do |root|
50
50
  op = root.find_node(:opelementasgn)
51
51
  op.receiver = 1
52
52
  op.args[0] = 2
@@ -0,0 +1,171 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../helpers"
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../../lib"
3
+ require 'jruby-parser'
4
+ require 'parser_helpers'
5
+ require 'node_helpers'
6
+
7
+ describe Parser do
8
+ [1.9].each do |v|
9
+ it "parses a simple multiple assignment [#{v}]" do
10
+ parse("a,b,c = 1,2,3", v).find_node(:multipleasgn19).tap do |masgn|
11
+ masgn.should have_static_assignments([[:a, 1], [:b, 2], [:c, 3]])
12
+ end
13
+ end
14
+
15
+ it "parses a simple lhs splat multiple assignment [#{v}]" do
16
+ parse("a,*b = 1,2,3", v).find_node(:multipleasgn19).tap do |masgn|
17
+ masgn.should have_static_assignments([[:a, 1], [:b, [2, 3]]])
18
+ end
19
+ parse("a,b,*c = 1,2,3,4", v).find_node(:multipleasgn19).tap do |masgn|
20
+ masgn.should have_static_assignments([[:a, 1], [:b, 2], [:c, [3,4]]])
21
+ end
22
+ end
23
+
24
+ it "parses a simple lhs splat multiple assignment [#{v}]" do
25
+ parse("*a,b = 1,2,3", v).find_node(:multipleasgn19).tap do |masgn|
26
+ masgn.should have_static_assignments([[:a, [1, 2]], [:b, 3]])
27
+ end
28
+ parse("*a,b,c = 1,2,3,4", v).find_node(:multipleasgn19).tap do |masgn|
29
+ masgn.should have_static_assignments([[:a, [1, 2]], [:b, 3], [:c, 4]])
30
+ end
31
+ end
32
+
33
+ it "parses a simple lhs splat multiple assignment [#{v}]" do
34
+ parse("a,*b, c = 1,2,3,4", v).find_node(:multipleasgn19).tap do |masgn|
35
+ masgn.should have_static_assignments([[:a, 1], [:b, [2, 3]], [:c, 4]])
36
+ end
37
+ parse("a, b, *c, d = 1,2,3,4,5", v).find_node(:multipleasgn19).tap do |masgn|
38
+ masgn.should have_static_assignments([[:a, 1], [:b, 2], [:c, [3, 4]], [:d, 5]])
39
+ end
40
+ parse("a, *b, c, d = 1,2,3,4,5", v).find_node(:multipleasgn19).tap do |masgn|
41
+ masgn.should have_static_assignments([[:a, 1], [:b, [2, 3]], [:c, 4], [:d, 5]])
42
+ end
43
+ end
44
+
45
+ it "parses a simple lhs splat multiple assignment [#{v}]" do
46
+ parse("a,*b,c,d = 1,2,3", v).find_node(:multipleasgn19).tap do |masgn|
47
+ masgn.should have_static_assignments([[:a, 1], [:b, []], [:c, 2], [:d, 3]])
48
+ end
49
+ end
50
+
51
+ it "parses a simple rhs splat multiple assignment [#{v}]" do
52
+ ast = parse("a,*b = 1,*foo", v)
53
+ foo = ast.find_node(:vcall)
54
+ ast.find_node(:multipleasgn19).tap do |masgn|
55
+ masgn.should have_static_assignments([[:a, 1], [:b, foo]])
56
+ end
57
+ end
58
+
59
+ it "parses a simple rhs splat multiple assignment [#{v}]" do
60
+ ast = parse("*a,b = *foo,1", v)
61
+ splatted_foo = ast.find_node(:splat)
62
+ ast.find_node(:multipleasgn19).tap do |masgn|
63
+ masgn.should have_static_assignments([[:a, splatted_foo], [:b, 1]])
64
+ end
65
+ end
66
+
67
+ it "method: Can detect simple parameter is used" do
68
+ parse("def foo(a); a; end").find_node(:defn) do |defn|
69
+ defn.args.get_normative_parameter_name_list(true).each do |parameter|
70
+ defn.is_parameter_used(parameter).should == true
71
+ end
72
+ end
73
+
74
+ parse("def foo(a,b); a; b; end").find_node(:defn) do |defn|
75
+ defn.args.get_normative_parameter_name_list(true).each do |parameter|
76
+ defn.is_parameter_used(parameter).should == true
77
+ end
78
+ end
79
+
80
+ parse("def foo(a,b); a=1; b; end").find_node(:defn) do |defn|
81
+ defn.is_parameter_used("a").should == false
82
+ defn.is_parameter_used("b").should == true
83
+ end
84
+ end
85
+
86
+ it "method: Can detect some simple parameters are used" do
87
+ parse("def foo(a,b); b; end").find_node(:defn) do |defn|
88
+ defn.is_parameter_used("a").should == false
89
+ defn.is_parameter_used("b").should == true
90
+ end
91
+
92
+ parse("def foo(a,b); b if true; end").find_node(:defn) do |defn|
93
+ defn.is_parameter_used("a").should == false
94
+ defn.is_parameter_used("b").should == true
95
+ end
96
+
97
+ parse("def foo(a,b); proc { b if true }; end").find_node(:defn) do |defn|
98
+ defn.is_parameter_used("a").should == false
99
+ defn.is_parameter_used("b").should == true
100
+ end
101
+
102
+ parse("def foo a, b, c\nputs a, b, c\nend").find_node(:defn) do |defn|
103
+ defn.is_parameter_used("a").should == true
104
+ defn.is_parameter_used("b").should == true
105
+ defn.is_parameter_used("c").should == true
106
+ end
107
+
108
+ parse("def foo(a, b); b.each_answer {|n| data if n == a }; end") do |defn|
109
+ defn.is_parameter_used("a").should == true
110
+ defn.is_parameter_used("b").should == true
111
+ end
112
+ end
113
+
114
+ it "method: Can detect some simple optarg params are used" do
115
+ parse("def foo(a,b = {}); b; end").find_node(:defn) do |defn|
116
+ defn.is_parameter_used("a").should == false
117
+ defn.is_parameter_used("b").should == true
118
+ end
119
+ end
120
+
121
+ it "method: Can detect zsuper usage" do
122
+ parse("def foo(a,b = {}); super; end").find_node(:defn) do |defn|
123
+ defn.is_parameter_used("a").should == true
124
+ defn.is_parameter_used("b").should == true
125
+ end
126
+ end
127
+
128
+ it "block/iter: Can detect simple parameter is used" do
129
+ parse("proc { |a, b| a; b }").find_node(:iter) do |iter|
130
+ iter.is_parameter_used("a").should == true
131
+ iter.is_parameter_used("b").should == true
132
+ end
133
+ end
134
+
135
+ it "block/iter: Can detect simple parameter is used" do
136
+ parse("proc { |a, b| a=1; b }").find_node(:iter) do |iter|
137
+ iter.is_parameter_used("a").should == false
138
+ iter.is_parameter_used("b").should == true
139
+ end
140
+ end
141
+
142
+ it "block/iter: Can detect some simple parameters are used" do
143
+ parse("proc {|a,b| b }").find_node(:iter) do |iter|
144
+ iter.is_parameter_used("a").should == false
145
+ iter.is_parameter_used("b").should == true
146
+ end
147
+
148
+ parse("proc {|a,b| b if true }").find_node(:iter) do |iter|
149
+ iter.is_parameter_used("a").should == false
150
+ iter.is_parameter_used("b").should == true
151
+ end
152
+
153
+ parse("proc {|a,b| proc { b if true } }").find_node(:iter) do |iter|
154
+ iter.is_parameter_used("a").should == false
155
+ iter.is_parameter_used("b").should == true
156
+ end
157
+
158
+ parse("proc {|a, b, c| puts a, b, c }").find_node(:iter) do |iter|
159
+ iter.is_parameter_used("a").should == true
160
+ iter.is_parameter_used("b").should == true
161
+ iter.is_parameter_used("c").should == true
162
+ end
163
+
164
+ parse("proc {|a, b| b.each_answer {|n| data if n == a } }") do |iter|
165
+ iter.is_parameter_used("a").should == true
166
+ iter.is_parameter_used("b").should == true
167
+ end
168
+ end
169
+
170
+ end
171
+ end
@@ -10,6 +10,7 @@ describe Parser do
10
10
  parse("def foo\nend\n", v).find_node(:defn).tap do |defn|
11
11
  defn.should have_name_and_position("foo", 0, 1, 0, 11)
12
12
  defn.args_node.should have_arg_counts(0, 0, false, false)
13
+ defn.args_node.should have_parameters()
13
14
  end
14
15
  end
15
16
 
@@ -17,6 +18,7 @@ describe Parser do
17
18
  parse("def foo()\nend\n", v).find_node(:defn).tap do |defn|
18
19
  defn.should have_name_and_position("foo", 0, 1, 0, 13)
19
20
  defn.args_node.should have_arg_counts(0, 0, false, false)
21
+ defn.args_node.should have_parameters()
20
22
  end
21
23
  end
22
24
 
@@ -24,6 +26,7 @@ describe Parser do
24
26
  parse("def foo a\nend\n", v).find_node(:defn).tap do |defn|
25
27
  defn.should have_name_and_position("foo", 0, 1, 0, 13)
26
28
  defn.args_node.should have_arg_counts(1, 0, false, false)
29
+ defn.args_node.should have_parameters('a')
27
30
  defn.args_node.pre.tap do |pre|
28
31
  pre.should have_position(0, 0, 8, 9)
29
32
  pre[0].should have_name_and_position("a", 0, 0, 8, 9)
@@ -35,6 +38,7 @@ describe Parser do
35
38
  parse("def foo(a)\nend\n", v).find_node(:defn).tap do |defn|
36
39
  defn.should have_name_and_position("foo", 0, 1, 0, 14)
37
40
  defn.args_node.should have_arg_counts(1, 0, false, false)
41
+ defn.args_node.should have_parameters('a')
38
42
  defn.args_node.pre.tap do |pre|
39
43
  pre.should have_position(0, 0, 8, 9)
40
44
  pre[0].should have_name_and_position("a", 0, 0, 8, 9)
@@ -46,6 +50,7 @@ describe Parser do
46
50
  parse("def foo a, b\nend\n", v).find_node(:defn).tap do |defn|
47
51
  defn.should have_name_and_position("foo", 0, 1, 0, 16)
48
52
  defn.args_node.should have_arg_counts(2, 0, false, false)
53
+ defn.args_node.should have_parameters('a', 'b')
49
54
  defn.args_node.pre.tap do |pre|
50
55
  pre.should have_position(0, 0, 8, 12)
51
56
  pre[0].should have_name_and_position("a", 0, 0, 8, 9)
@@ -58,6 +63,7 @@ describe Parser do
58
63
  parse("def foo(a, b)\nend\n", v).find_node(:defn) do |defn|
59
64
  defn.should have_name_and_position("foo", 0, 1, 0, 17)
60
65
  defn.args_node.should have_arg_counts(2, 0, false, false)
66
+ defn.args_node.should have_parameters('a', 'b')
61
67
  defn.args_node.pre.tap do |pre|
62
68
  pre.should have_position(0, 0, 8, 12)
63
69
  pre[0].should have_name_and_position("a", 0, 0, 8, 9)
@@ -70,6 +76,7 @@ describe Parser do
70
76
  parse("def foo a=1\nend\n", v).find_node(:defn).tap do |defn|
71
77
  defn.should have_name_and_position("foo", 0, 1, 0, 15)
72
78
  defn.args_node.should have_arg_counts(0, 1, false, false)
79
+ defn.args_node.should have_parameters('a')
73
80
  lasgn = defn.args_node.optional.find_node(:localasgn)
74
81
  lasgn.should have_name_and_position("a", 0, 0, 8, 11)
75
82
  end
@@ -79,6 +86,7 @@ describe Parser do
79
86
  parse("def foo(a=1)\nend\n", v).find_node(:defn).tap do |defn|
80
87
  defn.should have_name_and_position("foo", 0, 1, 0, 16)
81
88
  defn.args_node.should have_arg_counts(0, 1, false, false)
89
+ defn.args_node.should have_parameters('a')
82
90
  lasgn = defn.args_node.optional.find_node(:localasgn)
83
91
  lasgn.should have_name_and_position("a", 0, 0, 8, 11)
84
92
  end
@@ -88,6 +96,7 @@ describe Parser do
88
96
  parse("def foo *a\nend\n", v).find_node(:defn).tap do |defn|
89
97
  defn.should have_name_and_position("foo", 0, 1, 0, 14)
90
98
  defn.args_node.should have_arg_counts(0, 0, true, false)
99
+ defn.args_node.should have_parameters(['a', '*a'])
91
100
  end
92
101
  end
93
102
 
@@ -95,6 +104,8 @@ describe Parser do
95
104
  parse("def foo(*a)\nend\n", v).find_node(:defn).tap do |defn|
96
105
  defn.should have_name_and_position("foo", 0, 1, 0, 15)
97
106
  defn.args_node.should have_arg_counts(0, 0, true, false)
107
+ defn.args_node.rest.should have_position(0, 0, 8, 10)
108
+ defn.args_node.should have_parameters(['a', '*a'])
98
109
  end
99
110
  end
100
111
 
@@ -102,6 +113,7 @@ describe Parser do
102
113
  parse("def foo &a\nend\n", v).find_node(:defn).tap do |defn|
103
114
  defn.should have_name_and_position("foo", 0, 1, 0, 14)
104
115
  defn.args_node.should have_arg_counts(0, 0, false, true)
116
+ defn.args_node.should have_parameters(['a', '&a'])
105
117
  end
106
118
  end
107
119
 
@@ -109,13 +121,17 @@ describe Parser do
109
121
  parse("def foo(&a)\nend\n", v).find_node(:defn).tap do |defn|
110
122
  defn.should have_name_and_position("foo", 0, 1, 0, 15)
111
123
  defn.args_node.should have_arg_counts(0, 0, false, true)
124
+ defn.args_node.block.should have_position(0, 0, 8, 10)
125
+ defn.args_node.should have_parameters(['a', '&a'])
112
126
  end
113
127
  end
114
128
 
115
129
  it "parses a mixed-arg method sans parens [#{v}]" do
116
130
  parse("def foo a, b, c = 1, *d\nend\n", v).find_node(:defn).tap do |defn|
117
131
  defn.should have_name_and_position("foo", 0, 1, 0, 27)
118
- defn.args_node.should have_arg_counts(2, 1, true, false)
132
+ args = defn.args_node
133
+ args.should have_arg_counts(2, 1, true, false)
134
+ defn.args_node.should have_parameters('a', 'b', 'c', ['d', '*d'])
119
135
  end
120
136
  end
121
137
 
@@ -123,6 +139,7 @@ describe Parser do
123
139
  parse("def foo(a, b, c = 1, *d)\nend\n", v).find_node(:defn).tap do |defn|
124
140
  defn.should have_name_and_position("foo", 0, 1, 0, 28)
125
141
  defn.args_node.should have_arg_counts(2, 1, true, false)
142
+ defn.args_node.should have_parameters('a', 'b', 'c', ['d', '*d'])
126
143
  end
127
144
  end
128
145
  end
@@ -0,0 +1,15 @@
1
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../helpers"
2
+ $LOAD_PATH.unshift File.dirname(__FILE__) + "/../../lib"
3
+ require 'jruby-parser'
4
+ require 'parser_helpers'
5
+ require 'node_helpers'
6
+
7
+ describe Parser do
8
+ [1.8, 1.9].each do |v|
9
+ it "Should parse attr assign" do
10
+ parse("a[1] = 2", v).find_node(:attrassign).tap do |asgn|
11
+ asgn.should_not == nil
12
+ end
13
+ end
14
+ end
15
+ end
@@ -6,6 +6,12 @@ require 'node_helpers'
6
6
 
7
7
  describe Parser do
8
8
  [1.8, 1.9].each do |v|
9
+ it "parses a 0-arg method call sans parens +extra line [#{v}]" do
10
+ parse("\nblock_given?\n", v).find_node(:fcall).tap do |call|
11
+ call.should have_name_and_position("block_given?", 1, 1, 1, 13)
12
+ end
13
+ end
14
+
9
15
  it "parses a 0-arg method call sans parens +extra line [#{v}]" do
10
16
  parse("\nputs\n", v).find_node(:vcall).tap do |call|
11
17
  call.should have_name_and_position("puts", 1, 1, 1, 5)
metadata CHANGED
@@ -1,33 +1,22 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: jruby-parser
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 3
8
- version: "0.3"
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: '0.4'
9
6
  platform: ruby
10
- authors:
7
+ authors:
11
8
  - Thomas E. Enebo
12
- autorequire:
9
+ autorequire:
13
10
  bindir: bin
14
11
  cert_chain: []
15
-
16
- date: 2012-04-18 00:00:00 -05:00
17
- default_executable:
12
+ date: 2013-03-27 00:00:00.000000000 Z
18
13
  dependencies: []
19
-
20
14
  description: A Gem for syntactically correct parse trees of Ruby source
21
15
  email: tom.enebo@gmail.com
22
- executables:
23
- - generate_parser
24
- - optimize_parser.rb
25
- - patch_parser.rb
16
+ executables: []
26
17
  extensions: []
27
-
28
18
  extra_rdoc_files: []
29
-
30
- files:
19
+ files:
31
20
  - lib/jruby-parser.rb
32
21
  - lib/jruby-parser/core_ext/array.rb
33
22
  - lib/jruby-parser/core_ext/attr_assign_node.rb
@@ -48,56 +37,64 @@ files:
48
37
  - spec/ast/node_path.rb
49
38
  - spec/helpers/node_helpers.rb
50
39
  - spec/helpers/parser_helpers.rb
40
+ - spec/jruby-parser/find_scopes_spec.rb
51
41
  - spec/jruby-parser/find_spec.rb
42
+ - spec/jruby-parser/get_node_at_spec.rb
43
+ - spec/jruby-parser/is_block_parameter_spec.rb
44
+ - spec/jruby-parser/is_method_parameter_spec.rb
52
45
  - spec/jruby-parser/rewriting_spec.rb
46
+ - spec/jruby-parser/static_analysis_spec.rb
53
47
  - spec/parser/alias_spec.rb
54
48
  - spec/parser/broken_spec.rb
55
49
  - spec/positions/arg_spec.rb
50
+ - spec/positions/attr_asgn_spec.rb
56
51
  - spec/positions/call_spec.rb
57
52
  - spec/positions/conditionals_spec.rb
58
53
  - spec/positions/hash_spec.rb
59
54
  - spec/positions/heredoc_spec.rb
60
55
  - spec/positions/str_spec.rb
61
56
  - lib/jruby-parser.jar
62
- has_rdoc: true
63
57
  homepage: http://github.com/jruby/jruby-parser
64
58
  licenses: []
65
-
66
- post_install_message:
59
+ post_install_message:
67
60
  rdoc_options: []
68
-
69
- require_paths:
61
+ require_paths:
70
62
  - lib
71
- required_ruby_version: !ruby/object:Gem::Requirement
72
- requirements:
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
73
65
  - - ">="
74
- - !ruby/object:Gem::Version
75
- segments:
76
- - 0
77
- version: "0"
78
- required_rubygems_version: !ruby/object:Gem::Requirement
79
- requirements:
66
+ - !ruby/object:Gem::Version
67
+ version: !binary |-
68
+ MA==
69
+ none: false
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
80
72
  - - ">="
81
- - !ruby/object:Gem::Version
82
- segments:
83
- - 0
84
- version: "0"
73
+ - !ruby/object:Gem::Version
74
+ version: !binary |-
75
+ MA==
76
+ none: false
85
77
  requirements: []
86
-
87
78
  rubyforge_project: jruby-parser
88
- rubygems_version: 1.3.6
89
- signing_key:
79
+ rubygems_version: 1.8.24
80
+ signing_key:
90
81
  specification_version: 3
91
82
  summary: A Gem for syntactically correct parse trees of Ruby source
92
- test_files:
83
+ test_files:
93
84
  - spec/ast/node_path.rb
94
85
  - spec/helpers/node_helpers.rb
95
86
  - spec/helpers/parser_helpers.rb
87
+ - spec/jruby-parser/find_scopes_spec.rb
96
88
  - spec/jruby-parser/find_spec.rb
89
+ - spec/jruby-parser/get_node_at_spec.rb
90
+ - spec/jruby-parser/is_block_parameter_spec.rb
91
+ - spec/jruby-parser/is_method_parameter_spec.rb
97
92
  - spec/jruby-parser/rewriting_spec.rb
93
+ - spec/jruby-parser/static_analysis_spec.rb
98
94
  - spec/parser/alias_spec.rb
99
95
  - spec/parser/broken_spec.rb
100
96
  - spec/positions/arg_spec.rb
97
+ - spec/positions/attr_asgn_spec.rb
101
98
  - spec/positions/call_spec.rb
102
99
  - spec/positions/conditionals_spec.rb
103
100
  - spec/positions/hash_spec.rb
@@ -1,46 +0,0 @@
1
- #!/bin/sh
2
-
3
- # Run from your JRuby home directory....More smarts needed here.
4
-
5
- ###### Change these to tastes ######
6
- JAY=jay
7
- RUBY=ruby
8
- PARSER_BASE=DefaultRubyParser
9
- YYTABLE_PREFIX=
10
- DEBUG=true
11
- ###### Do not change below ######
12
-
13
- if [ "$1" != "" ]; then
14
- PARSER_BASE=$1
15
- fi
16
- shift
17
-
18
- if [ "$1" != "" ]; then
19
- YYTABLE_PREFIX=$1
20
- fi
21
-
22
- if [ "$DEBUG" != "" ]; then
23
- DEBUG_FLAG=-t
24
- # Nonesense...my script-fu is weak
25
- DEBUG_STRIP="xdyhbk"
26
- else
27
- DEBUG_FLAG=
28
- DEBUG_STRIP="^//t"
29
- fi
30
-
31
- echo "Generating Parser '$PARSER_BASE' w/ YYTable prefix of '$YYTABLE_PREFIX'"
32
-
33
- PARSER_DIR=src/org/jrubyparser/parser
34
-
35
- pushd $PARSER_DIR
36
-
37
- # Generate grammar as intermediate file
38
- $JAY $DEBUG_FLAG $PARSER_BASE.y < skeleton.parser | grep -v $DEBUG_STRIP >$PARSER_BASE.out
39
-
40
- # Patch file to get around Java static initialization issues plus extract
41
- # a bunch of stuff to seperate file (yytables).
42
- $RUBY ../../../../bin/patch_parser.rb $PARSER_BASE.out $YYTABLE_PREFIX > $PARSER_BASE.out2
43
- $RUBY ../../../../bin/optimize_parser.rb $PARSER_BASE.out2 $YYTABLE_PREFIX > $PARSER_BASE.java
44
- rm -f $PARSER_BASE.out $PARSER_BASE.out2
45
-
46
- popd
@@ -1,106 +0,0 @@
1
- class PostProcessor
2
- def initialize(source, out=STDOUT)
3
- @out = out
4
- @lines = File.readlines(source)
5
- @index = -1
6
- @case_bodies = {}
7
- @max_case_number = -1
8
- end
9
-
10
- # Read/Unread with ability to push back one line for a single lookahead
11
- def read
12
- @index += 1
13
- line = @last ? @last : @lines[@index]
14
- @last = nil
15
- line
16
- end
17
-
18
- def unread(line)
19
- @index -= 1
20
- @last = line
21
- end
22
-
23
- def end_of_actions?(line)
24
- return line =~ %r{^//\s*ACTIONS_END}
25
- end
26
-
27
- def translate
28
- while (line = read)
29
- if line =~ %r{^//\s*ACTIONS_BEGIN}
30
- translate_actions
31
- elsif line =~ %r{^//\s*ACTION_BODIES}
32
- generate_action_body_methods
33
- else
34
- @out.puts line
35
- end
36
- end
37
- end
38
-
39
- def generate_action_body_methods
40
- @out.puts "static ParserState[] states = new ParserState[#{@max_case_number+1}];"
41
- @out.puts "static {";
42
- @case_bodies.each do |state, code_body|
43
- generate_action_body_method(state, code_body)
44
- end
45
- @out.puts "}";
46
- end
47
-
48
- def generate_action_body_method(state, code_body)
49
- @out.puts "states[#{state}] = new ParserState() {"
50
- @out.puts " public Object execute(ParserSupport support, Lexer lexer, Object yyVal, Object[] yyVals, int yyTop) {"
51
- code_body.each { |line| @out.puts line }
52
- @out.puts " return yyVal;"
53
- @out.puts " }"
54
- @out.puts "};"
55
- end
56
-
57
- def translate_actions
58
- count = 1
59
- while (translate_action)
60
- count += 1
61
- end
62
- end
63
-
64
- # Assumptions:
65
- # 1. no break; in our code. A bit weak, but this is highly specialized code.
66
- # 2. All productions will have a line containing only { (with optional comment)
67
- # 3. All productions will end with a line containly only } followed by break in ass 1.
68
- def translate_action
69
- line = read
70
- return false if end_of_actions?(line) || line !~ /case\s+(\d+):/
71
- case_number = $1.to_i
72
-
73
- line = read
74
- return false if line !~ /line\s+(\d+)/
75
- line_number = $1
76
-
77
- # Extra boiler plate '{' that we do not need
78
- line = read
79
- return false if line !~ /^\s*\{\s*(\/\*.*\*\/)?$/
80
-
81
- @max_case_number = case_number if case_number > @max_case_number
82
-
83
- label = "case#{case_number}_line#{line_number}"
84
-
85
- body = []
86
- last_line = nil
87
- while (line = read)
88
- if line =~ /^\s*\}\s*$/ # Extra trailing boiler plate
89
- next_line = read
90
- if next_line =~ /break;/
91
- break
92
- else
93
- body << line
94
- unread next_line
95
- end
96
- else
97
- body << line
98
- end
99
- end
100
-
101
- @case_bodies[case_number] = body
102
- true
103
- end
104
- end
105
-
106
- PostProcessor.new(ARGV.shift).translate
@@ -1,105 +0,0 @@
1
- def get_numbers_until_end_block(table)
2
- while gets
3
- break if /\};/ =~ $_
4
- next if /^\/\// =~ $_
5
- split(/,/).each do |number|
6
- n = number.strip
7
- table.push(n.to_i) unless n == ""
8
- end
9
- end
10
- table
11
- end
12
-
13
- while gets
14
- break if /protected static final short\[\] yyTable = \{/ =~ $_
15
- print $_
16
- end
17
-
18
- # A little hacky...gets before ARGV to shift off and open file
19
- yytable_prefix = ARGV.shift || ''
20
-
21
- table4 = get_numbers_until_end_block([])
22
-
23
- puts " protected static final short[] yyTable = #{yytable_prefix}YyTables.yyTable();"
24
-
25
- while gets
26
- break if /protected static final short\[\] yyCheck = \{/ =~ $_
27
- print $_
28
- end
29
-
30
- check4 = get_numbers_until_end_block([])
31
-
32
- puts " protected static final short[] yyCheck = #{yytable_prefix}YyTables.yyCheck();"
33
-
34
- while gets
35
- print $_
36
- end
37
-
38
- table2 = table4.slice!(0, table4.size / 2)
39
- table3 = table4.slice!(0, table4.size / 2)
40
- table1 = table2.slice!(0, table2.size / 2)
41
- check2 = check4.slice!(0, check4.size / 2)
42
- check3 = check4.slice!(0, check4.size / 2)
43
- check1 = check2.slice!(0, check2.size / 2)
44
-
45
- def printShortArray(table, f)
46
- table.each_with_index { |e, i|
47
- f.print "\n " if (i % 10 == 0)
48
- begin
49
- f.printf "%4d, ", e
50
- rescue ArgumentError => a
51
- $stderr.puts "Trouble printing '#{e}' on index #{i}"
52
- end
53
- }
54
- end
55
-
56
- def printShortMethod(f, table, name)
57
- f.puts " private static final short[] yy#{name}() {"
58
- f.puts " return new short[] {"
59
- printShortArray table, f
60
- f.puts
61
- f.puts " };"
62
- f.puts " }"
63
- f.puts
64
- end
65
-
66
- open("#{yytable_prefix}YyTables.java", "w") { |f|
67
- f.print <<END
68
- package org.jrubyparser.parser;
69
-
70
- public class #{yytable_prefix}YyTables {
71
- private static short[] combine(short[] t1, short[] t2,
72
- short[] t3, short[] t4) {
73
- short[] t = new short[t1.length + t2.length + t3.length + t4.length];
74
- int index = 0;
75
- System.arraycopy(t1, 0, t, index, t1.length);
76
- index += t1.length;
77
- System.arraycopy(t2, 0, t, index, t2.length);
78
- index += t2.length;
79
- System.arraycopy(t3, 0, t, index, t3.length);
80
- index += t3.length;
81
- System.arraycopy(t4, 0, t, index, t4.length);
82
- return t;
83
- }
84
-
85
- public static final short[] yyTable() {
86
- return combine(yyTable1(), yyTable2(), yyTable3(), yyTable4());
87
- }
88
-
89
- public static final short[] yyCheck() {
90
- return combine(yyCheck1(), yyCheck2(), yyCheck3(), yyCheck4());
91
- }
92
- END
93
-
94
- printShortMethod(f, table1, "Table1")
95
- printShortMethod(f, table2, "Table2")
96
- printShortMethod(f, table3, "Table3")
97
- printShortMethod(f, table4, "Table4")
98
-
99
- printShortMethod(f, check1, "Check1")
100
- printShortMethod(f, check2, "Check2")
101
- printShortMethod(f, check3, "Check3")
102
- printShortMethod(f, check4, "Check4")
103
-
104
- f.puts "}"
105
- }