Skip to content

Commit 137b4be

Browse files
authored
Merge pull request #450 from bradleybuda/bare-assoc-hash-with-ruby-3.1-keyword
2 parents a27e617 + c86b692 commit 137b4be

File tree

2 files changed

+53
-34
lines changed

2 files changed

+53
-34
lines changed

lib/syntax_tree/node.rb

Lines changed: 49 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1783,45 +1783,60 @@ def format_key(q, key)
17831783
end
17841784
end
17851785

1786-
def self.for(container)
1787-
container.assocs.each do |assoc|
1788-
if assoc.is_a?(AssocSplat)
1789-
# Splat nodes do not impact the formatting choice.
1790-
elsif assoc.value.nil?
1791-
# If the value is nil, then it has been omitted. In this case we have
1792-
# to match the existing formatting because standardizing would
1793-
# potentially break the code. For example:
1794-
#
1795-
# { first:, "second" => "value" }
1796-
#
1797-
return Identity.new
1798-
else
1799-
# Otherwise, we need to check the type of the key. If it's a label or
1800-
# dynamic symbol, we can use labels. If it's a symbol literal then it
1801-
# needs to match a certain pattern to be used as a label. If it's
1802-
# anything else, then we need to use hash rockets.
1803-
case assoc.key
1804-
when Label, DynaSymbol
1805-
# Here labels can be used.
1806-
when SymbolLiteral
1807-
# When attempting to convert a hash rocket into a hash label,
1808-
# you need to take care because only certain patterns are
1809-
# allowed. Ruby source says that they have to match keyword
1810-
# arguments to methods, but don't specify what that is. After
1811-
# some experimentation, it looks like it's:
1812-
value = assoc.key.value.value
1813-
1814-
if !value.match?(/^[_A-Za-z]/) || value.end_with?("=")
1815-
return Rockets.new
1816-
end
1786+
class << self
1787+
def for(container)
1788+
(assocs = container.assocs).each_with_index do |assoc, index|
1789+
if assoc.is_a?(AssocSplat)
1790+
# Splat nodes do not impact the formatting choice.
1791+
elsif assoc.value.nil?
1792+
# If the value is nil, then it has been omitted. In this case we
1793+
# have to match the existing formatting because standardizing would
1794+
# potentially break the code. For example:
1795+
#
1796+
# { first:, "second" => "value" }
1797+
#
1798+
return Identity.new
18171799
else
1818-
# If the value is anything else, we have to use hash rockets.
1819-
return Rockets.new
1800+
# Otherwise, we need to check the type of the key. If it's a label
1801+
# or dynamic symbol, we can use labels. If it's a symbol literal
1802+
# then it needs to match a certain pattern to be used as a label. If
1803+
# it's anything else, then we need to use hash rockets.
1804+
case assoc.key
1805+
when Label, DynaSymbol
1806+
# Here labels can be used.
1807+
when SymbolLiteral
1808+
# When attempting to convert a hash rocket into a hash label,
1809+
# you need to take care because only certain patterns are
1810+
# allowed. Ruby source says that they have to match keyword
1811+
# arguments to methods, but don't specify what that is. After
1812+
# some experimentation, it looks like it's:
1813+
value = assoc.key.value.value
1814+
1815+
if !value.match?(/^[_A-Za-z]/) || value.end_with?("=")
1816+
if omitted_value?(assocs[(index + 1)..])
1817+
return Identity.new
1818+
else
1819+
return Rockets.new
1820+
end
1821+
end
1822+
else
1823+
if omitted_value?(assocs[(index + 1)..])
1824+
return Identity.new
1825+
else
1826+
return Rockets.new
1827+
end
1828+
end
18201829
end
18211830
end
1831+
1832+
Labels.new
18221833
end
18231834

1824-
Labels.new
1835+
private
1836+
1837+
def omitted_value?(assocs)
1838+
assocs.any? { |assoc| !assoc.is_a?(AssocSplat) && assoc.value.nil? }
1839+
end
18251840
end
18261841
end
18271842

test/fixtures/assoc.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,7 @@
4848
{ "foo #{bar}": "baz" }
4949
%
5050
{ "foo=": "baz" }
51+
% # >= 3.1.0
52+
{ bar => 1, baz: }
53+
% # >= 3.1.0
54+
{ baz:, bar => 1 }

0 commit comments

Comments
 (0)