unparser 0.5.3 → 0.6.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 +12 -0
- data/lib/unparser.rb +34 -24
- data/lib/unparser/abstract_type.rb +121 -0
- data/lib/unparser/adamantium.rb +150 -0
- data/lib/unparser/adamantium/method_builder.rb +110 -0
- data/lib/unparser/anima.rb +184 -0
- data/lib/unparser/anima/attribute.rb +59 -0
- data/lib/unparser/anima/error.rb +23 -0
- data/lib/unparser/ast.rb +1 -2
- data/lib/unparser/color.rb +1 -1
- data/lib/unparser/concord.rb +114 -0
- data/lib/unparser/diff.rb +1 -1
- data/lib/unparser/either.rb +153 -0
- data/lib/unparser/emitter.rb +1 -1
- data/lib/unparser/emitter/flow_modifier.rb +11 -2
- data/lib/unparser/emitter/hash.rb +1 -31
- data/lib/unparser/emitter/if.rb +8 -0
- data/lib/unparser/emitter/in_pattern.rb +2 -0
- data/lib/unparser/emitter/index.rb +1 -1
- data/lib/unparser/emitter/kwargs.rb +13 -0
- data/lib/unparser/emitter/match_pattern.rb +22 -0
- data/lib/unparser/emitter/op_assign.rb +2 -2
- data/lib/unparser/emitter/pair.rb +33 -0
- data/lib/unparser/emitter/primitive.rb +2 -2
- data/lib/unparser/emitter/simple.rb +2 -2
- data/lib/unparser/emitter/splat.rb +11 -1
- data/lib/unparser/equalizer.rb +98 -0
- data/lib/unparser/generation.rb +3 -1
- data/lib/unparser/node_details.rb +1 -1
- data/lib/unparser/node_helpers.rb +1 -0
- data/lib/unparser/validation.rb +3 -3
- data/lib/unparser/writer/binary.rb +1 -1
- data/lib/unparser/writer/dynamic_string.rb +13 -23
- data/lib/unparser/writer/rescue.rb +5 -1
- data/lib/unparser/writer/send.rb +7 -16
- metadata +32 -114
data/lib/unparser/emitter.rb
CHANGED
@@ -5,7 +5,7 @@ module Unparser
|
|
5
5
|
|
6
6
|
# Emitter base class
|
7
7
|
class Emitter
|
8
|
-
include Adamantium
|
8
|
+
include Adamantium, AbstractType, Constants, Generation, NodeHelpers
|
9
9
|
include Anima.new(:buffer, :comments, :node, :local_variable_scope)
|
10
10
|
|
11
11
|
public :node
|
@@ -14,13 +14,22 @@ 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
|
+
|
17
23
|
private
|
18
24
|
|
19
25
|
def dispatch
|
20
26
|
write(MAP.fetch(node.type))
|
21
27
|
|
22
|
-
|
23
|
-
|
28
|
+
if children.one? && n_if?(children.first)
|
29
|
+
ws
|
30
|
+
emitter(children.first).emit_ternary
|
31
|
+
else
|
32
|
+
emit_arguments unless children.empty?
|
24
33
|
end
|
25
34
|
end
|
26
35
|
|
@@ -4,10 +4,6 @@ module Unparser
|
|
4
4
|
class Emitter
|
5
5
|
# Emitter for Hash literals
|
6
6
|
class Hash < self
|
7
|
-
BAREWORD = /\A[A-Za-z_][A-Za-z_0-9]*[?!]?\z/.freeze
|
8
|
-
|
9
|
-
private_constant(*constants(false))
|
10
|
-
|
11
7
|
handle :hash
|
12
8
|
|
13
9
|
def emit_last_argument_hash
|
@@ -41,34 +37,8 @@ module Unparser
|
|
41
37
|
end
|
42
38
|
|
43
39
|
def emit_hash_body
|
44
|
-
delimited(children
|
45
|
-
end
|
46
|
-
|
47
|
-
def emit_hash_member(node)
|
48
|
-
if n_kwsplat?(node)
|
49
|
-
visit(node)
|
50
|
-
else
|
51
|
-
emit_pair(node)
|
52
|
-
end
|
40
|
+
delimited(children)
|
53
41
|
end
|
54
|
-
|
55
|
-
def emit_pair(pair)
|
56
|
-
key, value = *pair.children
|
57
|
-
|
58
|
-
if colon?(key)
|
59
|
-
write(key.children.first.to_s, ': ')
|
60
|
-
else
|
61
|
-
visit(key)
|
62
|
-
write(' => ')
|
63
|
-
end
|
64
|
-
|
65
|
-
visit(value)
|
66
|
-
end
|
67
|
-
|
68
|
-
def colon?(key)
|
69
|
-
n_sym?(key) && BAREWORD.match?(key.children.first)
|
70
|
-
end
|
71
|
-
|
72
42
|
end # Hash
|
73
43
|
end # Emitter
|
74
44
|
end # Unparser
|
data/lib/unparser/emitter/if.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Unparser
|
4
|
+
class Emitter
|
5
|
+
# Emitter for in pattern nodes
|
6
|
+
class MatchPattern < self
|
7
|
+
|
8
|
+
handle :match_pattern
|
9
|
+
handle :match_pattern_p
|
10
|
+
|
11
|
+
children :target, :pattern
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def dispatch
|
16
|
+
visit(target)
|
17
|
+
write(' in ')
|
18
|
+
visit(pattern)
|
19
|
+
end
|
20
|
+
end # InPattern
|
21
|
+
end # Emitter
|
22
|
+
end # Unparser
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Unparser
|
4
|
+
class Emitter
|
5
|
+
# Emitter for key value pairs in hash literals or kwargs
|
6
|
+
class Pair < self
|
7
|
+
BAREWORD = /\A[A-Za-z_][A-Za-z_0-9]*[?!]?\z/.freeze
|
8
|
+
|
9
|
+
private_constant(*constants(false))
|
10
|
+
|
11
|
+
handle :pair
|
12
|
+
|
13
|
+
children :key, :value
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def dispatch
|
18
|
+
if colon?(key)
|
19
|
+
write(key.children.first.to_s, ': ')
|
20
|
+
else
|
21
|
+
visit(key)
|
22
|
+
write(' => ')
|
23
|
+
end
|
24
|
+
|
25
|
+
visit(value)
|
26
|
+
end
|
27
|
+
|
28
|
+
def colon?(key)
|
29
|
+
n_sym?(key) && BAREWORD.match?(key.children.first)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -4,7 +4,7 @@ module Unparser
|
|
4
4
|
class Emitter
|
5
5
|
# Emitter for simple nodes that generate a single token
|
6
6
|
class Simple < self
|
7
|
-
MAP =
|
7
|
+
MAP = {
|
8
8
|
__ENCODING__: '__ENCODING__',
|
9
9
|
__FILE__: '__FILE__',
|
10
10
|
__LINE__: '__LINE__',
|
@@ -19,7 +19,7 @@ module Unparser
|
|
19
19
|
self: 'self',
|
20
20
|
true: 'true',
|
21
21
|
zsuper: 'super'
|
22
|
-
|
22
|
+
}.freeze
|
23
23
|
|
24
24
|
handle(*MAP.keys)
|
25
25
|
|
@@ -22,12 +22,22 @@ module Unparser
|
|
22
22
|
|
23
23
|
children :subject
|
24
24
|
|
25
|
+
def emit_mlhs
|
26
|
+
write('*')
|
27
|
+
subject_emitter.emit_mlhs if subject
|
28
|
+
end
|
29
|
+
|
25
30
|
private
|
26
31
|
|
27
32
|
def dispatch
|
28
33
|
write('*')
|
29
|
-
|
34
|
+
subject_emitter.write_to_buffer
|
35
|
+
end
|
36
|
+
|
37
|
+
def subject_emitter
|
38
|
+
emitter(subject)
|
30
39
|
end
|
40
|
+
memoize :subject_emitter
|
31
41
|
end
|
32
42
|
end
|
33
43
|
end # Unparser
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Unparser
|
4
|
+
# Define equality, equivalence and inspection methods
|
5
|
+
#
|
6
|
+
# Original code before vendoring and reduction from: https://github.com/dkubb/equalizer.
|
7
|
+
class Equalizer < Module
|
8
|
+
# Initialize an Equalizer with the given keys
|
9
|
+
#
|
10
|
+
# Will use the keys with which it is initialized to define #cmp?,
|
11
|
+
# #hash, and #inspect
|
12
|
+
#
|
13
|
+
# @param [Array<Symbol>] keys
|
14
|
+
#
|
15
|
+
# @return [undefined]
|
16
|
+
#
|
17
|
+
# @api private
|
18
|
+
#
|
19
|
+
# rubocop:disable Lint/MissingSuper
|
20
|
+
def initialize(*keys)
|
21
|
+
@keys = keys
|
22
|
+
define_methods
|
23
|
+
freeze
|
24
|
+
end
|
25
|
+
# rubocop:enable Lint/MissingSuper
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def included(descendant)
|
30
|
+
descendant.include(Methods)
|
31
|
+
end
|
32
|
+
|
33
|
+
def define_methods
|
34
|
+
define_cmp_method
|
35
|
+
define_hash_method
|
36
|
+
define_inspect_method
|
37
|
+
end
|
38
|
+
|
39
|
+
def define_cmp_method
|
40
|
+
keys = @keys
|
41
|
+
define_method(:cmp?) do |comparator, other|
|
42
|
+
keys.all? do |key|
|
43
|
+
__send__(key).public_send(comparator, other.__send__(key))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
private :cmp?
|
47
|
+
end
|
48
|
+
|
49
|
+
def define_hash_method
|
50
|
+
keys = @keys
|
51
|
+
define_method(:hash) do
|
52
|
+
keys.map(&public_method(:__send__)).push(self.class).hash
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def define_inspect_method
|
57
|
+
keys = @keys
|
58
|
+
define_method(:inspect) do
|
59
|
+
klass = self.class
|
60
|
+
name = klass.name || klass.inspect
|
61
|
+
"#<#{name}#{keys.map { |key| " #{key}=#{__send__(key).inspect}" }.join}>"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# The comparison methods
|
66
|
+
module Methods
|
67
|
+
# Compare the object with other object for equality
|
68
|
+
#
|
69
|
+
# @example
|
70
|
+
# object.eql?(other) # => true or false
|
71
|
+
#
|
72
|
+
# @param [Object] other
|
73
|
+
# the other object to compare with
|
74
|
+
#
|
75
|
+
# @return [Boolean]
|
76
|
+
#
|
77
|
+
# @api public
|
78
|
+
def eql?(other)
|
79
|
+
instance_of?(other.class) && cmp?(__method__, other)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Compare the object with other object for equivalency
|
83
|
+
#
|
84
|
+
# @example
|
85
|
+
# object == other # => true or false
|
86
|
+
#
|
87
|
+
# @param [Object] other
|
88
|
+
# the other object to compare with
|
89
|
+
#
|
90
|
+
# @return [Boolean]
|
91
|
+
#
|
92
|
+
# @api public
|
93
|
+
def ==(other)
|
94
|
+
instance_of?(other.class) && cmp?(__method__, other)
|
95
|
+
end
|
96
|
+
end # module Methods
|
97
|
+
end # class Equalizer
|
98
|
+
end # Unparser
|
data/lib/unparser/generation.rb
CHANGED
@@ -204,7 +204,9 @@ module Unparser
|
|
204
204
|
end
|
205
205
|
|
206
206
|
def emit_rescue_postcontrol(node)
|
207
|
-
writer_with(Writer::Rescue, node)
|
207
|
+
writer = writer_with(Writer::Rescue, node)
|
208
|
+
writer.emit_postcontrol
|
209
|
+
writer.emit_heredoc_reminders
|
208
210
|
end
|
209
211
|
|
210
212
|
def emit_rescue_regular(node)
|
data/lib/unparser/validation.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
module Unparser
|
4
4
|
# Validation of unparser results
|
5
5
|
class Validation
|
6
|
-
include Adamantium
|
6
|
+
include Adamantium, Anima.new(
|
7
7
|
:generated_node,
|
8
8
|
:generated_source,
|
9
9
|
:identification,
|
@@ -64,7 +64,7 @@ module Unparser
|
|
64
64
|
|
65
65
|
new(
|
66
66
|
identification: '(string)',
|
67
|
-
original_source:
|
67
|
+
original_source: Either::Right.new(original_source),
|
68
68
|
original_node: original_node,
|
69
69
|
generated_source: generated_source,
|
70
70
|
generated_node: generated_node
|
@@ -86,7 +86,7 @@ module Unparser
|
|
86
86
|
new(
|
87
87
|
identification: '(string)',
|
88
88
|
original_source: generated_source,
|
89
|
-
original_node:
|
89
|
+
original_node: Either::Right.new(original_node),
|
90
90
|
generated_source: generated_source,
|
91
91
|
generated_node: generated_node
|
92
92
|
)
|
@@ -3,24 +3,22 @@
|
|
3
3
|
module Unparser
|
4
4
|
module Writer
|
5
5
|
class DynamicString
|
6
|
-
include Writer, Adamantium
|
6
|
+
include Writer, Adamantium
|
7
7
|
|
8
|
-
PATTERNS_2 =
|
8
|
+
PATTERNS_2 =
|
9
9
|
[
|
10
|
-
%i[str_empty begin],
|
11
|
-
%i[begin str_nl]
|
12
|
-
]
|
13
|
-
)
|
10
|
+
%i[str_empty begin].freeze,
|
11
|
+
%i[begin str_nl].freeze
|
12
|
+
].freeze
|
14
13
|
|
15
|
-
PATTERNS_3 =
|
14
|
+
PATTERNS_3 =
|
16
15
|
[
|
17
|
-
%i[begin str_nl_eol str_nl_eol],
|
18
|
-
%i[str_nl_eol begin str_nl_eol],
|
19
|
-
%i[str_ws begin str_nl_eol]
|
20
|
-
]
|
21
|
-
)
|
16
|
+
%i[begin str_nl_eol str_nl_eol].freeze,
|
17
|
+
%i[str_nl_eol begin str_nl_eol].freeze,
|
18
|
+
%i[str_ws begin str_nl_eol].freeze
|
19
|
+
].freeze
|
22
20
|
|
23
|
-
FLAT_INTERPOLATION = %i[ivar cvar gvar].to_set.freeze
|
21
|
+
FLAT_INTERPOLATION = %i[ivar cvar gvar nth_ref].to_set.freeze
|
24
22
|
|
25
23
|
private_constant(*constants(false))
|
26
24
|
|
@@ -42,7 +40,7 @@ module Unparser
|
|
42
40
|
private
|
43
41
|
|
44
42
|
def heredoc_header
|
45
|
-
|
43
|
+
'<<-HEREDOC'
|
46
44
|
end
|
47
45
|
|
48
46
|
def heredoc?
|
@@ -55,11 +53,7 @@ module Unparser
|
|
55
53
|
|
56
54
|
def emit_heredoc_body
|
57
55
|
nl
|
58
|
-
|
59
|
-
emit_squiggly_heredoc_body
|
60
|
-
else
|
61
|
-
emit_normal_heredoc_body
|
62
|
-
end
|
56
|
+
emit_normal_heredoc_body
|
63
57
|
end
|
64
58
|
|
65
59
|
def emit_heredoc_footer
|
@@ -119,10 +113,6 @@ module Unparser
|
|
119
113
|
n_str?(last) && last.children.first[-1].eql?("\n")
|
120
114
|
end
|
121
115
|
|
122
|
-
def need_squiggly?
|
123
|
-
children.any?(s(:str, ''))
|
124
|
-
end
|
125
|
-
|
126
116
|
def emit_squiggly_heredoc_body
|
127
117
|
buffer.indent
|
128
118
|
children.each do |child|
|