syntax_tree 3.6.3 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +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
|