ripper2ruby 0.0.1

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.
Files changed (111) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.markdown +10 -0
  3. data/lib/core_ext/array/flush.rb +5 -0
  4. data/lib/core_ext/hash/delete_at.rb +5 -0
  5. data/lib/core_ext/object/meta_class.rb +5 -0
  6. data/lib/core_ext/object/try.rb +12 -0
  7. data/lib/erb/stripper.rb +48 -0
  8. data/lib/highlighters/ansi.rb +29 -0
  9. data/lib/ripper/event_log.rb +45 -0
  10. data/lib/ripper/ruby_builder.rb +168 -0
  11. data/lib/ripper/ruby_builder/buffer.rb +34 -0
  12. data/lib/ripper/ruby_builder/events/args.rb +40 -0
  13. data/lib/ripper/ruby_builder/events/array.rb +71 -0
  14. data/lib/ripper/ruby_builder/events/assignment.rb +55 -0
  15. data/lib/ripper/ruby_builder/events/block.rb +80 -0
  16. data/lib/ripper/ruby_builder/events/call.rb +123 -0
  17. data/lib/ripper/ruby_builder/events/case.rb +17 -0
  18. data/lib/ripper/ruby_builder/events/const.rb +47 -0
  19. data/lib/ripper/ruby_builder/events/for.rb +13 -0
  20. data/lib/ripper/ruby_builder/events/hash.rb +24 -0
  21. data/lib/ripper/ruby_builder/events/identifier.rb +41 -0
  22. data/lib/ripper/ruby_builder/events/if.rb +37 -0
  23. data/lib/ripper/ruby_builder/events/lexer.rb +159 -0
  24. data/lib/ripper/ruby_builder/events/literal.rb +47 -0
  25. data/lib/ripper/ruby_builder/events/method.rb +21 -0
  26. data/lib/ripper/ruby_builder/events/operator.rb +23 -0
  27. data/lib/ripper/ruby_builder/events/statements.rb +50 -0
  28. data/lib/ripper/ruby_builder/events/string.rb +117 -0
  29. data/lib/ripper/ruby_builder/events/symbol.rb +22 -0
  30. data/lib/ripper/ruby_builder/events/while.rb +27 -0
  31. data/lib/ripper/ruby_builder/queue.rb +33 -0
  32. data/lib/ripper/ruby_builder/stack.rb +125 -0
  33. data/lib/ripper/ruby_builder/token.rb +91 -0
  34. data/lib/ripper2ruby.rb +1 -0
  35. data/lib/ruby.rb +28 -0
  36. data/lib/ruby/aggregate.rb +71 -0
  37. data/lib/ruby/alternation/args.rb +25 -0
  38. data/lib/ruby/alternation/hash.rb +25 -0
  39. data/lib/ruby/alternation/list.rb +19 -0
  40. data/lib/ruby/args.rb +36 -0
  41. data/lib/ruby/array.rb +27 -0
  42. data/lib/ruby/assignment.rb +32 -0
  43. data/lib/ruby/assoc.rb +17 -0
  44. data/lib/ruby/block.rb +42 -0
  45. data/lib/ruby/call.rb +34 -0
  46. data/lib/ruby/case.rb +30 -0
  47. data/lib/ruby/const.rb +49 -0
  48. data/lib/ruby/for.rb +18 -0
  49. data/lib/ruby/hash.rb +14 -0
  50. data/lib/ruby/if.rb +35 -0
  51. data/lib/ruby/list.rb +40 -0
  52. data/lib/ruby/literal.rb +45 -0
  53. data/lib/ruby/method.rb +19 -0
  54. data/lib/ruby/node.rb +47 -0
  55. data/lib/ruby/node/composite.rb +68 -0
  56. data/lib/ruby/node/conversions.rb +66 -0
  57. data/lib/ruby/node/position.rb +35 -0
  58. data/lib/ruby/node/source.rb +29 -0
  59. data/lib/ruby/node/text.rb +121 -0
  60. data/lib/ruby/node/traversal.rb +82 -0
  61. data/lib/ruby/operator.rb +49 -0
  62. data/lib/ruby/params.rb +41 -0
  63. data/lib/ruby/statements.rb +45 -0
  64. data/lib/ruby/string.rb +40 -0
  65. data/lib/ruby/symbol.rb +27 -0
  66. data/lib/ruby/token.rb +51 -0
  67. data/lib/ruby/while.rb +32 -0
  68. data/test/all.rb +3 -0
  69. data/test/builder/stack_test.rb +67 -0
  70. data/test/builder/text_test.rb +118 -0
  71. data/test/context_test.rb +54 -0
  72. data/test/erb_stripper_test.rb +29 -0
  73. data/test/fixtures/all.rb.src +150 -0
  74. data/test/fixtures/source_1.rb +16 -0
  75. data/test/fixtures/source_2.rb +1 -0
  76. data/test/fixtures/stuff.rb +371 -0
  77. data/test/fixtures/template.html.erb +22 -0
  78. data/test/fixtures/tmp.rb +6 -0
  79. data/test/lib_test.rb +92 -0
  80. data/test/lib_test_helper.rb +103 -0
  81. data/test/libs.txt +227 -0
  82. data/test/nodes/args_test.rb +100 -0
  83. data/test/nodes/array_test.rb +141 -0
  84. data/test/nodes/assignment_test.rb +49 -0
  85. data/test/nodes/block_test.rb +125 -0
  86. data/test/nodes/call_test.rb +229 -0
  87. data/test/nodes/case_test.rb +68 -0
  88. data/test/nodes/comments_test.rb +25 -0
  89. data/test/nodes/const_test.rb +46 -0
  90. data/test/nodes/conversions_test.rb +9 -0
  91. data/test/nodes/for_test.rb +34 -0
  92. data/test/nodes/hash_test.rb +71 -0
  93. data/test/nodes/heredoc_test.rb +202 -0
  94. data/test/nodes/identifier_test.rb +51 -0
  95. data/test/nodes/if_test.rb +100 -0
  96. data/test/nodes/literals_test.rb +63 -0
  97. data/test/nodes/method_test.rb +92 -0
  98. data/test/nodes/namespaces_test.rb +65 -0
  99. data/test/nodes/node_test.rb +74 -0
  100. data/test/nodes/nodes_test.rb +23 -0
  101. data/test/nodes/operator_test.rb +241 -0
  102. data/test/nodes/separators_test.rb +97 -0
  103. data/test/nodes/statements_test.rb +70 -0
  104. data/test/nodes/string_test.rb +92 -0
  105. data/test/nodes/symbol_test.rb +57 -0
  106. data/test/nodes/unless_test.rb +42 -0
  107. data/test/nodes/until_test.rb +61 -0
  108. data/test/nodes/while_test.rb +71 -0
  109. data/test/test_helper.rb +51 -0
  110. data/test/traversal_test.rb +53 -0
  111. metadata +163 -0
