unparser 0.6.7 → 0.9.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.
- checksums.yaml +4 -4
- data/README.md +10 -10
- data/lib/unparser/adamantium.rb +3 -1
- data/lib/unparser/anima.rb +12 -3
- data/lib/unparser/ast/local_variable_scope.rb +29 -26
- data/lib/unparser/ast.rb +32 -49
- data/lib/unparser/buffer.rb +44 -2
- data/lib/unparser/cli.rb +48 -11
- data/lib/unparser/color.rb +9 -1
- data/lib/unparser/comments.rb +2 -2
- data/lib/unparser/diff.rb +8 -1
- data/lib/unparser/either.rb +13 -11
- data/lib/unparser/emitter/args.rb +5 -1
- data/lib/unparser/emitter/array.rb +0 -4
- data/lib/unparser/emitter/array_pattern.rb +1 -9
- data/lib/unparser/emitter/assignment.rb +17 -8
- data/lib/unparser/emitter/begin.rb +0 -6
- data/lib/unparser/emitter/binary.rb +1 -1
- data/lib/unparser/emitter/block.rb +18 -7
- data/lib/unparser/emitter/def.rb +1 -1
- data/lib/unparser/emitter/dstr.rb +6 -5
- data/lib/unparser/emitter/dsym.rb +1 -1
- data/lib/unparser/emitter/ensure.rb +16 -0
- data/lib/unparser/emitter/flipflop.rb +7 -2
- data/lib/unparser/emitter/flow_modifier.rb +1 -7
- data/lib/unparser/emitter/for.rb +1 -1
- data/lib/unparser/emitter/hash.rb +0 -8
- data/lib/unparser/emitter/hash_pattern.rb +1 -1
- data/lib/unparser/emitter/in_pattern.rb +9 -1
- data/lib/unparser/emitter/index.rb +0 -4
- data/lib/unparser/emitter/kwbegin.rb +1 -1
- data/lib/unparser/emitter/match_pattern.rb +7 -11
- data/lib/unparser/emitter/match_pattern_p.rb +6 -1
- data/lib/unparser/emitter/mlhs.rb +7 -1
- data/lib/unparser/emitter/op_assign.rb +0 -5
- data/lib/unparser/emitter/pair.rb +31 -5
- data/lib/unparser/emitter/primitive.rb +4 -6
- data/lib/unparser/emitter/range.rb +23 -2
- data/lib/unparser/emitter/regexp.rb +5 -17
- data/lib/unparser/emitter/rescue.rb +7 -1
- data/lib/unparser/emitter/root.rb +2 -9
- data/lib/unparser/emitter/send.rb +1 -5
- data/lib/unparser/emitter/string.rb +31 -0
- data/lib/unparser/emitter/xstr.rb +8 -1
- data/lib/unparser/emitter.rb +11 -11
- data/lib/unparser/equalizer.rb +105 -71
- data/lib/unparser/generation.rb +33 -29
- data/lib/unparser/node_details/send.rb +1 -0
- data/lib/unparser/node_details.rb +8 -1
- data/lib/unparser/node_helpers.rb +19 -9
- data/lib/unparser/util.rb +24 -0
- data/lib/unparser/validation.rb +70 -28
- data/lib/unparser/writer/array.rb +51 -0
- data/lib/unparser/writer/binary.rb +8 -4
- data/lib/unparser/writer/dynamic_string.rb +130 -138
- data/lib/unparser/writer/regexp.rb +101 -0
- data/lib/unparser/writer/resbody.rb +37 -3
- data/lib/unparser/writer/rescue.rb +3 -7
- data/lib/unparser/writer/send/unary.rb +9 -4
- data/lib/unparser/writer/send.rb +8 -14
- data/lib/unparser/writer.rb +31 -1
- data/lib/unparser.rb +157 -41
- metadata +82 -33
- data/lib/unparser/concord.rb +0 -114
data/lib/unparser/either.rb
CHANGED
|
@@ -19,11 +19,13 @@ module Unparser
|
|
|
19
19
|
end # RequireBLock
|
|
20
20
|
|
|
21
21
|
class Either
|
|
22
|
-
include(
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
)
|
|
22
|
+
include Adamantium, Equalizer.new(:value), RequireBlock
|
|
23
|
+
|
|
24
|
+
attr_reader :value
|
|
25
|
+
|
|
26
|
+
def initialize(value)
|
|
27
|
+
@value = value
|
|
28
|
+
end
|
|
27
29
|
|
|
28
30
|
# Execute block and wrap error in left
|
|
29
31
|
#
|
|
@@ -54,15 +56,15 @@ module Unparser
|
|
|
54
56
|
# Evaluate functor block
|
|
55
57
|
#
|
|
56
58
|
# @return [Either::Left<Object>]
|
|
57
|
-
def fmap(&
|
|
58
|
-
require_block(&
|
|
59
|
+
def fmap(&)
|
|
60
|
+
require_block(&)
|
|
59
61
|
end
|
|
60
62
|
|
|
61
63
|
# Evaluate applicative block
|
|
62
64
|
#
|
|
63
65
|
# @return [Either::Left<Object>]
|
|
64
|
-
def bind(&
|
|
65
|
-
require_block(&
|
|
66
|
+
def bind(&)
|
|
67
|
+
require_block(&)
|
|
66
68
|
end
|
|
67
69
|
|
|
68
70
|
# Unwrap value from left
|
|
@@ -137,8 +139,8 @@ module Unparser
|
|
|
137
139
|
# Map over left value
|
|
138
140
|
#
|
|
139
141
|
# @return [Either::Right<Object>]
|
|
140
|
-
def lmap(&
|
|
141
|
-
require_block(&
|
|
142
|
+
def lmap(&)
|
|
143
|
+
require_block(&)
|
|
142
144
|
end
|
|
143
145
|
|
|
144
146
|
# Evaluate right side of branch
|
|
@@ -13,7 +13,11 @@ module Unparser
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def emit_def_arguments
|
|
16
|
-
|
|
16
|
+
if children.one? && n_mlhs?(Util.one(children))
|
|
17
|
+
emitter(Util.one(children)).dispatch_def
|
|
18
|
+
else
|
|
19
|
+
delimited(normal_arguments)
|
|
20
|
+
end
|
|
17
21
|
end
|
|
18
22
|
|
|
19
23
|
def emit_lambda_arguments
|
|
@@ -12,18 +12,10 @@ module Unparser
|
|
|
12
12
|
|
|
13
13
|
def dispatch
|
|
14
14
|
write('[')
|
|
15
|
-
delimited(children
|
|
15
|
+
delimited(children)
|
|
16
16
|
write(', ') if node_type.equal?(:array_pattern_with_tail)
|
|
17
17
|
write(']')
|
|
18
18
|
end
|
|
19
|
-
|
|
20
|
-
def emit_member(node)
|
|
21
|
-
if n_match_rest?(node)
|
|
22
|
-
writer_with(MatchRest, node).emit_array_pattern
|
|
23
|
-
else
|
|
24
|
-
visit(node)
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
19
|
end # Pin
|
|
28
20
|
end # Emitter
|
|
29
21
|
end # Unparser
|
|
@@ -11,12 +11,6 @@ module Unparser
|
|
|
11
11
|
true
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def emit_heredoc_reminders
|
|
15
|
-
return unless right
|
|
16
|
-
|
|
17
|
-
emitter(right).emit_heredoc_reminders
|
|
18
|
-
end
|
|
19
|
-
|
|
20
14
|
private
|
|
21
15
|
|
|
22
16
|
def dispatch
|
|
@@ -30,12 +24,27 @@ module Unparser
|
|
|
30
24
|
write(' = ')
|
|
31
25
|
|
|
32
26
|
if BINARY_OPERATOR.include?(right.type)
|
|
33
|
-
writer_with(Writer::Binary, right).emit_operator
|
|
27
|
+
writer_with(Writer::Binary, node: right).emit_operator
|
|
28
|
+
elsif n_array?(right)
|
|
29
|
+
emit_array
|
|
30
|
+
else
|
|
31
|
+
right_emitter.write_to_buffer
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def emit_array
|
|
36
|
+
if right.children.size > 1
|
|
37
|
+
delimited(right.children)
|
|
34
38
|
else
|
|
35
|
-
|
|
39
|
+
right_emitter.write_to_buffer
|
|
36
40
|
end
|
|
37
41
|
end
|
|
38
42
|
|
|
43
|
+
def right_emitter
|
|
44
|
+
emitter(right)
|
|
45
|
+
end
|
|
46
|
+
memoize :right_emitter
|
|
47
|
+
|
|
39
48
|
abstract_method :emit_left
|
|
40
49
|
|
|
41
50
|
# Variable assignment emitter
|
|
@@ -5,7 +5,7 @@ module Unparser
|
|
|
5
5
|
|
|
6
6
|
# Block emitter
|
|
7
7
|
class Block < self
|
|
8
|
-
handle :block, :numblock
|
|
8
|
+
handle :block, :numblock, :itblock
|
|
9
9
|
|
|
10
10
|
children :target, :arguments, :body
|
|
11
11
|
|
|
@@ -16,7 +16,6 @@ module Unparser
|
|
|
16
16
|
ws
|
|
17
17
|
write_open
|
|
18
18
|
emit_block_arguments unless n_lambda?(target)
|
|
19
|
-
target_writer.emit_heredoc_reminders if n_send?(target)
|
|
20
19
|
emit_optional_body_ensure_rescue(body)
|
|
21
20
|
write_close
|
|
22
21
|
end
|
|
@@ -42,7 +41,7 @@ module Unparser
|
|
|
42
41
|
end
|
|
43
42
|
|
|
44
43
|
def target_writer
|
|
45
|
-
writer_with(Writer::Send::Regular, target)
|
|
44
|
+
writer_with(Writer::Send::Regular, node: target)
|
|
46
45
|
end
|
|
47
46
|
memoize :target_writer
|
|
48
47
|
|
|
@@ -52,7 +51,7 @@ module Unparser
|
|
|
52
51
|
emit_send_target
|
|
53
52
|
when :lambda
|
|
54
53
|
visit(target)
|
|
55
|
-
emit_lambda_arguments
|
|
54
|
+
emit_lambda_arguments
|
|
56
55
|
else
|
|
57
56
|
visit(target)
|
|
58
57
|
end
|
|
@@ -64,21 +63,33 @@ module Unparser
|
|
|
64
63
|
target_writer.emit_arguments_without_heredoc_body
|
|
65
64
|
end
|
|
66
65
|
|
|
66
|
+
# NOTE: mutant fails on Ruby < 3.4
|
|
67
|
+
# mutant:disable
|
|
67
68
|
def emit_lambda_arguments
|
|
68
|
-
|
|
69
|
+
return if node.type.equal?(:numblock) || itblock?
|
|
70
|
+
|
|
71
|
+
parentheses { writer_with(Args, node: arguments).emit_lambda_arguments }
|
|
69
72
|
end
|
|
70
73
|
|
|
71
74
|
def numblock?
|
|
72
75
|
node.type.equal?(:numblock)
|
|
73
76
|
end
|
|
74
77
|
|
|
78
|
+
# NOTE: mutant fails on Ruby < 3.4
|
|
79
|
+
# mutant:disable
|
|
80
|
+
def itblock?
|
|
81
|
+
node.type.equal?(:itblock)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# NOTE: mutant fails on Ruby < 3.4
|
|
85
|
+
# mutant:disable
|
|
75
86
|
def emit_block_arguments
|
|
76
|
-
return if numblock? || arguments.children.empty?
|
|
87
|
+
return if numblock? || itblock? || arguments.children.empty?
|
|
77
88
|
|
|
78
89
|
ws
|
|
79
90
|
|
|
80
91
|
parentheses('|', '|') do
|
|
81
|
-
writer_with(Args, arguments).emit_block_arguments
|
|
92
|
+
writer_with(Args, node: arguments).emit_block_arguments
|
|
82
93
|
end
|
|
83
94
|
end
|
|
84
95
|
|
data/lib/unparser/emitter/def.rb
CHANGED
|
@@ -7,15 +7,16 @@ module Unparser
|
|
|
7
7
|
|
|
8
8
|
handle :dstr
|
|
9
9
|
|
|
10
|
-
def emit_heredoc_reminders
|
|
11
|
-
writer_with(Writer::DynamicString, node).emit_heredoc_reminder
|
|
12
|
-
end
|
|
13
|
-
|
|
14
10
|
private
|
|
15
11
|
|
|
16
12
|
def dispatch
|
|
17
|
-
|
|
13
|
+
dstr_writer.dispatch
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def dstr_writer
|
|
17
|
+
writer_with(Writer::DynamicString, node:)
|
|
18
18
|
end
|
|
19
|
+
memoize :dstr_writer
|
|
19
20
|
|
|
20
21
|
end # DStr
|
|
21
22
|
end # Emitter
|
|
@@ -14,12 +14,6 @@ module Unparser
|
|
|
14
14
|
|
|
15
15
|
handle(*MAP.keys)
|
|
16
16
|
|
|
17
|
-
def emit_heredoc_reminders
|
|
18
|
-
children.each do |node|
|
|
19
|
-
emitter(node).emit_heredoc_reminders
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
17
|
private
|
|
24
18
|
|
|
25
19
|
def dispatch
|
|
@@ -27,7 +21,7 @@ module Unparser
|
|
|
27
21
|
|
|
28
22
|
if children.one? && n_if?(children.first)
|
|
29
23
|
ws
|
|
30
|
-
emitter(children
|
|
24
|
+
emitter(Util.one(children)).emit_ternary
|
|
31
25
|
else
|
|
32
26
|
emit_arguments unless children.empty?
|
|
33
27
|
end
|
data/lib/unparser/emitter/for.rb
CHANGED
|
@@ -6,10 +6,6 @@ module Unparser
|
|
|
6
6
|
class Hash < self
|
|
7
7
|
handle :hash
|
|
8
8
|
|
|
9
|
-
def emit_heredoc_reminders
|
|
10
|
-
children.each(&method(:emit_heredoc_reminder_member))
|
|
11
|
-
end
|
|
12
|
-
|
|
13
9
|
private
|
|
14
10
|
|
|
15
11
|
def dispatch
|
|
@@ -24,10 +20,6 @@ module Unparser
|
|
|
24
20
|
end
|
|
25
21
|
end
|
|
26
22
|
|
|
27
|
-
def emit_heredoc_reminder_member(node)
|
|
28
|
-
emitter(node.children.last).emit_heredoc_reminders
|
|
29
|
-
end
|
|
30
|
-
|
|
31
23
|
def emit_hash_body
|
|
32
24
|
delimited(children)
|
|
33
25
|
end
|
|
@@ -16,7 +16,7 @@ module Unparser
|
|
|
16
16
|
|
|
17
17
|
ws
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
dispatch_target(target)
|
|
20
20
|
|
|
21
21
|
if unless_guard
|
|
22
22
|
ws
|
|
@@ -31,6 +31,14 @@ module Unparser
|
|
|
31
31
|
nl
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
|
+
|
|
35
|
+
def dispatch_target(target)
|
|
36
|
+
if n_array?(target)
|
|
37
|
+
writer_with(Writer::Array, node: target).emit_compact
|
|
38
|
+
else
|
|
39
|
+
visit(target)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
34
42
|
end # InPattern
|
|
35
43
|
end # Emitter
|
|
36
44
|
end # Unparser
|
|
@@ -9,21 +9,17 @@ module Unparser
|
|
|
9
9
|
|
|
10
10
|
children :target, :pattern
|
|
11
11
|
|
|
12
|
-
# Modern ast format emits `match_pattern`
|
|
13
|
-
# node on single line pre 3.0, but 3.0+ uses `match_pattern_p`
|
|
14
|
-
SYMBOL =
|
|
15
|
-
if RUBY_VERSION < '3.0'
|
|
16
|
-
' in '
|
|
17
|
-
else
|
|
18
|
-
' => '
|
|
19
|
-
end
|
|
20
|
-
|
|
21
12
|
private
|
|
22
13
|
|
|
23
14
|
def dispatch
|
|
24
15
|
visit(target)
|
|
25
|
-
write(
|
|
26
|
-
|
|
16
|
+
write(' => ')
|
|
17
|
+
|
|
18
|
+
if n_array?(pattern)
|
|
19
|
+
writer_with(Writer::Array, node: pattern).emit_compact
|
|
20
|
+
else
|
|
21
|
+
visit(pattern)
|
|
22
|
+
end
|
|
27
23
|
end
|
|
28
24
|
end # MatchPattern
|
|
29
25
|
end # Emitter
|
|
@@ -6,10 +6,16 @@ module Unparser
|
|
|
6
6
|
class MLHS < self
|
|
7
7
|
handle :mlhs
|
|
8
8
|
|
|
9
|
-
NO_COMMA = %i[arg splat
|
|
9
|
+
NO_COMMA = %i[arg splat restarg].freeze
|
|
10
10
|
|
|
11
11
|
private_constant(*constants(false))
|
|
12
12
|
|
|
13
|
+
def dispatch_def
|
|
14
|
+
parentheses do
|
|
15
|
+
delimited(children)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
13
19
|
private
|
|
14
20
|
|
|
15
21
|
def dispatch
|
|
@@ -15,19 +15,45 @@ module Unparser
|
|
|
15
15
|
private
|
|
16
16
|
|
|
17
17
|
def dispatch
|
|
18
|
-
if colon?
|
|
19
|
-
|
|
18
|
+
if colon?
|
|
19
|
+
emit_colon
|
|
20
|
+
unless implicit_value_lvar? || implicit_value_send?
|
|
21
|
+
write(' ')
|
|
22
|
+
visit(value)
|
|
23
|
+
end
|
|
20
24
|
else
|
|
21
25
|
visit(key)
|
|
22
26
|
write(' => ')
|
|
27
|
+
visit(value)
|
|
23
28
|
end
|
|
24
|
-
|
|
25
|
-
visit(value)
|
|
26
29
|
end
|
|
27
30
|
|
|
28
|
-
def colon?
|
|
31
|
+
def colon?
|
|
29
32
|
n_sym?(key) && BAREWORD.match?(key.children.first)
|
|
30
33
|
end
|
|
34
|
+
|
|
35
|
+
def emit_colon
|
|
36
|
+
write(key.children.first.to_s, ':')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def key_value
|
|
40
|
+
key.children.first
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def implicit_value_lvar?
|
|
44
|
+
n_lvar?(value) && value.children.first.equal?(key_value)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def implicit_value_send?
|
|
48
|
+
children = value.children
|
|
49
|
+
|
|
50
|
+
n_send?(value) \
|
|
51
|
+
&& !key_value.end_with?('?') \
|
|
52
|
+
&& !key_value.end_with?('!') \
|
|
53
|
+
&& children.fetch(0).nil? \
|
|
54
|
+
&& children.fetch(1).equal?(key_value) \
|
|
55
|
+
&& children.at(2).nil?
|
|
56
|
+
end
|
|
31
57
|
end
|
|
32
58
|
end
|
|
33
59
|
end
|
|
@@ -7,18 +7,16 @@ module Unparser
|
|
|
7
7
|
|
|
8
8
|
children :value
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
class Inspect < self
|
|
10
|
+
class Symbol < self
|
|
12
11
|
|
|
13
|
-
handle :sym
|
|
12
|
+
handle :sym
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
private
|
|
16
15
|
|
|
17
16
|
def dispatch
|
|
18
17
|
write(value.inspect)
|
|
19
18
|
end
|
|
20
|
-
|
|
21
|
-
end # Inspect
|
|
19
|
+
end # Symbol
|
|
22
20
|
|
|
23
21
|
# Emitter for complex literals
|
|
24
22
|
class Complex < self
|
|
@@ -25,9 +25,30 @@ module Unparser
|
|
|
25
25
|
private
|
|
26
26
|
|
|
27
27
|
def dispatch
|
|
28
|
-
|
|
28
|
+
visit_begin_node(begin_node)
|
|
29
29
|
write(TOKENS.fetch(node.type))
|
|
30
|
-
|
|
30
|
+
visit_end_node(end_node)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def visit_begin_node(node)
|
|
34
|
+
return unless node
|
|
35
|
+
|
|
36
|
+
if n_array?(begin_node)
|
|
37
|
+
writer_with(Writer::Array, node: begin_node).emit_compact
|
|
38
|
+
else
|
|
39
|
+
visit(begin_node)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def visit_end_node(node)
|
|
44
|
+
return unless node
|
|
45
|
+
|
|
46
|
+
write(' ') if n_range?(node)
|
|
47
|
+
if n_array?(node)
|
|
48
|
+
writer_with(Writer::Array, node: node).emit_compact
|
|
49
|
+
else
|
|
50
|
+
visit(node)
|
|
51
|
+
end
|
|
31
52
|
end
|
|
32
53
|
|
|
33
54
|
end # Range
|
|
@@ -4,32 +4,20 @@ module Unparser
|
|
|
4
4
|
class Emitter
|
|
5
5
|
# Emitter for regexp literals
|
|
6
6
|
class Regexp < self
|
|
7
|
-
handle :regexp
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
handle :regexp
|
|
10
9
|
|
|
11
10
|
private
|
|
12
11
|
|
|
13
12
|
def dispatch
|
|
14
|
-
|
|
15
|
-
body.each(&method(:emit_body))
|
|
16
|
-
end
|
|
17
|
-
emit_options
|
|
13
|
+
writer.dispatch
|
|
18
14
|
end
|
|
19
15
|
|
|
20
|
-
def
|
|
21
|
-
|
|
16
|
+
def writer
|
|
17
|
+
writer_with(Writer::Regexp, node:)
|
|
22
18
|
end
|
|
19
|
+
memoize :writer
|
|
23
20
|
|
|
24
|
-
def emit_body(node)
|
|
25
|
-
if n_begin?(node)
|
|
26
|
-
write('#{')
|
|
27
|
-
node.children.each(&method(:visit))
|
|
28
|
-
write('}')
|
|
29
|
-
else
|
|
30
|
-
buffer.append_without_prefix(node.children.first.gsub('/', '\/'))
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
21
|
end # Regexp
|
|
34
22
|
end # Emitter
|
|
35
23
|
end # Unparser
|
|
@@ -9,7 +9,13 @@ module Unparser
|
|
|
9
9
|
private
|
|
10
10
|
|
|
11
11
|
def dispatch
|
|
12
|
-
|
|
12
|
+
resbody = children.fetch(1)
|
|
13
|
+
|
|
14
|
+
if resbody.children.fetch(1)
|
|
15
|
+
emit_rescue_regular(node)
|
|
16
|
+
else
|
|
17
|
+
emit_rescue_postcontrol(node)
|
|
18
|
+
end
|
|
13
19
|
end
|
|
14
20
|
end # Rescue
|
|
15
21
|
end # Emitter
|