syntax_tree 3.6.3 → 4.0.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/.rubocop.yml +3 -0
- data/CHANGELOG.md +15 -1
- data/Gemfile.lock +5 -5
- data/README.md +32 -10
- data/bin/profile +5 -6
- data/lib/syntax_tree/cli.rb +3 -3
- data/lib/syntax_tree/formatter.rb +67 -8
- data/lib/syntax_tree/node.rb +775 -527
- data/lib/syntax_tree/parser.rb +335 -245
- data/lib/syntax_tree/version.rb +1 -1
- data/lib/syntax_tree/visitor/environment.rb +81 -0
- data/lib/syntax_tree/visitor/with_environment.rb +141 -0
- data/lib/syntax_tree.rb +14 -2
- data/syntax_tree.gemspec +1 -1
- metadata +6 -4
data/lib/syntax_tree/node.rb
CHANGED
@@ -177,10 +177,10 @@ module SyntaxTree
|
|
177
177
|
q.text("BEGIN ")
|
178
178
|
q.format(lbrace)
|
179
179
|
q.indent do
|
180
|
-
q.
|
180
|
+
q.breakable_space
|
181
181
|
q.format(statements)
|
182
182
|
end
|
183
|
-
q.
|
183
|
+
q.breakable_space
|
184
184
|
q.text("}")
|
185
185
|
end
|
186
186
|
end
|
@@ -280,10 +280,10 @@ module SyntaxTree
|
|
280
280
|
q.text("END ")
|
281
281
|
q.format(lbrace)
|
282
282
|
q.indent do
|
283
|
-
q.
|
283
|
+
q.breakable_space
|
284
284
|
q.format(statements)
|
285
285
|
end
|
286
|
-
q.
|
286
|
+
q.breakable_space
|
287
287
|
q.text("}")
|
288
288
|
end
|
289
289
|
end
|
@@ -327,10 +327,20 @@ module SyntaxTree
|
|
327
327
|
|
328
328
|
def format(q)
|
329
329
|
q.text("__END__")
|
330
|
-
q.
|
330
|
+
q.breakable_force
|
331
331
|
|
332
|
-
|
333
|
-
|
332
|
+
first = true
|
333
|
+
value.each_line(chomp: true) do |line|
|
334
|
+
if first
|
335
|
+
first = false
|
336
|
+
else
|
337
|
+
q.breakable_return
|
338
|
+
end
|
339
|
+
|
340
|
+
q.text(line)
|
341
|
+
end
|
342
|
+
|
343
|
+
q.breakable_return if value.end_with?("\n")
|
334
344
|
end
|
335
345
|
end
|
336
346
|
|
@@ -412,7 +422,7 @@ module SyntaxTree
|
|
412
422
|
q.format(left_argument, stackable: false)
|
413
423
|
q.group do
|
414
424
|
q.nest(keyword.length) do
|
415
|
-
|
425
|
+
left_argument.comments.any? ? q.breakable_force : q.breakable_space
|
416
426
|
q.format(AliasArgumentFormatter.new(right), stackable: false)
|
417
427
|
end
|
418
428
|
end
|
@@ -476,10 +486,10 @@ module SyntaxTree
|
|
476
486
|
|
477
487
|
if index
|
478
488
|
q.indent do
|
479
|
-
q.
|
489
|
+
q.breakable_empty
|
480
490
|
q.format(index)
|
481
491
|
end
|
482
|
-
q.
|
492
|
+
q.breakable_empty
|
483
493
|
end
|
484
494
|
|
485
495
|
q.text("]")
|
@@ -537,10 +547,10 @@ module SyntaxTree
|
|
537
547
|
|
538
548
|
if index
|
539
549
|
q.indent do
|
540
|
-
q.
|
550
|
+
q.breakable_empty
|
541
551
|
q.format(index)
|
542
552
|
end
|
543
|
-
q.
|
553
|
+
q.breakable_empty
|
544
554
|
end
|
545
555
|
|
546
556
|
q.text("]")
|
@@ -593,25 +603,30 @@ module SyntaxTree
|
|
593
603
|
return
|
594
604
|
end
|
595
605
|
|
596
|
-
q.
|
606
|
+
q.text("(")
|
607
|
+
q.group do
|
597
608
|
q.indent do
|
598
|
-
q.
|
609
|
+
q.breakable_empty
|
599
610
|
q.format(arguments)
|
600
611
|
q.if_break { q.text(",") } if q.trailing_comma? && trailing_comma?
|
601
612
|
end
|
602
|
-
q.
|
613
|
+
q.breakable_empty
|
603
614
|
end
|
615
|
+
q.text(")")
|
604
616
|
end
|
605
617
|
|
606
618
|
private
|
607
619
|
|
608
620
|
def trailing_comma?
|
609
|
-
|
610
|
-
|
621
|
+
return false unless arguments.is_a?(Args)
|
622
|
+
parts = arguments.parts
|
623
|
+
|
624
|
+
if parts.last.is_a?(ArgBlock)
|
611
625
|
# If the last argument is a block, then we can't put a trailing comma
|
612
626
|
# after it without resulting in a syntax error.
|
613
627
|
false
|
614
|
-
|
628
|
+
elsif (parts.length == 1) && (part = parts.first) &&
|
629
|
+
(part.is_a?(Command) || part.is_a?(CommandCall))
|
615
630
|
# If the only argument is a command or command call, then a trailing
|
616
631
|
# comma would be parsed as part of that expression instead of on this
|
617
632
|
# one, so we don't want to add a trailing comma.
|
@@ -790,6 +805,17 @@ module SyntaxTree
|
|
790
805
|
# [one, two, three]
|
791
806
|
#
|
792
807
|
class ArrayLiteral < Node
|
808
|
+
# It's very common to use seplist with ->(q) { q.breakable_space }. We wrap
|
809
|
+
# that pattern into an object to cut down on having to create a bunch of
|
810
|
+
# lambdas all over the place.
|
811
|
+
class BreakableSpaceSeparator
|
812
|
+
def call(q)
|
813
|
+
q.breakable_space
|
814
|
+
end
|
815
|
+
end
|
816
|
+
|
817
|
+
BREAKABLE_SPACE_SEPARATOR = BreakableSpaceSeparator.new
|
818
|
+
|
793
819
|
# Formats an array of multiple simple string literals into the %w syntax.
|
794
820
|
class QWordsFormatter
|
795
821
|
# [Args] the contents of the array
|
@@ -800,10 +826,11 @@ module SyntaxTree
|
|
800
826
|
end
|
801
827
|
|
802
828
|
def format(q)
|
803
|
-
q.
|
829
|
+
q.text("%w[")
|
830
|
+
q.group do
|
804
831
|
q.indent do
|
805
|
-
q.
|
806
|
-
q.seplist(contents.parts,
|
832
|
+
q.breakable_empty
|
833
|
+
q.seplist(contents.parts, BREAKABLE_SPACE_SEPARATOR) do |part|
|
807
834
|
if part.is_a?(StringLiteral)
|
808
835
|
q.format(part.parts.first)
|
809
836
|
else
|
@@ -811,8 +838,9 @@ module SyntaxTree
|
|
811
838
|
end
|
812
839
|
end
|
813
840
|
end
|
814
|
-
q.
|
841
|
+
q.breakable_empty
|
815
842
|
end
|
843
|
+
q.text("]")
|
816
844
|
end
|
817
845
|
end
|
818
846
|
|
@@ -826,15 +854,17 @@ module SyntaxTree
|
|
826
854
|
end
|
827
855
|
|
828
856
|
def format(q)
|
829
|
-
q.
|
857
|
+
q.text("%i[")
|
858
|
+
q.group do
|
830
859
|
q.indent do
|
831
|
-
q.
|
832
|
-
q.seplist(contents.parts,
|
860
|
+
q.breakable_empty
|
861
|
+
q.seplist(contents.parts, BREAKABLE_SPACE_SEPARATOR) do |part|
|
833
862
|
q.format(part.value)
|
834
863
|
end
|
835
864
|
end
|
836
|
-
q.
|
865
|
+
q.breakable_empty
|
837
866
|
end
|
867
|
+
q.text("]")
|
838
868
|
end
|
839
869
|
end
|
840
870
|
|
@@ -861,6 +891,14 @@ module SyntaxTree
|
|
861
891
|
#
|
862
892
|
# provided the line length was hit between `bar` and `baz`.
|
863
893
|
class VarRefsFormatter
|
894
|
+
# The separator for the fill algorithm.
|
895
|
+
class Separator
|
896
|
+
def call(q)
|
897
|
+
q.text(",")
|
898
|
+
q.fill_breakable
|
899
|
+
end
|
900
|
+
end
|
901
|
+
|
864
902
|
# [Args] the contents of the array
|
865
903
|
attr_reader :contents
|
866
904
|
|
@@ -869,20 +907,16 @@ module SyntaxTree
|
|
869
907
|
end
|
870
908
|
|
871
909
|
def format(q)
|
872
|
-
q.
|
910
|
+
q.text("[")
|
911
|
+
q.group do
|
873
912
|
q.indent do
|
874
|
-
q.
|
875
|
-
|
876
|
-
separator = -> do
|
877
|
-
q.text(",")
|
878
|
-
q.fill_breakable
|
879
|
-
end
|
880
|
-
|
881
|
-
q.seplist(contents.parts, separator) { |part| q.format(part) }
|
913
|
+
q.breakable_empty
|
914
|
+
q.seplist(contents.parts, Separator.new) { |part| q.format(part) }
|
882
915
|
q.if_break { q.text(",") } if q.trailing_comma?
|
883
916
|
end
|
884
|
-
q.
|
917
|
+
q.breakable_empty
|
885
918
|
end
|
919
|
+
q.text("]")
|
886
920
|
end
|
887
921
|
end
|
888
922
|
|
@@ -902,11 +936,11 @@ module SyntaxTree
|
|
902
936
|
q.text("[")
|
903
937
|
q.indent do
|
904
938
|
lbracket.comments.each do |comment|
|
905
|
-
q.
|
939
|
+
q.breakable_force
|
906
940
|
comment.format(q)
|
907
941
|
end
|
908
942
|
end
|
909
|
-
q.
|
943
|
+
q.breakable_force
|
910
944
|
q.text("]")
|
911
945
|
end
|
912
946
|
end
|
@@ -973,13 +1007,13 @@ module SyntaxTree
|
|
973
1007
|
|
974
1008
|
if contents
|
975
1009
|
q.indent do
|
976
|
-
q.
|
1010
|
+
q.breakable_empty
|
977
1011
|
q.format(contents)
|
978
1012
|
q.if_break { q.text(",") } if q.trailing_comma?
|
979
1013
|
end
|
980
1014
|
end
|
981
1015
|
|
982
|
-
q.
|
1016
|
+
q.breakable_empty
|
983
1017
|
q.text("]")
|
984
1018
|
end
|
985
1019
|
end
|
@@ -1127,7 +1161,7 @@ module SyntaxTree
|
|
1127
1161
|
q.format(constant) if constant
|
1128
1162
|
q.text("[")
|
1129
1163
|
q.indent do
|
1130
|
-
q.
|
1164
|
+
q.breakable_empty
|
1131
1165
|
|
1132
1166
|
parts = [*requireds]
|
1133
1167
|
parts << RestFormatter.new(rest) if rest
|
@@ -1135,7 +1169,7 @@ module SyntaxTree
|
|
1135
1169
|
|
1136
1170
|
q.seplist(parts) { |part| q.format(part) }
|
1137
1171
|
end
|
1138
|
-
q.
|
1172
|
+
q.breakable_empty
|
1139
1173
|
q.text("]")
|
1140
1174
|
end
|
1141
1175
|
end
|
@@ -1145,13 +1179,13 @@ module SyntaxTree
|
|
1145
1179
|
module AssignFormatting
|
1146
1180
|
def self.skip_indent?(value)
|
1147
1181
|
case value
|
1148
|
-
|
1149
|
-
Symbols
|
1182
|
+
when ArrayLiteral, HashLiteral, Heredoc, Lambda, QSymbols, QWords,
|
1183
|
+
Symbols, Words
|
1150
1184
|
true
|
1151
|
-
|
1152
|
-
skip_indent?(receiver)
|
1153
|
-
|
1154
|
-
quote.start_with?("%s")
|
1185
|
+
when Call
|
1186
|
+
skip_indent?(value.receiver)
|
1187
|
+
when DynaSymbol
|
1188
|
+
value.quote.start_with?("%s")
|
1155
1189
|
else
|
1156
1190
|
false
|
1157
1191
|
end
|
@@ -1206,7 +1240,7 @@ module SyntaxTree
|
|
1206
1240
|
q.format(value)
|
1207
1241
|
else
|
1208
1242
|
q.indent do
|
1209
|
-
q.
|
1243
|
+
q.breakable_space
|
1210
1244
|
q.format(value)
|
1211
1245
|
end
|
1212
1246
|
end
|
@@ -1277,7 +1311,7 @@ module SyntaxTree
|
|
1277
1311
|
q.format(value)
|
1278
1312
|
else
|
1279
1313
|
q.indent do
|
1280
|
-
q.
|
1314
|
+
q.breakable_space
|
1281
1315
|
q.format(value)
|
1282
1316
|
end
|
1283
1317
|
end
|
@@ -1404,17 +1438,22 @@ module SyntaxTree
|
|
1404
1438
|
|
1405
1439
|
def format_key(q, key)
|
1406
1440
|
case key
|
1407
|
-
|
1441
|
+
when Label
|
1408
1442
|
q.format(key)
|
1409
|
-
|
1443
|
+
when SymbolLiteral
|
1410
1444
|
q.format(key.value)
|
1411
1445
|
q.text(":")
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1446
|
+
when DynaSymbol
|
1447
|
+
parts = key.parts
|
1448
|
+
|
1449
|
+
if parts.length == 1 && (part = parts.first) &&
|
1450
|
+
part.is_a?(TStringContent) && part.value.match?(LABEL)
|
1451
|
+
q.format(part)
|
1452
|
+
q.text(":")
|
1453
|
+
else
|
1454
|
+
q.format(key)
|
1455
|
+
q.text(":")
|
1456
|
+
end
|
1418
1457
|
end
|
1419
1458
|
end
|
1420
1459
|
end
|
@@ -1424,8 +1463,7 @@ module SyntaxTree
|
|
1424
1463
|
def format_key(q, key)
|
1425
1464
|
case key
|
1426
1465
|
when Label
|
1427
|
-
q.text(":")
|
1428
|
-
q.text(key.value.chomp(":"))
|
1466
|
+
q.text(":#{key.value.chomp(":")}")
|
1429
1467
|
when DynaSymbol
|
1430
1468
|
q.text(":")
|
1431
1469
|
q.format(key)
|
@@ -1544,12 +1582,12 @@ module SyntaxTree
|
|
1544
1582
|
|
1545
1583
|
unless bodystmt.empty?
|
1546
1584
|
q.indent do
|
1547
|
-
q.
|
1585
|
+
q.breakable_force unless bodystmt.statements.empty?
|
1548
1586
|
q.format(bodystmt)
|
1549
1587
|
end
|
1550
1588
|
end
|
1551
1589
|
|
1552
|
-
q.
|
1590
|
+
q.breakable_force
|
1553
1591
|
q.text("end")
|
1554
1592
|
end
|
1555
1593
|
end
|
@@ -1592,10 +1630,10 @@ module SyntaxTree
|
|
1592
1630
|
q.text("^(")
|
1593
1631
|
q.nest(1) do
|
1594
1632
|
q.indent do
|
1595
|
-
q.
|
1633
|
+
q.breakable_empty
|
1596
1634
|
q.format(statement)
|
1597
1635
|
end
|
1598
|
-
q.
|
1636
|
+
q.breakable_empty
|
1599
1637
|
q.text(")")
|
1600
1638
|
end
|
1601
1639
|
end
|
@@ -1661,15 +1699,13 @@ module SyntaxTree
|
|
1661
1699
|
q.text(" ") unless power
|
1662
1700
|
|
1663
1701
|
if operator == :<<
|
1664
|
-
q.text(
|
1665
|
-
q.text(" ")
|
1702
|
+
q.text("<< ")
|
1666
1703
|
q.format(right)
|
1667
1704
|
else
|
1668
1705
|
q.group do
|
1669
|
-
q.text(operator.
|
1670
|
-
|
1706
|
+
q.text(operator.name)
|
1671
1707
|
q.indent do
|
1672
|
-
|
1708
|
+
power ? q.breakable_empty : q.breakable_space
|
1673
1709
|
q.format(right)
|
1674
1710
|
end
|
1675
1711
|
end
|
@@ -1716,15 +1752,29 @@ module SyntaxTree
|
|
1716
1752
|
{ params: params, locals: locals, location: location, comments: comments }
|
1717
1753
|
end
|
1718
1754
|
|
1755
|
+
# Within the pipes of the block declaration, we don't want any spaces. So
|
1756
|
+
# we'll separate the parameters with a comma and space but no breakables.
|
1757
|
+
class Separator
|
1758
|
+
def call(q)
|
1759
|
+
q.text(", ")
|
1760
|
+
end
|
1761
|
+
end
|
1762
|
+
|
1763
|
+
# We'll keep a single instance of this separator around for all block vars
|
1764
|
+
# to cut down on allocations.
|
1765
|
+
SEPARATOR = Separator.new
|
1766
|
+
|
1719
1767
|
def format(q)
|
1720
|
-
q.
|
1768
|
+
q.text("|")
|
1769
|
+
q.group do
|
1721
1770
|
q.remove_breaks(q.format(params))
|
1722
1771
|
|
1723
1772
|
if locals.any?
|
1724
1773
|
q.text("; ")
|
1725
|
-
q.seplist(locals,
|
1774
|
+
q.seplist(locals, SEPARATOR) { |local| q.format(local) }
|
1726
1775
|
end
|
1727
1776
|
end
|
1777
|
+
q.text("|")
|
1728
1778
|
end
|
1729
1779
|
end
|
1730
1780
|
|
@@ -1816,10 +1866,8 @@ module SyntaxTree
|
|
1816
1866
|
end_column: end_column
|
1817
1867
|
)
|
1818
1868
|
|
1819
|
-
parts = [rescue_clause, else_clause, ensure_clause]
|
1820
|
-
|
1821
1869
|
# Here we're going to determine the bounds for the statements
|
1822
|
-
consequent =
|
1870
|
+
consequent = rescue_clause || else_clause || ensure_clause
|
1823
1871
|
statements.bind(
|
1824
1872
|
start_char,
|
1825
1873
|
start_column,
|
@@ -1829,7 +1877,7 @@ module SyntaxTree
|
|
1829
1877
|
|
1830
1878
|
# Next we're going to determine the rescue clause if there is one
|
1831
1879
|
if rescue_clause
|
1832
|
-
consequent =
|
1880
|
+
consequent = else_clause || ensure_clause
|
1833
1881
|
rescue_clause.bind_end(
|
1834
1882
|
consequent ? consequent.location.start_char : end_char,
|
1835
1883
|
consequent ? consequent.location.start_column : end_column
|
@@ -1868,26 +1916,26 @@ module SyntaxTree
|
|
1868
1916
|
|
1869
1917
|
if rescue_clause
|
1870
1918
|
q.nest(-2) do
|
1871
|
-
q.
|
1919
|
+
q.breakable_force
|
1872
1920
|
q.format(rescue_clause)
|
1873
1921
|
end
|
1874
1922
|
end
|
1875
1923
|
|
1876
1924
|
if else_clause
|
1877
1925
|
q.nest(-2) do
|
1878
|
-
q.
|
1926
|
+
q.breakable_force
|
1879
1927
|
q.format(else_keyword)
|
1880
1928
|
end
|
1881
1929
|
|
1882
1930
|
unless else_clause.empty?
|
1883
|
-
q.
|
1931
|
+
q.breakable_force
|
1884
1932
|
q.format(else_clause)
|
1885
1933
|
end
|
1886
1934
|
end
|
1887
1935
|
|
1888
1936
|
if ensure_clause
|
1889
1937
|
q.nest(-2) do
|
1890
|
-
q.
|
1938
|
+
q.breakable_force
|
1891
1939
|
q.format(ensure_clause)
|
1892
1940
|
end
|
1893
1941
|
end
|
@@ -1955,12 +2003,11 @@ module SyntaxTree
|
|
1955
2003
|
# If the receiver of this block a Command or CommandCall node, then there
|
1956
2004
|
# are no parentheses around the arguments to that command, so we need to
|
1957
2005
|
# break the block.
|
1958
|
-
case q.parent
|
1959
|
-
|
2006
|
+
case q.parent.call
|
2007
|
+
when Command, CommandCall
|
1960
2008
|
q.break_parent
|
1961
2009
|
format_break(q, break_opening, break_closing)
|
1962
2010
|
return
|
1963
|
-
else
|
1964
2011
|
end
|
1965
2012
|
|
1966
2013
|
q.group do
|
@@ -1980,9 +2027,9 @@ module SyntaxTree
|
|
1980
2027
|
# know for certain we're going to get split over multiple lines
|
1981
2028
|
# anyway.
|
1982
2029
|
case parent
|
1983
|
-
|
2030
|
+
when Statements, ArgParen
|
1984
2031
|
break false
|
1985
|
-
|
2032
|
+
when Command, CommandCall
|
1986
2033
|
true
|
1987
2034
|
else
|
1988
2035
|
false
|
@@ -1993,8 +2040,8 @@ module SyntaxTree
|
|
1993
2040
|
# If we're a sibling of a control-flow keyword, then we're going to have to
|
1994
2041
|
# use the do..end bounds.
|
1995
2042
|
def forced_do_end_bounds?(q)
|
1996
|
-
case q.parent
|
1997
|
-
|
2043
|
+
case q.parent.call
|
2044
|
+
when Break, Next, Return, Super
|
1998
2045
|
true
|
1999
2046
|
else
|
2000
2047
|
false
|
@@ -2004,22 +2051,19 @@ module SyntaxTree
|
|
2004
2051
|
# If we're the predicate of a loop or conditional, then we're going to have
|
2005
2052
|
# to go with the {..} bounds.
|
2006
2053
|
def forced_brace_bounds?(q)
|
2007
|
-
|
2008
|
-
parents.
|
2009
|
-
|
2010
|
-
|
2054
|
+
previous = nil
|
2055
|
+
q.parents.any? do |parent|
|
2056
|
+
case parent
|
2057
|
+
when Paren, Statements
|
2058
|
+
# If we hit certain breakpoints then we know we're safe.
|
2059
|
+
return false
|
2060
|
+
when If, IfMod, IfOp, Unless, UnlessMod, While, WhileMod, Until,
|
2061
|
+
UntilMod
|
2062
|
+
return true if parent.predicate == previous
|
2063
|
+
end
|
2011
2064
|
|
2012
|
-
|
2013
|
-
|
2014
|
-
IfMod,
|
2015
|
-
IfOp,
|
2016
|
-
Unless,
|
2017
|
-
UnlessMod,
|
2018
|
-
While,
|
2019
|
-
WhileMod,
|
2020
|
-
Until,
|
2021
|
-
UntilMod
|
2022
|
-
].include?(parent.class) && parent.predicate == parents[index - 1]
|
2065
|
+
previous = parent
|
2066
|
+
false
|
2023
2067
|
end
|
2024
2068
|
end
|
2025
2069
|
|
@@ -2034,12 +2078,12 @@ module SyntaxTree
|
|
2034
2078
|
|
2035
2079
|
unless statements.empty?
|
2036
2080
|
q.indent do
|
2037
|
-
q.
|
2081
|
+
q.breakable_space
|
2038
2082
|
q.format(statements)
|
2039
2083
|
end
|
2040
2084
|
end
|
2041
2085
|
|
2042
|
-
q.
|
2086
|
+
q.breakable_space
|
2043
2087
|
q.text(closing)
|
2044
2088
|
end
|
2045
2089
|
|
@@ -2048,17 +2092,17 @@ module SyntaxTree
|
|
2048
2092
|
q.format(BlockOpenFormatter.new(opening, block_open), stackable: false)
|
2049
2093
|
|
2050
2094
|
if node.block_var
|
2051
|
-
q.
|
2095
|
+
q.breakable_space
|
2052
2096
|
q.format(node.block_var)
|
2053
|
-
q.
|
2097
|
+
q.breakable_space
|
2054
2098
|
end
|
2055
2099
|
|
2056
2100
|
if statements.empty?
|
2057
2101
|
q.text(" ") if opening == "do"
|
2058
2102
|
else
|
2059
|
-
q.
|
2103
|
+
q.breakable_space unless node.block_var
|
2060
2104
|
q.format(statements)
|
2061
|
-
q.
|
2105
|
+
q.breakable_space
|
2062
2106
|
end
|
2063
2107
|
|
2064
2108
|
q.text(closing)
|
@@ -2133,105 +2177,128 @@ module SyntaxTree
|
|
2133
2177
|
q.group do
|
2134
2178
|
q.text(keyword)
|
2135
2179
|
|
2136
|
-
|
2137
|
-
|
2180
|
+
parts = node.arguments.parts
|
2181
|
+
length = parts.length
|
2182
|
+
|
2183
|
+
if length == 0
|
2138
2184
|
# Here there are no arguments at all, so we're not going to print
|
2139
2185
|
# anything. This would be like if we had:
|
2140
2186
|
#
|
2141
2187
|
# break
|
2142
2188
|
#
|
2143
|
-
|
2144
|
-
Paren[
|
2145
|
-
contents: {
|
2146
|
-
body: [ArrayLiteral[contents: { parts: [_, _, *] }] => array] }
|
2147
|
-
]
|
2148
|
-
]
|
2149
|
-
# Here we have a single argument that is a set of parentheses wrapping
|
2150
|
-
# an array literal that has at least 2 elements. We're going to print
|
2151
|
-
# the contents of the array directly. This would be like if we had:
|
2152
|
-
#
|
2153
|
-
# break([1, 2, 3])
|
2154
|
-
#
|
2155
|
-
# which we will print as:
|
2156
|
-
#
|
2157
|
-
# break 1, 2, 3
|
2158
|
-
#
|
2159
|
-
q.text(" ")
|
2160
|
-
format_array_contents(q, array)
|
2161
|
-
in [Paren[contents: { body: [ArrayLiteral => statement] }]]
|
2162
|
-
# Here we have a single argument that is a set of parentheses wrapping
|
2163
|
-
# an array literal that has 0 or 1 elements. We're going to skip the
|
2164
|
-
# parentheses but print the array itself. This would be like if we
|
2165
|
-
# had:
|
2166
|
-
#
|
2167
|
-
# break([1])
|
2168
|
-
#
|
2169
|
-
# which we will print as:
|
2170
|
-
#
|
2171
|
-
# break [1]
|
2172
|
-
#
|
2173
|
-
q.text(" ")
|
2174
|
-
q.format(statement)
|
2175
|
-
in [Paren[contents: { body: [statement] }]] if skip_parens?(statement)
|
2176
|
-
# Here we have a single argument that is a set of parentheses that
|
2177
|
-
# themselves contain a single statement. That statement is a simple
|
2178
|
-
# value that we can skip the parentheses for. This would be like if we
|
2179
|
-
# had:
|
2180
|
-
#
|
2181
|
-
# break(1)
|
2182
|
-
#
|
2183
|
-
# which we will print as:
|
2184
|
-
#
|
2185
|
-
# break 1
|
2186
|
-
#
|
2187
|
-
q.text(" ")
|
2188
|
-
q.format(statement)
|
2189
|
-
in [Paren => part]
|
2190
|
-
# Here we have a single argument that is a set of parentheses. We're
|
2191
|
-
# going to print the parentheses themselves as if they were the set of
|
2192
|
-
# arguments. This would be like if we had:
|
2193
|
-
#
|
2194
|
-
# break(foo.bar)
|
2195
|
-
#
|
2196
|
-
q.format(part)
|
2197
|
-
in [ArrayLiteral[contents: { parts: [_, _, *] }] => array]
|
2198
|
-
# Here there is a single argument that is an array literal with at
|
2199
|
-
# least two elements. We skip directly into the array literal's
|
2200
|
-
# elements in order to print the contents. This would be like if we
|
2201
|
-
# had:
|
2202
|
-
#
|
2203
|
-
# break [1, 2, 3]
|
2204
|
-
#
|
2205
|
-
# which we will print as:
|
2206
|
-
#
|
2207
|
-
# break 1, 2, 3
|
2208
|
-
#
|
2209
|
-
q.text(" ")
|
2210
|
-
format_array_contents(q, array)
|
2211
|
-
in [ArrayLiteral => part]
|
2212
|
-
# Here there is a single argument that is an array literal with 0 or 1
|
2213
|
-
# elements. In this case we're going to print the array as it is
|
2214
|
-
# because skipping the brackets would change the remaining. This would
|
2215
|
-
# be like if we had:
|
2216
|
-
#
|
2217
|
-
# break []
|
2218
|
-
# break [1]
|
2219
|
-
#
|
2220
|
-
q.text(" ")
|
2221
|
-
q.format(part)
|
2222
|
-
in [_]
|
2223
|
-
# Here there is a single argument that hasn't matched one of our
|
2224
|
-
# previous cases. We're going to print the argument as it is. This
|
2225
|
-
# would be like if we had:
|
2226
|
-
#
|
2227
|
-
# break foo
|
2228
|
-
#
|
2229
|
-
format_arguments(q, "(", ")")
|
2230
|
-
else
|
2189
|
+
elsif length >= 2
|
2231
2190
|
# If there are multiple arguments, format them all. If the line is
|
2232
2191
|
# going to break into multiple, then use brackets to start and end the
|
2233
2192
|
# expression.
|
2234
2193
|
format_arguments(q, " [", "]")
|
2194
|
+
else
|
2195
|
+
# If we get here, then we're formatting a single argument to the flow
|
2196
|
+
# control keyword.
|
2197
|
+
part = parts.first
|
2198
|
+
|
2199
|
+
case part
|
2200
|
+
when Paren
|
2201
|
+
statements = part.contents.body
|
2202
|
+
|
2203
|
+
if statements.length == 1
|
2204
|
+
statement = statements.first
|
2205
|
+
|
2206
|
+
if statement.is_a?(ArrayLiteral)
|
2207
|
+
contents = statement.contents
|
2208
|
+
|
2209
|
+
if contents && contents.parts.length >= 2
|
2210
|
+
# Here we have a single argument that is a set of parentheses
|
2211
|
+
# wrapping an array literal that has at least 2 elements.
|
2212
|
+
# We're going to print the contents of the array directly.
|
2213
|
+
# This would be like if we had:
|
2214
|
+
#
|
2215
|
+
# break([1, 2, 3])
|
2216
|
+
#
|
2217
|
+
# which we will print as:
|
2218
|
+
#
|
2219
|
+
# break 1, 2, 3
|
2220
|
+
#
|
2221
|
+
q.text(" ")
|
2222
|
+
format_array_contents(q, statement)
|
2223
|
+
else
|
2224
|
+
# Here we have a single argument that is a set of parentheses
|
2225
|
+
# wrapping an array literal that has 0 or 1 elements. We're
|
2226
|
+
# going to skip the parentheses but print the array itself.
|
2227
|
+
# This would be like if we had:
|
2228
|
+
#
|
2229
|
+
# break([1])
|
2230
|
+
#
|
2231
|
+
# which we will print as:
|
2232
|
+
#
|
2233
|
+
# break [1]
|
2234
|
+
#
|
2235
|
+
q.text(" ")
|
2236
|
+
q.format(statement)
|
2237
|
+
end
|
2238
|
+
elsif skip_parens?(statement)
|
2239
|
+
# Here we have a single argument that is a set of parentheses
|
2240
|
+
# that themselves contain a single statement. That statement is
|
2241
|
+
# a simple value that we can skip the parentheses for. This
|
2242
|
+
# would be like if we had:
|
2243
|
+
#
|
2244
|
+
# break(1)
|
2245
|
+
#
|
2246
|
+
# which we will print as:
|
2247
|
+
#
|
2248
|
+
# break 1
|
2249
|
+
#
|
2250
|
+
q.text(" ")
|
2251
|
+
q.format(statement)
|
2252
|
+
else
|
2253
|
+
# Here we have a single argument that is a set of parentheses.
|
2254
|
+
# We're going to print the parentheses themselves as if they
|
2255
|
+
# were the set of arguments. This would be like if we had:
|
2256
|
+
#
|
2257
|
+
# break(foo.bar)
|
2258
|
+
#
|
2259
|
+
q.format(part)
|
2260
|
+
end
|
2261
|
+
else
|
2262
|
+
q.format(part)
|
2263
|
+
end
|
2264
|
+
when ArrayLiteral
|
2265
|
+
contents = part.contents
|
2266
|
+
|
2267
|
+
if contents && contents.parts.length >= 2
|
2268
|
+
# Here there is a single argument that is an array literal with at
|
2269
|
+
# least two elements. We skip directly into the array literal's
|
2270
|
+
# elements in order to print the contents. This would be like if
|
2271
|
+
# we had:
|
2272
|
+
#
|
2273
|
+
# break [1, 2, 3]
|
2274
|
+
#
|
2275
|
+
# which we will print as:
|
2276
|
+
#
|
2277
|
+
# break 1, 2, 3
|
2278
|
+
#
|
2279
|
+
q.text(" ")
|
2280
|
+
format_array_contents(q, part)
|
2281
|
+
else
|
2282
|
+
# Here there is a single argument that is an array literal with 0
|
2283
|
+
# or 1 elements. In this case we're going to print the array as it
|
2284
|
+
# is because skipping the brackets would change the remaining.
|
2285
|
+
# This would be like if we had:
|
2286
|
+
#
|
2287
|
+
# break []
|
2288
|
+
# break [1]
|
2289
|
+
#
|
2290
|
+
q.text(" ")
|
2291
|
+
q.format(part)
|
2292
|
+
end
|
2293
|
+
else
|
2294
|
+
# Here there is a single argument that hasn't matched one of our
|
2295
|
+
# previous cases. We're going to print the argument as it is. This
|
2296
|
+
# would be like if we had:
|
2297
|
+
#
|
2298
|
+
# break foo
|
2299
|
+
#
|
2300
|
+
format_arguments(q, "(", ")")
|
2301
|
+
end
|
2235
2302
|
end
|
2236
2303
|
end
|
2237
2304
|
end
|
@@ -2241,29 +2308,34 @@ module SyntaxTree
|
|
2241
2308
|
def format_array_contents(q, array)
|
2242
2309
|
q.if_break { q.text("[") }
|
2243
2310
|
q.indent do
|
2244
|
-
q.
|
2311
|
+
q.breakable_empty
|
2245
2312
|
q.format(array.contents)
|
2246
2313
|
end
|
2247
|
-
q.
|
2314
|
+
q.breakable_empty
|
2248
2315
|
q.if_break { q.text("]") }
|
2249
2316
|
end
|
2250
2317
|
|
2251
2318
|
def format_arguments(q, opening, closing)
|
2252
2319
|
q.if_break { q.text(opening) }
|
2253
2320
|
q.indent do
|
2254
|
-
q.
|
2321
|
+
q.breakable_space
|
2255
2322
|
q.format(node.arguments)
|
2256
2323
|
end
|
2257
|
-
q.
|
2324
|
+
q.breakable_empty
|
2258
2325
|
q.if_break { q.text(closing) }
|
2259
2326
|
end
|
2260
2327
|
|
2261
2328
|
def skip_parens?(node)
|
2262
2329
|
case node
|
2263
|
-
|
2264
|
-
true
|
2265
|
-
in VarRef[value: Const | CVar | GVar | IVar | Kw]
|
2330
|
+
when FloatLiteral, Imaginary, Int, RationalLiteral
|
2266
2331
|
true
|
2332
|
+
when VarRef
|
2333
|
+
case node.value
|
2334
|
+
when Const, CVar, GVar, IVar, Kw
|
2335
|
+
true
|
2336
|
+
else
|
2337
|
+
false
|
2338
|
+
end
|
2267
2339
|
else
|
2268
2340
|
false
|
2269
2341
|
end
|
@@ -2326,8 +2398,10 @@ module SyntaxTree
|
|
2326
2398
|
|
2327
2399
|
def format(q)
|
2328
2400
|
case operator
|
2329
|
-
|
2401
|
+
when :"::"
|
2330
2402
|
q.text(".")
|
2403
|
+
when Op
|
2404
|
+
operator.value == "::" ? q.text(".") : operator.format(q)
|
2331
2405
|
else
|
2332
2406
|
operator.format(q)
|
2333
2407
|
end
|
@@ -2363,13 +2437,18 @@ module SyntaxTree
|
|
2363
2437
|
# First, walk down the chain until we get to the point where we're not
|
2364
2438
|
# longer at a chainable node.
|
2365
2439
|
loop do
|
2366
|
-
case children.last
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2440
|
+
case (child = children.last)
|
2441
|
+
when Call
|
2442
|
+
case (receiver = child.receiver)
|
2443
|
+
when Call
|
2444
|
+
children << receiver
|
2445
|
+
when MethodAddBlock
|
2446
|
+
receiver.call.is_a?(Call) ? children << receiver : break
|
2447
|
+
else
|
2448
|
+
break
|
2449
|
+
end
|
2450
|
+
when MethodAddBlock
|
2451
|
+
child.call.is_a?(Call) ? children << child.call : break
|
2373
2452
|
else
|
2374
2453
|
break
|
2375
2454
|
end
|
@@ -2388,10 +2467,9 @@ module SyntaxTree
|
|
2388
2467
|
# nodes.
|
2389
2468
|
parent = parents[3] if parent.is_a?(DoBlock)
|
2390
2469
|
|
2391
|
-
|
2392
|
-
|
2470
|
+
if parent.is_a?(MethodAddBlock) && parent.call.is_a?(FCall) &&
|
2471
|
+
parent.call.value.value == "sig"
|
2393
2472
|
threshold = 2
|
2394
|
-
else
|
2395
2473
|
end
|
2396
2474
|
end
|
2397
2475
|
|
@@ -2434,20 +2512,21 @@ module SyntaxTree
|
|
2434
2512
|
skip_operator = false
|
2435
2513
|
|
2436
2514
|
while (child = children.pop)
|
2437
|
-
|
2438
|
-
|
2439
|
-
|
2440
|
-
|
2441
|
-
|
2442
|
-
|
2443
|
-
|
2444
|
-
|
2445
|
-
|
2446
|
-
|
2447
|
-
|
2448
|
-
|
2449
|
-
|
2450
|
-
|
2515
|
+
if child.is_a?(Call)
|
2516
|
+
if child.receiver.is_a?(Call) &&
|
2517
|
+
(child.receiver.message != :call) &&
|
2518
|
+
(child.receiver.message.value == "where") &&
|
2519
|
+
(child.message.value == "not")
|
2520
|
+
# This is very specialized behavior wherein we group
|
2521
|
+
# .where.not calls together because it looks better. For more
|
2522
|
+
# information, see
|
2523
|
+
# https://github.com/prettier/plugin-ruby/issues/862.
|
2524
|
+
else
|
2525
|
+
# If we're at a Call node and not a MethodAddBlock node in the
|
2526
|
+
# chain then we're going to add a newline so it indents
|
2527
|
+
# properly.
|
2528
|
+
q.breakable_empty
|
2529
|
+
end
|
2451
2530
|
end
|
2452
2531
|
|
2453
2532
|
format_child(
|
@@ -2460,9 +2539,9 @@ module SyntaxTree
|
|
2460
2539
|
|
2461
2540
|
# If the parent call node has a comment on the message then we need
|
2462
2541
|
# to print the operator trailing in order to keep it working.
|
2463
|
-
|
2464
|
-
|
2465
|
-
q.format(CallOperatorFormatter.new(operator))
|
2542
|
+
last_child = children.last
|
2543
|
+
if last_child.is_a?(Call) && last_child.message.comments.any?
|
2544
|
+
q.format(CallOperatorFormatter.new(last_child.operator))
|
2466
2545
|
skip_operator = true
|
2467
2546
|
else
|
2468
2547
|
skip_operator = false
|
@@ -2477,18 +2556,22 @@ module SyntaxTree
|
|
2477
2556
|
|
2478
2557
|
if empty_except_last
|
2479
2558
|
case node
|
2480
|
-
|
2559
|
+
when Call
|
2481
2560
|
node.format_arguments(q)
|
2482
|
-
|
2483
|
-
q.format(block)
|
2561
|
+
when MethodAddBlock
|
2562
|
+
q.format(node.block)
|
2484
2563
|
end
|
2485
2564
|
end
|
2486
2565
|
end
|
2487
2566
|
|
2488
2567
|
def self.chained?(node)
|
2568
|
+
return false if ENV["STREE_FAST_FORMAT"]
|
2569
|
+
|
2489
2570
|
case node
|
2490
|
-
|
2571
|
+
when Call
|
2491
2572
|
true
|
2573
|
+
when MethodAddBlock
|
2574
|
+
node.call.is_a?(Call)
|
2492
2575
|
else
|
2493
2576
|
false
|
2494
2577
|
end
|
@@ -2500,9 +2583,12 @@ module SyntaxTree
|
|
2500
2583
|
# want to indent the first call. So we'll pop off the first children and
|
2501
2584
|
# format it separately here.
|
2502
2585
|
def attach_directly?(node)
|
2503
|
-
|
2504
|
-
|
2505
|
-
|
2586
|
+
case node.receiver
|
2587
|
+
when ArrayLiteral, HashLiteral, Heredoc, If, Unless, XStringLiteral
|
2588
|
+
true
|
2589
|
+
else
|
2590
|
+
false
|
2591
|
+
end
|
2506
2592
|
end
|
2507
2593
|
|
2508
2594
|
def format_child(
|
@@ -2514,7 +2600,7 @@ module SyntaxTree
|
|
2514
2600
|
)
|
2515
2601
|
# First, format the actual contents of the child.
|
2516
2602
|
case child
|
2517
|
-
|
2603
|
+
when Call
|
2518
2604
|
q.group do
|
2519
2605
|
unless skip_operator
|
2520
2606
|
q.format(CallOperatorFormatter.new(child.operator))
|
@@ -2522,7 +2608,7 @@ module SyntaxTree
|
|
2522
2608
|
q.format(child.message) if child.message != :call
|
2523
2609
|
child.format_arguments(q) unless skip_attached
|
2524
2610
|
end
|
2525
|
-
|
2611
|
+
when MethodAddBlock
|
2526
2612
|
q.format(child.block) unless skip_attached
|
2527
2613
|
end
|
2528
2614
|
|
@@ -2530,7 +2616,7 @@ module SyntaxTree
|
|
2530
2616
|
# them out here since we're bypassing the normal comment printing.
|
2531
2617
|
if child.comments.any? && !skip_comments
|
2532
2618
|
child.comments.each do |comment|
|
2533
|
-
comment.inline? ? q.text(" ") : q.
|
2619
|
+
comment.inline? ? q.text(" ") : q.breakable_space
|
2534
2620
|
comment.format(q)
|
2535
2621
|
end
|
2536
2622
|
|
@@ -2605,8 +2691,8 @@ module SyntaxTree
|
|
2605
2691
|
# If we're at the top of a call chain, then we're going to do some
|
2606
2692
|
# specialized printing in case we can print it nicely. We _only_ do this
|
2607
2693
|
# at the top of the chain to avoid weird recursion issues.
|
2608
|
-
if
|
2609
|
-
CallChainFormatter.chained?(
|
2694
|
+
if CallChainFormatter.chained?(receiver) &&
|
2695
|
+
!CallChainFormatter.chained?(q.parent)
|
2610
2696
|
q.group do
|
2611
2697
|
q
|
2612
2698
|
.if_break { CallChainFormatter.new(self).format(q) }
|
@@ -2617,15 +2703,15 @@ module SyntaxTree
|
|
2617
2703
|
end
|
2618
2704
|
end
|
2619
2705
|
|
2706
|
+
# Print out the arguments to this call. If there are no arguments, then do
|
2707
|
+
#nothing.
|
2620
2708
|
def format_arguments(q)
|
2621
2709
|
case arguments
|
2622
|
-
|
2710
|
+
when ArgParen
|
2623
2711
|
q.format(arguments)
|
2624
|
-
|
2712
|
+
when Args
|
2625
2713
|
q.text(" ")
|
2626
2714
|
q.format(arguments)
|
2627
|
-
else
|
2628
|
-
# Do nothing if there are no arguments.
|
2629
2715
|
end
|
2630
2716
|
end
|
2631
2717
|
|
@@ -2642,7 +2728,7 @@ module SyntaxTree
|
|
2642
2728
|
q.group do
|
2643
2729
|
q.indent do
|
2644
2730
|
if receiver.comments.any? || call_operator.comments.any?
|
2645
|
-
q.
|
2731
|
+
q.breakable_force
|
2646
2732
|
end
|
2647
2733
|
|
2648
2734
|
if call_operator.comments.empty?
|
@@ -2719,9 +2805,9 @@ module SyntaxTree
|
|
2719
2805
|
q.format(value)
|
2720
2806
|
end
|
2721
2807
|
|
2722
|
-
q.
|
2808
|
+
q.breakable_force
|
2723
2809
|
q.format(consequent)
|
2724
|
-
q.
|
2810
|
+
q.breakable_force
|
2725
2811
|
|
2726
2812
|
q.text("end")
|
2727
2813
|
end
|
@@ -2782,13 +2868,13 @@ module SyntaxTree
|
|
2782
2868
|
q.format(operator)
|
2783
2869
|
|
2784
2870
|
case pattern
|
2785
|
-
|
2871
|
+
when AryPtn, FndPtn, HshPtn
|
2786
2872
|
q.text(" ")
|
2787
2873
|
q.format(pattern)
|
2788
2874
|
else
|
2789
2875
|
q.group do
|
2790
2876
|
q.indent do
|
2791
|
-
q.
|
2877
|
+
q.breakable_space
|
2792
2878
|
q.format(pattern)
|
2793
2879
|
end
|
2794
2880
|
end
|
@@ -2872,38 +2958,40 @@ module SyntaxTree
|
|
2872
2958
|
end
|
2873
2959
|
|
2874
2960
|
def format(q)
|
2875
|
-
declaration = -> do
|
2876
|
-
q.group do
|
2877
|
-
q.text("class ")
|
2878
|
-
q.format(constant)
|
2879
|
-
|
2880
|
-
if superclass
|
2881
|
-
q.text(" < ")
|
2882
|
-
q.format(superclass)
|
2883
|
-
end
|
2884
|
-
end
|
2885
|
-
end
|
2886
|
-
|
2887
2961
|
if bodystmt.empty?
|
2888
2962
|
q.group do
|
2889
|
-
|
2890
|
-
q.
|
2963
|
+
format_declaration(q)
|
2964
|
+
q.breakable_force
|
2891
2965
|
q.text("end")
|
2892
2966
|
end
|
2893
2967
|
else
|
2894
2968
|
q.group do
|
2895
|
-
|
2969
|
+
format_declaration(q)
|
2896
2970
|
|
2897
2971
|
q.indent do
|
2898
|
-
q.
|
2972
|
+
q.breakable_force
|
2899
2973
|
q.format(bodystmt)
|
2900
2974
|
end
|
2901
2975
|
|
2902
|
-
q.
|
2976
|
+
q.breakable_force
|
2903
2977
|
q.text("end")
|
2904
2978
|
end
|
2905
2979
|
end
|
2906
2980
|
end
|
2981
|
+
|
2982
|
+
private
|
2983
|
+
|
2984
|
+
def format_declaration(q)
|
2985
|
+
q.group do
|
2986
|
+
q.text("class ")
|
2987
|
+
q.format(constant)
|
2988
|
+
|
2989
|
+
if superclass
|
2990
|
+
q.text(" < ")
|
2991
|
+
q.format(superclass)
|
2992
|
+
end
|
2993
|
+
end
|
2994
|
+
end
|
2907
2995
|
end
|
2908
2996
|
|
2909
2997
|
# Comma represents the use of the , operator.
|
@@ -2983,15 +3071,31 @@ module SyntaxTree
|
|
2983
3071
|
private
|
2984
3072
|
|
2985
3073
|
def align(q, node, &block)
|
2986
|
-
|
2987
|
-
|
2988
|
-
|
2989
|
-
|
2990
|
-
|
2991
|
-
|
2992
|
-
|
2993
|
-
|
2994
|
-
|
3074
|
+
arguments = node.arguments
|
3075
|
+
|
3076
|
+
if arguments.is_a?(Args)
|
3077
|
+
parts = arguments.parts
|
3078
|
+
|
3079
|
+
if parts.size == 1
|
3080
|
+
part = parts.first
|
3081
|
+
|
3082
|
+
case part
|
3083
|
+
when Def, Defs, DefEndless
|
3084
|
+
q.text(" ")
|
3085
|
+
yield
|
3086
|
+
when IfOp
|
3087
|
+
q.if_flat { q.text(" ") }
|
3088
|
+
yield
|
3089
|
+
when Command
|
3090
|
+
align(q, part, &block)
|
3091
|
+
else
|
3092
|
+
q.text(" ")
|
3093
|
+
q.nest(message.value.length + 1) { yield }
|
3094
|
+
end
|
3095
|
+
else
|
3096
|
+
q.text(" ")
|
3097
|
+
q.nest(message.value.length + 1) { yield }
|
3098
|
+
end
|
2995
3099
|
else
|
2996
3100
|
q.text(" ")
|
2997
3101
|
q.nest(message.value.length + 1) { yield }
|
@@ -3069,7 +3173,7 @@ module SyntaxTree
|
|
3069
3173
|
if message.comments.any?(&:leading?)
|
3070
3174
|
q.format(CallOperatorFormatter.new(operator), stackable: false)
|
3071
3175
|
q.indent do
|
3072
|
-
q.
|
3176
|
+
q.breakable_empty
|
3073
3177
|
q.format(message)
|
3074
3178
|
end
|
3075
3179
|
else
|
@@ -3078,15 +3182,18 @@ module SyntaxTree
|
|
3078
3182
|
end
|
3079
3183
|
end
|
3080
3184
|
|
3081
|
-
|
3082
|
-
|
3083
|
-
|
3084
|
-
|
3085
|
-
|
3086
|
-
|
3087
|
-
|
3088
|
-
|
3089
|
-
|
3185
|
+
# Format the arguments for this command call here. If there are no
|
3186
|
+
# arguments, then print nothing.
|
3187
|
+
if arguments
|
3188
|
+
parts = arguments.parts
|
3189
|
+
|
3190
|
+
if parts.length == 1 && parts.first.is_a?(IfOp)
|
3191
|
+
q.if_flat { q.text(" ") }
|
3192
|
+
q.format(arguments)
|
3193
|
+
else
|
3194
|
+
q.text(" ")
|
3195
|
+
q.nest(argument_alignment(q, doc)) { q.format(arguments) }
|
3196
|
+
end
|
3090
3197
|
end
|
3091
3198
|
end
|
3092
3199
|
end
|
@@ -3155,7 +3262,7 @@ module SyntaxTree
|
|
3155
3262
|
end
|
3156
3263
|
|
3157
3264
|
def ignore?
|
3158
|
-
value
|
3265
|
+
value.match?(/\A#\s*stree-ignore\s*\z/)
|
3159
3266
|
end
|
3160
3267
|
|
3161
3268
|
def comments
|
@@ -3455,12 +3562,12 @@ module SyntaxTree
|
|
3455
3562
|
|
3456
3563
|
unless bodystmt.empty?
|
3457
3564
|
q.indent do
|
3458
|
-
q.
|
3565
|
+
q.breakable_force
|
3459
3566
|
q.format(bodystmt)
|
3460
3567
|
end
|
3461
3568
|
end
|
3462
3569
|
|
3463
|
-
q.
|
3570
|
+
q.breakable_force
|
3464
3571
|
q.text("end")
|
3465
3572
|
end
|
3466
3573
|
end
|
@@ -3549,7 +3656,7 @@ module SyntaxTree
|
|
3549
3656
|
q.text(" =")
|
3550
3657
|
q.group do
|
3551
3658
|
q.indent do
|
3552
|
-
q.
|
3659
|
+
q.breakable_space
|
3553
3660
|
q.format(statement)
|
3554
3661
|
end
|
3555
3662
|
end
|
@@ -3590,13 +3697,15 @@ module SyntaxTree
|
|
3590
3697
|
end
|
3591
3698
|
|
3592
3699
|
def format(q)
|
3593
|
-
q.
|
3700
|
+
q.text("defined?(")
|
3701
|
+
q.group do
|
3594
3702
|
q.indent do
|
3595
|
-
q.
|
3703
|
+
q.breakable_empty
|
3596
3704
|
q.format(value)
|
3597
3705
|
end
|
3598
|
-
q.
|
3706
|
+
q.breakable_empty
|
3599
3707
|
end
|
3708
|
+
q.text(")")
|
3600
3709
|
end
|
3601
3710
|
end
|
3602
3711
|
|
@@ -3678,12 +3787,12 @@ module SyntaxTree
|
|
3678
3787
|
|
3679
3788
|
unless bodystmt.empty?
|
3680
3789
|
q.indent do
|
3681
|
-
q.
|
3790
|
+
q.breakable_force
|
3682
3791
|
q.format(bodystmt)
|
3683
3792
|
end
|
3684
3793
|
end
|
3685
3794
|
|
3686
|
-
q.
|
3795
|
+
q.breakable_force
|
3687
3796
|
q.text("end")
|
3688
3797
|
end
|
3689
3798
|
end
|
@@ -3755,15 +3864,18 @@ module SyntaxTree
|
|
3755
3864
|
end
|
3756
3865
|
|
3757
3866
|
def format(q)
|
3758
|
-
space = [If, IfMod, Unless, UnlessMod].include?(q.parent.class)
|
3759
|
-
|
3760
3867
|
left = node.left
|
3761
3868
|
right = node.right
|
3762
3869
|
|
3763
3870
|
q.format(left) if left
|
3764
|
-
|
3765
|
-
q.
|
3766
|
-
|
3871
|
+
|
3872
|
+
case q.parent
|
3873
|
+
when If, IfMod, Unless, UnlessMod
|
3874
|
+
q.text(" #{operator} ")
|
3875
|
+
else
|
3876
|
+
q.text(operator)
|
3877
|
+
end
|
3878
|
+
|
3767
3879
|
q.format(right) if right
|
3768
3880
|
end
|
3769
3881
|
end
|
@@ -3948,19 +4060,30 @@ module SyntaxTree
|
|
3948
4060
|
def format(q)
|
3949
4061
|
opening_quote, closing_quote = quotes(q)
|
3950
4062
|
|
3951
|
-
q.
|
4063
|
+
q.text(opening_quote)
|
4064
|
+
q.group do
|
3952
4065
|
parts.each do |part|
|
3953
4066
|
if part.is_a?(TStringContent)
|
3954
4067
|
value = Quotes.normalize(part.value, closing_quote)
|
3955
|
-
|
3956
|
-
|
3957
|
-
|
4068
|
+
first = true
|
4069
|
+
|
4070
|
+
value.each_line(chomp: true) do |line|
|
4071
|
+
if first
|
4072
|
+
first = false
|
4073
|
+
else
|
4074
|
+
q.breakable_return
|
4075
|
+
end
|
4076
|
+
|
4077
|
+
q.text(line)
|
3958
4078
|
end
|
4079
|
+
|
4080
|
+
q.breakable_return if value.end_with?("\n")
|
3959
4081
|
else
|
3960
4082
|
q.format(part)
|
3961
4083
|
end
|
3962
4084
|
end
|
3963
4085
|
end
|
4086
|
+
q.text(closing_quote)
|
3964
4087
|
end
|
3965
4088
|
|
3966
4089
|
private
|
@@ -4056,7 +4179,7 @@ module SyntaxTree
|
|
4056
4179
|
|
4057
4180
|
unless statements.empty?
|
4058
4181
|
q.indent do
|
4059
|
-
q.
|
4182
|
+
q.breakable_force
|
4060
4183
|
q.format(statements)
|
4061
4184
|
end
|
4062
4185
|
end
|
@@ -4126,14 +4249,14 @@ module SyntaxTree
|
|
4126
4249
|
|
4127
4250
|
unless statements.empty?
|
4128
4251
|
q.indent do
|
4129
|
-
q.
|
4252
|
+
q.breakable_force
|
4130
4253
|
q.format(statements)
|
4131
4254
|
end
|
4132
4255
|
end
|
4133
4256
|
|
4134
4257
|
if consequent
|
4135
4258
|
q.group do
|
4136
|
-
q.
|
4259
|
+
q.breakable_force
|
4137
4260
|
q.format(consequent)
|
4138
4261
|
end
|
4139
4262
|
end
|
@@ -4329,7 +4452,7 @@ module SyntaxTree
|
|
4329
4452
|
|
4330
4453
|
unless statements.empty?
|
4331
4454
|
q.indent do
|
4332
|
-
q.
|
4455
|
+
q.breakable_force
|
4333
4456
|
q.format(statements)
|
4334
4457
|
end
|
4335
4458
|
end
|
@@ -4588,7 +4711,7 @@ module SyntaxTree
|
|
4588
4711
|
q.text("[")
|
4589
4712
|
|
4590
4713
|
q.indent do
|
4591
|
-
q.
|
4714
|
+
q.breakable_empty
|
4592
4715
|
|
4593
4716
|
q.text("*")
|
4594
4717
|
q.format(left)
|
@@ -4601,7 +4724,7 @@ module SyntaxTree
|
|
4601
4724
|
q.format(right)
|
4602
4725
|
end
|
4603
4726
|
|
4604
|
-
q.
|
4727
|
+
q.breakable_empty
|
4605
4728
|
q.text("]")
|
4606
4729
|
end
|
4607
4730
|
end
|
@@ -4663,12 +4786,12 @@ module SyntaxTree
|
|
4663
4786
|
|
4664
4787
|
unless statements.empty?
|
4665
4788
|
q.indent do
|
4666
|
-
q.
|
4789
|
+
q.breakable_force
|
4667
4790
|
q.format(statements)
|
4668
4791
|
end
|
4669
4792
|
end
|
4670
4793
|
|
4671
|
-
q.
|
4794
|
+
q.breakable_force
|
4672
4795
|
q.text("end")
|
4673
4796
|
end
|
4674
4797
|
end
|
@@ -4731,11 +4854,11 @@ module SyntaxTree
|
|
4731
4854
|
q.text("{")
|
4732
4855
|
q.indent do
|
4733
4856
|
lbrace.comments.each do |comment|
|
4734
|
-
q.
|
4857
|
+
q.breakable_force
|
4735
4858
|
comment.format(q)
|
4736
4859
|
end
|
4737
4860
|
end
|
4738
|
-
q.
|
4861
|
+
q.breakable_force
|
4739
4862
|
q.text("}")
|
4740
4863
|
end
|
4741
4864
|
end
|
@@ -4800,14 +4923,14 @@ module SyntaxTree
|
|
4800
4923
|
q.format(lbrace)
|
4801
4924
|
|
4802
4925
|
if assocs.empty?
|
4803
|
-
q.
|
4926
|
+
q.breakable_empty
|
4804
4927
|
else
|
4805
4928
|
q.indent do
|
4806
|
-
q.
|
4929
|
+
q.breakable_space
|
4807
4930
|
q.seplist(assocs) { |assoc| q.format(assoc) }
|
4808
4931
|
q.if_break { q.text(",") } if q.trailing_comma?
|
4809
4932
|
end
|
4810
|
-
q.
|
4933
|
+
q.breakable_space
|
4811
4934
|
end
|
4812
4935
|
|
4813
4936
|
q.text("}")
|
@@ -4873,22 +4996,34 @@ module SyntaxTree
|
|
4873
4996
|
}
|
4874
4997
|
end
|
4875
4998
|
|
4876
|
-
|
4877
|
-
|
4878
|
-
|
4879
|
-
breakable = -> { q.breakable(indent: false, force: :skip_break_parent) }
|
4999
|
+
# This is a very specific behavior where you want to force a newline, but
|
5000
|
+
# don't want to force the break parent.
|
5001
|
+
SEPARATOR = PrettierPrint::Breakable.new(" ", 1, indent: false, force: true)
|
4880
5002
|
|
5003
|
+
def format(q)
|
4881
5004
|
q.group do
|
4882
5005
|
q.format(beginning)
|
4883
5006
|
|
4884
5007
|
q.line_suffix(priority: Formatter::HEREDOC_PRIORITY) do
|
4885
5008
|
q.group do
|
4886
|
-
|
5009
|
+
q.target << SEPARATOR
|
4887
5010
|
|
4888
5011
|
parts.each do |part|
|
4889
5012
|
if part.is_a?(TStringContent)
|
4890
|
-
|
4891
|
-
|
5013
|
+
value = part.value
|
5014
|
+
first = true
|
5015
|
+
|
5016
|
+
value.each_line(chomp: true) do |line|
|
5017
|
+
if first
|
5018
|
+
first = false
|
5019
|
+
else
|
5020
|
+
q.target << SEPARATOR
|
5021
|
+
end
|
5022
|
+
|
5023
|
+
q.text(line)
|
5024
|
+
end
|
5025
|
+
|
5026
|
+
q.target << SEPARATOR if value.end_with?("\n")
|
4892
5027
|
else
|
4893
5028
|
q.format(part)
|
4894
5029
|
end
|
@@ -5077,18 +5212,7 @@ module SyntaxTree
|
|
5077
5212
|
def format(q)
|
5078
5213
|
parts = keywords.map { |(key, value)| KeywordFormatter.new(key, value) }
|
5079
5214
|
parts << KeywordRestFormatter.new(keyword_rest) if keyword_rest
|
5080
|
-
|
5081
5215
|
nested = PATTERNS.include?(q.parent.class)
|
5082
|
-
contents = -> do
|
5083
|
-
q.group { q.seplist(parts) { |part| q.format(part, stackable: false) } }
|
5084
|
-
|
5085
|
-
# If there isn't a constant, and there's a blank keyword_rest, then we
|
5086
|
-
# have an plain ** that needs to have a `then` after it in order to
|
5087
|
-
# parse correctly on the next parse.
|
5088
|
-
if !constant && keyword_rest && keyword_rest.value.nil? && !nested
|
5089
|
-
q.text(" then")
|
5090
|
-
end
|
5091
|
-
end
|
5092
5216
|
|
5093
5217
|
# If there is a constant, we're going to format to have the constant name
|
5094
5218
|
# first and then use brackets.
|
@@ -5097,10 +5221,10 @@ module SyntaxTree
|
|
5097
5221
|
q.format(constant)
|
5098
5222
|
q.text("[")
|
5099
5223
|
q.indent do
|
5100
|
-
q.
|
5101
|
-
|
5224
|
+
q.breakable_empty
|
5225
|
+
format_contents(q, parts, nested)
|
5102
5226
|
end
|
5103
|
-
q.
|
5227
|
+
q.breakable_empty
|
5104
5228
|
q.text("]")
|
5105
5229
|
end
|
5106
5230
|
return
|
@@ -5115,7 +5239,7 @@ module SyntaxTree
|
|
5115
5239
|
# If there's only one pair, then we'll just print the contents provided
|
5116
5240
|
# we're not inside another pattern.
|
5117
5241
|
if !nested && parts.size == 1
|
5118
|
-
|
5242
|
+
format_contents(q, parts, nested)
|
5119
5243
|
return
|
5120
5244
|
end
|
5121
5245
|
|
@@ -5124,18 +5248,31 @@ module SyntaxTree
|
|
5124
5248
|
q.group do
|
5125
5249
|
q.text("{")
|
5126
5250
|
q.indent do
|
5127
|
-
q.
|
5128
|
-
|
5251
|
+
q.breakable_space
|
5252
|
+
format_contents(q, parts, nested)
|
5129
5253
|
end
|
5130
5254
|
|
5131
5255
|
if q.target_ruby_version < Gem::Version.new("2.7.3")
|
5132
5256
|
q.text(" }")
|
5133
5257
|
else
|
5134
|
-
q.
|
5258
|
+
q.breakable_space
|
5135
5259
|
q.text("}")
|
5136
5260
|
end
|
5137
5261
|
end
|
5138
5262
|
end
|
5263
|
+
|
5264
|
+
private
|
5265
|
+
|
5266
|
+
def format_contents(q, parts, nested)
|
5267
|
+
q.group { q.seplist(parts) { |part| q.format(part, stackable: false) } }
|
5268
|
+
|
5269
|
+
# If there isn't a constant, and there's a blank keyword_rest, then we
|
5270
|
+
# have an plain ** that needs to have a `then` after it in order to
|
5271
|
+
# parse correctly on the next parse.
|
5272
|
+
if !constant && keyword_rest && keyword_rest.value.nil? && !nested
|
5273
|
+
q.text(" then")
|
5274
|
+
end
|
5275
|
+
end
|
5139
5276
|
end
|
5140
5277
|
|
5141
5278
|
# The list of nodes that represent patterns inside of pattern matching so that
|
@@ -5188,8 +5325,12 @@ module SyntaxTree
|
|
5188
5325
|
queue = [parent]
|
5189
5326
|
|
5190
5327
|
while (node = queue.shift)
|
5191
|
-
|
5192
|
-
|
5328
|
+
case node
|
5329
|
+
when Assign, MAssign, OpAssign
|
5330
|
+
return true
|
5331
|
+
else
|
5332
|
+
node.child_nodes.each { |child| queue << child if child }
|
5333
|
+
end
|
5193
5334
|
end
|
5194
5335
|
|
5195
5336
|
false
|
@@ -5204,28 +5345,36 @@ module SyntaxTree
|
|
5204
5345
|
module Ternaryable
|
5205
5346
|
class << self
|
5206
5347
|
def call(q, node)
|
5207
|
-
|
5208
|
-
|
5209
|
-
|
5210
|
-
|
5211
|
-
|
5212
|
-
|
5213
|
-
|
5214
|
-
|
5215
|
-
|
5216
|
-
|
5217
|
-
in predicate: Assign | Command | CommandCall | MAssign | OpAssign
|
5218
|
-
false
|
5219
|
-
in predicate: Not[parentheses: false]
|
5220
|
-
false
|
5221
|
-
in {
|
5222
|
-
statements: { body: [truthy] },
|
5223
|
-
consequent: Else[statements: { body: [falsy] }] }
|
5224
|
-
ternaryable?(truthy) && ternaryable?(falsy)
|
5225
|
-
else
|
5226
|
-
false
|
5227
|
-
end
|
5348
|
+
return false if ENV["STREE_FAST_FORMAT"]
|
5349
|
+
|
5350
|
+
# If this is a conditional inside of a parentheses as the only content,
|
5351
|
+
# then we don't want to transform it into a ternary. Presumably the user
|
5352
|
+
# wanted it to be an explicit conditional because there are parentheses
|
5353
|
+
# around it. So we'll just leave it in place.
|
5354
|
+
grandparent = q.grandparent
|
5355
|
+
if grandparent.is_a?(Paren) && (body = grandparent.contents.body) &&
|
5356
|
+
body.length == 1 && body.first == node
|
5357
|
+
return false
|
5228
5358
|
end
|
5359
|
+
|
5360
|
+
# Otherwise, we'll check the type of predicate. For certain nodes we
|
5361
|
+
# want to force it to not be a ternary, like if the predicate is an
|
5362
|
+
# assignment because it's hard to read.
|
5363
|
+
case node.predicate
|
5364
|
+
when Assign, Command, CommandCall, MAssign, OpAssign
|
5365
|
+
return false
|
5366
|
+
when Not
|
5367
|
+
return false unless node.predicate.parentheses?
|
5368
|
+
end
|
5369
|
+
|
5370
|
+
# If there's no Else, then this can't be represented as a ternary.
|
5371
|
+
return false unless node.consequent.is_a?(Else)
|
5372
|
+
|
5373
|
+
truthy_body = node.statements.body
|
5374
|
+
falsy_body = node.consequent.statements.body
|
5375
|
+
|
5376
|
+
(truthy_body.length == 1) && ternaryable?(truthy_body.first) &&
|
5377
|
+
(falsy_body.length == 1) && ternaryable?(falsy_body.first)
|
5229
5378
|
end
|
5230
5379
|
|
5231
5380
|
private
|
@@ -5234,24 +5383,23 @@ module SyntaxTree
|
|
5234
5383
|
# parentheses around them. In this case we say they cannot be ternaried
|
5235
5384
|
# and default instead to breaking them into multiple lines.
|
5236
5385
|
def ternaryable?(statement)
|
5237
|
-
|
5238
|
-
|
5239
|
-
|
5240
|
-
|
5241
|
-
|
5242
|
-
|
5243
|
-
|
5244
|
-
|
5245
|
-
|
5246
|
-
|
5247
|
-
|
5248
|
-
|
5249
|
-
|
5250
|
-
|
5251
|
-
|
5252
|
-
|
5253
|
-
|
5254
|
-
!(statement.is_a?(Binary) && %i[and or].include?(statement.operator))
|
5386
|
+
case statement
|
5387
|
+
when Alias, Assign, Break, Command, CommandCall, Heredoc, If, IfMod,
|
5388
|
+
IfOp, Lambda, MAssign, Next, OpAssign, RescueMod, Return, Return0,
|
5389
|
+
Super, Undef, Unless, UnlessMod, Until, UntilMod, VarAlias,
|
5390
|
+
VoidStmt, While, WhileMod, Yield, Yield0, ZSuper
|
5391
|
+
# This is a list of nodes that should not be allowed to be a part of a
|
5392
|
+
# ternary clause.
|
5393
|
+
false
|
5394
|
+
when Binary
|
5395
|
+
# If the user is using one of the lower precedence "and" or "or"
|
5396
|
+
# operators, then we can't use a ternary expression as it would break
|
5397
|
+
# the flow control.
|
5398
|
+
operator = statement.operator
|
5399
|
+
operator != :and && operator != :or
|
5400
|
+
else
|
5401
|
+
true
|
5402
|
+
end
|
5255
5403
|
end
|
5256
5404
|
end
|
5257
5405
|
end
|
@@ -5311,17 +5459,17 @@ module SyntaxTree
|
|
5311
5459
|
|
5312
5460
|
unless node.statements.empty?
|
5313
5461
|
q.indent do
|
5314
|
-
q.
|
5462
|
+
force ? q.breakable_force : q.breakable_space
|
5315
5463
|
q.format(node.statements)
|
5316
5464
|
end
|
5317
5465
|
end
|
5318
5466
|
|
5319
5467
|
if node.consequent
|
5320
|
-
q.
|
5468
|
+
force ? q.breakable_force : q.breakable_space
|
5321
5469
|
q.format(node.consequent)
|
5322
5470
|
end
|
5323
5471
|
|
5324
|
-
q.
|
5472
|
+
force ? q.breakable_force : q.breakable_space
|
5325
5473
|
q.text("end")
|
5326
5474
|
end
|
5327
5475
|
|
@@ -5333,11 +5481,11 @@ module SyntaxTree
|
|
5333
5481
|
q.nest(keyword.length + 1) { q.format(node.predicate) }
|
5334
5482
|
|
5335
5483
|
q.indent do
|
5336
|
-
q.
|
5484
|
+
q.breakable_space
|
5337
5485
|
q.format(node.statements)
|
5338
5486
|
end
|
5339
5487
|
|
5340
|
-
q.
|
5488
|
+
q.breakable_space
|
5341
5489
|
q.group do
|
5342
5490
|
q.format(node.consequent.keyword)
|
5343
5491
|
q.indent do
|
@@ -5351,7 +5499,7 @@ module SyntaxTree
|
|
5351
5499
|
end
|
5352
5500
|
end
|
5353
5501
|
|
5354
|
-
q.
|
5502
|
+
q.breakable_space
|
5355
5503
|
q.text("end")
|
5356
5504
|
end
|
5357
5505
|
.if_flat do
|
@@ -5371,8 +5519,11 @@ module SyntaxTree
|
|
5371
5519
|
end
|
5372
5520
|
|
5373
5521
|
def contains_conditional?
|
5374
|
-
|
5375
|
-
|
5522
|
+
statements = node.statements.body
|
5523
|
+
return false if statements.length != 1
|
5524
|
+
|
5525
|
+
case statements.first
|
5526
|
+
when If, IfMod, IfOp, Unless, UnlessMod
|
5376
5527
|
true
|
5377
5528
|
else
|
5378
5529
|
false
|
@@ -5507,19 +5658,19 @@ module SyntaxTree
|
|
5507
5658
|
q.nest("if ".length) { q.format(predicate) }
|
5508
5659
|
|
5509
5660
|
q.indent do
|
5510
|
-
q.
|
5661
|
+
q.breakable_space
|
5511
5662
|
q.format(truthy)
|
5512
5663
|
end
|
5513
5664
|
|
5514
|
-
q.
|
5665
|
+
q.breakable_space
|
5515
5666
|
q.text("else")
|
5516
5667
|
|
5517
5668
|
q.indent do
|
5518
|
-
q.
|
5669
|
+
q.breakable_space
|
5519
5670
|
q.format(falsy)
|
5520
5671
|
end
|
5521
5672
|
|
5522
|
-
q.
|
5673
|
+
q.breakable_space
|
5523
5674
|
q.text("end")
|
5524
5675
|
end
|
5525
5676
|
end
|
@@ -5529,11 +5680,11 @@ module SyntaxTree
|
|
5529
5680
|
q.text(" ?")
|
5530
5681
|
|
5531
5682
|
q.indent do
|
5532
|
-
q.
|
5683
|
+
q.breakable_space
|
5533
5684
|
q.format(truthy)
|
5534
5685
|
q.text(" :")
|
5535
5686
|
|
5536
|
-
q.
|
5687
|
+
q.breakable_space
|
5537
5688
|
q.format(falsy)
|
5538
5689
|
end
|
5539
5690
|
end
|
@@ -5566,10 +5717,10 @@ module SyntaxTree
|
|
5566
5717
|
q.text("#{keyword} ")
|
5567
5718
|
q.nest(keyword.length + 1) { q.format(node.predicate) }
|
5568
5719
|
q.indent do
|
5569
|
-
q.
|
5720
|
+
q.breakable_space
|
5570
5721
|
q.format(node.statement)
|
5571
5722
|
end
|
5572
|
-
q.
|
5723
|
+
q.breakable_space
|
5573
5724
|
q.text("end")
|
5574
5725
|
end
|
5575
5726
|
|
@@ -5720,13 +5871,13 @@ module SyntaxTree
|
|
5720
5871
|
|
5721
5872
|
unless statements.empty?
|
5722
5873
|
q.indent do
|
5723
|
-
q.
|
5874
|
+
q.breakable_force
|
5724
5875
|
q.format(statements)
|
5725
5876
|
end
|
5726
5877
|
end
|
5727
5878
|
|
5728
5879
|
if consequent
|
5729
|
-
q.
|
5880
|
+
q.breakable_force
|
5730
5881
|
q.format(consequent)
|
5731
5882
|
end
|
5732
5883
|
end
|
@@ -5830,11 +5981,15 @@ module SyntaxTree
|
|
5830
5981
|
# [String] the value of the keyword
|
5831
5982
|
attr_reader :value
|
5832
5983
|
|
5984
|
+
# [Symbol] the symbol version of the value
|
5985
|
+
attr_reader :name
|
5986
|
+
|
5833
5987
|
# [Array[ Comment | EmbDoc ]] the comments attached to this node
|
5834
5988
|
attr_reader :comments
|
5835
5989
|
|
5836
5990
|
def initialize(value:, location:, comments: [])
|
5837
5991
|
@value = value
|
5992
|
+
@name = value.to_sym
|
5838
5993
|
@location = location
|
5839
5994
|
@comments = comments
|
5840
5995
|
end
|
@@ -6013,7 +6168,8 @@ module SyntaxTree
|
|
6013
6168
|
end
|
6014
6169
|
|
6015
6170
|
def format(q)
|
6016
|
-
q.
|
6171
|
+
q.text("->")
|
6172
|
+
q.group do
|
6017
6173
|
if params.is_a?(Paren)
|
6018
6174
|
q.format(params) unless params.contents.empty?
|
6019
6175
|
elsif params.empty? && params.comments.any?
|
@@ -6039,10 +6195,10 @@ module SyntaxTree
|
|
6039
6195
|
|
6040
6196
|
unless statements.empty?
|
6041
6197
|
q.indent do
|
6042
|
-
q.
|
6198
|
+
q.breakable_space
|
6043
6199
|
q.format(statements)
|
6044
6200
|
end
|
6045
|
-
q.
|
6201
|
+
q.breakable_space
|
6046
6202
|
end
|
6047
6203
|
|
6048
6204
|
q.text("}")
|
@@ -6051,12 +6207,12 @@ module SyntaxTree
|
|
6051
6207
|
|
6052
6208
|
unless statements.empty?
|
6053
6209
|
q.indent do
|
6054
|
-
q.
|
6210
|
+
q.breakable_space
|
6055
6211
|
q.format(statements)
|
6056
6212
|
end
|
6057
6213
|
end
|
6058
6214
|
|
6059
|
-
q.
|
6215
|
+
q.breakable_space
|
6060
6216
|
q.text("end")
|
6061
6217
|
end
|
6062
6218
|
end
|
@@ -6123,7 +6279,7 @@ module SyntaxTree
|
|
6123
6279
|
|
6124
6280
|
if locals.any?
|
6125
6281
|
q.text("; ")
|
6126
|
-
q.seplist(locals,
|
6282
|
+
q.seplist(locals, BlockVar::SEPARATOR) { |local| q.format(local) }
|
6127
6283
|
end
|
6128
6284
|
end
|
6129
6285
|
end
|
@@ -6277,7 +6433,7 @@ module SyntaxTree
|
|
6277
6433
|
q.group { q.format(target) }
|
6278
6434
|
q.text(" =")
|
6279
6435
|
q.indent do
|
6280
|
-
q.
|
6436
|
+
q.breakable_space
|
6281
6437
|
q.format(value)
|
6282
6438
|
end
|
6283
6439
|
end
|
@@ -6323,8 +6479,8 @@ module SyntaxTree
|
|
6323
6479
|
# If we're at the top of a call chain, then we're going to do some
|
6324
6480
|
# specialized printing in case we can print it nicely. We _only_ do this
|
6325
6481
|
# at the top of the chain to avoid weird recursion issues.
|
6326
|
-
if
|
6327
|
-
CallChainFormatter.chained?(
|
6482
|
+
if CallChainFormatter.chained?(call) &&
|
6483
|
+
!CallChainFormatter.chained?(q.parent)
|
6328
6484
|
q.group do
|
6329
6485
|
q
|
6330
6486
|
.if_break { CallChainFormatter.new(self).format(q) }
|
@@ -6431,15 +6587,17 @@ module SyntaxTree
|
|
6431
6587
|
q.format(contents)
|
6432
6588
|
q.text(",") if comma
|
6433
6589
|
else
|
6434
|
-
q.
|
6590
|
+
q.text("(")
|
6591
|
+
q.group do
|
6435
6592
|
q.indent do
|
6436
|
-
q.
|
6593
|
+
q.breakable_empty
|
6437
6594
|
q.format(contents)
|
6438
6595
|
end
|
6439
6596
|
|
6440
6597
|
q.text(",") if comma
|
6441
|
-
q.
|
6598
|
+
q.breakable_empty
|
6442
6599
|
end
|
6600
|
+
q.text(")")
|
6443
6601
|
end
|
6444
6602
|
end
|
6445
6603
|
end
|
@@ -6486,33 +6644,35 @@ module SyntaxTree
|
|
6486
6644
|
end
|
6487
6645
|
|
6488
6646
|
def format(q)
|
6489
|
-
declaration = -> do
|
6490
|
-
q.group do
|
6491
|
-
q.text("module ")
|
6492
|
-
q.format(constant)
|
6493
|
-
end
|
6494
|
-
end
|
6495
|
-
|
6496
6647
|
if bodystmt.empty?
|
6497
6648
|
q.group do
|
6498
|
-
|
6499
|
-
q.
|
6649
|
+
format_declaration(q)
|
6650
|
+
q.breakable_force
|
6500
6651
|
q.text("end")
|
6501
6652
|
end
|
6502
6653
|
else
|
6503
6654
|
q.group do
|
6504
|
-
|
6655
|
+
format_declaration(q)
|
6505
6656
|
|
6506
6657
|
q.indent do
|
6507
|
-
q.
|
6658
|
+
q.breakable_force
|
6508
6659
|
q.format(bodystmt)
|
6509
6660
|
end
|
6510
6661
|
|
6511
|
-
q.
|
6662
|
+
q.breakable_force
|
6512
6663
|
q.text("end")
|
6513
6664
|
end
|
6514
6665
|
end
|
6515
6666
|
end
|
6667
|
+
|
6668
|
+
private
|
6669
|
+
|
6670
|
+
def format_declaration(q)
|
6671
|
+
q.group do
|
6672
|
+
q.text("module ")
|
6673
|
+
q.format(constant)
|
6674
|
+
end
|
6675
|
+
end
|
6516
6676
|
end
|
6517
6677
|
|
6518
6678
|
# MRHS represents the values that are being assigned on the right-hand side of
|
@@ -6610,11 +6770,15 @@ module SyntaxTree
|
|
6610
6770
|
# [String] the operator
|
6611
6771
|
attr_reader :value
|
6612
6772
|
|
6773
|
+
# [Symbol] the symbol version of the value
|
6774
|
+
attr_reader :name
|
6775
|
+
|
6613
6776
|
# [Array[ Comment | EmbDoc ]] the comments attached to this node
|
6614
6777
|
attr_reader :comments
|
6615
6778
|
|
6616
6779
|
def initialize(value:, location:, comments: [])
|
6617
6780
|
@value = value
|
6781
|
+
@name = value.to_sym
|
6618
6782
|
@location = location
|
6619
6783
|
@comments = comments
|
6620
6784
|
end
|
@@ -6696,7 +6860,7 @@ module SyntaxTree
|
|
6696
6860
|
q.format(value)
|
6697
6861
|
else
|
6698
6862
|
q.indent do
|
6699
|
-
q.
|
6863
|
+
q.breakable_space
|
6700
6864
|
q.format(value)
|
6701
6865
|
end
|
6702
6866
|
end
|
@@ -6767,10 +6931,10 @@ module SyntaxTree
|
|
6767
6931
|
|
6768
6932
|
q.text("(")
|
6769
6933
|
q.indent do
|
6770
|
-
q.
|
6934
|
+
q.breakable_empty
|
6771
6935
|
yield
|
6772
6936
|
end
|
6773
|
-
q.
|
6937
|
+
q.breakable_empty
|
6774
6938
|
q.text(")")
|
6775
6939
|
end
|
6776
6940
|
end
|
@@ -6962,23 +7126,35 @@ module SyntaxTree
|
|
6962
7126
|
parts << KeywordRestFormatter.new(keyword_rest) if keyword_rest
|
6963
7127
|
parts << block if block
|
6964
7128
|
|
6965
|
-
|
6966
|
-
q.
|
6967
|
-
|
7129
|
+
if parts.empty?
|
7130
|
+
q.nest(0) { format_contents(q, parts) }
|
7131
|
+
return
|
6968
7132
|
end
|
6969
7133
|
|
6970
|
-
|
6971
|
-
|
6972
|
-
|
6973
|
-
|
6974
|
-
q.
|
6975
|
-
q.
|
6976
|
-
|
7134
|
+
case q.parent
|
7135
|
+
when Def, Defs, DefEndless
|
7136
|
+
q.nest(0) do
|
7137
|
+
q.text("(")
|
7138
|
+
q.group do
|
7139
|
+
q.indent do
|
7140
|
+
q.breakable_empty
|
7141
|
+
format_contents(q, parts)
|
7142
|
+
end
|
7143
|
+
q.breakable_empty
|
6977
7144
|
end
|
6978
|
-
q.
|
7145
|
+
q.text(")")
|
6979
7146
|
end
|
7147
|
+
else
|
7148
|
+
q.nest(0) { format_contents(q, parts) }
|
6980
7149
|
end
|
6981
7150
|
end
|
7151
|
+
|
7152
|
+
private
|
7153
|
+
|
7154
|
+
def format_contents(q, parts)
|
7155
|
+
q.seplist(parts) { |part| q.format(part) }
|
7156
|
+
q.format(rest) if rest.is_a?(ExcessedComma)
|
7157
|
+
end
|
6982
7158
|
end
|
6983
7159
|
|
6984
7160
|
# Paren represents using balanced parentheses in a couple places in a Ruby
|
@@ -7029,12 +7205,12 @@ module SyntaxTree
|
|
7029
7205
|
|
7030
7206
|
if contents && (!contents.is_a?(Params) || !contents.empty?)
|
7031
7207
|
q.indent do
|
7032
|
-
q.
|
7208
|
+
q.breakable_empty
|
7033
7209
|
q.format(contents)
|
7034
7210
|
end
|
7035
7211
|
end
|
7036
7212
|
|
7037
|
-
q.
|
7213
|
+
q.breakable_empty
|
7038
7214
|
q.text(")")
|
7039
7215
|
end
|
7040
7216
|
end
|
@@ -7108,7 +7284,7 @@ module SyntaxTree
|
|
7108
7284
|
# We're going to put a newline on the end so that it always has one unless
|
7109
7285
|
# it ends with the special __END__ syntax. In that case we want to
|
7110
7286
|
# replicate the text exactly so we will just let it be.
|
7111
|
-
q.
|
7287
|
+
q.breakable_force unless statements.body.last.is_a?(EndContent)
|
7112
7288
|
end
|
7113
7289
|
end
|
7114
7290
|
|
@@ -7160,15 +7336,18 @@ module SyntaxTree
|
|
7160
7336
|
closing = Quotes.matching(opening[2])
|
7161
7337
|
end
|
7162
7338
|
|
7163
|
-
q.
|
7339
|
+
q.text(opening)
|
7340
|
+
q.group do
|
7164
7341
|
q.indent do
|
7165
|
-
q.
|
7166
|
-
q.seplist(
|
7167
|
-
|
7168
|
-
|
7342
|
+
q.breakable_empty
|
7343
|
+
q.seplist(
|
7344
|
+
elements,
|
7345
|
+
ArrayLiteral::BREAKABLE_SPACE_SEPARATOR
|
7346
|
+
) { |element| q.format(element) }
|
7169
7347
|
end
|
7170
|
-
q.
|
7348
|
+
q.breakable_empty
|
7171
7349
|
end
|
7350
|
+
q.text(closing)
|
7172
7351
|
end
|
7173
7352
|
end
|
7174
7353
|
|
@@ -7251,15 +7430,18 @@ module SyntaxTree
|
|
7251
7430
|
closing = Quotes.matching(opening[2])
|
7252
7431
|
end
|
7253
7432
|
|
7254
|
-
q.
|
7433
|
+
q.text(opening)
|
7434
|
+
q.group do
|
7255
7435
|
q.indent do
|
7256
|
-
q.
|
7257
|
-
q.seplist(
|
7258
|
-
|
7259
|
-
|
7436
|
+
q.breakable_empty
|
7437
|
+
q.seplist(
|
7438
|
+
elements,
|
7439
|
+
ArrayLiteral::BREAKABLE_SPACE_SEPARATOR
|
7440
|
+
) { |element| q.format(element) }
|
7260
7441
|
end
|
7261
|
-
q.
|
7442
|
+
q.breakable_empty
|
7262
7443
|
end
|
7444
|
+
q.text(closing)
|
7263
7445
|
end
|
7264
7446
|
end
|
7265
7447
|
|
@@ -7781,13 +7963,13 @@ module SyntaxTree
|
|
7781
7963
|
|
7782
7964
|
unless statements.empty?
|
7783
7965
|
q.indent do
|
7784
|
-
q.
|
7966
|
+
q.breakable_force
|
7785
7967
|
q.format(statements)
|
7786
7968
|
end
|
7787
7969
|
end
|
7788
7970
|
|
7789
7971
|
if consequent
|
7790
|
-
q.
|
7972
|
+
q.breakable_force
|
7791
7973
|
q.format(consequent)
|
7792
7974
|
end
|
7793
7975
|
end
|
@@ -7835,19 +8017,21 @@ module SyntaxTree
|
|
7835
8017
|
end
|
7836
8018
|
|
7837
8019
|
def format(q)
|
7838
|
-
q.
|
8020
|
+
q.text("begin")
|
8021
|
+
q.group do
|
7839
8022
|
q.indent do
|
7840
|
-
q.
|
8023
|
+
q.breakable_force
|
7841
8024
|
q.format(statement)
|
7842
8025
|
end
|
7843
|
-
q.
|
8026
|
+
q.breakable_force
|
7844
8027
|
q.text("rescue StandardError")
|
7845
8028
|
q.indent do
|
7846
|
-
q.
|
8029
|
+
q.breakable_force
|
7847
8030
|
q.format(value)
|
7848
8031
|
end
|
7849
|
-
q.
|
8032
|
+
q.breakable_force
|
7850
8033
|
end
|
8034
|
+
q.text("end")
|
7851
8035
|
end
|
7852
8036
|
end
|
7853
8037
|
|
@@ -8066,14 +8250,16 @@ module SyntaxTree
|
|
8066
8250
|
end
|
8067
8251
|
|
8068
8252
|
def format(q)
|
8069
|
-
q.
|
8253
|
+
q.text("class << ")
|
8254
|
+
q.group do
|
8070
8255
|
q.format(target)
|
8071
8256
|
q.indent do
|
8072
|
-
q.
|
8257
|
+
q.breakable_force
|
8073
8258
|
q.format(bodystmt)
|
8074
8259
|
end
|
8075
|
-
q.
|
8260
|
+
q.breakable_force
|
8076
8261
|
end
|
8262
|
+
q.text("end")
|
8077
8263
|
end
|
8078
8264
|
end
|
8079
8265
|
|
@@ -8179,30 +8365,26 @@ module SyntaxTree
|
|
8179
8365
|
end
|
8180
8366
|
end
|
8181
8367
|
|
8182
|
-
|
8183
|
-
|
8184
|
-
hash[node] = node.is_a?(VCall) &&
|
8185
|
-
%w[private protected public].include?(node.value.value)
|
8186
|
-
end
|
8187
|
-
|
8188
|
-
body.each_with_index do |statement, index|
|
8368
|
+
previous = nil
|
8369
|
+
body.each do |statement|
|
8189
8370
|
next if statement.is_a?(VoidStmt)
|
8190
8371
|
|
8191
8372
|
if line.nil?
|
8192
8373
|
q.format(statement)
|
8193
8374
|
elsif (statement.location.start_line - line) > 1
|
8194
|
-
q.
|
8195
|
-
q.
|
8375
|
+
q.breakable_force
|
8376
|
+
q.breakable_force
|
8196
8377
|
q.format(statement)
|
8197
|
-
elsif
|
8198
|
-
|
8199
|
-
q.
|
8378
|
+
elsif (statement.is_a?(VCall) && statement.access_control?) ||
|
8379
|
+
(previous.is_a?(VCall) && previous.access_control?)
|
8380
|
+
q.breakable_force
|
8381
|
+
q.breakable_force
|
8200
8382
|
q.format(statement)
|
8201
8383
|
elsif statement.location.start_line != line
|
8202
|
-
q.
|
8384
|
+
q.breakable_force
|
8203
8385
|
q.format(statement)
|
8204
8386
|
elsif !q.parent.is_a?(StringEmbExpr)
|
8205
|
-
q.
|
8387
|
+
q.breakable_force
|
8206
8388
|
q.format(statement)
|
8207
8389
|
else
|
8208
8390
|
q.text("; ")
|
@@ -8210,6 +8392,7 @@ module SyntaxTree
|
|
8210
8392
|
end
|
8211
8393
|
|
8212
8394
|
line = statement.location.end_line
|
8395
|
+
previous = statement
|
8213
8396
|
end
|
8214
8397
|
end
|
8215
8398
|
|
@@ -8327,7 +8510,7 @@ module SyntaxTree
|
|
8327
8510
|
q.format(left)
|
8328
8511
|
q.text(" \\")
|
8329
8512
|
q.indent do
|
8330
|
-
q.
|
8513
|
+
q.breakable_force
|
8331
8514
|
q.format(right)
|
8332
8515
|
end
|
8333
8516
|
end
|
@@ -8413,15 +8596,21 @@ module SyntaxTree
|
|
8413
8596
|
# same line in the source, then we're going to leave them in place and
|
8414
8597
|
# assume that's the way the developer wanted this expression
|
8415
8598
|
# represented.
|
8416
|
-
q.remove_breaks(
|
8599
|
+
q.remove_breaks(
|
8600
|
+
q.group do
|
8601
|
+
q.text('#{')
|
8602
|
+
q.format(statements)
|
8603
|
+
q.text("}")
|
8604
|
+
end
|
8605
|
+
)
|
8417
8606
|
else
|
8418
8607
|
q.group do
|
8419
8608
|
q.text('#{')
|
8420
8609
|
q.indent do
|
8421
|
-
q.
|
8610
|
+
q.breakable_empty
|
8422
8611
|
q.format(statements)
|
8423
8612
|
end
|
8424
|
-
q.
|
8613
|
+
q.breakable_empty
|
8425
8614
|
q.text("}")
|
8426
8615
|
end
|
8427
8616
|
end
|
@@ -8479,19 +8668,30 @@ module SyntaxTree
|
|
8479
8668
|
[quote, quote]
|
8480
8669
|
end
|
8481
8670
|
|
8482
|
-
q.
|
8671
|
+
q.text(opening_quote)
|
8672
|
+
q.group do
|
8483
8673
|
parts.each do |part|
|
8484
8674
|
if part.is_a?(TStringContent)
|
8485
8675
|
value = Quotes.normalize(part.value, closing_quote)
|
8486
|
-
|
8487
|
-
|
8488
|
-
|
8676
|
+
first = true
|
8677
|
+
|
8678
|
+
value.each_line(chomp: true) do |line|
|
8679
|
+
if first
|
8680
|
+
first = false
|
8681
|
+
else
|
8682
|
+
q.breakable_return
|
8683
|
+
end
|
8684
|
+
|
8685
|
+
q.text(line)
|
8489
8686
|
end
|
8687
|
+
|
8688
|
+
q.breakable_return if value.end_with?("\n")
|
8490
8689
|
else
|
8491
8690
|
q.format(part)
|
8492
8691
|
end
|
8493
8692
|
end
|
8494
8693
|
end
|
8694
|
+
q.text(closing_quote)
|
8495
8695
|
end
|
8496
8696
|
end
|
8497
8697
|
|
@@ -8698,15 +8898,18 @@ module SyntaxTree
|
|
8698
8898
|
closing = Quotes.matching(opening[2])
|
8699
8899
|
end
|
8700
8900
|
|
8701
|
-
q.
|
8901
|
+
q.text(opening)
|
8902
|
+
q.group do
|
8702
8903
|
q.indent do
|
8703
|
-
q.
|
8704
|
-
q.seplist(
|
8705
|
-
|
8706
|
-
|
8904
|
+
q.breakable_empty
|
8905
|
+
q.seplist(
|
8906
|
+
elements,
|
8907
|
+
ArrayLiteral::BREAKABLE_SPACE_SEPARATOR
|
8908
|
+
) { |element| q.format(element) }
|
8707
8909
|
end
|
8708
|
-
q.
|
8910
|
+
q.breakable_empty
|
8709
8911
|
end
|
8912
|
+
q.text(closing)
|
8710
8913
|
end
|
8711
8914
|
end
|
8712
8915
|
|
@@ -9000,6 +9203,7 @@ module SyntaxTree
|
|
9000
9203
|
|
9001
9204
|
# [boolean] whether or not parentheses were used
|
9002
9205
|
attr_reader :parentheses
|
9206
|
+
alias parentheses? parentheses
|
9003
9207
|
|
9004
9208
|
# [Array[ Comment | EmbDoc ]] the comments attached to this node
|
9005
9209
|
attr_reader :comments
|
@@ -9031,27 +9235,26 @@ module SyntaxTree
|
|
9031
9235
|
end
|
9032
9236
|
|
9033
9237
|
def format(q)
|
9034
|
-
parent = q.parents.take(2)[1]
|
9035
|
-
ternary =
|
9036
|
-
(parent.is_a?(If) || parent.is_a?(Unless)) &&
|
9037
|
-
Ternaryable.call(q, parent)
|
9038
|
-
|
9039
9238
|
q.text("not")
|
9040
9239
|
|
9041
9240
|
if parentheses
|
9042
9241
|
q.text("(")
|
9043
|
-
|
9044
|
-
q.if_break { q.text(" ") }.if_flat { q.text("(") }
|
9045
|
-
else
|
9046
|
-
q.text(" ")
|
9047
|
-
end
|
9048
|
-
|
9049
|
-
q.format(statement) if statement
|
9050
|
-
|
9051
|
-
if parentheses
|
9242
|
+
q.format(statement) if statement
|
9052
9243
|
q.text(")")
|
9053
|
-
|
9054
|
-
|
9244
|
+
else
|
9245
|
+
grandparent = q.grandparent
|
9246
|
+
ternary =
|
9247
|
+
(grandparent.is_a?(If) || grandparent.is_a?(Unless)) &&
|
9248
|
+
Ternaryable.call(q, grandparent)
|
9249
|
+
|
9250
|
+
if ternary
|
9251
|
+
q.if_break { q.text(" ") }.if_flat { q.text("(") }
|
9252
|
+
q.format(statement) if statement
|
9253
|
+
q.if_flat { q.text(")") } if ternary
|
9254
|
+
else
|
9255
|
+
q.text(" ")
|
9256
|
+
q.format(statement) if statement
|
9257
|
+
end
|
9055
9258
|
end
|
9056
9259
|
end
|
9057
9260
|
end
|
@@ -9316,10 +9519,10 @@ module SyntaxTree
|
|
9316
9519
|
q.text("#{keyword} ")
|
9317
9520
|
q.nest(keyword.length + 1) { q.format(node.predicate) }
|
9318
9521
|
q.indent do
|
9319
|
-
q.
|
9522
|
+
q.breakable_empty
|
9320
9523
|
q.format(statements)
|
9321
9524
|
end
|
9322
|
-
q.
|
9525
|
+
q.breakable_empty
|
9323
9526
|
q.text("end")
|
9324
9527
|
end
|
9325
9528
|
end
|
@@ -9372,7 +9575,7 @@ module SyntaxTree
|
|
9372
9575
|
q.group do
|
9373
9576
|
q.text(keyword)
|
9374
9577
|
q.nest(keyword.length) { q.format(predicate) }
|
9375
|
-
q.
|
9578
|
+
q.breakable_force
|
9376
9579
|
q.text("end")
|
9377
9580
|
end
|
9378
9581
|
else
|
@@ -9572,6 +9775,29 @@ module SyntaxTree
|
|
9572
9775
|
def format(q)
|
9573
9776
|
q.format(value)
|
9574
9777
|
end
|
9778
|
+
|
9779
|
+
# Oh man I hate this so much. Basically, ripper doesn't provide enough
|
9780
|
+
# functionality to actually know where pins are within an expression. So we
|
9781
|
+
# have to walk the tree ourselves and insert more information. In doing so,
|
9782
|
+
# we have to replace this node by a pinned node when necessary.
|
9783
|
+
#
|
9784
|
+
# To be clear, this method should just not exist. It's not good. It's a
|
9785
|
+
# place of shame. But it's necessary for now, so I'm keeping it.
|
9786
|
+
def pin(parent)
|
9787
|
+
replace = PinnedVarRef.new(value: value, location: location)
|
9788
|
+
|
9789
|
+
parent
|
9790
|
+
.deconstruct_keys([])
|
9791
|
+
.each do |key, value|
|
9792
|
+
if value == self
|
9793
|
+
parent.instance_variable_set(:"@#{key}", replace)
|
9794
|
+
break
|
9795
|
+
elsif value.is_a?(Array) && (index = value.index(self))
|
9796
|
+
parent.public_send(key)[index] = replace
|
9797
|
+
break
|
9798
|
+
end
|
9799
|
+
end
|
9800
|
+
end
|
9575
9801
|
end
|
9576
9802
|
|
9577
9803
|
# PinnedVarRef represents a pinned variable reference within a pattern
|
@@ -9653,6 +9879,10 @@ module SyntaxTree
|
|
9653
9879
|
def format(q)
|
9654
9880
|
q.format(value)
|
9655
9881
|
end
|
9882
|
+
|
9883
|
+
def access_control?
|
9884
|
+
@access_control ||= %w[private protected public].include?(value.value)
|
9885
|
+
end
|
9656
9886
|
end
|
9657
9887
|
|
9658
9888
|
# VoidStmt represents an empty lexical block of code.
|
@@ -9742,6 +9972,22 @@ module SyntaxTree
|
|
9742
9972
|
}
|
9743
9973
|
end
|
9744
9974
|
|
9975
|
+
# We have a special separator here for when clauses which causes them to
|
9976
|
+
# fill as much of the line as possible as opposed to everything breaking
|
9977
|
+
# into its own line as soon as you hit the print limit.
|
9978
|
+
class Separator
|
9979
|
+
def call(q)
|
9980
|
+
q.group do
|
9981
|
+
q.text(",")
|
9982
|
+
q.breakable_space
|
9983
|
+
end
|
9984
|
+
end
|
9985
|
+
end
|
9986
|
+
|
9987
|
+
# We're going to keep a single instance of this separator around so we don't
|
9988
|
+
# have to allocate a new one every time we format a when clause.
|
9989
|
+
SEPARATOR = Separator.new
|
9990
|
+
|
9745
9991
|
def format(q)
|
9746
9992
|
keyword = "when "
|
9747
9993
|
|
@@ -9752,8 +9998,7 @@ module SyntaxTree
|
|
9752
9998
|
if arguments.comments.any?
|
9753
9999
|
q.format(arguments)
|
9754
10000
|
else
|
9755
|
-
|
9756
|
-
q.seplist(arguments.parts, separator) { |part| q.format(part) }
|
10001
|
+
q.seplist(arguments.parts, SEPARATOR) { |part| q.format(part) }
|
9757
10002
|
end
|
9758
10003
|
|
9759
10004
|
# Very special case here. If you're inside of a when clause and the
|
@@ -9768,13 +10013,13 @@ module SyntaxTree
|
|
9768
10013
|
|
9769
10014
|
unless statements.empty?
|
9770
10015
|
q.indent do
|
9771
|
-
q.
|
10016
|
+
q.breakable_force
|
9772
10017
|
q.format(statements)
|
9773
10018
|
end
|
9774
10019
|
end
|
9775
10020
|
|
9776
10021
|
if consequent
|
9777
|
-
q.
|
10022
|
+
q.breakable_force
|
9778
10023
|
q.format(consequent)
|
9779
10024
|
end
|
9780
10025
|
end
|
@@ -9829,7 +10074,7 @@ module SyntaxTree
|
|
9829
10074
|
q.group do
|
9830
10075
|
q.text(keyword)
|
9831
10076
|
q.nest(keyword.length) { q.format(predicate) }
|
9832
|
-
q.
|
10077
|
+
q.breakable_force
|
9833
10078
|
q.text("end")
|
9834
10079
|
end
|
9835
10080
|
else
|
@@ -9995,15 +10240,18 @@ module SyntaxTree
|
|
9995
10240
|
closing = Quotes.matching(opening[2])
|
9996
10241
|
end
|
9997
10242
|
|
9998
|
-
q.
|
10243
|
+
q.text(opening)
|
10244
|
+
q.group do
|
9999
10245
|
q.indent do
|
10000
|
-
q.
|
10001
|
-
q.seplist(
|
10002
|
-
|
10003
|
-
|
10246
|
+
q.breakable_empty
|
10247
|
+
q.seplist(
|
10248
|
+
elements,
|
10249
|
+
ArrayLiteral::BREAKABLE_SPACE_SEPARATOR
|
10250
|
+
) { |element| q.format(element) }
|
10004
10251
|
end
|
10005
|
-
q.
|
10252
|
+
q.breakable_empty
|
10006
10253
|
end
|
10254
|
+
q.text(closing)
|
10007
10255
|
end
|
10008
10256
|
end
|
10009
10257
|
|
@@ -10147,10 +10395,10 @@ module SyntaxTree
|
|
10147
10395
|
else
|
10148
10396
|
q.if_break { q.text("(") }.if_flat { q.text(" ") }
|
10149
10397
|
q.indent do
|
10150
|
-
q.
|
10398
|
+
q.breakable_empty
|
10151
10399
|
q.format(arguments)
|
10152
10400
|
end
|
10153
|
-
q.
|
10401
|
+
q.breakable_empty
|
10154
10402
|
q.if_break { q.text(")") }
|
10155
10403
|
end
|
10156
10404
|
end
|