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
|
@@ -2,22 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
module Unparser
|
|
4
4
|
class Emitter
|
|
5
|
-
# Root emitter a special case
|
|
6
5
|
class Root < self
|
|
7
|
-
include Concord::Public.new(:buffer, :node, :comments)
|
|
8
|
-
include LocalVariableRoot
|
|
9
|
-
|
|
10
6
|
END_NL = %i[class sclass module begin].freeze
|
|
11
7
|
|
|
12
8
|
private_constant(*constants(false))
|
|
13
9
|
|
|
14
10
|
def dispatch
|
|
15
|
-
|
|
16
|
-
emit_body(node, indent: false)
|
|
17
|
-
else
|
|
18
|
-
visit_deep(node)
|
|
19
|
-
end
|
|
11
|
+
emit_body(node, indent: false)
|
|
20
12
|
|
|
13
|
+
buffer.nl_flush_heredocs
|
|
21
14
|
emit_eof_comments
|
|
22
15
|
|
|
23
16
|
nl if END_NL.include?(node.type) && !buffer.fresh_line?
|
|
@@ -10,10 +10,6 @@ module Unparser
|
|
|
10
10
|
writer.emit_mlhs
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
def emit_heredoc_reminders
|
|
14
|
-
writer.emit_heredoc_reminders
|
|
15
|
-
end
|
|
16
|
-
|
|
17
13
|
private
|
|
18
14
|
|
|
19
15
|
def dispatch
|
|
@@ -21,7 +17,7 @@ module Unparser
|
|
|
21
17
|
end
|
|
22
18
|
|
|
23
19
|
def writer
|
|
24
|
-
writer_with(Writer::Send, node)
|
|
20
|
+
writer_with(Writer::Send, node:)
|
|
25
21
|
end
|
|
26
22
|
memoize :writer
|
|
27
23
|
end # Send
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Unparser
|
|
4
|
+
class Emitter
|
|
5
|
+
# Base class for primitive emitters
|
|
6
|
+
class String < self
|
|
7
|
+
children :value
|
|
8
|
+
|
|
9
|
+
handle :str
|
|
10
|
+
|
|
11
|
+
private
|
|
12
|
+
|
|
13
|
+
def dispatch
|
|
14
|
+
if explicit_encoding && !value.encoding.equal?(explicit_encoding)
|
|
15
|
+
write_utf8_escaped
|
|
16
|
+
else
|
|
17
|
+
write(value.inspect)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def write_utf8_escaped
|
|
22
|
+
write('"')
|
|
23
|
+
value.each_codepoint do |codepoint|
|
|
24
|
+
write("\\u{#{codepoint.to_s(16)}}")
|
|
25
|
+
end
|
|
26
|
+
write('"')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end # String
|
|
30
|
+
end # Emitter
|
|
31
|
+
end # Unparser
|
|
@@ -41,6 +41,8 @@ module Unparser
|
|
|
41
41
|
children.each do |child|
|
|
42
42
|
if n_begin?(child)
|
|
43
43
|
emit_begin(child)
|
|
44
|
+
elsif n_gvar?(child)
|
|
45
|
+
emit_gvar(child)
|
|
44
46
|
else
|
|
45
47
|
emit_string(child)
|
|
46
48
|
end
|
|
@@ -64,9 +66,14 @@ module Unparser
|
|
|
64
66
|
|
|
65
67
|
def emit_begin(component)
|
|
66
68
|
write('#{')
|
|
67
|
-
visit(
|
|
69
|
+
visit(Util.one(component.children)) if component.children.any?
|
|
68
70
|
write('}')
|
|
69
71
|
end
|
|
72
|
+
|
|
73
|
+
def emit_gvar(component)
|
|
74
|
+
write('#')
|
|
75
|
+
write(Util.one(component.children).to_s)
|
|
76
|
+
end
|
|
70
77
|
end # XStr
|
|
71
78
|
end # Emitter
|
|
72
79
|
end # Unparser
|
data/lib/unparser/emitter.rb
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Unparser
|
|
4
|
-
UnknownNodeError
|
|
4
|
+
class UnknownNodeError < ArgumentError
|
|
5
|
+
end
|
|
5
6
|
|
|
6
7
|
# Emitter base class
|
|
7
8
|
class Emitter
|
|
8
9
|
include Adamantium, AbstractType, Constants, Generation, NodeHelpers
|
|
9
|
-
include Anima.new(:buffer, :comments, :
|
|
10
|
+
include Anima.new(:buffer, :comments, :explicit_encoding, :local_variable_scope, :node)
|
|
10
11
|
|
|
11
12
|
public :node
|
|
12
13
|
|
|
@@ -22,10 +23,9 @@ module Unparser
|
|
|
22
23
|
#
|
|
23
24
|
# @return [Parser::AST::Node]
|
|
24
25
|
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
26
|
+
# mutant:disable
|
|
27
27
|
def local_variable_scope
|
|
28
|
-
AST::LocalVariableScope.new(node)
|
|
28
|
+
AST::LocalVariableScope.new(node: node, static_local_variables: Set.new)
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def self.included(descendant)
|
|
@@ -67,7 +67,7 @@ module Unparser
|
|
|
67
67
|
# @api private
|
|
68
68
|
#
|
|
69
69
|
# rubocop:disable Metrics/ParameterLists
|
|
70
|
-
def self.emitter(buffer:, comments:, node:, local_variable_scope:)
|
|
70
|
+
def self.emitter(buffer:, explicit_encoding:, comments:, node:, local_variable_scope:)
|
|
71
71
|
type = node.type
|
|
72
72
|
|
|
73
73
|
klass = REGISTRY.fetch(type) do
|
|
@@ -75,10 +75,11 @@ module Unparser
|
|
|
75
75
|
end
|
|
76
76
|
|
|
77
77
|
klass.new(
|
|
78
|
-
buffer
|
|
79
|
-
comments
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
buffer:,
|
|
79
|
+
comments:,
|
|
80
|
+
explicit_encoding:,
|
|
81
|
+
local_variable_scope:,
|
|
82
|
+
node:
|
|
82
83
|
)
|
|
83
84
|
end
|
|
84
85
|
# rubocop:enable Metrics/ParameterLists
|
|
@@ -90,6 +91,5 @@ module Unparser
|
|
|
90
91
|
# @api private
|
|
91
92
|
#
|
|
92
93
|
abstract_method :dispatch
|
|
93
|
-
|
|
94
94
|
end # Emitter
|
|
95
95
|
end # Unparser
|
data/lib/unparser/equalizer.rb
CHANGED
|
@@ -4,95 +4,129 @@ module Unparser
|
|
|
4
4
|
# Define equality, equivalence and inspection methods
|
|
5
5
|
#
|
|
6
6
|
# Original code before vendoring and reduction from: https://github.com/dkubb/equalizer.
|
|
7
|
-
|
|
8
|
-
#
|
|
7
|
+
module Equalizer
|
|
8
|
+
# Creates a module providing equality methods based on the given attributes
|
|
9
9
|
#
|
|
10
|
-
#
|
|
11
|
-
# #
|
|
10
|
+
# @param keys [Array<Symbol>] attribute names to use for equality
|
|
11
|
+
# @param inspect [Boolean] whether to override #inspect and #pretty_print
|
|
12
|
+
# @return [Module] a module to include in your class
|
|
13
|
+
# @raise [ArgumentError] if keys is empty or contains non-Symbols
|
|
12
14
|
#
|
|
13
|
-
# @
|
|
14
|
-
|
|
15
|
-
|
|
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
|
|
15
|
+
# @api public
|
|
16
|
+
def self.new(*keys, inspect: true)
|
|
17
|
+
build_module(keys.freeze, inspect:)
|
|
37
18
|
end
|
|
38
19
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
20
|
+
# Instance methods mixed into classes that include an Equalizer module
|
|
21
|
+
#
|
|
22
|
+
# @api private
|
|
23
|
+
module InstanceMethods
|
|
24
|
+
# Equality comparison allowing subclasses
|
|
25
|
+
#
|
|
26
|
+
# @param other [Object] object to compare
|
|
27
|
+
# @return [Boolean] true if other is_a? same class with equal attributes
|
|
28
|
+
def ==(other)
|
|
29
|
+
other.is_a?(self.class) &&
|
|
30
|
+
cmp?(:==, other)
|
|
45
31
|
end
|
|
46
|
-
private :cmp?
|
|
47
|
-
end
|
|
48
32
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
33
|
+
# Strict equality requiring exact class match
|
|
34
|
+
#
|
|
35
|
+
# @param other [Object] object to compare
|
|
36
|
+
# @return [Boolean] true if other is exact same class with eql? attributes
|
|
37
|
+
def eql?(other)
|
|
38
|
+
other.instance_of?(self.class) &&
|
|
39
|
+
cmp?(:eql?, other)
|
|
53
40
|
end
|
|
54
|
-
end
|
|
55
41
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"#<#{name}#{keys.map { |key| " #{key}=#{__send__(key).inspect}" }.join}>"
|
|
42
|
+
# Hash code based on class and attribute values
|
|
43
|
+
#
|
|
44
|
+
# @return [Integer] hash code
|
|
45
|
+
def hash
|
|
46
|
+
[self.class, *deconstruct].hash
|
|
62
47
|
end
|
|
63
|
-
end
|
|
64
48
|
|
|
65
|
-
|
|
66
|
-
module Methods
|
|
67
|
-
# Compare the object with other object for equality
|
|
49
|
+
# Array deconstruction for pattern matching
|
|
68
50
|
#
|
|
69
|
-
# @
|
|
70
|
-
|
|
51
|
+
# @return [Array] attribute values in order
|
|
52
|
+
def deconstruct
|
|
53
|
+
equalizer_keys.map { |key| public_send(key) }
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Hash deconstruction for pattern matching
|
|
71
57
|
#
|
|
72
|
-
# @param [
|
|
73
|
-
#
|
|
58
|
+
# @param requested [Array<Symbol>, nil] keys to include, or nil for all
|
|
59
|
+
# @return [Hash{Symbol => Object}] requested attribute key-value pairs
|
|
60
|
+
def deconstruct_keys(requested)
|
|
61
|
+
subset = requested.nil? ? equalizer_keys : equalizer_keys & requested
|
|
62
|
+
subset.to_h { |key| [key, public_send(key)] }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
# Compare all attributes using the given comparator
|
|
74
68
|
#
|
|
75
|
-
# @
|
|
69
|
+
# @param comparator [Symbol] method to use for comparison
|
|
70
|
+
# @param other [Object] object to compare against
|
|
71
|
+
# @return [Boolean] true if all attributes match
|
|
76
72
|
#
|
|
77
|
-
# @api
|
|
78
|
-
def
|
|
79
|
-
|
|
73
|
+
# @api private
|
|
74
|
+
def cmp?(comparator, other)
|
|
75
|
+
equalizer_keys.all? do |key|
|
|
76
|
+
public_send(key)
|
|
77
|
+
.public_send(comparator, other.public_send(key))
|
|
78
|
+
end
|
|
80
79
|
end
|
|
80
|
+
end
|
|
81
81
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
# Instance methods for inspect and pretty print output
|
|
83
|
+
#
|
|
84
|
+
# @api private
|
|
85
|
+
module InspectMethods
|
|
86
|
+
# String representation showing only equalizer attributes
|
|
86
87
|
#
|
|
87
|
-
# @
|
|
88
|
-
|
|
88
|
+
# @return [String] inspect output
|
|
89
|
+
def inspect
|
|
90
|
+
attrs = equalizer_keys
|
|
91
|
+
.map { |key| "@#{key}=#{public_send(key).inspect}" }
|
|
92
|
+
.join(', ')
|
|
93
|
+
Object.instance_method(:to_s).bind_call(self).sub(/>\z/, " #{attrs}>")
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Pretty print output using PP's object formatting
|
|
89
97
|
#
|
|
90
|
-
# @
|
|
98
|
+
# @param q [PP] pretty printer
|
|
99
|
+
# @return [void]
|
|
100
|
+
def pretty_print(pretty_printer)
|
|
101
|
+
pretty_printer.pp_object(self)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Instance variables to display in pretty print output
|
|
91
105
|
#
|
|
92
|
-
# @
|
|
93
|
-
def
|
|
94
|
-
|
|
106
|
+
# @return [Array<Symbol>] instance variable names
|
|
107
|
+
def pretty_print_instance_variables
|
|
108
|
+
equalizer_keys.map { |key| :"@#{key}" }
|
|
95
109
|
end
|
|
96
|
-
end
|
|
97
|
-
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
# Builds the module with equality methods for the given keys
|
|
113
|
+
#
|
|
114
|
+
# @param keys [Array<Symbol>] attribute names (frozen)
|
|
115
|
+
# @param inspect [Boolean] whether to include inspect methods
|
|
116
|
+
# @return [Module] the configured module
|
|
117
|
+
#
|
|
118
|
+
# @api private
|
|
119
|
+
def self.build_module(keys, inspect:)
|
|
120
|
+
Module.new do
|
|
121
|
+
include InstanceMethods
|
|
122
|
+
include InspectMethods if inspect
|
|
123
|
+
|
|
124
|
+
set_temporary_name("Equalizer(#{keys.join(', ')})")
|
|
125
|
+
|
|
126
|
+
define_method(:equalizer_keys) { keys }
|
|
127
|
+
private :equalizer_keys
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
private_class_method :build_module
|
|
131
|
+
end # module Equalizer
|
|
98
132
|
end # Unparser
|
data/lib/unparser/generation.rb
CHANGED
|
@@ -7,8 +7,6 @@ module Unparser
|
|
|
7
7
|
|
|
8
8
|
private_constant(*constants(false))
|
|
9
9
|
|
|
10
|
-
def emit_heredoc_reminders; end
|
|
11
|
-
|
|
12
10
|
def symbol_name; end
|
|
13
11
|
|
|
14
12
|
def write_to_buffer
|
|
@@ -121,40 +119,50 @@ module Unparser
|
|
|
121
119
|
end
|
|
122
120
|
|
|
123
121
|
def emit_body(node, indent: true)
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
122
|
+
with_indent(indent: indent) do
|
|
123
|
+
if n_begin?(node)
|
|
124
|
+
if node.children.empty?
|
|
125
|
+
write('()')
|
|
126
|
+
elsif node.children.one?
|
|
127
|
+
visit_deep(node)
|
|
128
|
+
else
|
|
129
|
+
emit_body_inner(node)
|
|
130
|
+
end
|
|
132
131
|
else
|
|
133
|
-
|
|
132
|
+
visit_deep(node)
|
|
134
133
|
end
|
|
135
|
-
else
|
|
136
|
-
visit_deep(node)
|
|
137
134
|
end
|
|
135
|
+
end
|
|
138
136
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
def with_indent(indent:)
|
|
138
|
+
return yield unless indent
|
|
139
|
+
|
|
140
|
+
buffer.indent
|
|
141
|
+
nl
|
|
142
|
+
yield
|
|
143
|
+
buffer.unindent
|
|
144
|
+
nl
|
|
143
145
|
end
|
|
144
146
|
|
|
145
147
|
def emit_body_inner(node)
|
|
146
148
|
head, *tail = node.children
|
|
147
149
|
emit_body_member(head)
|
|
150
|
+
write(';') if requires_explicit_statement_terminator?(head, tail)
|
|
148
151
|
|
|
149
152
|
tail.each do |child|
|
|
150
|
-
|
|
153
|
+
buffer.ensure_nl
|
|
151
154
|
|
|
152
155
|
nl if EXTRA_NL.include?(child.type)
|
|
153
156
|
|
|
154
157
|
emit_body_member(child)
|
|
158
|
+
write(';') if requires_explicit_statement_terminator?(child, tail)
|
|
155
159
|
end
|
|
156
160
|
end
|
|
157
161
|
|
|
162
|
+
def requires_explicit_statement_terminator?(node, nodes_group)
|
|
163
|
+
n_range?(node) && node.children.fetch(1).nil? && !node.eql?(nodes_group.fetch(-1))
|
|
164
|
+
end
|
|
165
|
+
|
|
158
166
|
def emit_body_member(node)
|
|
159
167
|
if n_rescue?(node)
|
|
160
168
|
emit_rescue_postcontrol(node)
|
|
@@ -204,21 +212,20 @@ module Unparser
|
|
|
204
212
|
end
|
|
205
213
|
|
|
206
214
|
def emit_rescue_postcontrol(node)
|
|
207
|
-
writer = writer_with(Writer::Rescue, node)
|
|
215
|
+
writer = writer_with(Writer::Rescue, node:)
|
|
208
216
|
writer.emit_postcontrol
|
|
209
|
-
writer.emit_heredoc_reminders
|
|
210
217
|
end
|
|
211
218
|
|
|
212
219
|
def emit_rescue_regular(node)
|
|
213
|
-
writer_with(Writer::Rescue, node).emit_regular
|
|
220
|
+
writer_with(Writer::Rescue, node:).emit_regular
|
|
214
221
|
end
|
|
215
222
|
|
|
216
|
-
def
|
|
217
|
-
|
|
223
|
+
def emitter(node)
|
|
224
|
+
Emitter.emitter(**to_h, node: node)
|
|
218
225
|
end
|
|
219
226
|
|
|
220
|
-
def
|
|
221
|
-
|
|
227
|
+
def writer_with(klass, node:, **attributes)
|
|
228
|
+
klass.new(to_h.merge(node: node, **attributes))
|
|
222
229
|
end
|
|
223
230
|
|
|
224
231
|
def visit(node)
|
|
@@ -226,10 +233,7 @@ module Unparser
|
|
|
226
233
|
end
|
|
227
234
|
|
|
228
235
|
def visit_deep(node)
|
|
229
|
-
emitter(node).tap
|
|
230
|
-
emitter.write_to_buffer
|
|
231
|
-
emitter.emit_heredoc_reminders
|
|
232
|
-
end
|
|
236
|
+
emitter(node).tap(&:write_to_buffer)
|
|
233
237
|
end
|
|
234
238
|
|
|
235
239
|
def first_child
|
|
@@ -4,9 +4,16 @@ module Unparser
|
|
|
4
4
|
module NodeDetails
|
|
5
5
|
include Constants, NodeHelpers
|
|
6
6
|
|
|
7
|
+
# mutant:disable
|
|
7
8
|
def self.included(descendant)
|
|
8
9
|
descendant.class_eval do
|
|
9
|
-
include Adamantium,
|
|
10
|
+
include Adamantium, Equalizer.new(:node)
|
|
11
|
+
|
|
12
|
+
attr_reader :node
|
|
13
|
+
|
|
14
|
+
def initialize(node)
|
|
15
|
+
@node = node
|
|
16
|
+
end
|
|
10
17
|
|
|
11
18
|
extend DSL
|
|
12
19
|
end
|
|
@@ -31,7 +31,16 @@ module Unparser
|
|
|
31
31
|
node.type.equal?(type)
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
+
def n_flipflop?(node)
|
|
35
|
+
n_iflipflop?(node) || n_eflipflop?(node)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def n_range?(node)
|
|
39
|
+
n_irange?(node) || n_erange?(node)
|
|
40
|
+
end
|
|
41
|
+
|
|
34
42
|
%i[
|
|
43
|
+
and
|
|
35
44
|
arg
|
|
36
45
|
args
|
|
37
46
|
array
|
|
@@ -41,18 +50,26 @@ module Unparser
|
|
|
41
50
|
cbase
|
|
42
51
|
const
|
|
43
52
|
dstr
|
|
53
|
+
eflipflop
|
|
44
54
|
empty_else
|
|
55
|
+
erange
|
|
45
56
|
ensure
|
|
57
|
+
gvar
|
|
46
58
|
hash
|
|
47
59
|
hash_pattern
|
|
48
60
|
if
|
|
61
|
+
iflipflop
|
|
49
62
|
in_pattern
|
|
50
63
|
int
|
|
64
|
+
irange
|
|
51
65
|
kwarg
|
|
52
66
|
kwargs
|
|
53
67
|
kwsplat
|
|
54
68
|
lambda
|
|
69
|
+
lvar
|
|
55
70
|
match_rest
|
|
71
|
+
mlhs
|
|
72
|
+
or
|
|
56
73
|
pair
|
|
57
74
|
rescue
|
|
58
75
|
send
|
|
@@ -60,20 +77,13 @@ module Unparser
|
|
|
60
77
|
splat
|
|
61
78
|
str
|
|
62
79
|
sym
|
|
63
|
-
|
|
80
|
+
xstr
|
|
81
|
+
].to_set.each do |type|
|
|
64
82
|
name = "n_#{type}?"
|
|
65
83
|
define_method(name) do |node|
|
|
66
84
|
n?(type, node)
|
|
67
85
|
end
|
|
68
86
|
private(name)
|
|
69
87
|
end
|
|
70
|
-
|
|
71
|
-
def unwrap_single_begin(node)
|
|
72
|
-
if n_begin?(node) && node.children.one?
|
|
73
|
-
node.children.first
|
|
74
|
-
else
|
|
75
|
-
node
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
88
|
end # NodeHelpers
|
|
79
89
|
end # Unparser
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Unparser
|
|
4
|
+
# Original code before vendoring and reduction from: https://github.com/mbj/mutant/blob/main/lib/mutant/util.rb
|
|
5
|
+
module Util
|
|
6
|
+
# Error raised by `Util.one` if size is not exactly one
|
|
7
|
+
class SizeError < IndexError
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Return only element in array if it contains exactly one member
|
|
11
|
+
#
|
|
12
|
+
# @param array [Array]
|
|
13
|
+
#
|
|
14
|
+
# @return [Object] first entry
|
|
15
|
+
def self.one(array)
|
|
16
|
+
case array
|
|
17
|
+
in [value]
|
|
18
|
+
value
|
|
19
|
+
else
|
|
20
|
+
fail SizeError, "expected size to be exactly 1 but size was #{array.size}"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|