1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
|
# frozen_string_literal: true
module Unparser
# rubocop:disable Metrics/ModuleLength
module Generation
EXTRA_NL = %i[kwbegin def defs module class sclass].freeze
private_constant(*constants(false))
def emit_heredoc_reminders; end
def symbol_name; end
def write_to_buffer
with_comments { dispatch }
self
end
private
def delimited(nodes, delimiter = ', ', &block)
return if nodes.empty?
emit_join(nodes, block || method(:visit), -> { write(delimiter) })
end
def emit_join(nodes, emit_node, emit_delimiter)
return if nodes.empty?
head, *tail = nodes
emit_node.call(head)
tail.each do |node|
emit_delimiter.call
emit_node.call(node)
end
end
def nl
emit_eol_comments
buffer.nl
end
def with_comments
emit_comments_before if buffer.fresh_line?
yield
comments.consume(node)
end
def ws
write(' ')
end
def emit_eol_comments
comments.take_eol_comments.each do |comment|
write(' ', comment.text)
end
end
def emit_eof_comments
emit_eol_comments
comments_left = comments.take_all
return if comments_left.empty?
buffer.nl
emit_comments(comments_left)
end
def emit_comments_before(source_part = :expression)
comments_before = comments.take_before(node, source_part)
return if comments_before.empty?
emit_comments(comments_before)
buffer.nl
end
def emit_comments(comments)
max = comments.size - 1
comments.each_with_index do |comment, index|
if comment.type.equal?(:document)
buffer.append_without_prefix(comment.text.chomp)
else
write(comment.text)
end
buffer.nl if index < max
end
end
def write(*strings)
strings.each(&buffer.method(:append))
end
def k_end
buffer.indent
emit_comments_before(:end)
buffer.unindent
write('end')
end
def parentheses(open = '(', close = ')')
write(open)
yield
write(close)
end
def indented
buffer = buffer()
buffer.indent
nl
yield
nl
buffer.unindent
end
def emit_optional_body(node, indent: true)
if node
emit_body(node, indent: indent)
else
nl
end
end
def emit_body(node, indent: true)
with_indent(indent: indent) do
if n_begin?(node)
if node.children.empty?
write('()')
elsif node.children.one?
visit_deep(node)
else
emit_body_inner(node)
end
else
visit_deep(node)
end
end
end
def with_indent(indent:)
return yield unless indent
buffer.indent
nl
yield
buffer.unindent
nl
end
def emit_body_inner(node)
head, *tail = node.children
emit_body_member(head)
tail.each do |child|
nl
nl if EXTRA_NL.include?(child.type)
emit_body_member(child)
end
end
def emit_body_member(node)
if n_rescue?(node)
emit_rescue_postcontrol(node)
else
visit_deep(node)
end
end
def emit_ensure(node)
body, ensure_body = node.children
if body
emit_body_rescue(body)
else
nl
end
write('ensure')
emit_optional_body(ensure_body)
end
def emit_body_rescue(node)
if n_rescue?(node)
emit_rescue_regular(node)
else
emit_body(node)
end
end
def emit_optional_body_ensure_rescue(node)
if node
emit_body_ensure_rescue(node)
else
nl
end
end
def emit_body_ensure_rescue(node)
if n_ensure?(node)
emit_ensure(node)
elsif n_rescue?(node)
emit_rescue_regular(node)
else
emit_body(node)
end
end
def emit_rescue_postcontrol(node)
writer = writer_with(Writer::Rescue, node)
writer.emit_postcontrol
writer.emit_heredoc_reminders
end
def emit_rescue_regular(node)
writer_with(Writer::Rescue, node).emit_regular
end
def writer_with(klass, node)
klass.new(to_h.merge(node: node))
end
def emitter(node)
Emitter.emitter(**to_h.merge(node: node))
end
def visit(node)
emitter(node).write_to_buffer
end
def visit_deep(node)
emitter(node).tap do |emitter|
emitter.write_to_buffer
emitter.emit_heredoc_reminders
end
end
def first_child
children.first
end
def conditional_parentheses(flag, &block)
if flag
parentheses(&block)
else
block.call
end
end
def children
node.children
end
end # Generation
# rubocop:enable Metrics/ModuleLength
end # Unparser
|