syntax_tree 3.6.3 → 4.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -0
- data/CHANGELOG.md +23 -1
- data/Gemfile.lock +6 -6
- 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 +789 -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 +4 -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
|
@@ -1613,6 +1651,20 @@ module SyntaxTree
|
|
1613
1651
|
# array << value
|
1614
1652
|
#
|
1615
1653
|
class Binary < Node
|
1654
|
+
# Since Binary's operator is a symbol, it's better to use the `name` method
|
1655
|
+
# than to allocate a new string every time. This is a tiny performance
|
1656
|
+
# optimization, but enough that it shows up in the profiler. Adding this in
|
1657
|
+
# for older Ruby versions.
|
1658
|
+
unless :+.respond_to?(:name)
|
1659
|
+
using Module.new {
|
1660
|
+
refine Symbol do
|
1661
|
+
def name
|
1662
|
+
to_s.freeze
|
1663
|
+
end
|
1664
|
+
end
|
1665
|
+
}
|
1666
|
+
end
|
1667
|
+
|
1616
1668
|
# [untyped] the left-hand side of the expression
|
1617
1669
|
attr_reader :left
|
1618
1670
|
|
@@ -1661,15 +1713,13 @@ module SyntaxTree
|
|
1661
1713
|
q.text(" ") unless power
|
1662
1714
|
|
1663
1715
|
if operator == :<<
|
1664
|
-
q.text(
|
1665
|
-
q.text(" ")
|
1716
|
+
q.text("<< ")
|
1666
1717
|
q.format(right)
|
1667
1718
|
else
|
1668
1719
|
q.group do
|
1669
|
-
q.text(operator.
|
1670
|
-
|
1720
|
+
q.text(operator.name)
|
1671
1721
|
q.indent do
|
1672
|
-
|
1722
|
+
power ? q.breakable_empty : q.breakable_space
|
1673
1723
|
q.format(right)
|
1674
1724
|
end
|
1675
1725
|
end
|
@@ -1716,15 +1766,29 @@ module SyntaxTree
|
|
1716
1766
|
{ params: params, locals: locals, location: location, comments: comments }
|
1717
1767
|
end
|
1718
1768
|
|
1769
|
+
# Within the pipes of the block declaration, we don't want any spaces. So
|
1770
|
+
# we'll separate the parameters with a comma and space but no breakables.
|
1771
|
+
class Separator
|
1772
|
+
def call(q)
|
1773
|
+
q.text(", ")
|
1774
|
+
end
|
1775
|
+
end
|
1776
|
+
|
1777
|
+
# We'll keep a single instance of this separator around for all block vars
|
1778
|
+
# to cut down on allocations.
|
1779
|
+
SEPARATOR = Separator.new
|
1780
|
+
|
1719
1781
|
def format(q)
|
1720
|
-
q.
|
1782
|
+
q.text("|")
|
1783
|
+
q.group do
|
1721
1784
|
q.remove_breaks(q.format(params))
|
1722
1785
|
|
1723
1786
|
if locals.any?
|
1724
1787
|
q.text("; ")
|
1725
|
-
q.seplist(locals,
|
1788
|
+
q.seplist(locals, SEPARATOR) { |local| q.format(local) }
|
1726
1789
|
end
|
1727
1790
|
end
|
1791
|
+
q.text("|")
|
1728
1792
|
end
|
1729
1793
|
end
|
1730
1794
|
|
@@ -1816,10 +1880,8 @@ module SyntaxTree
|
|
1816
1880
|
end_column: end_column
|
1817
1881
|
)
|
1818
1882
|
|
1819
|
-
parts = [rescue_clause, else_clause, ensure_clause]
|
1820
|
-
|
1821
1883
|
# Here we're going to determine the bounds for the statements
|
1822
|
-
consequent =
|
1884
|
+
consequent = rescue_clause || else_clause || ensure_clause
|
1823
1885
|
statements.bind(
|
1824
1886
|
start_char,
|
1825
1887
|
start_column,
|
@@ -1829,7 +1891,7 @@ module SyntaxTree
|
|
1829
1891
|
|
1830
1892
|
# Next we're going to determine the rescue clause if there is one
|
1831
1893
|
if rescue_clause
|
1832
|
-
consequent =
|
1894
|
+
consequent = else_clause || ensure_clause
|
1833
1895
|
rescue_clause.bind_end(
|
1834
1896
|
consequent ? consequent.location.start_char : end_char,
|
1835
1897
|
consequent ? consequent.location.start_column : end_column
|
@@ -1868,26 +1930,26 @@ module SyntaxTree
|
|
1868
1930
|
|
1869
1931
|
if rescue_clause
|
1870
1932
|
q.nest(-2) do
|
1871
|
-
q.
|
1933
|
+
q.breakable_force
|
1872
1934
|
q.format(rescue_clause)
|
1873
1935
|
end
|
1874
1936
|
end
|
1875
1937
|
|
1876
1938
|
if else_clause
|
1877
1939
|
q.nest(-2) do
|
1878
|
-
q.
|
1940
|
+
q.breakable_force
|
1879
1941
|
q.format(else_keyword)
|
1880
1942
|
end
|
1881
1943
|
|
1882
1944
|
unless else_clause.empty?
|
1883
|
-
q.
|
1945
|
+
q.breakable_force
|
1884
1946
|
q.format(else_clause)
|
1885
1947
|
end
|
1886
1948
|
end
|
1887
1949
|
|
1888
1950
|
if ensure_clause
|
1889
1951
|
q.nest(-2) do
|
1890
|
-
q.
|
1952
|
+
q.breakable_force
|
1891
1953
|
q.format(ensure_clause)
|
1892
1954
|
end
|
1893
1955
|
end
|
@@ -1955,12 +2017,11 @@ module SyntaxTree
|
|
1955
2017
|
# If the receiver of this block a Command or CommandCall node, then there
|
1956
2018
|
# are no parentheses around the arguments to that command, so we need to
|
1957
2019
|
# break the block.
|
1958
|
-
case q.parent
|
1959
|
-
|
2020
|
+
case q.parent.call
|
2021
|
+
when Command, CommandCall
|
1960
2022
|
q.break_parent
|
1961
2023
|
format_break(q, break_opening, break_closing)
|
1962
2024
|
return
|
1963
|
-
else
|
1964
2025
|
end
|
1965
2026
|
|
1966
2027
|
q.group do
|
@@ -1980,9 +2041,9 @@ module SyntaxTree
|
|
1980
2041
|
# know for certain we're going to get split over multiple lines
|
1981
2042
|
# anyway.
|
1982
2043
|
case parent
|
1983
|
-
|
2044
|
+
when Statements, ArgParen
|
1984
2045
|
break false
|
1985
|
-
|
2046
|
+
when Command, CommandCall
|
1986
2047
|
true
|
1987
2048
|
else
|
1988
2049
|
false
|
@@ -1993,8 +2054,8 @@ module SyntaxTree
|
|
1993
2054
|
# If we're a sibling of a control-flow keyword, then we're going to have to
|
1994
2055
|
# use the do..end bounds.
|
1995
2056
|
def forced_do_end_bounds?(q)
|
1996
|
-
case q.parent
|
1997
|
-
|
2057
|
+
case q.parent.call
|
2058
|
+
when Break, Next, Return, Super
|
1998
2059
|
true
|
1999
2060
|
else
|
2000
2061
|
false
|
@@ -2004,22 +2065,19 @@ module SyntaxTree
|
|
2004
2065
|
# If we're the predicate of a loop or conditional, then we're going to have
|
2005
2066
|
# to go with the {..} bounds.
|
2006
2067
|
def forced_brace_bounds?(q)
|
2007
|
-
|
2008
|
-
parents.
|
2009
|
-
|
2010
|
-
|
2068
|
+
previous = nil
|
2069
|
+
q.parents.any? do |parent|
|
2070
|
+
case parent
|
2071
|
+
when Paren, Statements
|
2072
|
+
# If we hit certain breakpoints then we know we're safe.
|
2073
|
+
return false
|
2074
|
+
when If, IfMod, IfOp, Unless, UnlessMod, While, WhileMod, Until,
|
2075
|
+
UntilMod
|
2076
|
+
return true if parent.predicate == previous
|
2077
|
+
end
|
2011
2078
|
|
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]
|
2079
|
+
previous = parent
|
2080
|
+
false
|
2023
2081
|
end
|
2024
2082
|
end
|
2025
2083
|
|
@@ -2034,12 +2092,12 @@ module SyntaxTree
|
|
2034
2092
|
|
2035
2093
|
unless statements.empty?
|
2036
2094
|
q.indent do
|
2037
|
-
q.
|
2095
|
+
q.breakable_space
|
2038
2096
|
q.format(statements)
|
2039
2097
|
end
|
2040
2098
|
end
|
2041
2099
|
|
2042
|
-
q.
|
2100
|
+
q.breakable_space
|
2043
2101
|
q.text(closing)
|
2044
2102
|
end
|
2045
2103
|
|
@@ -2048,17 +2106,17 @@ module SyntaxTree
|
|
2048
2106
|
q.format(BlockOpenFormatter.new(opening, block_open), stackable: false)
|
2049
2107
|
|
2050
2108
|
if node.block_var
|
2051
|
-
q.
|
2109
|
+
q.breakable_space
|
2052
2110
|
q.format(node.block_var)
|
2053
|
-
q.
|
2111
|
+
q.breakable_space
|
2054
2112
|
end
|
2055
2113
|
|
2056
2114
|
if statements.empty?
|
2057
2115
|
q.text(" ") if opening == "do"
|
2058
2116
|
else
|
2059
|
-
q.
|
2117
|
+
q.breakable_space unless node.block_var
|
2060
2118
|
q.format(statements)
|
2061
|
-
q.
|
2119
|
+
q.breakable_space
|
2062
2120
|
end
|
2063
2121
|
|
2064
2122
|
q.text(closing)
|
@@ -2133,105 +2191,128 @@ module SyntaxTree
|
|
2133
2191
|
q.group do
|
2134
2192
|
q.text(keyword)
|
2135
2193
|
|
2136
|
-
|
2137
|
-
|
2194
|
+
parts = node.arguments.parts
|
2195
|
+
length = parts.length
|
2196
|
+
|
2197
|
+
if length == 0
|
2138
2198
|
# Here there are no arguments at all, so we're not going to print
|
2139
2199
|
# anything. This would be like if we had:
|
2140
2200
|
#
|
2141
2201
|
# break
|
2142
2202
|
#
|
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
|
2203
|
+
elsif length >= 2
|
2231
2204
|
# If there are multiple arguments, format them all. If the line is
|
2232
2205
|
# going to break into multiple, then use brackets to start and end the
|
2233
2206
|
# expression.
|
2234
2207
|
format_arguments(q, " [", "]")
|
2208
|
+
else
|
2209
|
+
# If we get here, then we're formatting a single argument to the flow
|
2210
|
+
# control keyword.
|
2211
|
+
part = parts.first
|
2212
|
+
|
2213
|
+
case part
|
2214
|
+
when Paren
|
2215
|
+
statements = part.contents.body
|
2216
|
+
|
2217
|
+
if statements.length == 1
|
2218
|
+
statement = statements.first
|
2219
|
+
|
2220
|
+
if statement.is_a?(ArrayLiteral)
|
2221
|
+
contents = statement.contents
|
2222
|
+
|
2223
|
+
if contents && contents.parts.length >= 2
|
2224
|
+
# Here we have a single argument that is a set of parentheses
|
2225
|
+
# wrapping an array literal that has at least 2 elements.
|
2226
|
+
# We're going to print the contents of the array directly.
|
2227
|
+
# This would be like if we had:
|
2228
|
+
#
|
2229
|
+
# break([1, 2, 3])
|
2230
|
+
#
|
2231
|
+
# which we will print as:
|
2232
|
+
#
|
2233
|
+
# break 1, 2, 3
|
2234
|
+
#
|
2235
|
+
q.text(" ")
|
2236
|
+
format_array_contents(q, statement)
|
2237
|
+
else
|
2238
|
+
# Here we have a single argument that is a set of parentheses
|
2239
|
+
# wrapping an array literal that has 0 or 1 elements. We're
|
2240
|
+
# going to skip the parentheses but print the array itself.
|
2241
|
+
# This would be like if we had:
|
2242
|
+
#
|
2243
|
+
# break([1])
|
2244
|
+
#
|
2245
|
+
# which we will print as:
|
2246
|
+
#
|
2247
|
+
# break [1]
|
2248
|
+
#
|
2249
|
+
q.text(" ")
|
2250
|
+
q.format(statement)
|
2251
|
+
end
|
2252
|
+
elsif skip_parens?(statement)
|
2253
|
+
# Here we have a single argument that is a set of parentheses
|
2254
|
+
# that themselves contain a single statement. That statement is
|
2255
|
+
# a simple value that we can skip the parentheses for. This
|
2256
|
+
# would be like if we had:
|
2257
|
+
#
|
2258
|
+
# break(1)
|
2259
|
+
#
|
2260
|
+
# which we will print as:
|
2261
|
+
#
|
2262
|
+
# break 1
|
2263
|
+
#
|
2264
|
+
q.text(" ")
|
2265
|
+
q.format(statement)
|
2266
|
+
else
|
2267
|
+
# Here we have a single argument that is a set of parentheses.
|
2268
|
+
# We're going to print the parentheses themselves as if they
|
2269
|
+
# were the set of arguments. This would be like if we had:
|
2270
|
+
#
|
2271
|
+
# break(foo.bar)
|
2272
|
+
#
|
2273
|
+
q.format(part)
|
2274
|
+
end
|
2275
|
+
else
|
2276
|
+
q.format(part)
|
2277
|
+
end
|
2278
|
+
when ArrayLiteral
|
2279
|
+
contents = part.contents
|
2280
|
+
|
2281
|
+
if contents && contents.parts.length >= 2
|
2282
|
+
# Here there is a single argument that is an array literal with at
|
2283
|
+
# least two elements. We skip directly into the array literal's
|
2284
|
+
# elements in order to print the contents. This would be like if
|
2285
|
+
# we had:
|
2286
|
+
#
|
2287
|
+
# break [1, 2, 3]
|
2288
|
+
#
|
2289
|
+
# which we will print as:
|
2290
|
+
#
|
2291
|
+
# break 1, 2, 3
|
2292
|
+
#
|
2293
|
+
q.text(" ")
|
2294
|
+
format_array_contents(q, part)
|
2295
|
+
else
|
2296
|
+
# Here there is a single argument that is an array literal with 0
|
2297
|
+
# or 1 elements. In this case we're going to print the array as it
|
2298
|
+
# is because skipping the brackets would change the remaining.
|
2299
|
+
# This would be like if we had:
|
2300
|
+
#
|
2301
|
+
# break []
|
2302
|
+
# break [1]
|
2303
|
+
#
|
2304
|
+
q.text(" ")
|
2305
|
+
q.format(part)
|
2306
|
+
end
|
2307
|
+
else
|
2308
|
+
# Here there is a single argument that hasn't matched one of our
|
2309
|
+
# previous cases. We're going to print the argument as it is. This
|
2310
|
+
# would be like if we had:
|
2311
|
+
#
|
2312
|
+
# break foo
|
2313
|
+
#
|
2314
|
+
format_arguments(q, "(", ")")
|
2315
|
+
end
|
2235
2316
|
end
|
2236
2317
|
end
|
2237
2318
|
end
|
@@ -2241,29 +2322,34 @@ module SyntaxTree
|
|
2241
2322
|
def format_array_contents(q, array)
|
2242
2323
|
q.if_break { q.text("[") }
|
2243
2324
|
q.indent do
|
2244
|
-
q.
|
2325
|
+
q.breakable_empty
|
2245
2326
|
q.format(array.contents)
|
2246
2327
|
end
|
2247
|
-
q.
|
2328
|
+
q.breakable_empty
|
2248
2329
|
q.if_break { q.text("]") }
|
2249
2330
|
end
|
2250
2331
|
|
2251
2332
|
def format_arguments(q, opening, closing)
|
2252
2333
|
q.if_break { q.text(opening) }
|
2253
2334
|
q.indent do
|
2254
|
-
q.
|
2335
|
+
q.breakable_space
|
2255
2336
|
q.format(node.arguments)
|
2256
2337
|
end
|
2257
|
-
q.
|
2338
|
+
q.breakable_empty
|
2258
2339
|
q.if_break { q.text(closing) }
|
2259
2340
|
end
|
2260
2341
|
|
2261
2342
|
def skip_parens?(node)
|
2262
2343
|
case node
|
2263
|
-
|
2264
|
-
true
|
2265
|
-
in VarRef[value: Const | CVar | GVar | IVar | Kw]
|
2344
|
+
when FloatLiteral, Imaginary, Int, RationalLiteral
|
2266
2345
|
true
|
2346
|
+
when VarRef
|
2347
|
+
case node.value
|
2348
|
+
when Const, CVar, GVar, IVar, Kw
|
2349
|
+
true
|
2350
|
+
else
|
2351
|
+
false
|
2352
|
+
end
|
2267
2353
|
else
|
2268
2354
|
false
|
2269
2355
|
end
|
@@ -2326,8 +2412,10 @@ module SyntaxTree
|
|
2326
2412
|
|
2327
2413
|
def format(q)
|
2328
2414
|
case operator
|
2329
|
-
|
2415
|
+
when :"::"
|
2330
2416
|
q.text(".")
|
2417
|
+
when Op
|
2418
|
+
operator.value == "::" ? q.text(".") : operator.format(q)
|
2331
2419
|
else
|
2332
2420
|
operator.format(q)
|
2333
2421
|
end
|
@@ -2363,13 +2451,18 @@ module SyntaxTree
|
|
2363
2451
|
# First, walk down the chain until we get to the point where we're not
|
2364
2452
|
# longer at a chainable node.
|
2365
2453
|
loop do
|
2366
|
-
case children.last
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2454
|
+
case (child = children.last)
|
2455
|
+
when Call
|
2456
|
+
case (receiver = child.receiver)
|
2457
|
+
when Call
|
2458
|
+
children << receiver
|
2459
|
+
when MethodAddBlock
|
2460
|
+
receiver.call.is_a?(Call) ? children << receiver : break
|
2461
|
+
else
|
2462
|
+
break
|
2463
|
+
end
|
2464
|
+
when MethodAddBlock
|
2465
|
+
child.call.is_a?(Call) ? children << child.call : break
|
2373
2466
|
else
|
2374
2467
|
break
|
2375
2468
|
end
|
@@ -2388,10 +2481,9 @@ module SyntaxTree
|
|
2388
2481
|
# nodes.
|
2389
2482
|
parent = parents[3] if parent.is_a?(DoBlock)
|
2390
2483
|
|
2391
|
-
|
2392
|
-
|
2484
|
+
if parent.is_a?(MethodAddBlock) && parent.call.is_a?(FCall) &&
|
2485
|
+
parent.call.value.value == "sig"
|
2393
2486
|
threshold = 2
|
2394
|
-
else
|
2395
2487
|
end
|
2396
2488
|
end
|
2397
2489
|
|
@@ -2434,20 +2526,21 @@ module SyntaxTree
|
|
2434
2526
|
skip_operator = false
|
2435
2527
|
|
2436
2528
|
while (child = children.pop)
|
2437
|
-
|
2438
|
-
|
2439
|
-
|
2440
|
-
|
2441
|
-
|
2442
|
-
|
2443
|
-
|
2444
|
-
|
2445
|
-
|
2446
|
-
|
2447
|
-
|
2448
|
-
|
2449
|
-
|
2450
|
-
|
2529
|
+
if child.is_a?(Call)
|
2530
|
+
if child.receiver.is_a?(Call) &&
|
2531
|
+
(child.receiver.message != :call) &&
|
2532
|
+
(child.receiver.message.value == "where") &&
|
2533
|
+
(child.message.value == "not")
|
2534
|
+
# This is very specialized behavior wherein we group
|
2535
|
+
# .where.not calls together because it looks better. For more
|
2536
|
+
# information, see
|
2537
|
+
# https://github.com/prettier/plugin-ruby/issues/862.
|
2538
|
+
else
|
2539
|
+
# If we're at a Call node and not a MethodAddBlock node in the
|
2540
|
+
# chain then we're going to add a newline so it indents
|
2541
|
+
# properly.
|
2542
|
+
q.breakable_empty
|
2543
|
+
end
|
2451
2544
|
end
|
2452
2545
|
|
2453
2546
|
format_child(
|
@@ -2460,9 +2553,9 @@ module SyntaxTree
|
|
2460
2553
|
|
2461
2554
|
# If the parent call node has a comment on the message then we need
|
2462
2555
|
# to print the operator trailing in order to keep it working.
|
2463
|
-
|
2464
|
-
|
2465
|
-
q.format(CallOperatorFormatter.new(operator))
|
2556
|
+
last_child = children.last
|
2557
|
+
if last_child.is_a?(Call) && last_child.message.comments.any?
|
2558
|
+
q.format(CallOperatorFormatter.new(last_child.operator))
|
2466
2559
|
skip_operator = true
|
2467
2560
|
else
|
2468
2561
|
skip_operator = false
|
@@ -2477,18 +2570,22 @@ module SyntaxTree
|
|
2477
2570
|
|
2478
2571
|
if empty_except_last
|
2479
2572
|
case node
|
2480
|
-
|
2573
|
+
when Call
|
2481
2574
|
node.format_arguments(q)
|
2482
|
-
|
2483
|
-
q.format(block)
|
2575
|
+
when MethodAddBlock
|
2576
|
+
q.format(node.block)
|
2484
2577
|
end
|
2485
2578
|
end
|
2486
2579
|
end
|
2487
2580
|
|
2488
2581
|
def self.chained?(node)
|
2582
|
+
return false if ENV["STREE_FAST_FORMAT"]
|
2583
|
+
|
2489
2584
|
case node
|
2490
|
-
|
2585
|
+
when Call
|
2491
2586
|
true
|
2587
|
+
when MethodAddBlock
|
2588
|
+
node.call.is_a?(Call)
|
2492
2589
|
else
|
2493
2590
|
false
|
2494
2591
|
end
|
@@ -2500,9 +2597,12 @@ module SyntaxTree
|
|
2500
2597
|
# want to indent the first call. So we'll pop off the first children and
|
2501
2598
|
# format it separately here.
|
2502
2599
|
def attach_directly?(node)
|
2503
|
-
|
2504
|
-
|
2505
|
-
|
2600
|
+
case node.receiver
|
2601
|
+
when ArrayLiteral, HashLiteral, Heredoc, If, Unless, XStringLiteral
|
2602
|
+
true
|
2603
|
+
else
|
2604
|
+
false
|
2605
|
+
end
|
2506
2606
|
end
|
2507
2607
|
|
2508
2608
|
def format_child(
|
@@ -2514,7 +2614,7 @@ module SyntaxTree
|
|
2514
2614
|
)
|
2515
2615
|
# First, format the actual contents of the child.
|
2516
2616
|
case child
|
2517
|
-
|
2617
|
+
when Call
|
2518
2618
|
q.group do
|
2519
2619
|
unless skip_operator
|
2520
2620
|
q.format(CallOperatorFormatter.new(child.operator))
|
@@ -2522,7 +2622,7 @@ module SyntaxTree
|
|
2522
2622
|
q.format(child.message) if child.message != :call
|
2523
2623
|
child.format_arguments(q) unless skip_attached
|
2524
2624
|
end
|
2525
|
-
|
2625
|
+
when MethodAddBlock
|
2526
2626
|
q.format(child.block) unless skip_attached
|
2527
2627
|
end
|
2528
2628
|
|
@@ -2530,7 +2630,7 @@ module SyntaxTree
|
|
2530
2630
|
# them out here since we're bypassing the normal comment printing.
|
2531
2631
|
if child.comments.any? && !skip_comments
|
2532
2632
|
child.comments.each do |comment|
|
2533
|
-
comment.inline? ? q.text(" ") : q.
|
2633
|
+
comment.inline? ? q.text(" ") : q.breakable_space
|
2534
2634
|
comment.format(q)
|
2535
2635
|
end
|
2536
2636
|
|
@@ -2605,8 +2705,8 @@ module SyntaxTree
|
|
2605
2705
|
# If we're at the top of a call chain, then we're going to do some
|
2606
2706
|
# specialized printing in case we can print it nicely. We _only_ do this
|
2607
2707
|
# at the top of the chain to avoid weird recursion issues.
|
2608
|
-
if
|
2609
|
-
CallChainFormatter.chained?(
|
2708
|
+
if CallChainFormatter.chained?(receiver) &&
|
2709
|
+
!CallChainFormatter.chained?(q.parent)
|
2610
2710
|
q.group do
|
2611
2711
|
q
|
2612
2712
|
.if_break { CallChainFormatter.new(self).format(q) }
|
@@ -2617,15 +2717,15 @@ module SyntaxTree
|
|
2617
2717
|
end
|
2618
2718
|
end
|
2619
2719
|
|
2720
|
+
# Print out the arguments to this call. If there are no arguments, then do
|
2721
|
+
#nothing.
|
2620
2722
|
def format_arguments(q)
|
2621
2723
|
case arguments
|
2622
|
-
|
2724
|
+
when ArgParen
|
2623
2725
|
q.format(arguments)
|
2624
|
-
|
2726
|
+
when Args
|
2625
2727
|
q.text(" ")
|
2626
2728
|
q.format(arguments)
|
2627
|
-
else
|
2628
|
-
# Do nothing if there are no arguments.
|
2629
2729
|
end
|
2630
2730
|
end
|
2631
2731
|
|
@@ -2642,7 +2742,7 @@ module SyntaxTree
|
|
2642
2742
|
q.group do
|
2643
2743
|
q.indent do
|
2644
2744
|
if receiver.comments.any? || call_operator.comments.any?
|
2645
|
-
q.
|
2745
|
+
q.breakable_force
|
2646
2746
|
end
|
2647
2747
|
|
2648
2748
|
if call_operator.comments.empty?
|
@@ -2719,9 +2819,9 @@ module SyntaxTree
|
|
2719
2819
|
q.format(value)
|
2720
2820
|
end
|
2721
2821
|
|
2722
|
-
q.
|
2822
|
+
q.breakable_force
|
2723
2823
|
q.format(consequent)
|
2724
|
-
q.
|
2824
|
+
q.breakable_force
|
2725
2825
|
|
2726
2826
|
q.text("end")
|
2727
2827
|
end
|
@@ -2782,13 +2882,13 @@ module SyntaxTree
|
|
2782
2882
|
q.format(operator)
|
2783
2883
|
|
2784
2884
|
case pattern
|
2785
|
-
|
2885
|
+
when AryPtn, FndPtn, HshPtn
|
2786
2886
|
q.text(" ")
|
2787
2887
|
q.format(pattern)
|
2788
2888
|
else
|
2789
2889
|
q.group do
|
2790
2890
|
q.indent do
|
2791
|
-
q.
|
2891
|
+
q.breakable_space
|
2792
2892
|
q.format(pattern)
|
2793
2893
|
end
|
2794
2894
|
end
|
@@ -2872,38 +2972,40 @@ module SyntaxTree
|
|
2872
2972
|
end
|
2873
2973
|
|
2874
2974
|
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
2975
|
if bodystmt.empty?
|
2888
2976
|
q.group do
|
2889
|
-
|
2890
|
-
q.
|
2977
|
+
format_declaration(q)
|
2978
|
+
q.breakable_force
|
2891
2979
|
q.text("end")
|
2892
2980
|
end
|
2893
2981
|
else
|
2894
2982
|
q.group do
|
2895
|
-
|
2983
|
+
format_declaration(q)
|
2896
2984
|
|
2897
2985
|
q.indent do
|
2898
|
-
q.
|
2986
|
+
q.breakable_force
|
2899
2987
|
q.format(bodystmt)
|
2900
2988
|
end
|
2901
2989
|
|
2902
|
-
q.
|
2990
|
+
q.breakable_force
|
2903
2991
|
q.text("end")
|
2904
2992
|
end
|
2905
2993
|
end
|
2906
2994
|
end
|
2995
|
+
|
2996
|
+
private
|
2997
|
+
|
2998
|
+
def format_declaration(q)
|
2999
|
+
q.group do
|
3000
|
+
q.text("class ")
|
3001
|
+
q.format(constant)
|
3002
|
+
|
3003
|
+
if superclass
|
3004
|
+
q.text(" < ")
|
3005
|
+
q.format(superclass)
|
3006
|
+
end
|
3007
|
+
end
|
3008
|
+
end
|
2907
3009
|
end
|
2908
3010
|
|
2909
3011
|
# Comma represents the use of the , operator.
|
@@ -2983,15 +3085,31 @@ module SyntaxTree
|
|
2983
3085
|
private
|
2984
3086
|
|
2985
3087
|
def align(q, node, &block)
|
2986
|
-
|
2987
|
-
|
2988
|
-
|
2989
|
-
|
2990
|
-
|
2991
|
-
|
2992
|
-
|
2993
|
-
|
2994
|
-
|
3088
|
+
arguments = node.arguments
|
3089
|
+
|
3090
|
+
if arguments.is_a?(Args)
|
3091
|
+
parts = arguments.parts
|
3092
|
+
|
3093
|
+
if parts.size == 1
|
3094
|
+
part = parts.first
|
3095
|
+
|
3096
|
+
case part
|
3097
|
+
when Def, Defs, DefEndless
|
3098
|
+
q.text(" ")
|
3099
|
+
yield
|
3100
|
+
when IfOp
|
3101
|
+
q.if_flat { q.text(" ") }
|
3102
|
+
yield
|
3103
|
+
when Command
|
3104
|
+
align(q, part, &block)
|
3105
|
+
else
|
3106
|
+
q.text(" ")
|
3107
|
+
q.nest(message.value.length + 1) { yield }
|
3108
|
+
end
|
3109
|
+
else
|
3110
|
+
q.text(" ")
|
3111
|
+
q.nest(message.value.length + 1) { yield }
|
3112
|
+
end
|
2995
3113
|
else
|
2996
3114
|
q.text(" ")
|
2997
3115
|
q.nest(message.value.length + 1) { yield }
|
@@ -3069,7 +3187,7 @@ module SyntaxTree
|
|
3069
3187
|
if message.comments.any?(&:leading?)
|
3070
3188
|
q.format(CallOperatorFormatter.new(operator), stackable: false)
|
3071
3189
|
q.indent do
|
3072
|
-
q.
|
3190
|
+
q.breakable_empty
|
3073
3191
|
q.format(message)
|
3074
3192
|
end
|
3075
3193
|
else
|
@@ -3078,15 +3196,18 @@ module SyntaxTree
|
|
3078
3196
|
end
|
3079
3197
|
end
|
3080
3198
|
|
3081
|
-
|
3082
|
-
|
3083
|
-
|
3084
|
-
|
3085
|
-
|
3086
|
-
|
3087
|
-
|
3088
|
-
|
3089
|
-
|
3199
|
+
# Format the arguments for this command call here. If there are no
|
3200
|
+
# arguments, then print nothing.
|
3201
|
+
if arguments
|
3202
|
+
parts = arguments.parts
|
3203
|
+
|
3204
|
+
if parts.length == 1 && parts.first.is_a?(IfOp)
|
3205
|
+
q.if_flat { q.text(" ") }
|
3206
|
+
q.format(arguments)
|
3207
|
+
else
|
3208
|
+
q.text(" ")
|
3209
|
+
q.nest(argument_alignment(q, doc)) { q.format(arguments) }
|
3210
|
+
end
|
3090
3211
|
end
|
3091
3212
|
end
|
3092
3213
|
end
|
@@ -3155,7 +3276,7 @@ module SyntaxTree
|
|
3155
3276
|
end
|
3156
3277
|
|
3157
3278
|
def ignore?
|
3158
|
-
value
|
3279
|
+
value.match?(/\A#\s*stree-ignore\s*\z/)
|
3159
3280
|
end
|
3160
3281
|
|
3161
3282
|
def comments
|
@@ -3455,12 +3576,12 @@ module SyntaxTree
|
|
3455
3576
|
|
3456
3577
|
unless bodystmt.empty?
|
3457
3578
|
q.indent do
|
3458
|
-
q.
|
3579
|
+
q.breakable_force
|
3459
3580
|
q.format(bodystmt)
|
3460
3581
|
end
|
3461
3582
|
end
|
3462
3583
|
|
3463
|
-
q.
|
3584
|
+
q.breakable_force
|
3464
3585
|
q.text("end")
|
3465
3586
|
end
|
3466
3587
|
end
|
@@ -3549,7 +3670,7 @@ module SyntaxTree
|
|
3549
3670
|
q.text(" =")
|
3550
3671
|
q.group do
|
3551
3672
|
q.indent do
|
3552
|
-
q.
|
3673
|
+
q.breakable_space
|
3553
3674
|
q.format(statement)
|
3554
3675
|
end
|
3555
3676
|
end
|
@@ -3590,13 +3711,15 @@ module SyntaxTree
|
|
3590
3711
|
end
|
3591
3712
|
|
3592
3713
|
def format(q)
|
3593
|
-
q.
|
3714
|
+
q.text("defined?(")
|
3715
|
+
q.group do
|
3594
3716
|
q.indent do
|
3595
|
-
q.
|
3717
|
+
q.breakable_empty
|
3596
3718
|
q.format(value)
|
3597
3719
|
end
|
3598
|
-
q.
|
3720
|
+
q.breakable_empty
|
3599
3721
|
end
|
3722
|
+
q.text(")")
|
3600
3723
|
end
|
3601
3724
|
end
|
3602
3725
|
|
@@ -3678,12 +3801,12 @@ module SyntaxTree
|
|
3678
3801
|
|
3679
3802
|
unless bodystmt.empty?
|
3680
3803
|
q.indent do
|
3681
|
-
q.
|
3804
|
+
q.breakable_force
|
3682
3805
|
q.format(bodystmt)
|
3683
3806
|
end
|
3684
3807
|
end
|
3685
3808
|
|
3686
|
-
q.
|
3809
|
+
q.breakable_force
|
3687
3810
|
q.text("end")
|
3688
3811
|
end
|
3689
3812
|
end
|
@@ -3755,15 +3878,18 @@ module SyntaxTree
|
|
3755
3878
|
end
|
3756
3879
|
|
3757
3880
|
def format(q)
|
3758
|
-
space = [If, IfMod, Unless, UnlessMod].include?(q.parent.class)
|
3759
|
-
|
3760
3881
|
left = node.left
|
3761
3882
|
right = node.right
|
3762
3883
|
|
3763
3884
|
q.format(left) if left
|
3764
|
-
|
3765
|
-
q.
|
3766
|
-
|
3885
|
+
|
3886
|
+
case q.parent
|
3887
|
+
when If, IfMod, Unless, UnlessMod
|
3888
|
+
q.text(" #{operator} ")
|
3889
|
+
else
|
3890
|
+
q.text(operator)
|
3891
|
+
end
|
3892
|
+
|
3767
3893
|
q.format(right) if right
|
3768
3894
|
end
|
3769
3895
|
end
|
@@ -3948,19 +4074,30 @@ module SyntaxTree
|
|
3948
4074
|
def format(q)
|
3949
4075
|
opening_quote, closing_quote = quotes(q)
|
3950
4076
|
|
3951
|
-
q.
|
4077
|
+
q.text(opening_quote)
|
4078
|
+
q.group do
|
3952
4079
|
parts.each do |part|
|
3953
4080
|
if part.is_a?(TStringContent)
|
3954
4081
|
value = Quotes.normalize(part.value, closing_quote)
|
3955
|
-
|
3956
|
-
|
3957
|
-
|
4082
|
+
first = true
|
4083
|
+
|
4084
|
+
value.each_line(chomp: true) do |line|
|
4085
|
+
if first
|
4086
|
+
first = false
|
4087
|
+
else
|
4088
|
+
q.breakable_return
|
4089
|
+
end
|
4090
|
+
|
4091
|
+
q.text(line)
|
3958
4092
|
end
|
4093
|
+
|
4094
|
+
q.breakable_return if value.end_with?("\n")
|
3959
4095
|
else
|
3960
4096
|
q.format(part)
|
3961
4097
|
end
|
3962
4098
|
end
|
3963
4099
|
end
|
4100
|
+
q.text(closing_quote)
|
3964
4101
|
end
|
3965
4102
|
|
3966
4103
|
private
|
@@ -4056,7 +4193,7 @@ module SyntaxTree
|
|
4056
4193
|
|
4057
4194
|
unless statements.empty?
|
4058
4195
|
q.indent do
|
4059
|
-
q.
|
4196
|
+
q.breakable_force
|
4060
4197
|
q.format(statements)
|
4061
4198
|
end
|
4062
4199
|
end
|
@@ -4126,14 +4263,14 @@ module SyntaxTree
|
|
4126
4263
|
|
4127
4264
|
unless statements.empty?
|
4128
4265
|
q.indent do
|
4129
|
-
q.
|
4266
|
+
q.breakable_force
|
4130
4267
|
q.format(statements)
|
4131
4268
|
end
|
4132
4269
|
end
|
4133
4270
|
|
4134
4271
|
if consequent
|
4135
4272
|
q.group do
|
4136
|
-
q.
|
4273
|
+
q.breakable_force
|
4137
4274
|
q.format(consequent)
|
4138
4275
|
end
|
4139
4276
|
end
|
@@ -4329,7 +4466,7 @@ module SyntaxTree
|
|
4329
4466
|
|
4330
4467
|
unless statements.empty?
|
4331
4468
|
q.indent do
|
4332
|
-
q.
|
4469
|
+
q.breakable_force
|
4333
4470
|
q.format(statements)
|
4334
4471
|
end
|
4335
4472
|
end
|
@@ -4588,7 +4725,7 @@ module SyntaxTree
|
|
4588
4725
|
q.text("[")
|
4589
4726
|
|
4590
4727
|
q.indent do
|
4591
|
-
q.
|
4728
|
+
q.breakable_empty
|
4592
4729
|
|
4593
4730
|
q.text("*")
|
4594
4731
|
q.format(left)
|
@@ -4601,7 +4738,7 @@ module SyntaxTree
|
|
4601
4738
|
q.format(right)
|
4602
4739
|
end
|
4603
4740
|
|
4604
|
-
q.
|
4741
|
+
q.breakable_empty
|
4605
4742
|
q.text("]")
|
4606
4743
|
end
|
4607
4744
|
end
|
@@ -4663,12 +4800,12 @@ module SyntaxTree
|
|
4663
4800
|
|
4664
4801
|
unless statements.empty?
|
4665
4802
|
q.indent do
|
4666
|
-
q.
|
4803
|
+
q.breakable_force
|
4667
4804
|
q.format(statements)
|
4668
4805
|
end
|
4669
4806
|
end
|
4670
4807
|
|
4671
|
-
q.
|
4808
|
+
q.breakable_force
|
4672
4809
|
q.text("end")
|
4673
4810
|
end
|
4674
4811
|
end
|
@@ -4731,11 +4868,11 @@ module SyntaxTree
|
|
4731
4868
|
q.text("{")
|
4732
4869
|
q.indent do
|
4733
4870
|
lbrace.comments.each do |comment|
|
4734
|
-
q.
|
4871
|
+
q.breakable_force
|
4735
4872
|
comment.format(q)
|
4736
4873
|
end
|
4737
4874
|
end
|
4738
|
-
q.
|
4875
|
+
q.breakable_force
|
4739
4876
|
q.text("}")
|
4740
4877
|
end
|
4741
4878
|
end
|
@@ -4800,14 +4937,14 @@ module SyntaxTree
|
|
4800
4937
|
q.format(lbrace)
|
4801
4938
|
|
4802
4939
|
if assocs.empty?
|
4803
|
-
q.
|
4940
|
+
q.breakable_empty
|
4804
4941
|
else
|
4805
4942
|
q.indent do
|
4806
|
-
q.
|
4943
|
+
q.breakable_space
|
4807
4944
|
q.seplist(assocs) { |assoc| q.format(assoc) }
|
4808
4945
|
q.if_break { q.text(",") } if q.trailing_comma?
|
4809
4946
|
end
|
4810
|
-
q.
|
4947
|
+
q.breakable_space
|
4811
4948
|
end
|
4812
4949
|
|
4813
4950
|
q.text("}")
|
@@ -4873,22 +5010,34 @@ module SyntaxTree
|
|
4873
5010
|
}
|
4874
5011
|
end
|
4875
5012
|
|
4876
|
-
|
4877
|
-
|
4878
|
-
|
4879
|
-
breakable = -> { q.breakable(indent: false, force: :skip_break_parent) }
|
5013
|
+
# This is a very specific behavior where you want to force a newline, but
|
5014
|
+
# don't want to force the break parent.
|
5015
|
+
SEPARATOR = PrettierPrint::Breakable.new(" ", 1, indent: false, force: true)
|
4880
5016
|
|
5017
|
+
def format(q)
|
4881
5018
|
q.group do
|
4882
5019
|
q.format(beginning)
|
4883
5020
|
|
4884
5021
|
q.line_suffix(priority: Formatter::HEREDOC_PRIORITY) do
|
4885
5022
|
q.group do
|
4886
|
-
|
5023
|
+
q.target << SEPARATOR
|
4887
5024
|
|
4888
5025
|
parts.each do |part|
|
4889
5026
|
if part.is_a?(TStringContent)
|
4890
|
-
|
4891
|
-
|
5027
|
+
value = part.value
|
5028
|
+
first = true
|
5029
|
+
|
5030
|
+
value.each_line(chomp: true) do |line|
|
5031
|
+
if first
|
5032
|
+
first = false
|
5033
|
+
else
|
5034
|
+
q.target << SEPARATOR
|
5035
|
+
end
|
5036
|
+
|
5037
|
+
q.text(line)
|
5038
|
+
end
|
5039
|
+
|
5040
|
+
q.target << SEPARATOR if value.end_with?("\n")
|
4892
5041
|
else
|
4893
5042
|
q.format(part)
|
4894
5043
|
end
|
@@ -5077,18 +5226,7 @@ module SyntaxTree
|
|
5077
5226
|
def format(q)
|
5078
5227
|
parts = keywords.map { |(key, value)| KeywordFormatter.new(key, value) }
|
5079
5228
|
parts << KeywordRestFormatter.new(keyword_rest) if keyword_rest
|
5080
|
-
|
5081
5229
|
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
5230
|
|
5093
5231
|
# If there is a constant, we're going to format to have the constant name
|
5094
5232
|
# first and then use brackets.
|
@@ -5097,10 +5235,10 @@ module SyntaxTree
|
|
5097
5235
|
q.format(constant)
|
5098
5236
|
q.text("[")
|
5099
5237
|
q.indent do
|
5100
|
-
q.
|
5101
|
-
|
5238
|
+
q.breakable_empty
|
5239
|
+
format_contents(q, parts, nested)
|
5102
5240
|
end
|
5103
|
-
q.
|
5241
|
+
q.breakable_empty
|
5104
5242
|
q.text("]")
|
5105
5243
|
end
|
5106
5244
|
return
|
@@ -5115,7 +5253,7 @@ module SyntaxTree
|
|
5115
5253
|
# If there's only one pair, then we'll just print the contents provided
|
5116
5254
|
# we're not inside another pattern.
|
5117
5255
|
if !nested && parts.size == 1
|
5118
|
-
|
5256
|
+
format_contents(q, parts, nested)
|
5119
5257
|
return
|
5120
5258
|
end
|
5121
5259
|
|
@@ -5124,18 +5262,31 @@ module SyntaxTree
|
|
5124
5262
|
q.group do
|
5125
5263
|
q.text("{")
|
5126
5264
|
q.indent do
|
5127
|
-
q.
|
5128
|
-
|
5265
|
+
q.breakable_space
|
5266
|
+
format_contents(q, parts, nested)
|
5129
5267
|
end
|
5130
5268
|
|
5131
5269
|
if q.target_ruby_version < Gem::Version.new("2.7.3")
|
5132
5270
|
q.text(" }")
|
5133
5271
|
else
|
5134
|
-
q.
|
5272
|
+
q.breakable_space
|
5135
5273
|
q.text("}")
|
5136
5274
|
end
|
5137
5275
|
end
|
5138
5276
|
end
|
5277
|
+
|
5278
|
+
private
|
5279
|
+
|
5280
|
+
def format_contents(q, parts, nested)
|
5281
|
+
q.group { q.seplist(parts) { |part| q.format(part, stackable: false) } }
|
5282
|
+
|
5283
|
+
# If there isn't a constant, and there's a blank keyword_rest, then we
|
5284
|
+
# have an plain ** that needs to have a `then` after it in order to
|
5285
|
+
# parse correctly on the next parse.
|
5286
|
+
if !constant && keyword_rest && keyword_rest.value.nil? && !nested
|
5287
|
+
q.text(" then")
|
5288
|
+
end
|
5289
|
+
end
|
5139
5290
|
end
|
5140
5291
|
|
5141
5292
|
# The list of nodes that represent patterns inside of pattern matching so that
|
@@ -5188,8 +5339,12 @@ module SyntaxTree
|
|
5188
5339
|
queue = [parent]
|
5189
5340
|
|
5190
5341
|
while (node = queue.shift)
|
5191
|
-
|
5192
|
-
|
5342
|
+
case node
|
5343
|
+
when Assign, MAssign, OpAssign
|
5344
|
+
return true
|
5345
|
+
else
|
5346
|
+
node.child_nodes.each { |child| queue << child if child }
|
5347
|
+
end
|
5193
5348
|
end
|
5194
5349
|
|
5195
5350
|
false
|
@@ -5204,28 +5359,36 @@ module SyntaxTree
|
|
5204
5359
|
module Ternaryable
|
5205
5360
|
class << self
|
5206
5361
|
def call(q, node)
|
5207
|
-
|
5208
|
-
|
5209
|
-
|
5210
|
-
|
5211
|
-
|
5212
|
-
|
5213
|
-
|
5214
|
-
|
5215
|
-
|
5216
|
-
|
5217
|
-
|
5218
|
-
|
5219
|
-
|
5220
|
-
|
5221
|
-
|
5222
|
-
|
5223
|
-
|
5224
|
-
|
5225
|
-
|
5226
|
-
|
5227
|
-
end
|
5362
|
+
return false if ENV["STREE_FAST_FORMAT"]
|
5363
|
+
|
5364
|
+
# If this is a conditional inside of a parentheses as the only content,
|
5365
|
+
# then we don't want to transform it into a ternary. Presumably the user
|
5366
|
+
# wanted it to be an explicit conditional because there are parentheses
|
5367
|
+
# around it. So we'll just leave it in place.
|
5368
|
+
grandparent = q.grandparent
|
5369
|
+
if grandparent.is_a?(Paren) && (body = grandparent.contents.body) &&
|
5370
|
+
body.length == 1 && body.first == node
|
5371
|
+
return false
|
5372
|
+
end
|
5373
|
+
|
5374
|
+
# Otherwise, we'll check the type of predicate. For certain nodes we
|
5375
|
+
# want to force it to not be a ternary, like if the predicate is an
|
5376
|
+
# assignment because it's hard to read.
|
5377
|
+
case node.predicate
|
5378
|
+
when Assign, Command, CommandCall, MAssign, OpAssign
|
5379
|
+
return false
|
5380
|
+
when Not
|
5381
|
+
return false unless node.predicate.parentheses?
|
5228
5382
|
end
|
5383
|
+
|
5384
|
+
# If there's no Else, then this can't be represented as a ternary.
|
5385
|
+
return false unless node.consequent.is_a?(Else)
|
5386
|
+
|
5387
|
+
truthy_body = node.statements.body
|
5388
|
+
falsy_body = node.consequent.statements.body
|
5389
|
+
|
5390
|
+
(truthy_body.length == 1) && ternaryable?(truthy_body.first) &&
|
5391
|
+
(falsy_body.length == 1) && ternaryable?(falsy_body.first)
|
5229
5392
|
end
|
5230
5393
|
|
5231
5394
|
private
|
@@ -5234,24 +5397,23 @@ module SyntaxTree
|
|
5234
5397
|
# parentheses around them. In this case we say they cannot be ternaried
|
5235
5398
|
# and default instead to breaking them into multiple lines.
|
5236
5399
|
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))
|
5400
|
+
case statement
|
5401
|
+
when Alias, Assign, Break, Command, CommandCall, Heredoc, If, IfMod,
|
5402
|
+
IfOp, Lambda, MAssign, Next, OpAssign, RescueMod, Return, Return0,
|
5403
|
+
Super, Undef, Unless, UnlessMod, Until, UntilMod, VarAlias,
|
5404
|
+
VoidStmt, While, WhileMod, Yield, Yield0, ZSuper
|
5405
|
+
# This is a list of nodes that should not be allowed to be a part of a
|
5406
|
+
# ternary clause.
|
5407
|
+
false
|
5408
|
+
when Binary
|
5409
|
+
# If the user is using one of the lower precedence "and" or "or"
|
5410
|
+
# operators, then we can't use a ternary expression as it would break
|
5411
|
+
# the flow control.
|
5412
|
+
operator = statement.operator
|
5413
|
+
operator != :and && operator != :or
|
5414
|
+
else
|
5415
|
+
true
|
5416
|
+
end
|
5255
5417
|
end
|
5256
5418
|
end
|
5257
5419
|
end
|
@@ -5311,17 +5473,17 @@ module SyntaxTree
|
|
5311
5473
|
|
5312
5474
|
unless node.statements.empty?
|
5313
5475
|
q.indent do
|
5314
|
-
q.
|
5476
|
+
force ? q.breakable_force : q.breakable_space
|
5315
5477
|
q.format(node.statements)
|
5316
5478
|
end
|
5317
5479
|
end
|
5318
5480
|
|
5319
5481
|
if node.consequent
|
5320
|
-
q.
|
5482
|
+
force ? q.breakable_force : q.breakable_space
|
5321
5483
|
q.format(node.consequent)
|
5322
5484
|
end
|
5323
5485
|
|
5324
|
-
q.
|
5486
|
+
force ? q.breakable_force : q.breakable_space
|
5325
5487
|
q.text("end")
|
5326
5488
|
end
|
5327
5489
|
|
@@ -5333,11 +5495,11 @@ module SyntaxTree
|
|
5333
5495
|
q.nest(keyword.length + 1) { q.format(node.predicate) }
|
5334
5496
|
|
5335
5497
|
q.indent do
|
5336
|
-
q.
|
5498
|
+
q.breakable_space
|
5337
5499
|
q.format(node.statements)
|
5338
5500
|
end
|
5339
5501
|
|
5340
|
-
q.
|
5502
|
+
q.breakable_space
|
5341
5503
|
q.group do
|
5342
5504
|
q.format(node.consequent.keyword)
|
5343
5505
|
q.indent do
|
@@ -5351,7 +5513,7 @@ module SyntaxTree
|
|
5351
5513
|
end
|
5352
5514
|
end
|
5353
5515
|
|
5354
|
-
q.
|
5516
|
+
q.breakable_space
|
5355
5517
|
q.text("end")
|
5356
5518
|
end
|
5357
5519
|
.if_flat do
|
@@ -5371,8 +5533,11 @@ module SyntaxTree
|
|
5371
5533
|
end
|
5372
5534
|
|
5373
5535
|
def contains_conditional?
|
5374
|
-
|
5375
|
-
|
5536
|
+
statements = node.statements.body
|
5537
|
+
return false if statements.length != 1
|
5538
|
+
|
5539
|
+
case statements.first
|
5540
|
+
when If, IfMod, IfOp, Unless, UnlessMod
|
5376
5541
|
true
|
5377
5542
|
else
|
5378
5543
|
false
|
@@ -5507,19 +5672,19 @@ module SyntaxTree
|
|
5507
5672
|
q.nest("if ".length) { q.format(predicate) }
|
5508
5673
|
|
5509
5674
|
q.indent do
|
5510
|
-
q.
|
5675
|
+
q.breakable_space
|
5511
5676
|
q.format(truthy)
|
5512
5677
|
end
|
5513
5678
|
|
5514
|
-
q.
|
5679
|
+
q.breakable_space
|
5515
5680
|
q.text("else")
|
5516
5681
|
|
5517
5682
|
q.indent do
|
5518
|
-
q.
|
5683
|
+
q.breakable_space
|
5519
5684
|
q.format(falsy)
|
5520
5685
|
end
|
5521
5686
|
|
5522
|
-
q.
|
5687
|
+
q.breakable_space
|
5523
5688
|
q.text("end")
|
5524
5689
|
end
|
5525
5690
|
end
|
@@ -5529,11 +5694,11 @@ module SyntaxTree
|
|
5529
5694
|
q.text(" ?")
|
5530
5695
|
|
5531
5696
|
q.indent do
|
5532
|
-
q.
|
5697
|
+
q.breakable_space
|
5533
5698
|
q.format(truthy)
|
5534
5699
|
q.text(" :")
|
5535
5700
|
|
5536
|
-
q.
|
5701
|
+
q.breakable_space
|
5537
5702
|
q.format(falsy)
|
5538
5703
|
end
|
5539
5704
|
end
|
@@ -5566,10 +5731,10 @@ module SyntaxTree
|
|
5566
5731
|
q.text("#{keyword} ")
|
5567
5732
|
q.nest(keyword.length + 1) { q.format(node.predicate) }
|
5568
5733
|
q.indent do
|
5569
|
-
q.
|
5734
|
+
q.breakable_space
|
5570
5735
|
q.format(node.statement)
|
5571
5736
|
end
|
5572
|
-
q.
|
5737
|
+
q.breakable_space
|
5573
5738
|
q.text("end")
|
5574
5739
|
end
|
5575
5740
|
|
@@ -5720,13 +5885,13 @@ module SyntaxTree
|
|
5720
5885
|
|
5721
5886
|
unless statements.empty?
|
5722
5887
|
q.indent do
|
5723
|
-
q.
|
5888
|
+
q.breakable_force
|
5724
5889
|
q.format(statements)
|
5725
5890
|
end
|
5726
5891
|
end
|
5727
5892
|
|
5728
5893
|
if consequent
|
5729
|
-
q.
|
5894
|
+
q.breakable_force
|
5730
5895
|
q.format(consequent)
|
5731
5896
|
end
|
5732
5897
|
end
|
@@ -5830,11 +5995,15 @@ module SyntaxTree
|
|
5830
5995
|
# [String] the value of the keyword
|
5831
5996
|
attr_reader :value
|
5832
5997
|
|
5998
|
+
# [Symbol] the symbol version of the value
|
5999
|
+
attr_reader :name
|
6000
|
+
|
5833
6001
|
# [Array[ Comment | EmbDoc ]] the comments attached to this node
|
5834
6002
|
attr_reader :comments
|
5835
6003
|
|
5836
6004
|
def initialize(value:, location:, comments: [])
|
5837
6005
|
@value = value
|
6006
|
+
@name = value.to_sym
|
5838
6007
|
@location = location
|
5839
6008
|
@comments = comments
|
5840
6009
|
end
|
@@ -6013,7 +6182,8 @@ module SyntaxTree
|
|
6013
6182
|
end
|
6014
6183
|
|
6015
6184
|
def format(q)
|
6016
|
-
q.
|
6185
|
+
q.text("->")
|
6186
|
+
q.group do
|
6017
6187
|
if params.is_a?(Paren)
|
6018
6188
|
q.format(params) unless params.contents.empty?
|
6019
6189
|
elsif params.empty? && params.comments.any?
|
@@ -6039,10 +6209,10 @@ module SyntaxTree
|
|
6039
6209
|
|
6040
6210
|
unless statements.empty?
|
6041
6211
|
q.indent do
|
6042
|
-
q.
|
6212
|
+
q.breakable_space
|
6043
6213
|
q.format(statements)
|
6044
6214
|
end
|
6045
|
-
q.
|
6215
|
+
q.breakable_space
|
6046
6216
|
end
|
6047
6217
|
|
6048
6218
|
q.text("}")
|
@@ -6051,12 +6221,12 @@ module SyntaxTree
|
|
6051
6221
|
|
6052
6222
|
unless statements.empty?
|
6053
6223
|
q.indent do
|
6054
|
-
q.
|
6224
|
+
q.breakable_space
|
6055
6225
|
q.format(statements)
|
6056
6226
|
end
|
6057
6227
|
end
|
6058
6228
|
|
6059
|
-
q.
|
6229
|
+
q.breakable_space
|
6060
6230
|
q.text("end")
|
6061
6231
|
end
|
6062
6232
|
end
|
@@ -6123,7 +6293,7 @@ module SyntaxTree
|
|
6123
6293
|
|
6124
6294
|
if locals.any?
|
6125
6295
|
q.text("; ")
|
6126
|
-
q.seplist(locals,
|
6296
|
+
q.seplist(locals, BlockVar::SEPARATOR) { |local| q.format(local) }
|
6127
6297
|
end
|
6128
6298
|
end
|
6129
6299
|
end
|
@@ -6277,7 +6447,7 @@ module SyntaxTree
|
|
6277
6447
|
q.group { q.format(target) }
|
6278
6448
|
q.text(" =")
|
6279
6449
|
q.indent do
|
6280
|
-
q.
|
6450
|
+
q.breakable_space
|
6281
6451
|
q.format(value)
|
6282
6452
|
end
|
6283
6453
|
end
|
@@ -6323,8 +6493,8 @@ module SyntaxTree
|
|
6323
6493
|
# If we're at the top of a call chain, then we're going to do some
|
6324
6494
|
# specialized printing in case we can print it nicely. We _only_ do this
|
6325
6495
|
# at the top of the chain to avoid weird recursion issues.
|
6326
|
-
if
|
6327
|
-
CallChainFormatter.chained?(
|
6496
|
+
if CallChainFormatter.chained?(call) &&
|
6497
|
+
!CallChainFormatter.chained?(q.parent)
|
6328
6498
|
q.group do
|
6329
6499
|
q
|
6330
6500
|
.if_break { CallChainFormatter.new(self).format(q) }
|
@@ -6431,15 +6601,17 @@ module SyntaxTree
|
|
6431
6601
|
q.format(contents)
|
6432
6602
|
q.text(",") if comma
|
6433
6603
|
else
|
6434
|
-
q.
|
6604
|
+
q.text("(")
|
6605
|
+
q.group do
|
6435
6606
|
q.indent do
|
6436
|
-
q.
|
6607
|
+
q.breakable_empty
|
6437
6608
|
q.format(contents)
|
6438
6609
|
end
|
6439
6610
|
|
6440
6611
|
q.text(",") if comma
|
6441
|
-
q.
|
6612
|
+
q.breakable_empty
|
6442
6613
|
end
|
6614
|
+
q.text(")")
|
6443
6615
|
end
|
6444
6616
|
end
|
6445
6617
|
end
|
@@ -6486,33 +6658,35 @@ module SyntaxTree
|
|
6486
6658
|
end
|
6487
6659
|
|
6488
6660
|
def format(q)
|
6489
|
-
declaration = -> do
|
6490
|
-
q.group do
|
6491
|
-
q.text("module ")
|
6492
|
-
q.format(constant)
|
6493
|
-
end
|
6494
|
-
end
|
6495
|
-
|
6496
6661
|
if bodystmt.empty?
|
6497
6662
|
q.group do
|
6498
|
-
|
6499
|
-
q.
|
6663
|
+
format_declaration(q)
|
6664
|
+
q.breakable_force
|
6500
6665
|
q.text("end")
|
6501
6666
|
end
|
6502
6667
|
else
|
6503
6668
|
q.group do
|
6504
|
-
|
6669
|
+
format_declaration(q)
|
6505
6670
|
|
6506
6671
|
q.indent do
|
6507
|
-
q.
|
6672
|
+
q.breakable_force
|
6508
6673
|
q.format(bodystmt)
|
6509
6674
|
end
|
6510
6675
|
|
6511
|
-
q.
|
6676
|
+
q.breakable_force
|
6512
6677
|
q.text("end")
|
6513
6678
|
end
|
6514
6679
|
end
|
6515
6680
|
end
|
6681
|
+
|
6682
|
+
private
|
6683
|
+
|
6684
|
+
def format_declaration(q)
|
6685
|
+
q.group do
|
6686
|
+
q.text("module ")
|
6687
|
+
q.format(constant)
|
6688
|
+
end
|
6689
|
+
end
|
6516
6690
|
end
|
6517
6691
|
|
6518
6692
|
# MRHS represents the values that are being assigned on the right-hand side of
|
@@ -6610,11 +6784,15 @@ module SyntaxTree
|
|
6610
6784
|
# [String] the operator
|
6611
6785
|
attr_reader :value
|
6612
6786
|
|
6787
|
+
# [Symbol] the symbol version of the value
|
6788
|
+
attr_reader :name
|
6789
|
+
|
6613
6790
|
# [Array[ Comment | EmbDoc ]] the comments attached to this node
|
6614
6791
|
attr_reader :comments
|
6615
6792
|
|
6616
6793
|
def initialize(value:, location:, comments: [])
|
6617
6794
|
@value = value
|
6795
|
+
@name = value.to_sym
|
6618
6796
|
@location = location
|
6619
6797
|
@comments = comments
|
6620
6798
|
end
|
@@ -6696,7 +6874,7 @@ module SyntaxTree
|
|
6696
6874
|
q.format(value)
|
6697
6875
|
else
|
6698
6876
|
q.indent do
|
6699
|
-
q.
|
6877
|
+
q.breakable_space
|
6700
6878
|
q.format(value)
|
6701
6879
|
end
|
6702
6880
|
end
|
@@ -6767,10 +6945,10 @@ module SyntaxTree
|
|
6767
6945
|
|
6768
6946
|
q.text("(")
|
6769
6947
|
q.indent do
|
6770
|
-
q.
|
6948
|
+
q.breakable_empty
|
6771
6949
|
yield
|
6772
6950
|
end
|
6773
|
-
q.
|
6951
|
+
q.breakable_empty
|
6774
6952
|
q.text(")")
|
6775
6953
|
end
|
6776
6954
|
end
|
@@ -6962,23 +7140,35 @@ module SyntaxTree
|
|
6962
7140
|
parts << KeywordRestFormatter.new(keyword_rest) if keyword_rest
|
6963
7141
|
parts << block if block
|
6964
7142
|
|
6965
|
-
|
6966
|
-
q.
|
6967
|
-
|
7143
|
+
if parts.empty?
|
7144
|
+
q.nest(0) { format_contents(q, parts) }
|
7145
|
+
return
|
6968
7146
|
end
|
6969
7147
|
|
6970
|
-
|
6971
|
-
|
6972
|
-
|
6973
|
-
|
6974
|
-
q.
|
6975
|
-
q.
|
6976
|
-
|
7148
|
+
case q.parent
|
7149
|
+
when Def, Defs, DefEndless
|
7150
|
+
q.nest(0) do
|
7151
|
+
q.text("(")
|
7152
|
+
q.group do
|
7153
|
+
q.indent do
|
7154
|
+
q.breakable_empty
|
7155
|
+
format_contents(q, parts)
|
7156
|
+
end
|
7157
|
+
q.breakable_empty
|
6977
7158
|
end
|
6978
|
-
q.
|
7159
|
+
q.text(")")
|
6979
7160
|
end
|
7161
|
+
else
|
7162
|
+
q.nest(0) { format_contents(q, parts) }
|
6980
7163
|
end
|
6981
7164
|
end
|
7165
|
+
|
7166
|
+
private
|
7167
|
+
|
7168
|
+
def format_contents(q, parts)
|
7169
|
+
q.seplist(parts) { |part| q.format(part) }
|
7170
|
+
q.format(rest) if rest.is_a?(ExcessedComma)
|
7171
|
+
end
|
6982
7172
|
end
|
6983
7173
|
|
6984
7174
|
# Paren represents using balanced parentheses in a couple places in a Ruby
|
@@ -7029,12 +7219,12 @@ module SyntaxTree
|
|
7029
7219
|
|
7030
7220
|
if contents && (!contents.is_a?(Params) || !contents.empty?)
|
7031
7221
|
q.indent do
|
7032
|
-
q.
|
7222
|
+
q.breakable_empty
|
7033
7223
|
q.format(contents)
|
7034
7224
|
end
|
7035
7225
|
end
|
7036
7226
|
|
7037
|
-
q.
|
7227
|
+
q.breakable_empty
|
7038
7228
|
q.text(")")
|
7039
7229
|
end
|
7040
7230
|
end
|
@@ -7108,7 +7298,7 @@ module SyntaxTree
|
|
7108
7298
|
# We're going to put a newline on the end so that it always has one unless
|
7109
7299
|
# it ends with the special __END__ syntax. In that case we want to
|
7110
7300
|
# replicate the text exactly so we will just let it be.
|
7111
|
-
q.
|
7301
|
+
q.breakable_force unless statements.body.last.is_a?(EndContent)
|
7112
7302
|
end
|
7113
7303
|
end
|
7114
7304
|
|
@@ -7160,15 +7350,18 @@ module SyntaxTree
|
|
7160
7350
|
closing = Quotes.matching(opening[2])
|
7161
7351
|
end
|
7162
7352
|
|
7163
|
-
q.
|
7353
|
+
q.text(opening)
|
7354
|
+
q.group do
|
7164
7355
|
q.indent do
|
7165
|
-
q.
|
7166
|
-
q.seplist(
|
7167
|
-
|
7168
|
-
|
7356
|
+
q.breakable_empty
|
7357
|
+
q.seplist(
|
7358
|
+
elements,
|
7359
|
+
ArrayLiteral::BREAKABLE_SPACE_SEPARATOR
|
7360
|
+
) { |element| q.format(element) }
|
7169
7361
|
end
|
7170
|
-
q.
|
7362
|
+
q.breakable_empty
|
7171
7363
|
end
|
7364
|
+
q.text(closing)
|
7172
7365
|
end
|
7173
7366
|
end
|
7174
7367
|
|
@@ -7251,15 +7444,18 @@ module SyntaxTree
|
|
7251
7444
|
closing = Quotes.matching(opening[2])
|
7252
7445
|
end
|
7253
7446
|
|
7254
|
-
q.
|
7447
|
+
q.text(opening)
|
7448
|
+
q.group do
|
7255
7449
|
q.indent do
|
7256
|
-
q.
|
7257
|
-
q.seplist(
|
7258
|
-
|
7259
|
-
|
7450
|
+
q.breakable_empty
|
7451
|
+
q.seplist(
|
7452
|
+
elements,
|
7453
|
+
ArrayLiteral::BREAKABLE_SPACE_SEPARATOR
|
7454
|
+
) { |element| q.format(element) }
|
7260
7455
|
end
|
7261
|
-
q.
|
7456
|
+
q.breakable_empty
|
7262
7457
|
end
|
7458
|
+
q.text(closing)
|
7263
7459
|
end
|
7264
7460
|
end
|
7265
7461
|
|
@@ -7781,13 +7977,13 @@ module SyntaxTree
|
|
7781
7977
|
|
7782
7978
|
unless statements.empty?
|
7783
7979
|
q.indent do
|
7784
|
-
q.
|
7980
|
+
q.breakable_force
|
7785
7981
|
q.format(statements)
|
7786
7982
|
end
|
7787
7983
|
end
|
7788
7984
|
|
7789
7985
|
if consequent
|
7790
|
-
q.
|
7986
|
+
q.breakable_force
|
7791
7987
|
q.format(consequent)
|
7792
7988
|
end
|
7793
7989
|
end
|
@@ -7835,19 +8031,21 @@ module SyntaxTree
|
|
7835
8031
|
end
|
7836
8032
|
|
7837
8033
|
def format(q)
|
7838
|
-
q.
|
8034
|
+
q.text("begin")
|
8035
|
+
q.group do
|
7839
8036
|
q.indent do
|
7840
|
-
q.
|
8037
|
+
q.breakable_force
|
7841
8038
|
q.format(statement)
|
7842
8039
|
end
|
7843
|
-
q.
|
8040
|
+
q.breakable_force
|
7844
8041
|
q.text("rescue StandardError")
|
7845
8042
|
q.indent do
|
7846
|
-
q.
|
8043
|
+
q.breakable_force
|
7847
8044
|
q.format(value)
|
7848
8045
|
end
|
7849
|
-
q.
|
8046
|
+
q.breakable_force
|
7850
8047
|
end
|
8048
|
+
q.text("end")
|
7851
8049
|
end
|
7852
8050
|
end
|
7853
8051
|
|
@@ -8066,14 +8264,16 @@ module SyntaxTree
|
|
8066
8264
|
end
|
8067
8265
|
|
8068
8266
|
def format(q)
|
8069
|
-
q.
|
8267
|
+
q.text("class << ")
|
8268
|
+
q.group do
|
8070
8269
|
q.format(target)
|
8071
8270
|
q.indent do
|
8072
|
-
q.
|
8271
|
+
q.breakable_force
|
8073
8272
|
q.format(bodystmt)
|
8074
8273
|
end
|
8075
|
-
q.
|
8274
|
+
q.breakable_force
|
8076
8275
|
end
|
8276
|
+
q.text("end")
|
8077
8277
|
end
|
8078
8278
|
end
|
8079
8279
|
|
@@ -8179,30 +8379,26 @@ module SyntaxTree
|
|
8179
8379
|
end
|
8180
8380
|
end
|
8181
8381
|
|
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|
|
8382
|
+
previous = nil
|
8383
|
+
body.each do |statement|
|
8189
8384
|
next if statement.is_a?(VoidStmt)
|
8190
8385
|
|
8191
8386
|
if line.nil?
|
8192
8387
|
q.format(statement)
|
8193
8388
|
elsif (statement.location.start_line - line) > 1
|
8194
|
-
q.
|
8195
|
-
q.
|
8389
|
+
q.breakable_force
|
8390
|
+
q.breakable_force
|
8196
8391
|
q.format(statement)
|
8197
|
-
elsif
|
8198
|
-
|
8199
|
-
q.
|
8392
|
+
elsif (statement.is_a?(VCall) && statement.access_control?) ||
|
8393
|
+
(previous.is_a?(VCall) && previous.access_control?)
|
8394
|
+
q.breakable_force
|
8395
|
+
q.breakable_force
|
8200
8396
|
q.format(statement)
|
8201
8397
|
elsif statement.location.start_line != line
|
8202
|
-
q.
|
8398
|
+
q.breakable_force
|
8203
8399
|
q.format(statement)
|
8204
8400
|
elsif !q.parent.is_a?(StringEmbExpr)
|
8205
|
-
q.
|
8401
|
+
q.breakable_force
|
8206
8402
|
q.format(statement)
|
8207
8403
|
else
|
8208
8404
|
q.text("; ")
|
@@ -8210,6 +8406,7 @@ module SyntaxTree
|
|
8210
8406
|
end
|
8211
8407
|
|
8212
8408
|
line = statement.location.end_line
|
8409
|
+
previous = statement
|
8213
8410
|
end
|
8214
8411
|
end
|
8215
8412
|
|
@@ -8327,7 +8524,7 @@ module SyntaxTree
|
|
8327
8524
|
q.format(left)
|
8328
8525
|
q.text(" \\")
|
8329
8526
|
q.indent do
|
8330
|
-
q.
|
8527
|
+
q.breakable_force
|
8331
8528
|
q.format(right)
|
8332
8529
|
end
|
8333
8530
|
end
|
@@ -8413,15 +8610,21 @@ module SyntaxTree
|
|
8413
8610
|
# same line in the source, then we're going to leave them in place and
|
8414
8611
|
# assume that's the way the developer wanted this expression
|
8415
8612
|
# represented.
|
8416
|
-
q.remove_breaks(
|
8613
|
+
q.remove_breaks(
|
8614
|
+
q.group do
|
8615
|
+
q.text('#{')
|
8616
|
+
q.format(statements)
|
8617
|
+
q.text("}")
|
8618
|
+
end
|
8619
|
+
)
|
8417
8620
|
else
|
8418
8621
|
q.group do
|
8419
8622
|
q.text('#{')
|
8420
8623
|
q.indent do
|
8421
|
-
q.
|
8624
|
+
q.breakable_empty
|
8422
8625
|
q.format(statements)
|
8423
8626
|
end
|
8424
|
-
q.
|
8627
|
+
q.breakable_empty
|
8425
8628
|
q.text("}")
|
8426
8629
|
end
|
8427
8630
|
end
|
@@ -8479,19 +8682,30 @@ module SyntaxTree
|
|
8479
8682
|
[quote, quote]
|
8480
8683
|
end
|
8481
8684
|
|
8482
|
-
q.
|
8685
|
+
q.text(opening_quote)
|
8686
|
+
q.group do
|
8483
8687
|
parts.each do |part|
|
8484
8688
|
if part.is_a?(TStringContent)
|
8485
8689
|
value = Quotes.normalize(part.value, closing_quote)
|
8486
|
-
|
8487
|
-
|
8488
|
-
|
8690
|
+
first = true
|
8691
|
+
|
8692
|
+
value.each_line(chomp: true) do |line|
|
8693
|
+
if first
|
8694
|
+
first = false
|
8695
|
+
else
|
8696
|
+
q.breakable_return
|
8697
|
+
end
|
8698
|
+
|
8699
|
+
q.text(line)
|
8489
8700
|
end
|
8701
|
+
|
8702
|
+
q.breakable_return if value.end_with?("\n")
|
8490
8703
|
else
|
8491
8704
|
q.format(part)
|
8492
8705
|
end
|
8493
8706
|
end
|
8494
8707
|
end
|
8708
|
+
q.text(closing_quote)
|
8495
8709
|
end
|
8496
8710
|
end
|
8497
8711
|
|
@@ -8698,15 +8912,18 @@ module SyntaxTree
|
|
8698
8912
|
closing = Quotes.matching(opening[2])
|
8699
8913
|
end
|
8700
8914
|
|
8701
|
-
q.
|
8915
|
+
q.text(opening)
|
8916
|
+
q.group do
|
8702
8917
|
q.indent do
|
8703
|
-
q.
|
8704
|
-
q.seplist(
|
8705
|
-
|
8706
|
-
|
8918
|
+
q.breakable_empty
|
8919
|
+
q.seplist(
|
8920
|
+
elements,
|
8921
|
+
ArrayLiteral::BREAKABLE_SPACE_SEPARATOR
|
8922
|
+
) { |element| q.format(element) }
|
8707
8923
|
end
|
8708
|
-
q.
|
8924
|
+
q.breakable_empty
|
8709
8925
|
end
|
8926
|
+
q.text(closing)
|
8710
8927
|
end
|
8711
8928
|
end
|
8712
8929
|
|
@@ -9000,6 +9217,7 @@ module SyntaxTree
|
|
9000
9217
|
|
9001
9218
|
# [boolean] whether or not parentheses were used
|
9002
9219
|
attr_reader :parentheses
|
9220
|
+
alias parentheses? parentheses
|
9003
9221
|
|
9004
9222
|
# [Array[ Comment | EmbDoc ]] the comments attached to this node
|
9005
9223
|
attr_reader :comments
|
@@ -9031,27 +9249,26 @@ module SyntaxTree
|
|
9031
9249
|
end
|
9032
9250
|
|
9033
9251
|
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
9252
|
q.text("not")
|
9040
9253
|
|
9041
9254
|
if parentheses
|
9042
9255
|
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
|
9256
|
+
q.format(statement) if statement
|
9052
9257
|
q.text(")")
|
9053
|
-
|
9054
|
-
|
9258
|
+
else
|
9259
|
+
grandparent = q.grandparent
|
9260
|
+
ternary =
|
9261
|
+
(grandparent.is_a?(If) || grandparent.is_a?(Unless)) &&
|
9262
|
+
Ternaryable.call(q, grandparent)
|
9263
|
+
|
9264
|
+
if ternary
|
9265
|
+
q.if_break { q.text(" ") }.if_flat { q.text("(") }
|
9266
|
+
q.format(statement) if statement
|
9267
|
+
q.if_flat { q.text(")") } if ternary
|
9268
|
+
else
|
9269
|
+
q.text(" ")
|
9270
|
+
q.format(statement) if statement
|
9271
|
+
end
|
9055
9272
|
end
|
9056
9273
|
end
|
9057
9274
|
end
|
@@ -9316,10 +9533,10 @@ module SyntaxTree
|
|
9316
9533
|
q.text("#{keyword} ")
|
9317
9534
|
q.nest(keyword.length + 1) { q.format(node.predicate) }
|
9318
9535
|
q.indent do
|
9319
|
-
q.
|
9536
|
+
q.breakable_empty
|
9320
9537
|
q.format(statements)
|
9321
9538
|
end
|
9322
|
-
q.
|
9539
|
+
q.breakable_empty
|
9323
9540
|
q.text("end")
|
9324
9541
|
end
|
9325
9542
|
end
|
@@ -9372,7 +9589,7 @@ module SyntaxTree
|
|
9372
9589
|
q.group do
|
9373
9590
|
q.text(keyword)
|
9374
9591
|
q.nest(keyword.length) { q.format(predicate) }
|
9375
|
-
q.
|
9592
|
+
q.breakable_force
|
9376
9593
|
q.text("end")
|
9377
9594
|
end
|
9378
9595
|
else
|
@@ -9572,6 +9789,29 @@ module SyntaxTree
|
|
9572
9789
|
def format(q)
|
9573
9790
|
q.format(value)
|
9574
9791
|
end
|
9792
|
+
|
9793
|
+
# Oh man I hate this so much. Basically, ripper doesn't provide enough
|
9794
|
+
# functionality to actually know where pins are within an expression. So we
|
9795
|
+
# have to walk the tree ourselves and insert more information. In doing so,
|
9796
|
+
# we have to replace this node by a pinned node when necessary.
|
9797
|
+
#
|
9798
|
+
# To be clear, this method should just not exist. It's not good. It's a
|
9799
|
+
# place of shame. But it's necessary for now, so I'm keeping it.
|
9800
|
+
def pin(parent)
|
9801
|
+
replace = PinnedVarRef.new(value: value, location: location)
|
9802
|
+
|
9803
|
+
parent
|
9804
|
+
.deconstruct_keys([])
|
9805
|
+
.each do |key, value|
|
9806
|
+
if value == self
|
9807
|
+
parent.instance_variable_set(:"@#{key}", replace)
|
9808
|
+
break
|
9809
|
+
elsif value.is_a?(Array) && (index = value.index(self))
|
9810
|
+
parent.public_send(key)[index] = replace
|
9811
|
+
break
|
9812
|
+
end
|
9813
|
+
end
|
9814
|
+
end
|
9575
9815
|
end
|
9576
9816
|
|
9577
9817
|
# PinnedVarRef represents a pinned variable reference within a pattern
|
@@ -9653,6 +9893,10 @@ module SyntaxTree
|
|
9653
9893
|
def format(q)
|
9654
9894
|
q.format(value)
|
9655
9895
|
end
|
9896
|
+
|
9897
|
+
def access_control?
|
9898
|
+
@access_control ||= %w[private protected public].include?(value.value)
|
9899
|
+
end
|
9656
9900
|
end
|
9657
9901
|
|
9658
9902
|
# VoidStmt represents an empty lexical block of code.
|
@@ -9742,6 +9986,22 @@ module SyntaxTree
|
|
9742
9986
|
}
|
9743
9987
|
end
|
9744
9988
|
|
9989
|
+
# We have a special separator here for when clauses which causes them to
|
9990
|
+
# fill as much of the line as possible as opposed to everything breaking
|
9991
|
+
# into its own line as soon as you hit the print limit.
|
9992
|
+
class Separator
|
9993
|
+
def call(q)
|
9994
|
+
q.group do
|
9995
|
+
q.text(",")
|
9996
|
+
q.breakable_space
|
9997
|
+
end
|
9998
|
+
end
|
9999
|
+
end
|
10000
|
+
|
10001
|
+
# We're going to keep a single instance of this separator around so we don't
|
10002
|
+
# have to allocate a new one every time we format a when clause.
|
10003
|
+
SEPARATOR = Separator.new
|
10004
|
+
|
9745
10005
|
def format(q)
|
9746
10006
|
keyword = "when "
|
9747
10007
|
|
@@ -9752,8 +10012,7 @@ module SyntaxTree
|
|
9752
10012
|
if arguments.comments.any?
|
9753
10013
|
q.format(arguments)
|
9754
10014
|
else
|
9755
|
-
|
9756
|
-
q.seplist(arguments.parts, separator) { |part| q.format(part) }
|
10015
|
+
q.seplist(arguments.parts, SEPARATOR) { |part| q.format(part) }
|
9757
10016
|
end
|
9758
10017
|
|
9759
10018
|
# Very special case here. If you're inside of a when clause and the
|
@@ -9768,13 +10027,13 @@ module SyntaxTree
|
|
9768
10027
|
|
9769
10028
|
unless statements.empty?
|
9770
10029
|
q.indent do
|
9771
|
-
q.
|
10030
|
+
q.breakable_force
|
9772
10031
|
q.format(statements)
|
9773
10032
|
end
|
9774
10033
|
end
|
9775
10034
|
|
9776
10035
|
if consequent
|
9777
|
-
q.
|
10036
|
+
q.breakable_force
|
9778
10037
|
q.format(consequent)
|
9779
10038
|
end
|
9780
10039
|
end
|
@@ -9829,7 +10088,7 @@ module SyntaxTree
|
|
9829
10088
|
q.group do
|
9830
10089
|
q.text(keyword)
|
9831
10090
|
q.nest(keyword.length) { q.format(predicate) }
|
9832
|
-
q.
|
10091
|
+
q.breakable_force
|
9833
10092
|
q.text("end")
|
9834
10093
|
end
|
9835
10094
|
else
|
@@ -9995,15 +10254,18 @@ module SyntaxTree
|
|
9995
10254
|
closing = Quotes.matching(opening[2])
|
9996
10255
|
end
|
9997
10256
|
|
9998
|
-
q.
|
10257
|
+
q.text(opening)
|
10258
|
+
q.group do
|
9999
10259
|
q.indent do
|
10000
|
-
q.
|
10001
|
-
q.seplist(
|
10002
|
-
|
10003
|
-
|
10260
|
+
q.breakable_empty
|
10261
|
+
q.seplist(
|
10262
|
+
elements,
|
10263
|
+
ArrayLiteral::BREAKABLE_SPACE_SEPARATOR
|
10264
|
+
) { |element| q.format(element) }
|
10004
10265
|
end
|
10005
|
-
q.
|
10266
|
+
q.breakable_empty
|
10006
10267
|
end
|
10268
|
+
q.text(closing)
|
10007
10269
|
end
|
10008
10270
|
end
|
10009
10271
|
|
@@ -10147,10 +10409,10 @@ module SyntaxTree
|
|
10147
10409
|
else
|
10148
10410
|
q.if_break { q.text("(") }.if_flat { q.text(" ") }
|
10149
10411
|
q.indent do
|
10150
|
-
q.
|
10412
|
+
q.breakable_empty
|
10151
10413
|
q.format(arguments)
|
10152
10414
|
end
|
10153
|
-
q.
|
10415
|
+
q.breakable_empty
|
10154
10416
|
q.if_break { q.text(")") }
|
10155
10417
|
end
|
10156
10418
|
end
|