jruby-parser 0.3 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
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
- }