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.
- data/MIT-LICENSE +20 -0
- data/README.markdown +10 -0
- data/lib/core_ext/array/flush.rb +5 -0
- data/lib/core_ext/hash/delete_at.rb +5 -0
- data/lib/core_ext/object/meta_class.rb +5 -0
- data/lib/core_ext/object/try.rb +12 -0
- data/lib/erb/stripper.rb +48 -0
- data/lib/highlighters/ansi.rb +29 -0
- data/lib/ripper/event_log.rb +45 -0
- data/lib/ripper/ruby_builder.rb +168 -0
- data/lib/ripper/ruby_builder/buffer.rb +34 -0
- data/lib/ripper/ruby_builder/events/args.rb +40 -0
- data/lib/ripper/ruby_builder/events/array.rb +71 -0
- data/lib/ripper/ruby_builder/events/assignment.rb +55 -0
- data/lib/ripper/ruby_builder/events/block.rb +80 -0
- data/lib/ripper/ruby_builder/events/call.rb +123 -0
- data/lib/ripper/ruby_builder/events/case.rb +17 -0
- data/lib/ripper/ruby_builder/events/const.rb +47 -0
- data/lib/ripper/ruby_builder/events/for.rb +13 -0
- data/lib/ripper/ruby_builder/events/hash.rb +24 -0
- data/lib/ripper/ruby_builder/events/identifier.rb +41 -0
- data/lib/ripper/ruby_builder/events/if.rb +37 -0
- data/lib/ripper/ruby_builder/events/lexer.rb +159 -0
- data/lib/ripper/ruby_builder/events/literal.rb +47 -0
- data/lib/ripper/ruby_builder/events/method.rb +21 -0
- data/lib/ripper/ruby_builder/events/operator.rb +23 -0
- data/lib/ripper/ruby_builder/events/statements.rb +50 -0
- data/lib/ripper/ruby_builder/events/string.rb +117 -0
- data/lib/ripper/ruby_builder/events/symbol.rb +22 -0
- data/lib/ripper/ruby_builder/events/while.rb +27 -0
- data/lib/ripper/ruby_builder/queue.rb +33 -0
- data/lib/ripper/ruby_builder/stack.rb +125 -0
- data/lib/ripper/ruby_builder/token.rb +91 -0
- data/lib/ripper2ruby.rb +1 -0
- data/lib/ruby.rb +28 -0
- data/lib/ruby/aggregate.rb +71 -0
- data/lib/ruby/alternation/args.rb +25 -0
- data/lib/ruby/alternation/hash.rb +25 -0
- data/lib/ruby/alternation/list.rb +19 -0
- data/lib/ruby/args.rb +36 -0
- data/lib/ruby/array.rb +27 -0
- data/lib/ruby/assignment.rb +32 -0
- data/lib/ruby/assoc.rb +17 -0
- data/lib/ruby/block.rb +42 -0
- data/lib/ruby/call.rb +34 -0
- data/lib/ruby/case.rb +30 -0
- data/lib/ruby/const.rb +49 -0
- data/lib/ruby/for.rb +18 -0
- data/lib/ruby/hash.rb +14 -0
- data/lib/ruby/if.rb +35 -0
- data/lib/ruby/list.rb +40 -0
- data/lib/ruby/literal.rb +45 -0
- data/lib/ruby/method.rb +19 -0
- data/lib/ruby/node.rb +47 -0
- data/lib/ruby/node/composite.rb +68 -0
- data/lib/ruby/node/conversions.rb +66 -0
- data/lib/ruby/node/position.rb +35 -0
- data/lib/ruby/node/source.rb +29 -0
- data/lib/ruby/node/text.rb +121 -0
- data/lib/ruby/node/traversal.rb +82 -0
- data/lib/ruby/operator.rb +49 -0
- data/lib/ruby/params.rb +41 -0
- data/lib/ruby/statements.rb +45 -0
- data/lib/ruby/string.rb +40 -0
- data/lib/ruby/symbol.rb +27 -0
- data/lib/ruby/token.rb +51 -0
- data/lib/ruby/while.rb +32 -0
- data/test/all.rb +3 -0
- data/test/builder/stack_test.rb +67 -0
- data/test/builder/text_test.rb +118 -0
- data/test/context_test.rb +54 -0
- data/test/erb_stripper_test.rb +29 -0
- data/test/fixtures/all.rb.src +150 -0
- data/test/fixtures/source_1.rb +16 -0
- data/test/fixtures/source_2.rb +1 -0
- data/test/fixtures/stuff.rb +371 -0
- data/test/fixtures/template.html.erb +22 -0
- data/test/fixtures/tmp.rb +6 -0
- data/test/lib_test.rb +92 -0
- data/test/lib_test_helper.rb +103 -0
- data/test/libs.txt +227 -0
- data/test/nodes/args_test.rb +100 -0
- data/test/nodes/array_test.rb +141 -0
- data/test/nodes/assignment_test.rb +49 -0
- data/test/nodes/block_test.rb +125 -0
- data/test/nodes/call_test.rb +229 -0
- data/test/nodes/case_test.rb +68 -0
- data/test/nodes/comments_test.rb +25 -0
- data/test/nodes/const_test.rb +46 -0
- data/test/nodes/conversions_test.rb +9 -0
- data/test/nodes/for_test.rb +34 -0
- data/test/nodes/hash_test.rb +71 -0
- data/test/nodes/heredoc_test.rb +202 -0
- data/test/nodes/identifier_test.rb +51 -0
- data/test/nodes/if_test.rb +100 -0
- data/test/nodes/literals_test.rb +63 -0
- data/test/nodes/method_test.rb +92 -0
- data/test/nodes/namespaces_test.rb +65 -0
- data/test/nodes/node_test.rb +74 -0
- data/test/nodes/nodes_test.rb +23 -0
- data/test/nodes/operator_test.rb +241 -0
- data/test/nodes/separators_test.rb +97 -0
- data/test/nodes/statements_test.rb +70 -0
- data/test/nodes/string_test.rb +92 -0
- data/test/nodes/symbol_test.rb +57 -0
- data/test/nodes/unless_test.rb +42 -0
- data/test/nodes/until_test.rb +61 -0
- data/test/nodes/while_test.rb +71 -0
- data/test/test_helper.rb +51 -0
- data/test/traversal_test.rb +53 -0
- metadata +163 -0
data/lib/ruby/node.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'core_ext/object/meta_class'
|
2
|
+
require 'core_ext/object/try'
|
3
|
+
require 'ruby/node/composite'
|
4
|
+
require 'ruby/node/source'
|
5
|
+
require 'ruby/node/traversal'
|
6
|
+
require 'ruby/node/conversions'
|
7
|
+
|
8
|
+
module Ruby
|
9
|
+
class Node
|
10
|
+
include Comparable
|
11
|
+
include Composite
|
12
|
+
include Source
|
13
|
+
include Traversal
|
14
|
+
include Conversions
|
15
|
+
|
16
|
+
def row
|
17
|
+
position[0]
|
18
|
+
end
|
19
|
+
|
20
|
+
def column
|
21
|
+
position[1]
|
22
|
+
end
|
23
|
+
|
24
|
+
def length(prolog = false)
|
25
|
+
to_ruby(prolog).length
|
26
|
+
end
|
27
|
+
|
28
|
+
def nodes
|
29
|
+
[]
|
30
|
+
end
|
31
|
+
|
32
|
+
def all_nodes
|
33
|
+
nodes + nodes.map { |node| node.all_nodes }.flatten
|
34
|
+
end
|
35
|
+
|
36
|
+
def <=>(other)
|
37
|
+
position <=> (other.respond_to?(:position) ? other.position : other)
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
def update_positions(row, column, offset_column)
|
42
|
+
pos = self.position
|
43
|
+
pos.col += offset_column if pos && self.row == row && self.column > column
|
44
|
+
nodes.each { |c| c.send(:update_positions, row, column, offset_column) }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Ruby
|
2
|
+
class Node
|
3
|
+
module Composite
|
4
|
+
class Array < ::Array
|
5
|
+
include Composite
|
6
|
+
|
7
|
+
def initialize(objects = [])
|
8
|
+
objects.each { |object| self << object }
|
9
|
+
end
|
10
|
+
|
11
|
+
def detect
|
12
|
+
each { |element| return element if yield(element) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def <<(object)
|
16
|
+
if object.respond_to?(:parent=)
|
17
|
+
object.parent = self.parent
|
18
|
+
elsif object.respond_to?(:each)
|
19
|
+
object.each { |o| o.try(:parent=, parent) }
|
20
|
+
end
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def []=(ix, object)
|
25
|
+
object.parent = parent
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
def parent=(parent)
|
30
|
+
each { |object| object.try(:parent=, parent) }
|
31
|
+
@parent = parent
|
32
|
+
end
|
33
|
+
|
34
|
+
def +(other)
|
35
|
+
self.dup.tap { |dup| other.each { |object| dup << object } }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.included(target)
|
40
|
+
target.class_eval do
|
41
|
+
class << self
|
42
|
+
def child_accessor(*names, &block)
|
43
|
+
names.each do |name|
|
44
|
+
attr_reader name
|
45
|
+
define_method("#{name}=") do |value|
|
46
|
+
value = Composite::Array.new(value) if value.is_a?(::Array)
|
47
|
+
value.parent = self if value
|
48
|
+
instance_variable_set(:"@#{name}", value)
|
49
|
+
yield(value) if block_given?
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
attr_accessor :parent
|
58
|
+
|
59
|
+
def root?
|
60
|
+
parent.nil?
|
61
|
+
end
|
62
|
+
|
63
|
+
def root
|
64
|
+
root? ? self : parent.root
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Ruby
|
2
|
+
module Conversions
|
3
|
+
class << self
|
4
|
+
def included(target)
|
5
|
+
target.send(:extend, ClassMethods)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_node(node, position, prolog)
|
10
|
+
node = self.class.from_native(node) unless node.is_a?(Node)
|
11
|
+
node.position = position
|
12
|
+
node.prolog = prolog
|
13
|
+
node
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def from_native(object, position = nil, prolog = nil)
|
18
|
+
from_ruby(object.inspect, position, prolog)
|
19
|
+
end
|
20
|
+
|
21
|
+
def from_ruby(src, position = nil, prolog = nil)
|
22
|
+
Ripper::RubyBuilder.new(src).parse.statements.first.tap do |node|
|
23
|
+
node.position = position if position
|
24
|
+
node.prolog = prolog if prolog
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
module Token
|
30
|
+
def to_identifier
|
31
|
+
Identifier.new(token, position, prolog)
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_string_content
|
35
|
+
Ruby::StringContent.new(token, position, prolog)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
module List
|
40
|
+
def to_array(ldelim, rdelim)
|
41
|
+
Ruby::Array.new(elements, ldelim, rdelim)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module Statements
|
46
|
+
def to_block(params = nil, ldelim = nil, rdelim = nil)
|
47
|
+
Block.new(elements, params, ldelim, rdelim)
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_named_block(identifier = nil, params = nil, ldelim = nil, rdelim = nil)
|
51
|
+
NamedBlock.new(identifier = nil, elements, params, ldelim, rdelim)
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_chained_block(identifier = nil, blocks = nil, params = nil, ldelim = nil, rdelim = nil)
|
55
|
+
ldelim ||= self.ldelim
|
56
|
+
rdelim ||= self.rdelim
|
57
|
+
identifier ||= self.identifier if respond_to?(:identifier)
|
58
|
+
ChainedBlock.new(identifier, blocks, elements, params, ldelim, rdelim)
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_program(src, filename, end_data)
|
62
|
+
Program.new(src, filename, elements, end_data)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Ruby
|
2
|
+
class Node
|
3
|
+
class Position
|
4
|
+
include Comparable
|
5
|
+
|
6
|
+
attr_accessor :row, :col
|
7
|
+
|
8
|
+
def initialize(row, col)
|
9
|
+
@row = row
|
10
|
+
@col = col
|
11
|
+
end
|
12
|
+
|
13
|
+
def [](ix)
|
14
|
+
ix == 0 ? row : col
|
15
|
+
end
|
16
|
+
|
17
|
+
def <=>(other)
|
18
|
+
row < other.row ? -1 : row > other.row ? 1 : col <=> other.col
|
19
|
+
end
|
20
|
+
|
21
|
+
def ==(other)
|
22
|
+
to_a == other.to_a
|
23
|
+
end
|
24
|
+
alias eql? ==
|
25
|
+
|
26
|
+
def to_a
|
27
|
+
[row, col]
|
28
|
+
end
|
29
|
+
|
30
|
+
def inspect
|
31
|
+
to_a.inspect
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'ruby/node/text'
|
2
|
+
|
3
|
+
module Ruby
|
4
|
+
class Node
|
5
|
+
module Source
|
6
|
+
def filename
|
7
|
+
root? ? @filename : root.filename
|
8
|
+
end
|
9
|
+
|
10
|
+
def src(prolog = false)
|
11
|
+
root? ? @src : Ruby::Node::Text.new(root.src).clip(position(prolog), length(prolog)).to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def lines
|
15
|
+
root.src.split("\n")
|
16
|
+
end
|
17
|
+
|
18
|
+
def line
|
19
|
+
Ruby::Node::Text.new(lines[row]).clip([0, column], length)
|
20
|
+
end
|
21
|
+
|
22
|
+
def context(options = {})
|
23
|
+
filter = options.has_key?(:highlight) ? options[:highlight] : false
|
24
|
+
line = filter ? self.line.head + filter.highlight(to_ruby) + self.line.tail : nil
|
25
|
+
Ruby::Node::Text::Context.new(lines, row, options[:width] || 2, line).to_s
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'ruby/node/position'
|
2
|
+
|
3
|
+
module Ruby
|
4
|
+
class Node
|
5
|
+
class Text
|
6
|
+
class << self
|
7
|
+
def split(str)
|
8
|
+
str.gsub(/\n/, "\n\000").split(/\000/)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Context
|
13
|
+
@@context_width = 2
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def context_width
|
17
|
+
@@context_width
|
18
|
+
end
|
19
|
+
|
20
|
+
def context_width=(context_width)
|
21
|
+
@@context_width = context_width
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_reader :lines, :line, :row, :width
|
26
|
+
|
27
|
+
def initialize(lines, row, width = nil, line = nil)
|
28
|
+
@lines = lines
|
29
|
+
@line = line || lines[row]
|
30
|
+
@row = row
|
31
|
+
@width = width || Context.width
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_s(options = {})
|
35
|
+
(head + [line] + tail).join("\n")
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
|
40
|
+
def head
|
41
|
+
min = [0, row - width].max
|
42
|
+
min < row ? lines[min..(row - 1)] : []
|
43
|
+
end
|
44
|
+
|
45
|
+
def tail
|
46
|
+
max = [row + width, lines.size].min
|
47
|
+
max > row ? lines[(row + 1)..max] : []
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
class Clip
|
52
|
+
attr_reader :lines, :row, :col, :length, :end
|
53
|
+
|
54
|
+
def initialize(lines, pos, length = nil)
|
55
|
+
@lines = lines.is_a?(::String) ? Text.split(lines) : lines
|
56
|
+
@row, @col = *pos
|
57
|
+
@length = length.nil? ? self.lines.join.length : length
|
58
|
+
init
|
59
|
+
end
|
60
|
+
|
61
|
+
def end
|
62
|
+
@end ||= Position.new(row, col + self.length)
|
63
|
+
end
|
64
|
+
|
65
|
+
def end=(position)
|
66
|
+
@end = Position.new(*position)
|
67
|
+
end
|
68
|
+
|
69
|
+
def head
|
70
|
+
lines[0, row].join + lines[row][0, col]
|
71
|
+
end
|
72
|
+
|
73
|
+
def tail
|
74
|
+
lines[self.end.row][self.end.col..-1] + lines[(self.end.row + 1)..-1].join
|
75
|
+
end
|
76
|
+
|
77
|
+
def src
|
78
|
+
lines.join
|
79
|
+
end
|
80
|
+
|
81
|
+
def to_s
|
82
|
+
@string
|
83
|
+
end
|
84
|
+
|
85
|
+
protected
|
86
|
+
|
87
|
+
def init # TODO how to simplify this?
|
88
|
+
@string = lines[row][col, self.length]
|
89
|
+
col = self.length - @string.length
|
90
|
+
row = self.row + 1
|
91
|
+
while (line = lines[row]) && col > 0
|
92
|
+
@string << line[0..(col - 1)]
|
93
|
+
if col - line.length >= 0
|
94
|
+
col -= line.length
|
95
|
+
row += 1
|
96
|
+
self.end = [row, col]
|
97
|
+
else
|
98
|
+
self.end = [row, col]
|
99
|
+
break
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
attr_reader :str, :sep
|
106
|
+
|
107
|
+
def initialize(str = '', sep = nil)
|
108
|
+
@str = str
|
109
|
+
@sep = sep || "\n"
|
110
|
+
end
|
111
|
+
|
112
|
+
def lines
|
113
|
+
@lines ||= Text.split(str)
|
114
|
+
end
|
115
|
+
|
116
|
+
def clip(pos, length)
|
117
|
+
Clip.new(lines, pos, length)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Ruby
|
2
|
+
class Node
|
3
|
+
module Traversal
|
4
|
+
def select(*args, &block)
|
5
|
+
result = []
|
6
|
+
result << self if matches?(args.dup, &block)
|
7
|
+
|
8
|
+
children = (prolog.try(:elements).to_a || []) + nodes
|
9
|
+
children.flatten.compact.inject(result) do |result, node|
|
10
|
+
result + node.select(*args, &block)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def matches?(args, &block)
|
15
|
+
conditions = args.last.is_a?(::Hash) ? args.pop : {}
|
16
|
+
conditions[:is_a] = args unless args.empty?
|
17
|
+
|
18
|
+
conditions.inject(!conditions.empty?) do |result, (type, value)|
|
19
|
+
result && case type
|
20
|
+
when :is_a
|
21
|
+
has_type?(value)
|
22
|
+
when :class
|
23
|
+
is_instance_of?(value)
|
24
|
+
when :token
|
25
|
+
has_token?(value)
|
26
|
+
when :value
|
27
|
+
has_value?(value)
|
28
|
+
when :pos, :position
|
29
|
+
position?(value)
|
30
|
+
when :right_of
|
31
|
+
right_of?(value)
|
32
|
+
when :left_of
|
33
|
+
left_of?(value)
|
34
|
+
end
|
35
|
+
end && (!block_given? || block.call(self))
|
36
|
+
end
|
37
|
+
|
38
|
+
def has_type?(klass)
|
39
|
+
case klass
|
40
|
+
when ::Array
|
41
|
+
klass.each { |klass| return true if has_type?(klass) } and false
|
42
|
+
else
|
43
|
+
is_a?(klass) # allow to pass a symbol or string, too
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def is_instance_of?(klass)
|
48
|
+
case klass
|
49
|
+
when ::Array
|
50
|
+
klass.each { |klass| return true if has_type?(klass) } and false
|
51
|
+
else
|
52
|
+
instance_of?(klass) # allow to pass a symbol or string, too
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def has_token?(token)
|
57
|
+
case token
|
58
|
+
when ::Array
|
59
|
+
type.each { |type| return true if has_token?(token) } and false
|
60
|
+
else
|
61
|
+
self.token == token
|
62
|
+
end if respond_to?(:token)
|
63
|
+
end
|
64
|
+
|
65
|
+
def has_value?(value)
|
66
|
+
self.value == value if respond_to?(:value)
|
67
|
+
end
|
68
|
+
|
69
|
+
def position?(pos)
|
70
|
+
position == pos
|
71
|
+
end
|
72
|
+
|
73
|
+
def left_of?(right)
|
74
|
+
right.nil? || self.position < right.position
|
75
|
+
end
|
76
|
+
|
77
|
+
def right_of?(left)
|
78
|
+
left.nil? || left.position < self.position
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|