unparser 0.0.18 → 0.1.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.
- data/README.md +2 -0
- data/config/flay.yml +1 -1
- data/config/flog.yml +1 -1
- data/config/reek.yml +1 -1
- data/lib/unparser.rb +2 -2
- data/lib/unparser/constants.rb +5 -0
- data/lib/unparser/emitter.rb +61 -32
- data/lib/unparser/emitter/begin.rb +1 -19
- data/lib/unparser/emitter/binary.rb +11 -22
- data/lib/unparser/emitter/flipflop.rb +2 -2
- data/lib/unparser/emitter/literal/range.rb +2 -2
- data/lib/unparser/emitter/root.rb +6 -5
- data/lib/unparser/emitter/send.rb +44 -93
- data/lib/unparser/emitter/send/binary.rb +2 -12
- data/lib/unparser/emitter/send/index.rb +1 -1
- data/lib/unparser/emitter/send/regular.rb +36 -0
- data/lib/unparser/emitter/send/unary.rb +1 -1
- data/lib/unparser/emitter/variable.rb +6 -6
- data/spec/unit/unparser_spec.rb +21 -22
- data/unparser.gemspec +1 -1
- metadata +20 -12
- checksums.yaml +0 -7
- data/lib/unparser/emitter/not.rb +0 -25
- data/spec/unit/unparser/class_methods/unparse_spec.rb +0 -16
- data/spec/unit/unparser/emitter/class_methods/visit_spec.rb +0 -37
data/README.md
CHANGED
@@ -11,6 +11,8 @@ This library is in early development stage and still has some bugs/missing featu
|
|
11
11
|
Nevertheless it is able to regenerate it own source and serves well for
|
12
12
|
[mutant](https://github.cm/mbj/mutant) mutators and the in-memory vendoring for self hosting mutant.
|
13
13
|
|
14
|
+
This library dropped the reproduction of 1.8 syntax in the 0.1.0 release.
|
15
|
+
|
14
16
|
Usage
|
15
17
|
-----
|
16
18
|
|
data/config/flay.yml
CHANGED
data/config/flog.yml
CHANGED
@@ -1,2 +1,2 @@
|
|
1
1
|
---
|
2
|
-
threshold:
|
2
|
+
threshold: 13.1
|
data/config/reek.yml
CHANGED
@@ -37,7 +37,7 @@ FeatureEnvy:
|
|
37
37
|
exclude:
|
38
38
|
- Unparser::Emitter::Literal::Regexp#escape # TODO Fixme!
|
39
39
|
- Unparser::Emitter::Send#binary_receiver?
|
40
|
-
- Unparser::Emitter
|
40
|
+
- Unparser::Emitter#visit_terminated
|
41
41
|
enabled: true
|
42
42
|
ClassVariable:
|
43
43
|
exclude: []
|
data/lib/unparser.rb
CHANGED
@@ -20,7 +20,7 @@ module Unparser
|
|
20
20
|
node = Parser::AST::Node.new(:empty)
|
21
21
|
end
|
22
22
|
buffer = Buffer.new
|
23
|
-
Emitter.
|
23
|
+
Emitter.emitter(node, Emitter::Root.new(buffer)).write_to_buffer
|
24
24
|
buffer.content
|
25
25
|
end
|
26
26
|
|
@@ -57,6 +57,7 @@ require 'unparser/emitter/send'
|
|
57
57
|
require 'unparser/emitter/send/unary'
|
58
58
|
require 'unparser/emitter/send/binary'
|
59
59
|
require 'unparser/emitter/send/index'
|
60
|
+
require 'unparser/emitter/send/regular'
|
60
61
|
require 'unparser/emitter/block'
|
61
62
|
require 'unparser/emitter/assignment'
|
62
63
|
require 'unparser/emitter/variable'
|
@@ -80,7 +81,6 @@ require 'unparser/emitter/next'
|
|
80
81
|
require 'unparser/emitter/if'
|
81
82
|
require 'unparser/emitter/alias'
|
82
83
|
require 'unparser/emitter/yield'
|
83
|
-
require 'unparser/emitter/not'
|
84
84
|
require 'unparser/emitter/binary'
|
85
85
|
require 'unparser/emitter/case'
|
86
86
|
require 'unparser/emitter/for'
|
data/lib/unparser/constants.rb
CHANGED
@@ -75,6 +75,10 @@ module Unparser
|
|
75
75
|
K_FILE = '__FILE__'
|
76
76
|
K_THEN = 'then'
|
77
77
|
|
78
|
+
TERMINATED = [
|
79
|
+
:int, :float, :self, :kwbegin, :const, :regexp
|
80
|
+
].to_set
|
81
|
+
|
78
82
|
KEYWORDS = constants.each_with_object([]) do |name, keywords|
|
79
83
|
value = const_get(name).freeze
|
80
84
|
if name.to_s.start_with?('K_')
|
@@ -82,5 +86,6 @@ module Unparser
|
|
82
86
|
end
|
83
87
|
end.to_set.freeze
|
84
88
|
|
89
|
+
|
85
90
|
end # Constants
|
86
91
|
end # Unparser
|
data/lib/unparser/emitter.rb
CHANGED
@@ -3,7 +3,7 @@ module Unparser
|
|
3
3
|
# Emitter base class
|
4
4
|
class Emitter
|
5
5
|
include Adamantium::Flat, AbstractType, Constants
|
6
|
-
include
|
6
|
+
include Concord.new(:node, :parent)
|
7
7
|
|
8
8
|
# Registry for node emitters
|
9
9
|
REGISTRY = {}
|
@@ -77,49 +77,40 @@ module Unparser
|
|
77
77
|
end
|
78
78
|
private_class_method :handle
|
79
79
|
|
80
|
-
#
|
80
|
+
# Trigger write to buffer
|
81
81
|
#
|
82
82
|
# @return [self]
|
83
83
|
#
|
84
84
|
# @api private
|
85
85
|
#
|
86
|
-
def
|
87
|
-
|
86
|
+
def write_to_buffer
|
87
|
+
dispatch
|
88
88
|
self
|
89
89
|
end
|
90
|
+
memoize :write_to_buffer
|
90
91
|
|
91
|
-
#
|
92
|
-
#
|
93
|
-
# @param [Parser::AST::Node] node
|
94
|
-
# @param [Buffer] buffer
|
92
|
+
# Emit node
|
95
93
|
#
|
96
|
-
# @return [
|
94
|
+
# @return [self]
|
97
95
|
#
|
98
96
|
# @api private
|
99
97
|
#
|
100
|
-
def
|
101
|
-
|
102
|
-
dispatch
|
98
|
+
def self.emit(*arguments)
|
99
|
+
new(*arguments).write_to_buffer
|
103
100
|
end
|
104
101
|
|
105
|
-
|
106
|
-
|
107
|
-
# Visit node
|
108
|
-
#
|
109
|
-
# @param [Parser::AST::Node] node
|
110
|
-
# @param [Buffer] buffer
|
102
|
+
# Return emitter
|
111
103
|
#
|
112
104
|
# @return [Emitter]
|
113
105
|
#
|
114
106
|
# @api private
|
115
107
|
#
|
116
|
-
def self.
|
108
|
+
def self.emitter(node, parent)
|
117
109
|
type = node.type
|
118
|
-
|
110
|
+
klass = REGISTRY.fetch(type) do
|
119
111
|
raise ArgumentError, "No emitter for node: #{type.inspect}"
|
120
112
|
end
|
121
|
-
|
122
|
-
self
|
113
|
+
klass.new(node, parent)
|
123
114
|
end
|
124
115
|
|
125
116
|
# Dispatch node
|
@@ -138,23 +129,31 @@ module Unparser
|
|
138
129
|
#
|
139
130
|
attr_reader :node
|
140
131
|
|
141
|
-
#
|
132
|
+
# Test if node is emitted as terminated expression
|
142
133
|
#
|
143
|
-
# @return [
|
134
|
+
# @return [false]
|
135
|
+
# if emitted node is unambigous
|
136
|
+
#
|
137
|
+
# @return [true]
|
144
138
|
#
|
145
139
|
# @api private
|
146
140
|
#
|
147
|
-
|
148
|
-
|
141
|
+
def terminated?
|
142
|
+
TERMINATED.include?(node.type)
|
143
|
+
end
|
144
|
+
|
145
|
+
protected
|
149
146
|
|
150
|
-
# Return
|
147
|
+
# Return buffer
|
151
148
|
#
|
152
|
-
# @return [
|
149
|
+
# @return [Buffer] buffer
|
153
150
|
#
|
154
151
|
# @api private
|
155
152
|
#
|
156
|
-
|
157
|
-
|
153
|
+
def buffer
|
154
|
+
parent.buffer
|
155
|
+
end
|
156
|
+
memoize :buffer, :freezer => :noop
|
158
157
|
|
159
158
|
private
|
160
159
|
|
@@ -180,7 +179,7 @@ module Unparser
|
|
180
179
|
SourceMap.emit(node, buffer)
|
181
180
|
end
|
182
181
|
|
183
|
-
#
|
182
|
+
# Visit node
|
184
183
|
#
|
185
184
|
# @param [Parser::AST::Node] node
|
186
185
|
#
|
@@ -189,7 +188,37 @@ module Unparser
|
|
189
188
|
# @api private
|
190
189
|
#
|
191
190
|
def visit(node)
|
192
|
-
|
191
|
+
emitter = emitter(node)
|
192
|
+
emitter.write_to_buffer
|
193
|
+
end
|
194
|
+
|
195
|
+
# Visit unambigous node
|
196
|
+
#
|
197
|
+
# @param [Parser::AST::Node] node
|
198
|
+
#
|
199
|
+
# @return [undefined]
|
200
|
+
#
|
201
|
+
# @api private
|
202
|
+
#
|
203
|
+
def visit_terminated(node)
|
204
|
+
emitter = emitter(node)
|
205
|
+
unless emitter.terminated?
|
206
|
+
parentheses { emitter.write_to_buffer }
|
207
|
+
return
|
208
|
+
end
|
209
|
+
emitter.write_to_buffer
|
210
|
+
end
|
211
|
+
|
212
|
+
# Return emitter for node
|
213
|
+
#
|
214
|
+
# @param [Parser::AST::Node] node
|
215
|
+
#
|
216
|
+
# @return [Emitter]
|
217
|
+
#
|
218
|
+
# @api private
|
219
|
+
#
|
220
|
+
def emitter(node)
|
221
|
+
self.class.emitter(node, self)
|
193
222
|
end
|
194
223
|
|
195
224
|
# Emit delimited body
|
@@ -37,25 +37,7 @@ module Unparser
|
|
37
37
|
# @api private
|
38
38
|
#
|
39
39
|
def dispatch
|
40
|
-
|
41
|
-
parentheses { emit_inner }
|
42
|
-
else
|
43
|
-
emit_inner
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# Test if begin node needs to be enclosed within parentheses
|
48
|
-
#
|
49
|
-
# @return [true]
|
50
|
-
# if parentheses are needed
|
51
|
-
#
|
52
|
-
# @return [false]
|
53
|
-
# otherwise
|
54
|
-
#
|
55
|
-
# @api private
|
56
|
-
#
|
57
|
-
def parentheses?
|
58
|
-
children.length == 1 && children.first.type == :send && BINARY_OPERATORS.include?(children.first.children[1])
|
40
|
+
emit_inner
|
59
41
|
end
|
60
42
|
|
61
43
|
end # Implicit
|
@@ -3,7 +3,6 @@ module Unparser
|
|
3
3
|
# Base class for binary emitters
|
4
4
|
class Binary < self
|
5
5
|
|
6
|
-
handle :or, :and
|
7
6
|
children :left, :right
|
8
7
|
|
9
8
|
MAP = {
|
@@ -11,40 +10,30 @@ module Unparser
|
|
11
10
|
:and => T_AND
|
12
11
|
}.freeze
|
13
12
|
|
14
|
-
|
13
|
+
handle *MAP.keys
|
15
14
|
|
16
|
-
#
|
15
|
+
# Test if expression is terminated
|
17
16
|
#
|
18
|
-
# @return [
|
17
|
+
# @return [false]
|
19
18
|
#
|
20
19
|
# @api private
|
21
20
|
#
|
22
|
-
def
|
23
|
-
|
24
|
-
emit_left
|
25
|
-
write(WS, MAP.fetch(node.type), WS)
|
26
|
-
emit_right
|
27
|
-
end
|
21
|
+
def terminated?
|
22
|
+
false
|
28
23
|
end
|
29
24
|
|
30
|
-
|
31
|
-
#
|
32
|
-
# @return [undefined]
|
33
|
-
#
|
34
|
-
# @api private
|
35
|
-
#
|
36
|
-
def emit_left
|
37
|
-
parentheses { visit(left) }
|
38
|
-
end
|
25
|
+
private
|
39
26
|
|
40
|
-
#
|
27
|
+
# Perform dispatch
|
41
28
|
#
|
42
29
|
# @return [undefined]
|
43
30
|
#
|
44
31
|
# @api private
|
45
32
|
#
|
46
|
-
def
|
47
|
-
|
33
|
+
def dispatch
|
34
|
+
visit_terminated(left)
|
35
|
+
write(WS, MAP.fetch(node.type), WS)
|
36
|
+
visit_terminated(right)
|
48
37
|
end
|
49
38
|
|
50
39
|
end # Binary
|
@@ -16,140 +16,91 @@ module Unparser
|
|
16
16
|
|
17
17
|
children :receiver, :selector
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
# Perform dispatch
|
22
|
-
#
|
23
|
-
# @return [undefined]
|
19
|
+
# Test for terminated expression
|
24
20
|
#
|
25
|
-
# @
|
26
|
-
#
|
27
|
-
def dispatch
|
28
|
-
case selector
|
29
|
-
when INDEX_REFERENCE
|
30
|
-
run(Index::Reference)
|
31
|
-
when INDEX_ASSIGN
|
32
|
-
run(Index::Assign)
|
33
|
-
else
|
34
|
-
non_index_dispatch
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# Return string selector
|
21
|
+
# @return [true]
|
22
|
+
# if send is terminated
|
39
23
|
#
|
40
|
-
# @return [
|
24
|
+
# @return [false]
|
25
|
+
# otherwise
|
41
26
|
#
|
42
27
|
# @api private
|
43
28
|
#
|
44
|
-
def
|
45
|
-
|
29
|
+
def terminated?
|
30
|
+
[
|
31
|
+
Unary,
|
32
|
+
Index::Reference,
|
33
|
+
Regular
|
34
|
+
].include?(effective_emitter)
|
46
35
|
end
|
47
|
-
memoize :string_selector
|
48
36
|
|
49
|
-
|
50
|
-
#
|
51
|
-
# @return [undefined]
|
52
|
-
#
|
53
|
-
# @api private
|
54
|
-
#
|
55
|
-
def emit_unambiguous_receiver
|
56
|
-
receiver = effective_receiver
|
57
|
-
if AMBIGOUS.include?(receiver.type) or binary_receiver?
|
58
|
-
parentheses { visit(receiver) }
|
59
|
-
return
|
60
|
-
end
|
61
|
-
|
62
|
-
visit(receiver)
|
63
|
-
end
|
37
|
+
private
|
64
38
|
|
65
|
-
#
|
39
|
+
# Perform dispatch
|
66
40
|
#
|
67
|
-
# @return [
|
41
|
+
# @return [undefined]
|
68
42
|
#
|
69
43
|
# @api private
|
70
44
|
#
|
71
|
-
def
|
72
|
-
|
73
|
-
children = receiver.children
|
74
|
-
if receiver.type == :begin && children.length == 1
|
75
|
-
receiver = children.first
|
76
|
-
end
|
77
|
-
receiver
|
45
|
+
def dispatch
|
46
|
+
run(effective_emitter)
|
78
47
|
end
|
79
48
|
|
80
|
-
#
|
49
|
+
# Return effective emitter
|
81
50
|
#
|
82
|
-
# @return [
|
83
|
-
# if receiver is a binary operation implemented by a method
|
84
|
-
#
|
85
|
-
# @return [false]
|
86
|
-
# otherwise
|
51
|
+
# @return [Class:Emitter]
|
87
52
|
#
|
88
53
|
# @api private
|
89
54
|
#
|
90
|
-
def
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
BINARY_OPERATORS.include?(receiver.children[1])
|
55
|
+
def effective_emitter
|
56
|
+
case selector
|
57
|
+
when INDEX_REFERENCE
|
58
|
+
Index::Reference
|
59
|
+
when INDEX_ASSIGN
|
60
|
+
Index::Assign
|
97
61
|
else
|
98
|
-
|
62
|
+
non_index_emitter
|
99
63
|
end
|
100
64
|
end
|
65
|
+
memoize :effective_emitter
|
101
66
|
|
102
|
-
#
|
103
|
-
#
|
104
|
-
# @param [Class:Emitter] emitter
|
67
|
+
# Return non index emitter
|
105
68
|
#
|
106
|
-
# @return [
|
69
|
+
# @return [Class:Emitter]
|
107
70
|
#
|
108
71
|
# @api private
|
109
72
|
#
|
110
|
-
def
|
111
|
-
emitter.emit(node, buffer, self)
|
112
|
-
end
|
113
|
-
|
114
|
-
# Perform non index dispatch
|
115
|
-
#
|
116
|
-
# @return [undefined]
|
117
|
-
#
|
118
|
-
# @api private
|
119
|
-
#
|
120
|
-
def non_index_dispatch
|
73
|
+
def non_index_emitter
|
121
74
|
if binary?
|
122
|
-
|
123
|
-
return
|
75
|
+
Binary
|
124
76
|
elsif unary?
|
125
|
-
|
126
|
-
|
77
|
+
Unary
|
78
|
+
else
|
79
|
+
Regular
|
127
80
|
end
|
128
|
-
regular_dispatch
|
129
81
|
end
|
130
82
|
|
131
|
-
#
|
83
|
+
# Return string selector
|
132
84
|
#
|
133
|
-
# @return [
|
85
|
+
# @return [String]
|
134
86
|
#
|
135
87
|
# @api private
|
136
88
|
#
|
137
|
-
def
|
138
|
-
|
139
|
-
emit_selector
|
140
|
-
emit_arguments
|
89
|
+
def string_selector
|
90
|
+
selector.to_s
|
141
91
|
end
|
92
|
+
memoize :string_selector
|
142
93
|
|
143
|
-
#
|
94
|
+
# Delegate to emitter
|
144
95
|
#
|
145
|
-
# @
|
96
|
+
# @param [Class:Emitter] emitter
|
97
|
+
#
|
98
|
+
# @return [undefined]
|
146
99
|
#
|
147
100
|
# @api private
|
148
101
|
#
|
149
|
-
def
|
150
|
-
|
151
|
-
emit_unambiguous_receiver
|
152
|
-
write(T_DOT)
|
102
|
+
def run(emitter)
|
103
|
+
emitter.new(node, self).write_to_buffer
|
153
104
|
end
|
154
105
|
|
155
106
|
# Test for unary operator implemented as method
|
@@ -13,21 +13,11 @@ module Unparser
|
|
13
13
|
# @api private
|
14
14
|
#
|
15
15
|
def dispatch
|
16
|
-
|
16
|
+
visit_terminated(receiver)
|
17
17
|
emit_operator
|
18
18
|
emit_right
|
19
19
|
end
|
20
20
|
|
21
|
-
# Emit receiver
|
22
|
-
#
|
23
|
-
# @return [undefined]
|
24
|
-
#
|
25
|
-
# @api private
|
26
|
-
#
|
27
|
-
def emit_receiver
|
28
|
-
emit_unambiguous_receiver
|
29
|
-
end
|
30
|
-
|
31
21
|
# Emit operator
|
32
22
|
#
|
33
23
|
# @return [undefined]
|
@@ -55,7 +45,7 @@ module Unparser
|
|
55
45
|
# @api private
|
56
46
|
#
|
57
47
|
def emit_right
|
58
|
-
|
48
|
+
visit_terminated(right_node)
|
59
49
|
end
|
60
50
|
|
61
51
|
end # Binary
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Unparser
|
2
|
+
class Emitter
|
3
|
+
class Send
|
4
|
+
# Emitter for "regular" receiver.selector(arguments...) case
|
5
|
+
class Regular < self
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
# Perform regular dispatch
|
10
|
+
#
|
11
|
+
# @return [undefined]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
#
|
15
|
+
def dispatch
|
16
|
+
emit_receiver
|
17
|
+
emit_selector
|
18
|
+
emit_arguments
|
19
|
+
end
|
20
|
+
|
21
|
+
# Return receiver
|
22
|
+
#
|
23
|
+
# @return [Parser::AST::Node]
|
24
|
+
#
|
25
|
+
# @api private
|
26
|
+
#
|
27
|
+
def emit_receiver
|
28
|
+
return unless first_child
|
29
|
+
visit_terminated(receiver)
|
30
|
+
write(T_DOT)
|
31
|
+
end
|
32
|
+
|
33
|
+
end # Regular
|
34
|
+
end # Send
|
35
|
+
end # Emitter
|
36
|
+
end # Unparser
|
@@ -27,7 +27,7 @@ module Unparser
|
|
27
27
|
|
28
28
|
handle :const
|
29
29
|
|
30
|
-
children :
|
30
|
+
children :scope, :name
|
31
31
|
|
32
32
|
private
|
33
33
|
|
@@ -38,7 +38,7 @@ module Unparser
|
|
38
38
|
# @api private
|
39
39
|
#
|
40
40
|
def dispatch
|
41
|
-
|
41
|
+
emit_scope
|
42
42
|
write(name.to_s)
|
43
43
|
end
|
44
44
|
|
@@ -48,10 +48,10 @@ module Unparser
|
|
48
48
|
#
|
49
49
|
# @api private
|
50
50
|
#
|
51
|
-
def
|
52
|
-
return unless
|
53
|
-
visit(
|
54
|
-
if
|
51
|
+
def emit_scope
|
52
|
+
return unless scope
|
53
|
+
visit(scope)
|
54
|
+
if scope.type != :cbase
|
55
55
|
write(T_DCL)
|
56
56
|
end
|
57
57
|
end
|
data/spec/unit/unparser_spec.rb
CHANGED
@@ -4,7 +4,6 @@ describe Unparser do
|
|
4
4
|
describe '.unparse' do
|
5
5
|
|
6
6
|
PARSERS = IceNine.deep_freeze(
|
7
|
-
'1.8' => Parser::Ruby18,
|
8
7
|
'1.9' => Parser::Ruby19,
|
9
8
|
'2.0' => Parser::Ruby20,
|
10
9
|
'2.1' => Parser::Ruby21
|
@@ -88,8 +87,7 @@ describe Unparser do
|
|
88
87
|
assert_generates '0x1', '1'
|
89
88
|
assert_generates '1_000', '1000'
|
90
89
|
assert_generates '1e10', '10000000000.0'
|
91
|
-
assert_generates '?c', '"c"'
|
92
|
-
assert_generates '?c', '99', %w(1.8)
|
90
|
+
assert_generates '?c', '"c"'
|
93
91
|
end
|
94
92
|
|
95
93
|
context 'string' do
|
@@ -163,8 +161,8 @@ describe Unparser do
|
|
163
161
|
assert_source '[1]'
|
164
162
|
assert_source '[]'
|
165
163
|
assert_source '[1, *@foo]'
|
166
|
-
assert_source '[*@foo, 1]'
|
167
|
-
assert_source '[*@foo, *@baz]'
|
164
|
+
assert_source '[*@foo, 1]'
|
165
|
+
assert_source '[*@foo, *@baz]'
|
168
166
|
assert_generates '%w(foo bar)', %q(["foo", "bar"])
|
169
167
|
end
|
170
168
|
|
@@ -213,7 +211,7 @@ describe Unparser do
|
|
213
211
|
end
|
214
212
|
|
215
213
|
context 'magic keywords' do
|
216
|
-
assert_generates '__ENCODING__', 'Encoding::UTF_8'
|
214
|
+
assert_generates '__ENCODING__', 'Encoding::UTF_8'
|
217
215
|
assert_source '__FILE__'
|
218
216
|
assert_source '__LINE__'
|
219
217
|
end
|
@@ -321,10 +319,11 @@ describe Unparser do
|
|
321
319
|
|
322
320
|
# Special cases
|
323
321
|
assert_source '(1..2).max'
|
322
|
+
assert_source '(a = b).bar'
|
324
323
|
|
325
324
|
assert_source 'foo.bar(*args)'
|
326
|
-
assert_source 'foo.bar(*arga, foo, *argb)'
|
327
|
-
assert_source 'foo.bar(*args, foo)'
|
325
|
+
assert_source 'foo.bar(*arga, foo, *argb)'
|
326
|
+
assert_source 'foo.bar(*args, foo)'
|
328
327
|
assert_source 'foo.bar(foo, *args)'
|
329
328
|
assert_source 'foo.bar(foo, *args, &block)'
|
330
329
|
assert_source <<-RUBY
|
@@ -894,31 +893,30 @@ describe Unparser do
|
|
894
893
|
|
895
894
|
context 'binary operator methods' do
|
896
895
|
%w(+ - * / & | << >> == === != <= < <=> > >= =~ !~ ^ **).each do |operator|
|
897
|
-
|
898
|
-
assert_source "
|
899
|
-
assert_source "left.#{operator}(
|
900
|
-
assert_source "
|
901
|
-
assert_source "
|
902
|
-
assert_source "a #{operator} b"
|
903
|
-
assert_source "(a #{operator} b).foo", rubies
|
896
|
+
assert_source "1 #{operator} 2"
|
897
|
+
assert_source "left.#{operator}(*foo)"
|
898
|
+
assert_source "left.#{operator}(a, b)"
|
899
|
+
assert_source "self #{operator} b"
|
900
|
+
assert_source "a #{operator} b"
|
901
|
+
assert_source "(a #{operator} b).foo"
|
904
902
|
end
|
905
903
|
end
|
906
904
|
|
907
905
|
context 'nested binary operators' do
|
908
906
|
assert_source '(a + b) / (c - d)'
|
909
|
-
assert_source '(a + b) /
|
910
|
-
assert_source '(a + b) /
|
907
|
+
assert_source '(a + b) / c.-(e, f)'
|
908
|
+
assert_source '(a + b) / c.-(*f)'
|
911
909
|
end
|
912
910
|
|
913
911
|
context 'binary operator' do
|
914
|
-
assert_source '
|
915
|
-
assert_source '(
|
916
|
-
assert_source '(
|
917
|
-
assert_source '
|
912
|
+
assert_source 'a || (break(foo))'
|
913
|
+
assert_source '(break(foo)) || (a)'
|
914
|
+
assert_source '(a || b).foo'
|
915
|
+
assert_source 'a || (b || c)'
|
918
916
|
end
|
919
917
|
|
920
918
|
{ :or => :'||', :and => :'&&' }.each do |word, symbol|
|
921
|
-
assert_generates "a #{word} break foo", "
|
919
|
+
assert_generates "a #{word} break foo", "a #{symbol} (break(foo))"
|
922
920
|
end
|
923
921
|
|
924
922
|
context 'expansion of shortcuts' do
|
@@ -1028,6 +1026,7 @@ describe Unparser do
|
|
1028
1026
|
context 'unary operators' do
|
1029
1027
|
assert_source '!1'
|
1030
1028
|
assert_source '!!1'
|
1029
|
+
assert_source '!(!1).baz'
|
1031
1030
|
assert_source '~a'
|
1032
1031
|
assert_source '-a'
|
1033
1032
|
assert_source '+a'
|
data/unparser.gemspec
CHANGED
metadata
CHANGED
@@ -1,18 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: unparser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
7
|
authors:
|
7
8
|
- Markus Schirp
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2013-09-
|
12
|
+
date: 2013-09-05 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: parser
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
16
18
|
requirements:
|
17
19
|
- - ~>
|
18
20
|
- !ruby/object:Gem::Version
|
@@ -20,6 +22,7 @@ dependencies:
|
|
20
22
|
type: :runtime
|
21
23
|
prerelease: false
|
22
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
23
26
|
requirements:
|
24
27
|
- - ~>
|
25
28
|
- !ruby/object:Gem::Version
|
@@ -27,6 +30,7 @@ dependencies:
|
|
27
30
|
- !ruby/object:Gem::Dependency
|
28
31
|
name: concord
|
29
32
|
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
30
34
|
requirements:
|
31
35
|
- - ~>
|
32
36
|
- !ruby/object:Gem::Version
|
@@ -34,6 +38,7 @@ dependencies:
|
|
34
38
|
type: :runtime
|
35
39
|
prerelease: false
|
36
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
37
42
|
requirements:
|
38
43
|
- - ~>
|
39
44
|
- !ruby/object:Gem::Version
|
@@ -41,6 +46,7 @@ dependencies:
|
|
41
46
|
- !ruby/object:Gem::Dependency
|
42
47
|
name: adamantium
|
43
48
|
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
44
50
|
requirements:
|
45
51
|
- - ~>
|
46
52
|
- !ruby/object:Gem::Version
|
@@ -48,6 +54,7 @@ dependencies:
|
|
48
54
|
type: :runtime
|
49
55
|
prerelease: false
|
50
56
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
51
58
|
requirements:
|
52
59
|
- - ~>
|
53
60
|
- !ruby/object:Gem::Version
|
@@ -55,6 +62,7 @@ dependencies:
|
|
55
62
|
- !ruby/object:Gem::Dependency
|
56
63
|
name: equalizer
|
57
64
|
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
58
66
|
requirements:
|
59
67
|
- - ~>
|
60
68
|
- !ruby/object:Gem::Version
|
@@ -62,6 +70,7 @@ dependencies:
|
|
62
70
|
type: :runtime
|
63
71
|
prerelease: false
|
64
72
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
65
74
|
requirements:
|
66
75
|
- - ~>
|
67
76
|
- !ruby/object:Gem::Version
|
@@ -69,6 +78,7 @@ dependencies:
|
|
69
78
|
- !ruby/object:Gem::Dependency
|
70
79
|
name: abstract_type
|
71
80
|
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
72
82
|
requirements:
|
73
83
|
- - ~>
|
74
84
|
- !ruby/object:Gem::Version
|
@@ -76,6 +86,7 @@ dependencies:
|
|
76
86
|
type: :runtime
|
77
87
|
prerelease: false
|
78
88
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
79
90
|
requirements:
|
80
91
|
- - ~>
|
81
92
|
- !ruby/object:Gem::Version
|
@@ -141,7 +152,6 @@ files:
|
|
141
152
|
- lib/unparser/emitter/match.rb
|
142
153
|
- lib/unparser/emitter/module.rb
|
143
154
|
- lib/unparser/emitter/next.rb
|
144
|
-
- lib/unparser/emitter/not.rb
|
145
155
|
- lib/unparser/emitter/op_assign.rb
|
146
156
|
- lib/unparser/emitter/redo.rb
|
147
157
|
- lib/unparser/emitter/repetition.rb
|
@@ -153,6 +163,7 @@ files:
|
|
153
163
|
- lib/unparser/emitter/send.rb
|
154
164
|
- lib/unparser/emitter/send/binary.rb
|
155
165
|
- lib/unparser/emitter/send/index.rb
|
166
|
+
- lib/unparser/emitter/send/regular.rb
|
156
167
|
- lib/unparser/emitter/send/unary.rb
|
157
168
|
- lib/unparser/emitter/splat.rb
|
158
169
|
- lib/unparser/emitter/super.rb
|
@@ -166,35 +177,34 @@ files:
|
|
166
177
|
- spec/unit/unparser/buffer/indent_spec.rb
|
167
178
|
- spec/unit/unparser/buffer/nl_spec.rb
|
168
179
|
- spec/unit/unparser/buffer/unindent_spec.rb
|
169
|
-
- spec/unit/unparser/class_methods/unparse_spec.rb
|
170
180
|
- spec/unit/unparser/emitter/class_methods/handle_spec.rb
|
171
|
-
- spec/unit/unparser/emitter/class_methods/visit_spec.rb
|
172
181
|
- spec/unit/unparser/emitter/source_map/class_methods/emit_spec.rb
|
173
182
|
- spec/unit/unparser_spec.rb
|
174
183
|
- unparser.gemspec
|
175
184
|
homepage: http://github.com/mbj/unparser
|
176
185
|
licenses:
|
177
186
|
- MIT
|
178
|
-
metadata: {}
|
179
187
|
post_install_message:
|
180
188
|
rdoc_options: []
|
181
189
|
require_paths:
|
182
190
|
- lib
|
183
191
|
required_ruby_version: !ruby/object:Gem::Requirement
|
192
|
+
none: false
|
184
193
|
requirements:
|
185
|
-
- - '>='
|
194
|
+
- - ! '>='
|
186
195
|
- !ruby/object:Gem::Version
|
187
196
|
version: '0'
|
188
197
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
198
|
+
none: false
|
189
199
|
requirements:
|
190
|
-
- - '>='
|
200
|
+
- - ! '>='
|
191
201
|
- !ruby/object:Gem::Version
|
192
202
|
version: '0'
|
193
203
|
requirements: []
|
194
204
|
rubyforge_project:
|
195
|
-
rubygems_version:
|
205
|
+
rubygems_version: 1.8.23
|
196
206
|
signing_key:
|
197
|
-
specification_version:
|
207
|
+
specification_version: 3
|
198
208
|
summary: Generate equivalent source for parser gem AST nodes
|
199
209
|
test_files:
|
200
210
|
- spec/spec_helper.rb
|
@@ -203,9 +213,7 @@ test_files:
|
|
203
213
|
- spec/unit/unparser/buffer/indent_spec.rb
|
204
214
|
- spec/unit/unparser/buffer/nl_spec.rb
|
205
215
|
- spec/unit/unparser/buffer/unindent_spec.rb
|
206
|
-
- spec/unit/unparser/class_methods/unparse_spec.rb
|
207
216
|
- spec/unit/unparser/emitter/class_methods/handle_spec.rb
|
208
|
-
- spec/unit/unparser/emitter/class_methods/visit_spec.rb
|
209
217
|
- spec/unit/unparser/emitter/source_map/class_methods/emit_spec.rb
|
210
218
|
- spec/unit/unparser_spec.rb
|
211
219
|
has_rdoc:
|
checksums.yaml
DELETED
@@ -1,7 +0,0 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
metadata.gz: e2fb94d62a7e99d2533e6507b8190ee433449b64
|
4
|
-
data.tar.gz: 6f3c81cd1f8a171c37ad49c4d1a135d4c8f2c49b
|
5
|
-
SHA512:
|
6
|
-
metadata.gz: 2a2a1ea342bee0e438770a92969087574aa086dd0ddce040b0e51d29fafefd7898b38b59661d7f71af297cb806b70c743ed4ff640cca0e66384e469caa120f51
|
7
|
-
data.tar.gz: fb25c1000ec5f4719a149ad85b260b2274d8bc87a5f1b55f0103f8e8be12a4a176ab89a74f4be514dd9116d3e2c6dd084b3b4f3ed4e3782d5804a5a329fe9749
|
data/lib/unparser/emitter/not.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
module Unparser
|
2
|
-
class Emitter
|
3
|
-
# Emitter for 1.8 only not node
|
4
|
-
class Not < self
|
5
|
-
|
6
|
-
handle :not
|
7
|
-
|
8
|
-
children :body
|
9
|
-
|
10
|
-
private
|
11
|
-
|
12
|
-
# Perform dispatch
|
13
|
-
#
|
14
|
-
# @return [undefined]
|
15
|
-
#
|
16
|
-
# @api private
|
17
|
-
#
|
18
|
-
def dispatch
|
19
|
-
write(T_NEG)
|
20
|
-
visit(body)
|
21
|
-
end
|
22
|
-
|
23
|
-
end # Not
|
24
|
-
end # Emitter
|
25
|
-
end # Unparser
|
@@ -1,16 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Unparser, '.unparse' do
|
4
|
-
subject { described_class.unparse(node) }
|
5
|
-
|
6
|
-
let(:node) { double('Node') }
|
7
|
-
|
8
|
-
before do
|
9
|
-
described_class::Emitter.should_receive(:visit) do |node, buffer|
|
10
|
-
node.should be(node)
|
11
|
-
buffer.append('foo')
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
it { should eql('foo') }
|
16
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Unparser::Emitter, '.visit' do
|
4
|
-
subject { object.visit(node, buffer) }
|
5
|
-
let(:object) { described_class }
|
6
|
-
|
7
|
-
let(:node) { double('Node', :type => type, :source_map => nil) }
|
8
|
-
let(:buffer) { Unparser::Buffer.new }
|
9
|
-
|
10
|
-
before do
|
11
|
-
stub_const('Unparser::Emitter::REGISTRY', { :dummy => Dummy })
|
12
|
-
end
|
13
|
-
|
14
|
-
class Dummy < Unparser::Emitter
|
15
|
-
def self.emit(node, buffer, parent)
|
16
|
-
buffer.append('foo')
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
context 'when handler for type is registred' do
|
21
|
-
let(:type) { :dummy }
|
22
|
-
it_should_behave_like 'a command method'
|
23
|
-
|
24
|
-
it 'should call emitter' do
|
25
|
-
subject
|
26
|
-
buffer.content.should eql('foo')
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
context 'when handler for type is NOT registred' do
|
31
|
-
let(:type) { :unknown }
|
32
|
-
|
33
|
-
it 'should raise error' do
|
34
|
-
expect { subject }.to raise_error(ArgumentError, 'No emitter for node: :unknown')
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|