syntax_tree 3.6.3 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|