@@ -0,0 +1,49 @@
1
+ require 'ruby/node'
2
+
3
+ module Ruby
4
+ class Operator < DelimitedAggregate
5
+ end
6
+
7
+ class Unary < Operator
8
+ child_accessor :operator, :operand
9
+
10
+ def initialize(operator, operand, ldelim, rdelim)
11
+ self.operator = operator or raise "operator can not be nil"
12
+ self.operand = operand
13
+ super(ldelim, rdelim)
14
+ end
15
+
16
+ def nodes
17
+ [operator, ldelim, operand, rdelim].compact
18
+ end
19
+ end
20
+
21
+ class Binary < Operator
22
+ child_accessor :operator, :left, :right
23
+
24
+ def initialize(operator, left, right)
25
+ self.operator = operator or raise "operator can not be nil"
26
+ self.left = left
27
+ self.right = right
28
+ end
29
+
30
+ def nodes
31
+ [left, operator, right].compact
32
+ end
33
+ end
34
+
35
+ class IfOp < Operator
36
+ child_accessor :condition, :left, :right, :operators
37
+
38
+ def initialize(condition, left, right, operators)
39
+ self.condition = condition
40
+ self.left = left
41
+ self.right = right
42
+ self.operators = operators
43
+ end
44
+
45
+ def nodes
46
+ [[condition, left, right].zip(operators)].flatten.compact
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,41 @@
1
+ require 'ruby/aggregate'
2
+ require 'ruby/list'
3
+
4
+ module Ruby
5
+ class Params < DelimitedList
6
+ def initialize(params = nil, ldelim = nil, rdelim = nil)
7
+ params = Array(params).map { |param| param.is_a?(Ruby::Param) ? param : Ruby::Param.new(param) }
8
+ super
9
+ end
10
+
11
+ def <<(param)
12
+ param = Ruby::Param.new(param) unless param.is_a?(Ruby::Param)
13
+ super
14
+ end
15
+ end
16
+
17
+ class Param < DelimitedAggregate
18
+ child_accessor :param
19
+
20
+ def initialize(param, ldelim = nil)
21
+ self.param = param
22
+ super(ldelim)
23
+ end
24
+
25
+ def nodes
26
+ [ldelim, param].compact
27
+ end
28
+
29
+ def method_missing(method, *args, &block)
30
+ param.respond_to?(method) ? param.send(method, *args, &block) : super
31
+ end
32
+ end
33
+
34
+ class RescueParams < Params
35
+ def initialize(types, var, operator)
36
+ types = Ruby::Array.new(types) if types
37
+ errors = Ruby::Assoc.new(types, var, operator)
38
+ super(errors)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,45 @@
1
+ require 'ruby/node'
2
+
3
+ module Ruby
4
+ class Statements < DelimitedList
5
+ include Conversions::Statements
6
+ end
7
+
8
+ class Program < Statements
9
+ child_accessor :end_data
10
+ attr_accessor :filename
11
+ attr_writer :src
12
+
13
+ def initialize(src, filename, statements, end_data)
14
+ self.src = src
15
+ self.filename = filename if filename
16
+ self.end_data = end_data if end_data
17
+ super(statements)
18
+ end
19
+
20
+ alias :statements :elements
21
+
22
+ def to_ruby(prolog = false)
23
+ super(true)
24
+ end
25
+
26
+ def nodes
27
+ [super, end_data].flatten.compact
28
+ end
29
+
30
+ # TODO replace this with Clip?
31
+ def line_pos(row)
32
+ (row > 0 ? src.split("\n")[0..(row - 1)].inject(0) { |pos, line| pos + line.length + 1 } : 0)
33
+ end
34
+
35
+ def replace_src(row, column, length, src)
36
+ self.src[line_pos(row) + column, length] = src
37
+ offset_column = src.length - length
38
+ update_positions(row, column + length, offset_column)
39
+ end
40
+
41
+ def save_src
42
+ File.open(filename, 'w+') { |f| f.write(src) }
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,40 @@
1
+ require 'ruby/node'
2
+
3
+ module Ruby
4
+ class StringConcat < List
5
+ end
6
+
7
+ class String < DelimitedList
8
+ def initialize(contents = nil, ldelim = nil, rdelim = nil)
9
+ super(contents, ldelim, rdelim)
10
+ end
11
+
12
+ def value
13
+ map { |content| content.value }.join
14
+ end
15
+
16
+ def dynamic?
17
+ !elements.inject(true) { |result, element| result && element.respond_to?(:value) }
18
+ end
19
+
20
+ def respond_to?(method)
21
+ return false if method.to_sym == :value && dynamic?
22
+ super
23
+ end
24
+ end
25
+
26
+ class Heredoc < String
27
+ end
28
+
29
+ class StringContent < Token
30
+ def value
31
+ token
32
+ end
33
+ end
34
+
35
+ class Regexp < String
36
+ end
37
+
38
+ class ExecutableString < String
39
+ end
40
+ end
@@ -0,0 +1,27 @@
1
+ require 'ruby/aggregate'
2
+ require 'ruby/string'
3
+
4
+ module Ruby
5
+ class Symbol < DelimitedAggregate
6
+ child_accessor :identifier
7
+
8
+ def initialize(identifier, ldelim)
9
+ self.identifier = identifier
10
+ super(ldelim)
11
+ end
12
+
13
+ def value
14
+ identifier.token.to_sym
15
+ end
16
+
17
+ def nodes
18
+ [ldelim, identifier].compact
19
+ end
20
+ end
21
+
22
+ class DynaSymbol < String
23
+ def value
24
+ super.to_sym
25
+ end
26
+ end
27
+ end
data/lib/ruby/token.rb ADDED
@@ -0,0 +1,51 @@
1
+ require 'ruby/node'
2
+
3
+ module Ruby
4
+ class Token < Node
5
+ include Conversions::Token
6
+
7
+ attr_accessor :token, :position, :prolog
8
+
9
+ def initialize(token = '', position = nil, prolog = nil)
10
+ self.token = token
11
+ self.position = position if position
12
+ self.prolog = prolog || Prolog.new
13
+ end
14
+
15
+ def position(prolog = false)
16
+ (self.prolog.try(:position) if prolog) || @position
17
+ end
18
+
19
+ def position=(position)
20
+ @position = position.dup if position
21
+ end
22
+
23
+ def to_s
24
+ token.to_s
25
+ end
26
+
27
+ def to_ruby(prolog = false)
28
+ (prolog && self.prolog.try(:to_ruby, prolog) || '') + token.to_s
29
+ end
30
+ end
31
+
32
+ class Whitespace < Token
33
+ def empty?
34
+ token.empty?
35
+ end
36
+
37
+ def inspect
38
+ token.inspect
39
+ end
40
+ end
41
+
42
+ class Keyword < Token
43
+ end
44
+
45
+ class HeredocBegin < Token
46
+ attr_accessor :heredoc
47
+ end
48
+
49
+ class Identifier < Token
50
+ end
51
+ end
data/lib/ruby/while.rb ADDED
@@ -0,0 +1,32 @@
1
+ require 'ruby/node'
2
+
3
+ module Ruby
4
+ class While < NamedBlock
5
+ child_accessor :expression
6
+
7
+ def initialize(identifier, expression, statements, ldelim = nil, rdelim = nil)
8
+ self.expression = expression
9
+ super(identifier, statements, nil, ldelim, rdelim)
10
+ end
11
+
12
+ def nodes
13
+ [identifier, expression, ldelim, elements, rdelim].flatten.compact
14
+ end
15
+ end
16
+
17
+ class WhileMod < NamedBlock
18
+ child_accessor :expression
19
+
20
+ def initialize(identifier, expression, statements)
21
+ self.expression = expression
22
+ super(identifier, statements)
23
+ end
24
+
25
+ def nodes
26
+ [elements, identifier, expression].flatten.compact
27
+ end
28
+ end
29
+
30
+ class Until < While; end
31
+ class UntilMod < WhileMod; end
32
+ end
data/test/all.rb ADDED
@@ -0,0 +1,3 @@
1
+ files = Dir[File.dirname(__FILE__) + '/**/*_test.rb']
2
+ files.reject! { |f| f.index('lib_test.rb') }
3
+ files.each { |file| require file }
@@ -0,0 +1,67 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class StackTest < Test::Unit::TestCase
4
+ def setup
5
+ @builder = Ripper::RubyBuilder.new('')
6
+ end
7
+
8
+ def push(*types)
9
+ types.each { |type| @builder.send(:push, Array(type)) }
10
+ end
11
+
12
+ def stack
13
+ @builder.stack
14
+ end
15
+
16
+ # define_method "test pop: pops off elements until it finds a token with the requested type" do
17
+ # push(:@lbrace, :@comma, :@comma, :@rbrace)
18
+ #
19
+ # assert_equal :@rbrace, @builder.send(:pop, :@rbrace).first.type
20
+ # assert !@builder.stack.empty?
21
+ # assert @builder.send(:pop, :foo).empty?
22
+ #
23
+ # commas = @builder.send(:pop, :@comma)
24
+ # assert_equal 2, commas.length
25
+ # assert_equal :@comma, commas[0].type
26
+ # assert_equal :@comma, commas[1].type
27
+ #
28
+ # assert_equal :@lbrace, @builder.send(:pop, :@lbrace).first.type
29
+ # assert @builder.stack.empty?
30
+ # assert @builder.send(:pop, :foo).empty?
31
+ # end
32
+ #
33
+ # define_method "test pop: leaves the stack untouched if it does not find a token with the requested type" do
34
+ # push(:@lbrace, :@comma, :@comma, :@rbrace)
35
+ #
36
+ # assert @builder.send(:pop, :foo).empty?
37
+ # assert !@builder.stack.empty?
38
+ # assert !@builder.send(:pop, :@rbrace).empty?
39
+ # end
40
+ #
41
+ # define_method "test push: pushes non-opening tokens directly to the stack" do
42
+ # push(:@rbrace)
43
+ # assert_equal :@rbrace, stack.last.type
44
+ # end
45
+
46
+ # define_method "test push: opening tokens are queued and then pushed together with the next token" do
47
+ # push([:@sp, ' '], [:@sp, ' '], :@lbrace)
48
+ # assert_equal nil, stack.last
49
+ # assert_equal :@lbrace, stack.queue.last.type
50
+ # assert_equal nil, @builder.send(:pop_context)
51
+ #
52
+ # push(:@rbrace)
53
+ # assert_equal :@rbrace, stack[1].type
54
+ # assert_equal :@lbrace, stack[0].type
55
+ # assert_equal ' ', stack[0].context.whitespace.token
56
+ # assert_equal nil, stack.queue.last
57
+ # end
58
+ #
59
+ # define_method "test push: context can be obtained by identifiers, keywords, etc." do
60
+ # push([:@sp, ' '])
61
+ # context = @builder.send(:pop_context)
62
+ # assert_not_nil context.whitespace.token
63
+ # assert_equal ' ', context.whitespace.token
64
+ # end
65
+ end
66
+
67
+
@@ -0,0 +1,118 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ require 'ruby/node/text'
3
+
4
+ class TextClipTest < Test::Unit::TestCase
5
+ include Ruby
6
+
7
+ def setup
8
+ @lines = Node::Text.split("abcd\nbbbb\ncccc\ndddd\neeee\nffff")
9
+ end
10
+
11
+ define_method :"test clip.to_s (1)" do
12
+ assert_equal "ab", Node::Text::Clip.new(@lines, [0, 0], 2).to_s
13
+ end
14
+
15
+ define_method :"test clip.to_s (2)" do
16
+ assert_equal "bc", Node::Text::Clip.new(@lines, [0, 1], 2).to_s
17
+ end
18
+
19
+ define_method :"test clip.to_s (3)" do
20
+ assert_equal "cd", Node::Text::Clip.new(@lines, [0, 2], 2).to_s
21
+ end
22
+
23
+ define_method :"test clip.to_s (4)" do
24
+ assert_equal "abcd\nbbbb\n", Node::Text::Clip.new(@lines, [0, 0], 10).to_s
25
+ end
26
+
27
+ define_method :"test clip.to_s (5)" do
28
+ assert_equal "abcd\nbbbb\ncc", Node::Text::Clip.new(@lines, [0, 0], 12).to_s
29
+ end
30
+
31
+ define_method :"test clip.to_s (6)" do
32
+ assert_equal "cc\ndddd\nee", Node::Text::Clip.new(@lines, [2, 2], 10).to_s
33
+ end
34
+
35
+ define_method :"test clip.head" do
36
+ assert_equal "abcd\nbbbb\ncc", Node::Text::Clip.new(@lines, [2, 2], 10).head
37
+ end
38
+
39
+ define_method :"test clip.tail (1)" do
40
+ assert_equal "b\ncccc\ndddd\neeee\nffff", Node::Text::Clip.new(@lines, [0, 2], 6).tail
41
+ end
42
+
43
+ define_method :"test clip.tail (2)" do
44
+ assert_equal "fff", Node::Text::Clip.new(@lines, [4, 2], 4).tail
45
+ end
46
+
47
+ define_method :"test clip.end (1)" do
48
+ assert_equal [0, 2], Node::Text::Clip.new(@lines, [0, 0], 2).end.to_a
49
+ end
50
+
51
+ define_method :"test clip.end (2)" do
52
+ assert_equal [2, 0], Node::Text::Clip.new(@lines, [0, 0], 10).end.to_a
53
+ end
54
+
55
+ define_method :"test clip.end (3)" do
56
+ assert_equal [3, 2], Node::Text::Clip.new(@lines, [1, 2], 10).end.to_a
57
+ end
58
+
59
+ define_method :"test clip.end (4)" do
60
+ assert_equal [5, 1], Node::Text::Clip.new(@lines, [4, 2], 4).end.to_a
61
+ end
62
+ end
63
+
64
+ class TextTest < Test::Unit::TestCase
65
+ include Ruby
66
+
67
+ def setup
68
+ @text = Node::Text.new("aa\nbb\ncc\ndd\nee\nff")
69
+ end
70
+
71
+ define_method :"test lines returns an array of lines" do
72
+ assert_equal ::Array, @text.lines.class
73
+ assert_equal 6, @text.lines.size
74
+ end
75
+
76
+ define_method :"test clip returns a clip" do
77
+ assert_equal Node::Text::Clip, @text.clip([1, 1], 6).class
78
+ assert_equal "b\ncc\nd", @text.clip([1, 1], 6).to_s
79
+ end
80
+ end
81
+
82
+ class TextNodeTest < Test::Unit::TestCase
83
+ include TestHelper
84
+
85
+ define_method :"test nodes yield expected src clips" do
86
+ src = " t(1, 2)\n t(3); t(4)\n t(5)"
87
+ calls = build(src)
88
+
89
+ assert_equal 't(1, 2)', calls[0].to_ruby
90
+ assert_equal 't(1, 2)', calls[0].src
91
+
92
+ assert_equal 't(3)', calls[1].to_ruby
93
+ assert_equal 't(3)', calls[1].src
94
+
95
+ assert_equal 't(4)', calls[2].to_ruby
96
+ assert_equal 't(4)', calls[2].src
97
+
98
+ assert_equal 't(5)', calls[3].to_ruby
99
+ assert_equal 't(5)', calls[3].src
100
+ end
101
+
102
+ define_method :"test nodes yield expected src clips, including whitespace" do
103
+ src = " t(1, 2)\n t(3); t(4)\n t(5)"
104
+ calls = build(src)
105
+
106
+ assert_equal " t(1, 2)", calls[0].to_ruby(true)
107
+ assert_equal " t(1, 2)", calls[0].src(true)
108
+
109
+ assert_equal "\n t(3)", calls[1].to_ruby(true)
110
+ assert_equal "\n t(3)", calls[1].src(true)
111
+
112
+ assert_equal "; t(4)", calls[2].to_ruby(true)
113
+ assert_equal "; t(4)", calls[2].src(true)
114
+
115
+ assert_equal "\n t(5)", calls[3].to_ruby(true)
116
+ assert_equal "\n t(5)", calls[3].src(true)
117
+ end
118
+ end