Skip to content

Commit 1572099

Browse files
committed
Add context tracking to only emit begin keyword when needed
1 parent cc87c77 commit 1572099

10 files changed

Lines changed: 80 additions & 37 deletions

File tree

.rspec

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
--color
22
--format progress
3-
--profile
43
--order random
5-
--fail-fast

config/flay.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
---
22
threshold: 14
3-
total_score: 341
3+
total_score: 342

config/reek.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ UncommunicativeParameterName:
1212
TooManyInstanceVariables:
1313
exclude: []
1414
enabled: true
15-
max_instance_variables: 2
15+
max_instance_variables: 3
1616
TooManyMethods:
1717
exclude:
1818
- Unparser::Emitter # TODO: 13 methods, mostly helpers for deduplicate sublcasses
@@ -27,7 +27,7 @@ UncommunicativeMethodName:
2727
- !ruby/regexp /[0-9]$/
2828
- !ruby/regexp /[A-Z]/
2929
LongParameterList:
30-
max_params: 2
30+
max_params: 3
3131
exclude:
3232
- Unparser#self.transquote
3333
enabled: true

lib/unparser.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,6 @@ def self.transquote(raw_quoted, current_delimiter, target_delimiter)
8282
require 'unparser/emitter/case'
8383
require 'unparser/emitter/for'
8484
require 'unparser/emitter/repetition'
85+
require 'unparser/emitter/root'
8586

8687
Unparser::Emitter::REGISTRY.freeze

lib/unparser/emitter.rb

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ module Unparser
22

33
# Emitter base class
44
class Emitter
5-
include Adamantium::Flat, AbstractType, Equalizer.new(:node, :buffer), Constants
5+
include Adamantium::Flat, AbstractType, Constants
6+
include Equalizer.new(:node, :buffer, :parent)
67

78
# Registry for node emitters
89
REGISTRY = {}
@@ -62,8 +63,8 @@ def self.emit(*arguments)
6263
#
6364
# @api private
6465
#
65-
def initialize(node, buffer)
66-
@node, @buffer = node, buffer
66+
def initialize(node, buffer, parent)
67+
@node, @buffer, @parent = node, buffer, parent
6768
dispatch
6869
end
6970

@@ -78,15 +79,29 @@ def initialize(node, buffer)
7879
#
7980
# @api private
8081
#
81-
def self.visit(node, buffer)
82+
def self.visit(node, buffer, parent = Root)
8283
type = node.type
8384
emitter = REGISTRY.fetch(type) do
8485
raise ArgumentError, "No emitter for node: #{type.inspect}"
8586
end
86-
emitter.emit(node, buffer)
87+
emitter.emit(node, buffer, parent)
8788
self
8889
end
8990

91+
# Test if node needs begin
92+
#
93+
# @return [true]
94+
# if if node needs begin
95+
#
96+
# @return [false]
97+
# otherwise
98+
#
99+
# @api private
100+
#
101+
def needs_begin?
102+
false
103+
end
104+
90105
# Return node
91106
#
92107
# @return [Parser::AST::Node] node
@@ -106,6 +121,15 @@ def self.visit(node, buffer)
106121
attr_reader :buffer
107122
protected :buffer
108123

124+
# Return parent emitter
125+
#
126+
# @return [Parent]
127+
#
128+
# @api private
129+
#
130+
attr_reader :parent
131+
protected :parent
132+
109133
# Emit contents of block within parentheses
110134
#
111135
# @return [undefined]
@@ -137,7 +161,7 @@ def emit_source_map
137161
# @api private
138162
#
139163
def visit(node)
140-
self.class.visit(node, buffer)
164+
self.class.visit(node, buffer, self)
141165
end
142166

143167
# Emit delimited body

lib/unparser/emitter/begin.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,13 @@ def dispatch
150150
# @api private
151151
#
152152
def emit_normal
153-
k_begin
154-
indented { emit_inner }
155-
k_end
153+
unless parent.needs_begin?
154+
emit_inner
155+
else
156+
k_begin
157+
indented { emit_inner }
158+
k_end
159+
end
156160
end
157161

158162
# Emit inner nodes

lib/unparser/emitter/root.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Unparser
2+
class Emitter
3+
Root = ::Class.new(self) do
4+
def initialize(); end
5+
end.send(:new)
6+
end
7+
end

lib/unparser/emitter/send.rb

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@ class Send < self
1414

1515
AMBIGOUS = [:irange, :erange].to_set.freeze
1616

17+
# Tell node needs begin
18+
#
19+
# @return [true]
20+
#
21+
# @api private
22+
#
23+
def needs_begin?
24+
true
25+
end
26+
1727
private
1828

1929
# Perform dispatch
@@ -95,9 +105,9 @@ def binary_receiver?
95105
# @api private
96106
#
97107
def run(emitter)
98-
emitter.emit(node, buffer)
108+
emitter.emit(node, buffer, self)
99109
end
100-
110+
101111
# Perform non index dispatch
102112
#
103113
# @return [undefined]
@@ -136,13 +146,13 @@ def regular_dispatch
136146
def emit_receiver
137147
return unless first_child
138148
emit_unambiguous_receiver
139-
write(O_DOT)
149+
write(O_DOT)
140150
end
141151

142152
# Test for unary operator implemented as method
143153
#
144154
# @return [true]
145-
# if node is a unary operator
155+
# if node is a unary operator
146156
#
147157
# @return [false]
148158
# otherwise
@@ -156,7 +166,7 @@ def unary?
156166
# Test for binary operator implemented as method
157167
#
158168
# @return [true]
159-
# if node is a binary operator
169+
# if node is a binary operator
160170
#
161171
# @return [false]
162172
# otherwise

spec/integration/unparser/spike_spec.rb

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -288,10 +288,8 @@ def self.assert_source(input, versions = RUBIES)
288288
assert_generates s(:begin), 'nil'
289289

290290
assert_source <<-RUBY
291-
begin
292-
foo
293-
bar
294-
end
291+
foo
292+
bar
295293
RUBY
296294

297295
assert_source <<-RUBY
@@ -307,6 +305,7 @@ def self.assert_source(input, versions = RUBIES)
307305
begin
308306
foo
309307
ensure
308+
bar
310309
baz
311310
end
312311
RUBY
@@ -321,12 +320,11 @@ def self.assert_source(input, versions = RUBIES)
321320

322321
assert_source <<-RUBY
323322
begin
324-
begin
325-
foo
326-
bar
327-
end
323+
foo
324+
bar
328325
rescue
329326
baz
327+
bar
330328
end
331329
RUBY
332330

@@ -598,15 +596,16 @@ def foo(bar, &block)
598596
RUBY
599597

600598
assert_source <<-RUBY
601-
def initialize(attributes, options)
602-
begin
603-
@attributes = freeze_object(attributes)
604-
@options = freeze_object(options)
605-
@attribute_for = Hash[@attributes.map do |attribute|
606-
attribute.name
607-
end.zip(@attributes)]
608-
@keys = coerce_keys
609-
end
599+
def foo
600+
bar
601+
baz
602+
end
603+
RUBY
604+
605+
assert_source <<-RUBY
606+
def self.foo
607+
bar
608+
baz
610609
end
611610
RUBY
612611
end

spec/unit/unparser/emitter/class_methods/visit_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
end
1313

1414
class Dummy < Unparser::Emitter
15-
def self.emit(node, buffer)
15+
def self.emit(node, buffer, parent)
1616
buffer.append('foo')
1717
end
1818
end

0 commit comments

Comments
 (0)