ParseTree 1.7.1 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -89,7 +89,8 @@ class TestParseTree < ParseTreeTestCase
89
89
  assert_equal expected, actual
90
90
  end
91
91
 
92
- @@self_classmethod = [:defn, :"self.classmethod",
92
+ @@self_classmethod = [:defs,
93
+ [:self], :classmethod,
93
94
  [:scope,
94
95
  [:block,
95
96
  [:args],
@@ -17,6 +17,11 @@ class SexpTestCase < Test::Unit::TestCase
17
17
 
18
18
  include SexpMatchSpecials
19
19
 
20
+ def util_equals(x, y)
21
+ result = x == y
22
+ assert_not_nil result, "#{x.inspect} does not === #{y.inspect}"
23
+ end
24
+
20
25
  def util_equals3(x, y)
21
26
  result = x === y
22
27
  assert_not_nil result, "#{x.inspect} does not === #{y.inspect}"
@@ -33,6 +38,12 @@ end
33
38
 
34
39
  class TestSexp < SexpTestCase # ZenTest FULL
35
40
 
41
+ class SexpFor
42
+ def method
43
+ 1
44
+ end
45
+ end
46
+
36
47
  def util_pretty_print(expect, input)
37
48
  io = StringIO.new
38
49
  PP.pp(input, io)
@@ -51,6 +62,14 @@ class TestSexp < SexpTestCase # ZenTest FULL
51
62
  @bad1 = s(:blah, 42)
52
63
  end
53
64
 
65
+ def test_class_for
66
+ sexp = Sexp.for SexpFor
67
+ assert_equal s(:class, :"TestSexp::SexpFor"), sexp[0..1]
68
+
69
+ sexp = Sexp.for SexpFor, :method
70
+ assert_equal s(:defn, :method), sexp[0..1]
71
+ end
72
+
54
73
  def test_class_from_array
55
74
  # raise NotImplementedError, 'Need to write test_class_from_array'
56
75
  end
@@ -89,7 +108,7 @@ class TestSexp < SexpTestCase # ZenTest FULL
89
108
  sexp2 = s(1, 2, 5)
90
109
  assert_not_equal(@sexp, sexp2)
91
110
  end
92
-
111
+
93
112
  def test_equals2_sexp
94
113
  sexp2 = s(1, 2, 3)
95
114
  if @sexp.class == Sexp then
@@ -142,14 +161,14 @@ class TestSexp < SexpTestCase # ZenTest FULL
142
161
 
143
162
  util_equals3 s(:a), s(:blah, s(:blah, s(:a))) # left deeper
144
163
  end
145
-
164
+
146
165
  # def test_equalstilde_any
147
166
  # result = @basic_sexp =~ s(:lit, ANY())
148
167
  # p result
149
168
  # assert result
150
169
  # end
151
170
 
152
- def test_equalstilde_fancy
171
+ def test_equalstilde_fancy
153
172
  assert_nil s(:b) =~ s(:a, s(:b), :c)
154
173
  assert_not_nil s(:a, s(:b), :c) =~ s(:b)
155
174
  end
@@ -282,6 +301,12 @@ class TestSexpAny < SexpTestCase
282
301
  super
283
302
  end
284
303
 
304
+ def test_equals
305
+ util_equals @any, s()
306
+ util_equals @any, s(:a)
307
+ util_equals @any, s(:a, :b, s(:c))
308
+ end
309
+
285
310
  def test_equals3
286
311
  util_equals3 @any, s()
287
312
  util_equals3 @any, s(:a)
@@ -24,9 +24,12 @@ class TestProcessor < SexpProcessor # ZenTest SKIP
24
24
  end
25
25
 
26
26
  def process_specific(exp)
27
- result = exp[1..-1]
28
- exp.clear
29
- self.expected.new(*result)
27
+ name = exp.shift
28
+ result = s(:blah)
29
+ until exp.empty?
30
+ result.push process(exp.shift)
31
+ end
32
+ result
30
33
  end
31
34
 
32
35
  def process_strip(exp)
@@ -59,7 +62,20 @@ class TestProcessor < SexpProcessor # ZenTest SKIP
59
62
  end
60
63
 
61
64
  def process_rewritable(exp)
62
- return s(exp.shift, exp.shift == 2, exp.shift == 1)
65
+ @n ||= 0
66
+ exp.shift # name
67
+ result = s(:rewritten)
68
+ until exp.empty?
69
+ result.push process(exp.shift)
70
+ end
71
+ result.push @n
72
+ @n += 1
73
+ result
74
+ end
75
+
76
+ def rewrite_major_rewrite(exp)
77
+ exp[0] = :rewritable
78
+ exp
63
79
  end
64
80
  end
65
81
 
@@ -84,12 +100,12 @@ class TestSexpProcessor < Test::Unit::TestCase
84
100
  end
85
101
 
86
102
  def test_process_specific
87
- a = [:specific, 1, 2, 3]
88
- expected = a[1..-1]
103
+ a = [:specific, [:x, 1], [:y, 2], [:z, 3]]
104
+ expected = [:blah, [:x, 1], [:y, 2], [:z, 3]]
89
105
  assert_equal(expected, @processor.process(a))
90
106
  end
91
107
 
92
- def test_process_general
108
+ def test_process_generic
93
109
  a = [:blah, 1, 2, 3]
94
110
  expected = a.deep_clone
95
111
  assert_equal(expected, @processor.process(a))
@@ -162,25 +178,66 @@ class TestSexpProcessor < Test::Unit::TestCase
162
178
  @processor.rewrite(s(:rewritable, :a, :b)))
163
179
  end
164
180
 
181
+ def test_rewrite_different_type
182
+ assert_equal(s(:rewritable, :b, :a),
183
+ @processor.rewrite(s(:major_rewrite, :a, :b)))
184
+ end
185
+
165
186
  def test_rewrite_deep
166
187
  assert_equal(s(:specific, s(:rewritable, :b, :a)),
167
188
  @processor.rewrite(s(:specific, s(:rewritable, :a, :b))))
168
189
  end
169
190
 
170
- def test_process_rewrite
171
- assert_equal(s(:rewritable, true, true),
172
- @processor.process(s(:rewritable, 1, 2)))
191
+ def test_rewrite_not_empty
192
+ insert = s(:rewritable, 1, 2, 2)
193
+ expect = s(:rewritable, 2, 1)
194
+ result = @processor.rewrite(insert)
195
+ assert_equal(expect, result)
196
+ assert_equal(s(2), insert) # post-processing
173
197
  end
174
198
 
175
- def test_process_rewrite_deep
176
- assert_equal(s(s(:rewritable, :b, :a)),
177
- @processor.process(s(:specific, s(:rewritable, :a, :b))))
199
+ def test_process_rewrite
200
+ assert_equal(s(:rewritten, s(:y, 2), s(:x, 1), 0),
201
+ @processor.process(s(:rewritable, s(:x, 1), s(:y, 2))))
178
202
  end
179
203
 
180
- def test_process_rewrite_not_empty
181
- assert_raise(NotEmptyError) do
182
- @processor.process(s(:rewritable, 1, 2, 2))
183
- end
204
+ def test_process_rewrite_deep
205
+ assert_equal(s(:blah, s(:rewritten, s(:b), s(:a), 0)),
206
+ @processor.process(s(:specific, s(:rewritable, s(:a), s(:b)))))
207
+ end
208
+
209
+ def test_rewrite_depth_first
210
+ inn = s(:specific,
211
+ s(:rewritable,
212
+ s(:a),
213
+ s(:rewritable,
214
+ s(:rewritable, s(:b), s(:c)),
215
+ s(:d))))
216
+ out = s(:specific,
217
+ s(:rewritable,
218
+ s(:rewritable,
219
+ s(:d),
220
+ s(:rewritable, s(:c), s(:b))),
221
+ s(:a)))
222
+
223
+ assert_equal(out, @processor.rewrite(inn))
224
+ end
225
+
226
+ def test_process_rewrite_depth_first
227
+ inn = s(:specific,
228
+ s(:rewritable,
229
+ s(:a),
230
+ s(:rewritable,
231
+ s(:rewritable, s(:b), s(:c)),
232
+ s(:d))))
233
+ out = s(:blah,
234
+ s(:rewritten,
235
+ s(:rewritten,
236
+ s(:d),
237
+ s(:rewritten, s(:c), s(:b), 0), 1),
238
+ s(:a), 2))
239
+
240
+ assert_equal(out, @processor.process(inn))
184
241
  end
185
242
 
186
243
  def test_assert_type_hit
@@ -0,0 +1,229 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ $TESTING = true
4
+
5
+ require 'test/unit' if $0 == __FILE__ unless defined? $ZENTEST and $ZENTEST
6
+ require 'test/unit/testcase'
7
+ require 'sexp'
8
+ require 'sexp_processor'
9
+ require 'unified_ruby'
10
+
11
+ class TestUnifier < SexpProcessor
12
+ include UnifiedRuby
13
+ end
14
+
15
+ # TODO:
16
+ #
17
+ # 1) DONE [vf]call => call
18
+ # 2) DONE defn scope block args -> defn args scope block
19
+ # 3) DONE [bd]method/fbody => defn
20
+ # 4) rescue cleanup
21
+ # 5) defs x -> defn self.x # ON HOLD
22
+ # 6) ? :block_arg into args list?
23
+
24
+ class TestUnifiedRuby < Test::Unit::TestCase
25
+ def setup
26
+ @sp = TestUnifier.new
27
+ @sp.require_empty = false
28
+ end
29
+
30
+ def doit
31
+ assert_equal @expect, @sp.process(@insert)
32
+ end
33
+
34
+ def test_rewrite_bmethod
35
+ @insert = s(:bmethod,
36
+ s(:dasgn_curr, :x),
37
+ s(:call, s(:dvar, :x), :+, s(:array, s(:lit, 1))))
38
+ @expect = s(:scope,
39
+ s(:block,
40
+ s(:args, :x),
41
+ s(:call, s(:lvar, :x), :+, s(:array, s(:lit, 1)))))
42
+
43
+ doit
44
+ end
45
+
46
+ def test_rewrite_bmethod_noargs
47
+ @insert = s(:bmethod,
48
+ nil,
49
+ s(:call, s(:vcall, :x), :+, s(:array, s(:lit, 1))))
50
+ @expect = s(:scope,
51
+ s(:block,
52
+ s(:args),
53
+ s(:call, s(:call, nil, :x, s(:arglist)),
54
+ :+, s(:array, s(:lit, 1)))))
55
+
56
+ doit
57
+ end
58
+
59
+ def test_rewrite_bmethod_splat
60
+ @insert = s(:bmethod,
61
+ s(:masgn, s(:dasgn_curr, :params)),
62
+ s(:lit, 42))
63
+ @expect = s(:scope,
64
+ s(:block,
65
+ s(:args, :"*params"),
66
+ s(:lit, 42)))
67
+
68
+ doit
69
+ end
70
+
71
+ def test_rewrite_defn
72
+ @insert = s(:defn, :x, s(:scope, s(:block, s(:args), s(:nil))))
73
+ @expect = s(:defn, :x, s(:args), s(:scope, s(:block, s(:nil))))
74
+
75
+ doit
76
+ end
77
+
78
+ def test_rewrite_defn_attr
79
+ @insert = s(:defn, :writer=, s(:attrset, :@writer))
80
+ @expect = s(:defn, :writer=, s(:args), s(:attrset, :@writer))
81
+
82
+ doit
83
+ end
84
+
85
+ def test_rewrite_defn_block_arg
86
+ @insert = s(:defn, :blah,
87
+ s(:scope,
88
+ s(:block,
89
+ s(:args, "*args".intern),
90
+ s(:block_arg, :block),
91
+ s(:block_pass,
92
+ s(:lvar, :block),
93
+ s(:fcall, :other, s(:splat, s(:lvar, :args)))))))
94
+ @expect = s(:defn, :blah,
95
+ s(:args, "*args".intern, s(:block_arg, :block)),
96
+ s(:scope,
97
+ s(:block,
98
+ s(:block_pass,
99
+ s(:lvar, :block),
100
+ s(:call, nil, :other,
101
+ s(:arglist, s(:splat, s(:lvar, :args))))))))
102
+
103
+ doit
104
+ end
105
+
106
+ def test_rewrite_dmethod
107
+ @insert = s(:dmethod,
108
+ :a_method,
109
+ s(:scope,
110
+ s(:block,
111
+ s(:args, :x),
112
+ s(:lit, 42))))
113
+ @expect = s(:scope,
114
+ s(:block,
115
+ s(:args, :x),
116
+ s(:lit, 42)))
117
+
118
+ doit
119
+ end
120
+
121
+ def test_rewrite_fbody
122
+ @insert = s(:fbody,
123
+ s(:scope,
124
+ s(:block,
125
+ s(:args, :x),
126
+ s(:call, s(:lvar, :x), :+, s(:array, s(:lit, 1))))))
127
+ @expect = s(:scope,
128
+ s(:block,
129
+ s(:args, :x),
130
+ s(:call, s(:lvar, :x), :+, s(:array, s(:lit, 1)))))
131
+
132
+ doit
133
+ end
134
+
135
+ def test_rewrite_defn_bmethod_alias
136
+ @insert = s(:defn, :group,
137
+ s(:fbody,
138
+ s(:bmethod,
139
+ s(:masgn, s(:dasgn_curr, :params)),
140
+ s(:block,
141
+ s(:lit, 42)))))
142
+ @expect = s(:defn, :group,
143
+ s(:args, :"*params"),
144
+ s(:scope,
145
+ s(:block, s(:lit, 42))))
146
+
147
+ doit
148
+ end
149
+
150
+ # TODO: think about flattening out to 1 resbody only
151
+ def test_rewrite_resbody
152
+ @insert = s(:resbody,
153
+ s(:array, s(:const, :SyntaxError)),
154
+ s(:block, s(:lasgn, :e1, s(:gvar, :$!)), s(:lit, 2)),
155
+ s(:resbody,
156
+ s(:array, s(:const, :Exception)),
157
+ s(:block, s(:lasgn, :e2, s(:gvar, :$!)), s(:lit, 3))))
158
+
159
+ @expect = s(:resbody,
160
+ s(:array, s(:const, :SyntaxError), s(:lasgn, :e1, s(:gvar, :$!))),
161
+ s(:block, s(:lit, 2)),
162
+ s(:resbody,
163
+ s(:array, s(:const, :Exception), s(:lasgn, :e2, s(:gvar, :$!))),
164
+ s(:block, s(:lit, 3))))
165
+
166
+ doit
167
+ end
168
+
169
+ def test_rewrite_resbody_empty
170
+ # begin require 'rubygems'; rescue LoadError; end
171
+ @insert = s(:begin,
172
+ s(:rescue,
173
+ s(:fcall, :require, s(:array, s(:str, "rubygems"))),
174
+ s(:resbody, s(:array, s(:const, :LoadError)))))
175
+ @expect = s(:begin,
176
+ s(:rescue,
177
+ s(:call, nil, :require, s(:arglist, s(:str, "rubygems"))),
178
+ s(:resbody, s(:array, s(:const, :LoadError)), nil)))
179
+
180
+ doit
181
+ end
182
+
183
+ def test_rewrite_resbody_lasgn
184
+ @insert = s(:resbody,
185
+ s(:array, s(:const, :SyntaxError)),
186
+ s(:lasgn, :e1, s(:gvar, :$!)),
187
+ s(:resbody,
188
+ s(:array, s(:const, :Exception)),
189
+ s(:block, s(:lasgn, :e2, s(:gvar, :$!)), s(:lit, 3))))
190
+
191
+ @expect = s(:resbody,
192
+ s(:array, s(:const, :SyntaxError), s(:lasgn, :e1, s(:gvar, :$!))),
193
+ nil,
194
+ s(:resbody,
195
+ s(:array, s(:const, :Exception), s(:lasgn, :e2, s(:gvar, :$!))),
196
+ s(:block, s(:lit, 3))))
197
+
198
+ doit
199
+ end
200
+
201
+ def test_rewrite_defn_ivar
202
+ @insert = s(:defn, :reader, s(:ivar, :@reader))
203
+ @expect = s(:defn, :reader, s(:args), s(:ivar, :@reader))
204
+
205
+ doit
206
+ end
207
+
208
+ def test_rewrite_vcall
209
+ @insert = s(:vcall, :puts)
210
+ @expect = s(:call, nil, :puts, s(:arglist))
211
+
212
+ doit
213
+ end
214
+
215
+ def test_rewrite_fcall
216
+ @insert = s(:fcall, :puts, s(:array, s(:lit, :blah)))
217
+ @expect = s(:call, nil, :puts, s(:arglist, s(:lit, :blah)))
218
+
219
+ doit
220
+ end
221
+
222
+ def test_rewrite_fcall_loop
223
+ @insert = s(:iter, s(:fcall, :loop), nil)
224
+ @expect = s(:iter, s(:call, nil, :loop, s(:arglist)), nil)
225
+
226
+ doit
227
+ end
228
+
229
+ end
metadata CHANGED
@@ -3,16 +3,16 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: ParseTree
5
5
  version: !ruby/object:Gem::Version
6
- version: 1.7.1
7
- date: 2007-06-05 00:00:00 -07:00
8
- summary: Extract and enumerate ruby parse trees.
6
+ version: 2.0.0
7
+ date: 2007-08-01 00:00:00 -07:00
8
+ summary: ParseTree is a C extension (using RubyInline) that extracts the parse tree for an entire class or a specific method and returns it as a s-expression (aka sexp) using ruby's arrays, strings, symbols, and integers.
9
9
  require_paths:
10
10
  - lib
11
11
  - test
12
12
  email: ryand-ruby@zenspider.com
13
13
  homepage: http://www.zenspider.com/ZSS/Products/ParseTree/
14
14
  rubyforge_project: parsetree
15
- description: ParseTree is a C extension (using RubyInline) that extracts the parse tree for an entire class or a specific method and returns it as a s-expression (aka sexp) using ruby's arrays, strings, symbols, and integers.
15
+ description: "ParseTree is a C extension (using RubyInline) that extracts the parse tree for an entire class or a specific method and returns it as a s-expression (aka sexp) using ruby's arrays, strings, symbols, and integers. As an example: def conditional1(arg1) if arg1 == 0 then return 1 end return 0 end becomes: [:defn, :conditional1, [:scope, [:block, [:args, :arg1], [:if, [:call, [:lvar, :arg1], :==, [:array, [:lit, 0]]], [:return, [:lit, 1]], nil], [:return, [:lit, 0]]]]] * Uses RubyInline, so it just drops in. * Includes SexpProcessor and CompositeSexpProcessor. * Allows you to write very clean filters. * Includes UnifiedRuby, allowing you to automatically rewrite ruby quirks. * ParseTree#parse_tree_for_string lets you parse arbitrary strings of ruby. * Includes parse_tree_show, which lets you quickly snoop code. * echo \"1+1\" | parse_tree_show -f for quick snippet output. * Includes parse_tree_abc, which lets you get abc metrics on code. * abc metrics = numbers of assignments, branches, and calls. * whitespace independent metric for method complexity. * Includes parse_tree_deps, which shows you basic class level dependencies. * Does not work on the core classes, as they are not ruby (yet)."
16
16
  autorequire:
17
17
  default_executable:
18
18
  bindir: bin
@@ -43,6 +43,7 @@ files:
43
43
  - lib/parse_tree.rb
44
44
  - lib/sexp.rb
45
45
  - lib/sexp_processor.rb
46
+ - lib/unified_ruby.rb
46
47
  - lib/unique.rb
47
48
  - test/pt_testcase.rb
48
49
  - test/something.rb
@@ -51,6 +52,7 @@ files:
51
52
  - test/test_parse_tree.rb
52
53
  - test/test_sexp.rb
53
54
  - test/test_sexp_processor.rb
55
+ - test/test_unified_ruby.rb
54
56
  - validate.sh
55
57
  test_files:
56
58
  - test/test_all.rb
@@ -78,7 +80,7 @@ dependencies:
78
80
  requirements:
79
81
  - - ">="
80
82
  - !ruby/object:Gem::Version
81
- version: 3.2.0
83
+ version: 3.6.0
82
84
  version:
83
85
  - !ruby/object:Gem::Dependency
84
86
  name: hoe
@@ -87,5 +89,5 @@ dependencies:
87
89
  requirements:
88
90
  - - ">="
89
91
  - !ruby/object:Gem::Version
90
- version: 1.2.1
92
+ version: 1.2.2
91
93
  version: