unparser 0.6.15 → 0.8.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 +4 -4
- data/lib/unparser/anima.rb +11 -0
- data/lib/unparser/ast/local_variable_scope.rb +28 -24
- data/lib/unparser/ast.rb +18 -22
- data/lib/unparser/buffer.rb +44 -2
- data/lib/unparser/cli.rb +28 -5
- data/lib/unparser/color.rb +2 -2
- data/lib/unparser/either.rb +6 -6
- 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 +13 -6
- 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/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 +6 -1
- 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 -10
- data/lib/unparser/emitter/primitive.rb +0 -13
- 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 +9 -10
- data/lib/unparser/generation.rb +14 -14
- data/lib/unparser/node_details.rb +1 -0
- data/lib/unparser/node_helpers.rb +18 -9
- data/lib/unparser/util.rb +23 -0
- data/lib/unparser/validation.rb +68 -28
- data/lib/unparser/writer/array.rb +51 -0
- data/lib/unparser/writer/binary.rb +8 -4
- data/lib/unparser/writer/dynamic_string.rb +128 -135
- 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 +149 -38
- metadata +33 -17
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Unparser
|
4
|
+
module Writer
|
5
|
+
# Writer for regexp literals
|
6
|
+
class Regexp
|
7
|
+
include Writer, Adamantium
|
8
|
+
|
9
|
+
CANDIDATES = [
|
10
|
+
['/', '/'].freeze,
|
11
|
+
['%r{', '}'].freeze
|
12
|
+
].freeze
|
13
|
+
|
14
|
+
define_group(:body, 0..-2)
|
15
|
+
|
16
|
+
def dispatch
|
17
|
+
effective_writer.write_to_buffer
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# mutant:disable
|
23
|
+
def effective_writer
|
24
|
+
CANDIDATES.each do |token_open, token_close|
|
25
|
+
source = render_with_delimiter(token_close:, token_open:)
|
26
|
+
|
27
|
+
next unless round_trips?(source:)
|
28
|
+
|
29
|
+
return writer_with(Effective, node:, token_close:, token_open:)
|
30
|
+
end
|
31
|
+
|
32
|
+
fail 'Could not find a round tripping solution for regexp'
|
33
|
+
end
|
34
|
+
|
35
|
+
class Effective
|
36
|
+
include Writer, Adamantium
|
37
|
+
|
38
|
+
include anima.add(:token_close, :token_open)
|
39
|
+
|
40
|
+
define_group(:body, 0..-2)
|
41
|
+
|
42
|
+
def dispatch
|
43
|
+
buffer.root_indent do
|
44
|
+
write(token_open)
|
45
|
+
body.each(&method(:emit_body))
|
46
|
+
write(token_close)
|
47
|
+
emit_options
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def emit_body(node)
|
54
|
+
if n_begin?(node)
|
55
|
+
write('#{')
|
56
|
+
node.children.each(&method(:visit))
|
57
|
+
write('}')
|
58
|
+
elsif n_gvar?(node)
|
59
|
+
write('#')
|
60
|
+
write_regular(node.children.first.to_s)
|
61
|
+
else
|
62
|
+
write_regular(node.children.first)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def write_regular(string)
|
67
|
+
if string.length > 1 && string.start_with?("\n")
|
68
|
+
string.each_char do |char|
|
69
|
+
buffer.append_without_prefix(char.eql?("\n") ? '\c*' : char)
|
70
|
+
end
|
71
|
+
else
|
72
|
+
buffer.append_without_prefix(string)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def emit_options
|
77
|
+
write(children.last.children.join)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# mutant:disable
|
82
|
+
def render_with_delimiter(token_close:, token_open:)
|
83
|
+
buffer = Buffer.new
|
84
|
+
|
85
|
+
writer = Effective.new(
|
86
|
+
buffer:,
|
87
|
+
comments:,
|
88
|
+
explicit_encoding:,
|
89
|
+
local_variable_scope:,
|
90
|
+
node:,
|
91
|
+
token_close:,
|
92
|
+
token_open:
|
93
|
+
)
|
94
|
+
|
95
|
+
writer.dispatch
|
96
|
+
buffer.nl_flush_heredocs
|
97
|
+
buffer.content
|
98
|
+
end
|
99
|
+
end # Regexp
|
100
|
+
end # Emitter
|
101
|
+
end # Unparser
|
@@ -6,11 +6,21 @@ module Unparser
|
|
6
6
|
class Resbody
|
7
7
|
include Writer
|
8
8
|
|
9
|
+
OPERATORS = {
|
10
|
+
csend: '&.',
|
11
|
+
send: '.'
|
12
|
+
}.freeze
|
13
|
+
|
9
14
|
children :exception, :assignment, :body
|
10
15
|
|
11
16
|
def emit_postcontrol
|
12
|
-
|
13
|
-
|
17
|
+
if body
|
18
|
+
write(' rescue ')
|
19
|
+
visit(body)
|
20
|
+
else
|
21
|
+
nl
|
22
|
+
write('rescue')
|
23
|
+
end
|
14
24
|
end
|
15
25
|
|
16
26
|
def emit_regular
|
@@ -33,7 +43,31 @@ module Unparser
|
|
33
43
|
return unless assignment
|
34
44
|
|
35
45
|
write(' => ')
|
36
|
-
|
46
|
+
|
47
|
+
case assignment.type
|
48
|
+
when :send, :csend
|
49
|
+
write_send_assignment
|
50
|
+
when :indexasgn
|
51
|
+
write_index_assignment
|
52
|
+
else
|
53
|
+
visit(assignment)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def write_send_assignment
|
58
|
+
details = NodeDetails::Send.new(assignment)
|
59
|
+
|
60
|
+
visit(details.receiver)
|
61
|
+
write(OPERATORS.fetch(assignment.type))
|
62
|
+
write(details.non_assignment_selector)
|
63
|
+
end
|
64
|
+
|
65
|
+
def write_index_assignment
|
66
|
+
receiver, *indexes = assignment.children
|
67
|
+
visit(receiver)
|
68
|
+
write('[')
|
69
|
+
delimited(indexes)
|
70
|
+
write(']')
|
37
71
|
end
|
38
72
|
end # Resbody
|
39
73
|
end # Writer
|
@@ -20,13 +20,9 @@ module Unparser
|
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
|
-
def emit_heredoc_reminders
|
24
|
-
emitter(body).emit_heredoc_reminders
|
25
|
-
end
|
26
|
-
|
27
23
|
def emit_postcontrol
|
28
|
-
visit(body)
|
29
|
-
writer_with(Resbody, rescue_body).emit_postcontrol
|
24
|
+
visit(body) if body
|
25
|
+
writer_with(Resbody, node: rescue_body).emit_postcontrol
|
30
26
|
end
|
31
27
|
|
32
28
|
private
|
@@ -36,7 +32,7 @@ module Unparser
|
|
36
32
|
end
|
37
33
|
|
38
34
|
def emit_rescue_body(node)
|
39
|
-
writer_with(Resbody, node).emit_regular
|
35
|
+
writer_with(Resbody, node:).emit_regular
|
40
36
|
end
|
41
37
|
end # Rescue
|
42
38
|
end # Writer
|
@@ -12,13 +12,18 @@ module Unparser
|
|
12
12
|
|
13
13
|
private_constant(*constants(false))
|
14
14
|
|
15
|
-
def dispatch
|
15
|
+
def dispatch # rubocop:disable Metrics/AbcSize
|
16
16
|
name = selector
|
17
|
+
first_child = children.fetch(0)
|
17
18
|
|
18
|
-
|
19
|
+
if n_flipflop?(first_child) || n_and?(first_child) || n_or?(first_child)
|
20
|
+
write 'not '
|
21
|
+
else
|
22
|
+
write(MAP.fetch(name, name).to_s)
|
19
23
|
|
20
|
-
|
21
|
-
|
24
|
+
if n_int?(receiver) && selector.equal?(:+@)
|
25
|
+
write('+')
|
26
|
+
end
|
22
27
|
end
|
23
28
|
|
24
29
|
visit(receiver)
|
data/lib/unparser/writer/send.rb
CHANGED
@@ -30,15 +30,10 @@ module Unparser
|
|
30
30
|
write(details.string_selector)
|
31
31
|
end
|
32
32
|
|
33
|
-
def emit_heredoc_reminders
|
34
|
-
emitter(receiver).emit_heredoc_reminders if receiver
|
35
|
-
arguments.each(&method(:emit_heredoc_reminder))
|
36
|
-
end
|
37
|
-
|
38
33
|
private
|
39
34
|
|
40
35
|
def effective_writer
|
41
|
-
writer_with(effective_writer_class, node)
|
36
|
+
writer_with(effective_writer_class, node:)
|
42
37
|
end
|
43
38
|
memoize :effective_writer
|
44
39
|
|
@@ -78,10 +73,6 @@ module Unparser
|
|
78
73
|
parentheses { delimited(arguments) }
|
79
74
|
end
|
80
75
|
|
81
|
-
def emit_heredoc_reminder(argument)
|
82
|
-
emitter(argument).emit_heredoc_reminders
|
83
|
-
end
|
84
|
-
|
85
76
|
def avoid_clash?
|
86
77
|
local_variable_clash? || parses_as_constant?
|
87
78
|
end
|
@@ -91,9 +82,12 @@ module Unparser
|
|
91
82
|
end
|
92
83
|
|
93
84
|
def parses_as_constant?
|
94
|
-
test = Unparser
|
95
|
-
|
96
|
-
|
85
|
+
test = Unparser
|
86
|
+
.parse_ast_either(selector.to_s)
|
87
|
+
.fmap(&:node)
|
88
|
+
.from_right do
|
89
|
+
fail InvalidNodeError.new("Invalid selector for send node: #{selector.inspect}", node)
|
90
|
+
end
|
97
91
|
|
98
92
|
n_const?(test)
|
99
93
|
end
|
@@ -105,7 +99,7 @@ module Unparser
|
|
105
99
|
|
106
100
|
def emit_send_regular(node)
|
107
101
|
if n_send?(node)
|
108
|
-
writer_with(Regular, node).dispatch
|
102
|
+
writer_with(Regular, node:).dispatch
|
109
103
|
else
|
110
104
|
visit(node)
|
111
105
|
end
|
data/lib/unparser/writer.rb
CHANGED
@@ -4,12 +4,42 @@ module Unparser
|
|
4
4
|
module Writer
|
5
5
|
include Generation, NodeHelpers
|
6
6
|
|
7
|
+
# mutant:disable
|
7
8
|
def self.included(descendant)
|
8
9
|
descendant.class_eval do
|
9
|
-
include Anima.new(:buffer, :comments, :node, :local_variable_scope)
|
10
|
+
include Adamantium, Anima.new(:buffer, :comments, :explicit_encoding, :node, :local_variable_scope)
|
10
11
|
|
11
12
|
extend DSL
|
12
13
|
end
|
13
14
|
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
# mutant:disable
|
19
|
+
def emitter(node)
|
20
|
+
Emitter.emitter(
|
21
|
+
buffer: buffer,
|
22
|
+
comments: comments,
|
23
|
+
explicit_encoding: explicit_encoding,
|
24
|
+
local_variable_scope: local_variable_scope,
|
25
|
+
node: node
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
# mutant:disable
|
30
|
+
def round_trips?(source:)
|
31
|
+
parser = Unparser.parser
|
32
|
+
local_variable_scope.local_variables_for_node(node).each do |local_variable|
|
33
|
+
parser.declare_local_variable(local_variable)
|
34
|
+
end
|
35
|
+
|
36
|
+
buffer = Buffer.new
|
37
|
+
buffer.write_encoding(explicit_encoding) if explicit_encoding
|
38
|
+
buffer.write(source)
|
39
|
+
|
40
|
+
node.eql?(parser.parse(Unparser.buffer(buffer.content)))
|
41
|
+
rescue Parser::SyntaxError
|
42
|
+
false
|
43
|
+
end
|
14
44
|
end # Writer
|
15
45
|
end # Unparser
|
data/lib/unparser.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
require 'diff/lcs'
|
4
4
|
require 'diff/lcs/hunk'
|
5
5
|
require 'optparse'
|
6
|
-
require 'parser/current'
|
7
6
|
require 'set'
|
8
7
|
|
9
8
|
require 'unparser/equalizer'
|
@@ -18,18 +17,53 @@ require 'unparser/anima/attribute'
|
|
18
17
|
require 'unparser/anima/error'
|
19
18
|
|
20
19
|
# Library namespace
|
21
|
-
module Unparser
|
20
|
+
module Unparser # rubocop:disable Metrics/ModuleLength
|
22
21
|
# Unparser specific AST builder defaulting to modern AST format
|
23
|
-
|
24
|
-
|
22
|
+
if Gem::Version.new(RUBY_VERSION) <= '3.4'
|
23
|
+
require 'parser/current'
|
24
|
+
class Builder < Parser::Builders::Default
|
25
|
+
modernize
|
25
26
|
|
26
|
-
|
27
|
-
|
27
|
+
# mutant:disable
|
28
|
+
def initialize
|
29
|
+
super
|
28
30
|
|
29
|
-
|
31
|
+
self.emit_file_line_as_literals = false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
else
|
35
|
+
require 'prism'
|
36
|
+
class Builder < Prism::Translation::Parser::Builder
|
37
|
+
modernize
|
38
|
+
|
39
|
+
# mutant:disable
|
40
|
+
def initialize
|
41
|
+
super
|
42
|
+
|
43
|
+
self.emit_file_line_as_literals = false
|
44
|
+
end
|
30
45
|
end
|
31
46
|
end
|
32
47
|
|
48
|
+
PARSER_CLASS =
|
49
|
+
if Gem::Version.new(RUBY_VERSION) <= '3.4'
|
50
|
+
Class.new(Parser::CurrentRuby) do
|
51
|
+
def declare_local_variable(local_variable)
|
52
|
+
static_env.declare(local_variable)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
else
|
56
|
+
Class.new(Prism::Translation::Parser34) do
|
57
|
+
def declare_local_variable(local_variable)
|
58
|
+
(@local_variables ||= Set.new) << local_variable
|
59
|
+
end
|
60
|
+
|
61
|
+
def prism_options
|
62
|
+
super.merge(scopes: [@local_variables.to_a])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
33
67
|
EMPTY_STRING = ''.freeze
|
34
68
|
EMPTY_ARRAY = [].freeze
|
35
69
|
|
@@ -44,57 +78,118 @@ module Unparser
|
|
44
78
|
@node = node
|
45
79
|
freeze
|
46
80
|
end
|
47
|
-
end
|
81
|
+
end # InvalidNodeError
|
82
|
+
|
83
|
+
# Error raised when unparser encounders AST it cannot generate source for that would parse to the same AST.
|
84
|
+
class UnsupportedNodeError < RuntimeError
|
85
|
+
end # UnsupportedNodeError
|
48
86
|
|
49
87
|
# Unparse an AST (and, optionally, comments) into a string
|
50
88
|
#
|
51
89
|
# @param [Parser::AST::Node, nil] node
|
52
|
-
# @param [Array]
|
90
|
+
# @param [Array] comments
|
91
|
+
# @param [Encoding, nil] explicit_encoding
|
92
|
+
# @param [Set<Symbol>] static_local_variables
|
93
|
+
#
|
94
|
+
# @return [String]
|
95
|
+
#
|
96
|
+
# @raise InvalidNodeError
|
97
|
+
# if the node passed is invalid
|
98
|
+
#
|
99
|
+
# @api public
|
100
|
+
#
|
101
|
+
# mutant:disable
|
102
|
+
# rubocop:disable Metrics/ParameterLists
|
103
|
+
def self.unparse(
|
104
|
+
node,
|
105
|
+
comments: EMPTY_ARRAY,
|
106
|
+
explicit_encoding: nil,
|
107
|
+
static_local_variables: Set.new
|
108
|
+
)
|
109
|
+
unparse_ast(
|
110
|
+
AST.new(
|
111
|
+
comments: comments,
|
112
|
+
explicit_encoding: explicit_encoding,
|
113
|
+
node: node,
|
114
|
+
static_local_variables: static_local_variables
|
115
|
+
)
|
116
|
+
)
|
117
|
+
end
|
118
|
+
# rubocop:enable Metrics/ParameterLists
|
119
|
+
|
120
|
+
# Unparse an AST
|
121
|
+
#
|
122
|
+
# @param [AST] ast
|
53
123
|
#
|
54
124
|
# @return [String]
|
55
125
|
#
|
56
126
|
# @raise InvalidNodeError
|
57
127
|
# if the node passed is invalid
|
58
128
|
#
|
129
|
+
# @raise UnsupportedNodeError
|
130
|
+
# if the node passed is valid but unparser cannot unparse it
|
131
|
+
#
|
59
132
|
# @api public
|
60
|
-
def self.
|
61
|
-
return
|
133
|
+
def self.unparse_ast(ast)
|
134
|
+
return EMPTY_STRING if ast.node.nil?
|
135
|
+
|
136
|
+
local_variable_scope = AST::LocalVariableScope.new(
|
137
|
+
node: ast.node,
|
138
|
+
static_local_variables: ast.static_local_variables
|
139
|
+
)
|
62
140
|
|
63
141
|
Buffer.new.tap do |buffer|
|
64
142
|
Emitter::Root.new(
|
65
|
-
buffer,
|
66
|
-
|
67
|
-
|
143
|
+
buffer: buffer,
|
144
|
+
comments: Comments.new(ast.comments),
|
145
|
+
explicit_encoding: ast.explicit_encoding,
|
146
|
+
local_variable_scope: local_variable_scope,
|
147
|
+
node: ast.node
|
68
148
|
).write_to_buffer
|
69
149
|
end.content
|
70
150
|
end
|
71
151
|
|
72
|
-
# Unparse
|
152
|
+
# Unparse AST either
|
73
153
|
#
|
74
|
-
# @param [
|
75
|
-
# @param [Array] comment_array
|
154
|
+
# @param [AST] ast
|
76
155
|
#
|
77
|
-
# @return [Either<
|
78
|
-
def self.
|
79
|
-
|
80
|
-
|
156
|
+
# @return [Either<Exception,String>]
|
157
|
+
def self.unparse_ast_either(ast)
|
158
|
+
Either.wrap_error(Exception) { unparse_ast(ast) }
|
159
|
+
end
|
160
|
+
|
161
|
+
# Unparse AST either
|
162
|
+
#
|
163
|
+
# @param [AST] ast
|
164
|
+
#
|
165
|
+
# @return [Either<Exception,String>]
|
166
|
+
#
|
167
|
+
# mutant:disable
|
168
|
+
def self.unparse_validate_ast_either(ast:)
|
169
|
+
validation = Validation.from_ast(ast:)
|
81
170
|
|
82
171
|
if validation.success?
|
83
|
-
Either::Right.new(
|
172
|
+
Either::Right.new(validation.generated_source.from_right)
|
84
173
|
else
|
85
174
|
Either::Left.new(validation)
|
86
175
|
end
|
87
176
|
end
|
88
177
|
|
89
|
-
# Unparse
|
90
|
-
#
|
91
|
-
# This is mostly useful for writing testing tools against unparser.
|
178
|
+
# Unparse with validation
|
92
179
|
#
|
93
180
|
# @param [Parser::AST::Node, nil] node
|
181
|
+
# @param [Array] comments
|
94
182
|
#
|
95
|
-
# @return [Either<
|
96
|
-
def self.
|
97
|
-
|
183
|
+
# @return [Either<Validation,String>]
|
184
|
+
def self.unparse_validate(node, comments: EMPTY_ARRAY)
|
185
|
+
generated = unparse(node, comments:)
|
186
|
+
validation = Validation.from_string(generated)
|
187
|
+
|
188
|
+
if validation.success?
|
189
|
+
Either::Right.new(generated)
|
190
|
+
else
|
191
|
+
Either::Left.new(validation)
|
192
|
+
end
|
98
193
|
end
|
99
194
|
|
100
195
|
# Parse string into AST
|
@@ -103,27 +198,37 @@ module Unparser
|
|
103
198
|
#
|
104
199
|
# @return [Parser::AST::Node, nil]
|
105
200
|
def self.parse(source)
|
106
|
-
|
201
|
+
parse_ast(source).node
|
107
202
|
end
|
108
203
|
|
109
204
|
# Parse string into either syntax error or AST
|
110
205
|
#
|
111
206
|
# @param [String] source
|
112
207
|
#
|
113
|
-
# @return [Either<
|
114
|
-
def self.
|
115
|
-
Either.wrap_error(
|
116
|
-
|
208
|
+
# @return [Either<Exception, (Parser::ASTNode, nil)>]
|
209
|
+
def self.parse_ast_either(source)
|
210
|
+
Either.wrap_error(Exception) do
|
211
|
+
parse_ast(source)
|
117
212
|
end
|
118
213
|
end
|
119
214
|
|
120
|
-
# Parse
|
215
|
+
# Parse source with ast details
|
121
216
|
#
|
122
217
|
# @param [String] source
|
123
218
|
#
|
124
|
-
# @return [
|
125
|
-
|
126
|
-
|
219
|
+
# @return [AST]
|
220
|
+
#
|
221
|
+
# mutant:disable
|
222
|
+
def self.parse_ast(source, static_local_variables: Set.new)
|
223
|
+
explicit_encoding = Parser::Source::Buffer.recognize_encoding(source.dup.force_encoding(Encoding::BINARY))
|
224
|
+
node, comments = parser.parse_with_comments(buffer(source))
|
225
|
+
|
226
|
+
AST.new(
|
227
|
+
comments: comments,
|
228
|
+
explicit_encoding: explicit_encoding,
|
229
|
+
node: node,
|
230
|
+
static_local_variables: static_local_variables
|
231
|
+
)
|
127
232
|
end
|
128
233
|
|
129
234
|
# Parser instance that produces AST unparser understands
|
@@ -131,8 +236,9 @@ module Unparser
|
|
131
236
|
# @return [Parser::Base]
|
132
237
|
#
|
133
238
|
# @api private
|
239
|
+
# mutant:disable
|
134
240
|
def self.parser
|
135
|
-
|
241
|
+
PARSER_CLASS.new(Builder.new).tap do |parser|
|
136
242
|
parser.diagnostics.tap do |diagnostics|
|
137
243
|
diagnostics.all_errors_are_fatal = true
|
138
244
|
end
|
@@ -179,6 +285,7 @@ require 'unparser/emitter/def'
|
|
179
285
|
require 'unparser/emitter/defined'
|
180
286
|
require 'unparser/emitter/dstr'
|
181
287
|
require 'unparser/emitter/dsym'
|
288
|
+
require 'unparser/emitter/ensure'
|
182
289
|
require 'unparser/emitter/flipflop'
|
183
290
|
require 'unparser/emitter/float'
|
184
291
|
require 'unparser/emitter/flow_modifier'
|
@@ -210,6 +317,7 @@ require 'unparser/emitter/rescue'
|
|
210
317
|
require 'unparser/emitter/root'
|
211
318
|
require 'unparser/emitter/send'
|
212
319
|
require 'unparser/emitter/simple'
|
320
|
+
require 'unparser/emitter/string'
|
213
321
|
require 'unparser/emitter/splat'
|
214
322
|
require 'unparser/emitter/super'
|
215
323
|
require 'unparser/emitter/undef'
|
@@ -222,8 +330,10 @@ require 'unparser/emitter/find_pattern'
|
|
222
330
|
require 'unparser/emitter/match_pattern'
|
223
331
|
require 'unparser/emitter/match_pattern_p'
|
224
332
|
require 'unparser/writer'
|
333
|
+
require 'unparser/writer/array'
|
225
334
|
require 'unparser/writer/binary'
|
226
335
|
require 'unparser/writer/dynamic_string'
|
336
|
+
require 'unparser/writer/regexp'
|
227
337
|
require 'unparser/writer/resbody'
|
228
338
|
require 'unparser/writer/rescue'
|
229
339
|
require 'unparser/writer/send'
|
@@ -234,6 +344,7 @@ require 'unparser/writer/send/unary'
|
|
234
344
|
require 'unparser/node_details'
|
235
345
|
require 'unparser/node_details/send'
|
236
346
|
require 'unparser/cli'
|
347
|
+
require 'unparser/util'
|
237
348
|
|
238
349
|
require 'unparser/validation'
|
239
350
|
# make it easy for zombie
|