syntax_tree 5.3.0 → 6.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.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +12 -1
  3. data/CHANGELOG.md +78 -1
  4. data/Gemfile.lock +7 -7
  5. data/README.md +33 -9
  6. data/Rakefile +12 -8
  7. data/bin/console +1 -0
  8. data/bin/whitequark +79 -0
  9. data/doc/changing_structure.md +16 -0
  10. data/lib/syntax_tree/basic_visitor.rb +44 -5
  11. data/lib/syntax_tree/cli.rb +2 -2
  12. data/lib/syntax_tree/dsl.rb +23 -11
  13. data/lib/syntax_tree/{visitor/field_visitor.rb → field_visitor.rb} +54 -55
  14. data/lib/syntax_tree/formatter.rb +1 -1
  15. data/lib/syntax_tree/index.rb +158 -59
  16. data/lib/syntax_tree/json_visitor.rb +55 -0
  17. data/lib/syntax_tree/language_server.rb +157 -2
  18. data/lib/syntax_tree/match_visitor.rb +120 -0
  19. data/lib/syntax_tree/mermaid.rb +177 -0
  20. data/lib/syntax_tree/mermaid_visitor.rb +69 -0
  21. data/lib/syntax_tree/{visitor/mutation_visitor.rb → mutation_visitor.rb} +27 -27
  22. data/lib/syntax_tree/node.rb +245 -123
  23. data/lib/syntax_tree/parser.rb +332 -119
  24. data/lib/syntax_tree/pretty_print_visitor.rb +83 -0
  25. data/lib/syntax_tree/reflection.rb +241 -0
  26. data/lib/syntax_tree/translation/parser.rb +3107 -0
  27. data/lib/syntax_tree/translation/rubocop_ast.rb +21 -0
  28. data/lib/syntax_tree/translation.rb +28 -0
  29. data/lib/syntax_tree/version.rb +1 -1
  30. data/lib/syntax_tree/with_scope.rb +244 -0
  31. data/lib/syntax_tree/yarv/basic_block.rb +53 -0
  32. data/lib/syntax_tree/yarv/calldata.rb +91 -0
  33. data/lib/syntax_tree/yarv/compiler.rb +110 -100
  34. data/lib/syntax_tree/yarv/control_flow_graph.rb +257 -0
  35. data/lib/syntax_tree/yarv/data_flow_graph.rb +338 -0
  36. data/lib/syntax_tree/yarv/decompiler.rb +1 -1
  37. data/lib/syntax_tree/yarv/disassembler.rb +104 -80
  38. data/lib/syntax_tree/yarv/instruction_sequence.rb +43 -18
  39. data/lib/syntax_tree/yarv/instructions.rb +203 -649
  40. data/lib/syntax_tree/yarv/legacy.rb +12 -24
  41. data/lib/syntax_tree/yarv/sea_of_nodes.rb +534 -0
  42. data/lib/syntax_tree/yarv.rb +18 -0
  43. data/lib/syntax_tree.rb +88 -56
  44. data/tasks/sorbet.rake +277 -0
  45. data/tasks/whitequark.rake +87 -0
  46. metadata +23 -11
  47. data/.gitmodules +0 -9
  48. data/lib/syntax_tree/language_server/inlay_hints.rb +0 -159
  49. data/lib/syntax_tree/visitor/environment.rb +0 -84
  50. data/lib/syntax_tree/visitor/json_visitor.rb +0 -55
  51. data/lib/syntax_tree/visitor/match_visitor.rb +0 -122
  52. data/lib/syntax_tree/visitor/pretty_print_visitor.rb +0 -85
  53. data/lib/syntax_tree/visitor/with_environment.rb +0 -140
@@ -126,18 +126,28 @@ module SyntaxTree
126
126
  raise NotImplementedError
127
127
  end
128
128
 
129
+ def start_char
130
+ location.start_char
131
+ end
132
+
133
+ def end_char
134
+ location.end_char
135
+ end
136
+
129
137
  def pretty_print(q)
130
- visitor = Visitor::PrettyPrintVisitor.new(q)
131
- visitor.visit(self)
138
+ accept(PrettyPrintVisitor.new(q))
132
139
  end
133
140
 
134
141
  def to_json(*opts)
135
- visitor = Visitor::JSONVisitor.new
136
- visitor.visit(self).to_json(*opts)
142
+ accept(JSONVisitor.new).to_json(*opts)
143
+ end
144
+
145
+ def to_mermaid
146
+ accept(MermaidVisitor.new)
137
147
  end
138
148
 
139
149
  def construct_keys
140
- PrettierPrint.format(+"") { |q| Visitor::MatchVisitor.new(q).visit(self) }
150
+ PrettierPrint.format(+"") { |q| accept(MatchVisitor.new(q)) }
141
151
  end
142
152
  end
143
153
 
@@ -555,7 +565,7 @@ module SyntaxTree
555
565
  # collection[]
556
566
  #
557
567
  class ARef < Node
558
- # [untyped] the value being indexed
568
+ # [Node] the value being indexed
559
569
  attr_reader :collection
560
570
 
561
571
  # [nil | Args] the value being passed within the brackets
@@ -633,7 +643,7 @@ module SyntaxTree
633
643
  # collection[index] = value
634
644
  #
635
645
  class ARefField < Node
636
- # [untyped] the value being indexed
646
+ # [Node] the value being indexed
637
647
  attr_reader :collection
638
648
 
639
649
  # [nil | Args] the value being passed within the brackets
@@ -808,7 +818,7 @@ module SyntaxTree
808
818
  # method(first, second, third)
809
819
  #
810
820
  class Args < Node
811
- # [Array[ untyped ]] the arguments that this node wraps
821
+ # [Array[ Node ]] the arguments that this node wraps
812
822
  attr_reader :parts
813
823
 
814
824
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -874,7 +884,7 @@ module SyntaxTree
874
884
  # method(&expression)
875
885
  #
876
886
  class ArgBlock < Node
877
- # [nil | untyped] the expression being turned into a block
887
+ # [nil | Node] the expression being turned into a block
878
888
  attr_reader :value
879
889
 
880
890
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -926,7 +936,7 @@ module SyntaxTree
926
936
  # method(*arguments)
927
937
  #
928
938
  class ArgStar < Node
929
- # [nil | untyped] the expression being splatted
939
+ # [nil | Node] the expression being splatted
930
940
  attr_reader :value
931
941
 
932
942
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -1129,7 +1139,8 @@ module SyntaxTree
1129
1139
  end
1130
1140
  end
1131
1141
 
1132
- # [LBracket] the bracket that opens this array
1142
+ # [nil | LBracket | QSymbolsBeg | QWordsBeg | SymbolsBeg | WordsBeg] the
1143
+ # bracket that opens this array
1133
1144
  attr_reader :lbracket
1134
1145
 
1135
1146
  # [nil | Args] the contents of the array
@@ -1287,7 +1298,7 @@ module SyntaxTree
1287
1298
  # [nil | VarRef] the optional constant wrapper
1288
1299
  attr_reader :constant
1289
1300
 
1290
- # [Array[ untyped ]] the regular positional arguments that this array
1301
+ # [Array[ Node ]] the regular positional arguments that this array
1291
1302
  # pattern is matching against
1292
1303
  attr_reader :requireds
1293
1304
 
@@ -1295,7 +1306,7 @@ module SyntaxTree
1295
1306
  # positional arguments
1296
1307
  attr_reader :rest
1297
1308
 
1298
- # [Array[ untyped ]] the list of positional arguments occurring after the
1309
+ # [Array[ Node ]] the list of positional arguments occurring after the
1299
1310
  # optional star if there is one
1300
1311
  attr_reader :posts
1301
1312
 
@@ -1405,7 +1416,7 @@ module SyntaxTree
1405
1416
  # to assign the result of the expression to
1406
1417
  attr_reader :target
1407
1418
 
1408
- # [untyped] the expression to be assigned
1419
+ # [Node] the expression to be assigned
1409
1420
  attr_reader :value
1410
1421
 
1411
1422
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -1480,10 +1491,10 @@ module SyntaxTree
1480
1491
  #
1481
1492
  # In the above example, the would be two Assoc nodes.
1482
1493
  class Assoc < Node
1483
- # [untyped] the key of this pair
1494
+ # [Node] the key of this pair
1484
1495
  attr_reader :key
1485
1496
 
1486
- # [untyped] the value of this pair
1497
+ # [nil | Node] the value of this pair
1487
1498
  attr_reader :value
1488
1499
 
1489
1500
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -1537,7 +1548,7 @@ module SyntaxTree
1537
1548
  private
1538
1549
 
1539
1550
  def format_contents(q)
1540
- q.parent.format_key(q, key)
1551
+ (q.parent || HashKeyFormatter::Identity.new).format_key(q, key)
1541
1552
  return unless value
1542
1553
 
1543
1554
  if key.comments.empty? && AssignFormatting.skip_indent?(value)
@@ -1558,7 +1569,7 @@ module SyntaxTree
1558
1569
  # { **pairs }
1559
1570
  #
1560
1571
  class AssocSplat < Node
1561
- # [nil | untyped] the expression that is being splatted
1572
+ # [nil | Node] the expression that is being splatted
1562
1573
  attr_reader :value
1563
1574
 
1564
1575
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -1754,14 +1765,40 @@ module SyntaxTree
1754
1765
  end
1755
1766
  end
1756
1767
 
1757
- def self.for(container)
1758
- labels =
1759
- container.assocs.all? do |assoc|
1760
- next true if assoc.is_a?(AssocSplat)
1768
+ # When formatting a single assoc node without the context of the parent
1769
+ # hash, this formatter is used. It uses whatever is present in the node,
1770
+ # because there is nothing to be consistent with.
1771
+ class Identity
1772
+ def format_key(q, key)
1773
+ if key.is_a?(Label)
1774
+ q.format(key)
1775
+ else
1776
+ q.format(key)
1777
+ q.text(" =>")
1778
+ end
1779
+ end
1780
+ end
1761
1781
 
1782
+ def self.for(container)
1783
+ container.assocs.each do |assoc|
1784
+ if assoc.is_a?(AssocSplat)
1785
+ # Splat nodes do not impact the formatting choice.
1786
+ elsif assoc.value.nil?
1787
+ # If the value is nil, then it has been omitted. In this case we have
1788
+ # to match the existing formatting because standardizing would
1789
+ # potentially break the code. For example:
1790
+ #
1791
+ # { first:, "second" => "value" }
1792
+ #
1793
+ return Identity.new
1794
+ else
1795
+ # Otherwise, we need to check the type of the key. If it's a label or
1796
+ # dynamic symbol, we can use labels. If it's a symbol literal then it
1797
+ # needs to match a certain pattern to be used as a label. If it's
1798
+ # anything else, then we need to use hash rockets.
1762
1799
  case assoc.key
1763
- when Label
1764
- true
1800
+ when Label, DynaSymbol
1801
+ # Here labels can be used.
1765
1802
  when SymbolLiteral
1766
1803
  # When attempting to convert a hash rocket into a hash label,
1767
1804
  # you need to take care because only certain patterns are
@@ -1769,15 +1806,18 @@ module SyntaxTree
1769
1806
  # arguments to methods, but don't specify what that is. After
1770
1807
  # some experimentation, it looks like it's:
1771
1808
  value = assoc.key.value.value
1772
- value.match?(/^[_A-Za-z]/) && !value.end_with?("=")
1773
- when DynaSymbol
1774
- true
1809
+
1810
+ if !value.match?(/^[_A-Za-z]/) || value.end_with?("=")
1811
+ return Rockets.new
1812
+ end
1775
1813
  else
1776
- false
1814
+ # If the value is anything else, we have to use hash rockets.
1815
+ return Rockets.new
1777
1816
  end
1778
1817
  end
1818
+ end
1779
1819
 
1780
- (labels ? Labels : Rockets).new
1820
+ Labels.new
1781
1821
  end
1782
1822
  end
1783
1823
 
@@ -1834,7 +1874,15 @@ module SyntaxTree
1834
1874
  end
1835
1875
 
1836
1876
  def format_key(q, key)
1837
- (@key_formatter ||= HashKeyFormatter.for(self)).format_key(q, key)
1877
+ @key_formatter ||=
1878
+ case q.parents.take(3).last
1879
+ when Break, Next, ReturnNode
1880
+ HashKeyFormatter::Identity.new
1881
+ else
1882
+ HashKeyFormatter.for(self)
1883
+ end
1884
+
1885
+ @key_formatter.format_key(q, key)
1838
1886
  end
1839
1887
  end
1840
1888
 
@@ -1908,7 +1956,7 @@ module SyntaxTree
1908
1956
  # end
1909
1957
  #
1910
1958
  class PinnedBegin < Node
1911
- # [untyped] the expression being pinned
1959
+ # [Node] the expression being pinned
1912
1960
  attr_reader :statement
1913
1961
 
1914
1962
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -1989,13 +2037,13 @@ module SyntaxTree
1989
2037
  }
1990
2038
  end
1991
2039
 
1992
- # [untyped] the left-hand side of the expression
2040
+ # [Node] the left-hand side of the expression
1993
2041
  attr_reader :left
1994
2042
 
1995
2043
  # [Symbol] the operator used between the two expressions
1996
2044
  attr_reader :operator
1997
2045
 
1998
- # [untyped] the right-hand side of the expression
2046
+ # [Node] the right-hand side of the expression
1999
2047
  attr_reader :right
2000
2048
 
2001
2049
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -2049,10 +2097,15 @@ module SyntaxTree
2049
2097
  q.group { q.format(left) }
2050
2098
  q.text(" ") unless power
2051
2099
 
2052
- if operator == :<<
2053
- q.text("<< ")
2054
- q.format(right)
2055
- else
2100
+ if operator != :<<
2101
+ q.group do
2102
+ q.text(operator.name)
2103
+ q.indent do
2104
+ power ? q.breakable_empty : q.breakable_space
2105
+ q.format(right)
2106
+ end
2107
+ end
2108
+ elsif left.is_a?(Binary) && left.operator == :<<
2056
2109
  q.group do
2057
2110
  q.text(operator.name)
2058
2111
  q.indent do
@@ -2060,6 +2113,9 @@ module SyntaxTree
2060
2113
  q.format(right)
2061
2114
  end
2062
2115
  end
2116
+ else
2117
+ q.text("<< ")
2118
+ q.format(right)
2063
2119
  end
2064
2120
  end
2065
2121
  end
@@ -2149,6 +2205,14 @@ module SyntaxTree
2149
2205
  other.is_a?(BlockVar) && params === other.params &&
2150
2206
  ArrayMatch.call(locals, other.locals)
2151
2207
  end
2208
+
2209
+ # When a single required parameter is declared for a block, it gets
2210
+ # automatically expanded if the values being yielded into it are an array.
2211
+ def arg0?
2212
+ params.requireds.length == 1 && params.optionals.empty? &&
2213
+ params.rest.nil? && params.posts.empty? && params.keywords.empty? &&
2214
+ params.keyword_rest.nil? && params.block.nil?
2215
+ end
2152
2216
  end
2153
2217
 
2154
2218
  # BlockArg represents declaring a block parameter on a method definition.
@@ -2242,7 +2306,7 @@ module SyntaxTree
2242
2306
  @comments = []
2243
2307
  end
2244
2308
 
2245
- def bind(start_char, start_column, end_char, end_column)
2309
+ def bind(parser, start_char, start_column, end_char, end_column)
2246
2310
  @location =
2247
2311
  Location.new(
2248
2312
  start_line: location.start_line,
@@ -2256,6 +2320,7 @@ module SyntaxTree
2256
2320
  # Here we're going to determine the bounds for the statements
2257
2321
  consequent = rescue_clause || else_clause || ensure_clause
2258
2322
  statements.bind(
2323
+ parser,
2259
2324
  start_char,
2260
2325
  start_column,
2261
2326
  consequent ? consequent.location.start_char : end_char,
@@ -2646,7 +2711,7 @@ module SyntaxTree
2646
2711
  # Of course there are a lot of caveats to that, including trailing operators
2647
2712
  # when necessary, where comments are places, how blocks are aligned, etc.
2648
2713
  class CallChainFormatter
2649
- # [Call | MethodAddBlock] the top of the call chain
2714
+ # [CallNode | MethodAddBlock] the top of the call chain
2650
2715
  attr_reader :node
2651
2716
 
2652
2717
  def initialize(node)
@@ -2867,7 +2932,7 @@ module SyntaxTree
2867
2932
  # receiver.message
2868
2933
  #
2869
2934
  class CallNode < Node
2870
- # [nil | untyped] the receiver of the method call
2935
+ # [nil | Node] the receiver of the method call
2871
2936
  attr_reader :receiver
2872
2937
 
2873
2938
  # [nil | :"::" | Op | Period] the operator being used to send the message
@@ -3043,7 +3108,7 @@ module SyntaxTree
3043
3108
  # [Kw] the keyword that opens this expression
3044
3109
  attr_reader :keyword
3045
3110
 
3046
- # [nil | untyped] optional value being switched on
3111
+ # [nil | Node] optional value being switched on
3047
3112
  attr_reader :value
3048
3113
 
3049
3114
  # [In | When] the next clause in the chain
@@ -3122,14 +3187,14 @@ module SyntaxTree
3122
3187
  # value => pattern
3123
3188
  #
3124
3189
  class RAssign < Node
3125
- # [untyped] the left-hand expression
3190
+ # [Node] the left-hand expression
3126
3191
  attr_reader :value
3127
3192
 
3128
3193
  # [Kw | Op] the operator being used to match against the pattern, which is
3129
3194
  # either => or in
3130
3195
  attr_reader :operator
3131
3196
 
3132
- # [untyped] the pattern on the right-hand side of the expression
3197
+ # [Node] the pattern on the right-hand side of the expression
3133
3198
  attr_reader :pattern
3134
3199
 
3135
3200
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -3240,7 +3305,7 @@ module SyntaxTree
3240
3305
  # defined
3241
3306
  attr_reader :constant
3242
3307
 
3243
- # [nil | untyped] the optional superclass declaration
3308
+ # [nil | Node] the optional superclass declaration
3244
3309
  attr_reader :superclass
3245
3310
 
3246
3311
  # [BodyStmt] the expressions to execute within the context of the class
@@ -3378,7 +3443,7 @@ module SyntaxTree
3378
3443
  # [Args] the arguments being sent with the message
3379
3444
  attr_reader :arguments
3380
3445
 
3381
- # [nil | Block] the optional block being passed to the method
3446
+ # [nil | BlockNode] the optional block being passed to the method
3382
3447
  attr_reader :block
3383
3448
 
3384
3449
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -3484,19 +3549,19 @@ module SyntaxTree
3484
3549
  # object.method argument
3485
3550
  #
3486
3551
  class CommandCall < Node
3487
- # [untyped] the receiver of the message
3552
+ # [nil | Node] the receiver of the message
3488
3553
  attr_reader :receiver
3489
3554
 
3490
- # [:"::" | Op | Period] the operator used to send the message
3555
+ # [nil | :"::" | Op | Period] the operator used to send the message
3491
3556
  attr_reader :operator
3492
3557
 
3493
- # [Const | Ident | Op] the message being send
3558
+ # [:call | Const | Ident | Op] the message being send
3494
3559
  attr_reader :message
3495
3560
 
3496
- # [nil | Args] the arguments going along with the message
3561
+ # [nil | Args | ArgParen] the arguments going along with the message
3497
3562
  attr_reader :arguments
3498
3563
 
3499
- # [nil | Block] the block associated with this method call
3564
+ # [nil | BlockNode] the block associated with this method call
3500
3565
  attr_reader :block
3501
3566
 
3502
3567
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -3782,7 +3847,7 @@ module SyntaxTree
3782
3847
  # object::Const = value
3783
3848
  #
3784
3849
  class ConstPathField < Node
3785
- # [untyped] the source of the constant
3850
+ # [Node] the source of the constant
3786
3851
  attr_reader :parent
3787
3852
 
3788
3853
  # [Const] the constant itself
@@ -3846,7 +3911,7 @@ module SyntaxTree
3846
3911
  # object::Const
3847
3912
  #
3848
3913
  class ConstPathRef < Node
3849
- # [untyped] the source of the constant
3914
+ # [Node] the source of the constant
3850
3915
  attr_reader :parent
3851
3916
 
3852
3917
  # [Const] the constant itself
@@ -4015,7 +4080,7 @@ module SyntaxTree
4015
4080
  # def object.method(param) result end
4016
4081
  #
4017
4082
  class DefNode < Node
4018
- # [nil | untyped] the target where the method is being defined
4083
+ # [nil | Node] the target where the method is being defined
4019
4084
  attr_reader :target
4020
4085
 
4021
4086
  # [nil | Op | Period] the operator being used to declare the method
@@ -4027,7 +4092,7 @@ module SyntaxTree
4027
4092
  # [nil | Params | Paren] the parameter declaration for the method
4028
4093
  attr_reader :params
4029
4094
 
4030
- # [BodyStmt | untyped] the expressions to be executed by the method
4095
+ # [BodyStmt | Node] the expressions to be executed by the method
4031
4096
  attr_reader :bodystmt
4032
4097
 
4033
4098
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -4090,7 +4155,8 @@ module SyntaxTree
4090
4155
  def format(q)
4091
4156
  q.group do
4092
4157
  q.group do
4093
- q.text("def ")
4158
+ q.text("def")
4159
+ q.text(" ") if target || name.comments.empty?
4094
4160
 
4095
4161
  if target
4096
4162
  q.format(target)
@@ -4160,7 +4226,7 @@ module SyntaxTree
4160
4226
  # defined?(variable)
4161
4227
  #
4162
4228
  class Defined < Node
4163
- # [untyped] the value being sent to the keyword
4229
+ # [Node] the value being sent to the keyword
4164
4230
  attr_reader :value
4165
4231
 
4166
4232
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -4317,7 +4383,7 @@ module SyntaxTree
4317
4383
  # are no parentheses around the arguments to that command, so we need to
4318
4384
  # break the block.
4319
4385
  case q.parent
4320
- when Command, CommandCall
4386
+ when nil, Command, CommandCall
4321
4387
  q.break_parent
4322
4388
  format_break(q, break_opening, break_closing)
4323
4389
  return
@@ -4371,7 +4437,7 @@ module SyntaxTree
4371
4437
  # If we're a sibling of a control-flow keyword, then we're going to have to
4372
4438
  # use the do..end bounds.
4373
4439
  def forced_do_end_bounds?(q)
4374
- case q.parent.call
4440
+ case q.parent&.call
4375
4441
  when Break, Next, ReturnNode, Super
4376
4442
  true
4377
4443
  else
@@ -4451,13 +4517,13 @@ module SyntaxTree
4451
4517
  #
4452
4518
  # One of the sides of the expression may be nil, but not both.
4453
4519
  class RangeNode < Node
4454
- # [nil | untyped] the left side of the expression
4520
+ # [nil | Node] the left side of the expression
4455
4521
  attr_reader :left
4456
4522
 
4457
4523
  # [Op] the operator used for this range
4458
4524
  attr_reader :operator
4459
4525
 
4460
- # [nil | untyped] the right side of the expression
4526
+ # [nil | Node] the right side of the expression
4461
4527
  attr_reader :right
4462
4528
 
4463
4529
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -4578,7 +4644,7 @@ module SyntaxTree
4578
4644
  # dynamic symbol
4579
4645
  attr_reader :parts
4580
4646
 
4581
- # [String] the quote used to delimit the dynamic symbol
4647
+ # [nil | String] the quote used to delimit the dynamic symbol
4582
4648
  attr_reader :quote
4583
4649
 
4584
4650
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -4776,7 +4842,7 @@ module SyntaxTree
4776
4842
  # end
4777
4843
  #
4778
4844
  class Elsif < Node
4779
- # [untyped] the expression to be checked
4845
+ # [Node] the expression to be checked
4780
4846
  attr_reader :predicate
4781
4847
 
4782
4848
  # [Statements] the expressions to be executed
@@ -4872,6 +4938,25 @@ module SyntaxTree
4872
4938
  def initialize(value:, location:)
4873
4939
  @value = value
4874
4940
  @location = location
4941
+
4942
+ @leading = false
4943
+ @trailing = false
4944
+ end
4945
+
4946
+ def leading!
4947
+ @leading = true
4948
+ end
4949
+
4950
+ def leading?
4951
+ @leading
4952
+ end
4953
+
4954
+ def trailing!
4955
+ @trailing = true
4956
+ end
4957
+
4958
+ def trailing?
4959
+ @trailing
4875
4960
  end
4876
4961
 
4877
4962
  def inline?
@@ -4908,7 +4993,13 @@ module SyntaxTree
4908
4993
  end
4909
4994
 
4910
4995
  def format(q)
4911
- q.trim
4996
+ if (q.parent.is_a?(DefNode) && q.parent.endless?) ||
4997
+ q.parent.is_a?(Statements)
4998
+ q.trim
4999
+ else
5000
+ q.breakable_return
5001
+ end
5002
+
4912
5003
  q.text(value)
4913
5004
  end
4914
5005
 
@@ -5177,7 +5268,7 @@ module SyntaxTree
5177
5268
  # object.variable = value
5178
5269
  #
5179
5270
  class Field < Node
5180
- # [untyped] the parent object that owns the field being assigned
5271
+ # [Node] the parent object that owns the field being assigned
5181
5272
  attr_reader :parent
5182
5273
 
5183
5274
  # [:"::" | Op | Period] the operator being used for the assignment
@@ -5303,13 +5394,13 @@ module SyntaxTree
5303
5394
  # end
5304
5395
  #
5305
5396
  class FndPtn < Node
5306
- # [nil | untyped] the optional constant wrapper
5397
+ # [nil | Node] the optional constant wrapper
5307
5398
  attr_reader :constant
5308
5399
 
5309
5400
  # [VarField] the splat on the left-hand side
5310
5401
  attr_reader :left
5311
5402
 
5312
- # [Array[ untyped ]] the list of positional expressions in the pattern that
5403
+ # [Array[ Node ]] the list of positional expressions in the pattern that
5313
5404
  # are being matched
5314
5405
  attr_reader :values
5315
5406
 
@@ -5405,7 +5496,7 @@ module SyntaxTree
5405
5496
  # pull values out of the object being enumerated
5406
5497
  attr_reader :index
5407
5498
 
5408
- # [untyped] the object being enumerated in the loop
5499
+ # [Node] the object being enumerated in the loop
5409
5500
  attr_reader :collection
5410
5501
 
5411
5502
  # [Statements] the statements to be executed
@@ -5884,7 +5975,7 @@ module SyntaxTree
5884
5975
  # [Label] the keyword being used
5885
5976
  attr_reader :key
5886
5977
 
5887
- # [untyped] the optional value for the keyword
5978
+ # [Node] the optional value for the keyword
5888
5979
  attr_reader :value
5889
5980
 
5890
5981
  def initialize(key, value)
@@ -5897,7 +5988,7 @@ module SyntaxTree
5897
5988
  end
5898
5989
 
5899
5990
  def format(q)
5900
- q.format(key)
5991
+ HashKeyFormatter::Labels.new.format_key(q, key)
5901
5992
 
5902
5993
  if value
5903
5994
  q.text(" ")
@@ -5925,11 +6016,11 @@ module SyntaxTree
5925
6016
  end
5926
6017
  end
5927
6018
 
5928
- # [nil | untyped] the optional constant wrapper
6019
+ # [nil | Node] the optional constant wrapper
5929
6020
  attr_reader :constant
5930
6021
 
5931
- # [Array[ [Label, untyped] ]] the set of tuples representing the keywords
5932
- # that should be matched against in the pattern
6022
+ # [Array[ [DynaSymbol | Label, nil | Node] ]] the set of tuples
6023
+ # representing the keywords that should be matched against in the pattern
5933
6024
  attr_reader :keywords
5934
6025
 
5935
6026
  # [nil | VarField] an optional parameter to gather up all remaining keywords
@@ -6354,7 +6445,7 @@ module SyntaxTree
6354
6445
  # end
6355
6446
  #
6356
6447
  class IfNode < Node
6357
- # [untyped] the expression to be checked
6448
+ # [Node] the expression to be checked
6358
6449
  attr_reader :predicate
6359
6450
 
6360
6451
  # [Statements] the expressions to be executed
@@ -6427,13 +6518,13 @@ module SyntaxTree
6427
6518
  # predicate ? truthy : falsy
6428
6519
  #
6429
6520
  class IfOp < Node
6430
- # [untyped] the expression to be checked
6521
+ # [Node] the expression to be checked
6431
6522
  attr_reader :predicate
6432
6523
 
6433
- # [untyped] the expression to be executed if the predicate is truthy
6524
+ # [Node] the expression to be executed if the predicate is truthy
6434
6525
  attr_reader :truthy
6435
6526
 
6436
- # [untyped] the expression to be executed if the predicate is falsy
6527
+ # [Node] the expression to be executed if the predicate is falsy
6437
6528
  attr_reader :falsy
6438
6529
 
6439
6530
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -6617,7 +6708,7 @@ module SyntaxTree
6617
6708
  # end
6618
6709
  #
6619
6710
  class In < Node
6620
- # [untyped] the pattern to check against
6711
+ # [Node] the pattern to check against
6621
6712
  attr_reader :pattern
6622
6713
 
6623
6714
  # [Statements] the expressions to execute if the pattern matched
@@ -7400,7 +7491,7 @@ module SyntaxTree
7400
7491
  # [MLHS | MLHSParen] the target of the multiple assignment
7401
7492
  attr_reader :target
7402
7493
 
7403
- # [untyped] the value being assigned
7494
+ # [Node] the value being assigned
7404
7495
  attr_reader :value
7405
7496
 
7406
7497
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -7460,10 +7551,10 @@ module SyntaxTree
7460
7551
  # method {}
7461
7552
  #
7462
7553
  class MethodAddBlock < Node
7463
- # [Call | Command | CommandCall] the method call
7554
+ # [ARef | CallNode | Command | CommandCall | Super | ZSuper] the method call
7464
7555
  attr_reader :call
7465
7556
 
7466
- # [Block] the block being sent with the method call
7557
+ # [BlockNode] the block being sent with the method call
7467
7558
  attr_reader :block
7468
7559
 
7469
7560
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -7535,8 +7626,12 @@ module SyntaxTree
7535
7626
  # first, second, third = value
7536
7627
  #
7537
7628
  class MLHS < Node
7538
- # Array[ARefField | ArgStar | Field | Ident | MLHSParen | VarField] the
7539
- # parts of the left-hand side of a multiple assignment
7629
+ # [
7630
+ # Array[
7631
+ # ARefField | ArgStar | ConstPathField | Field | Ident | MLHSParen |
7632
+ # TopConstField | VarField
7633
+ # ]
7634
+ # ] the parts of the left-hand side of a multiple assignment
7540
7635
  attr_reader :parts
7541
7636
 
7542
7637
  # [boolean] whether or not there is a trailing comma at the end of this
@@ -7762,7 +7857,7 @@ module SyntaxTree
7762
7857
  # values = first, second, third
7763
7858
  #
7764
7859
  class MRHS < Node
7765
- # Array[untyped] the parts that are being assigned
7860
+ # [Array[Node]] the parts that are being assigned
7766
7861
  attr_reader :parts
7767
7862
 
7768
7863
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -7938,7 +8033,7 @@ module SyntaxTree
7938
8033
  # [Op] the operator being used for the assignment
7939
8034
  attr_reader :operator
7940
8035
 
7941
- # [untyped] the expression to be assigned
8036
+ # [Node] the expression to be assigned
7942
8037
  attr_reader :value
7943
8038
 
7944
8039
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -8095,7 +8190,7 @@ module SyntaxTree
8095
8190
  # [Ident] the name of the parameter
8096
8191
  attr_reader :name
8097
8192
 
8098
- # [untyped] the value of the parameter
8193
+ # [Node] the value of the parameter
8099
8194
  attr_reader :value
8100
8195
 
8101
8196
  def initialize(name, value)
@@ -8120,7 +8215,7 @@ module SyntaxTree
8120
8215
  # [Ident] the name of the parameter
8121
8216
  attr_reader :name
8122
8217
 
8123
- # [nil | untyped] the value of the parameter
8218
+ # [nil | Node] the value of the parameter
8124
8219
  attr_reader :value
8125
8220
 
8126
8221
  def initialize(name, value)
@@ -8161,10 +8256,10 @@ module SyntaxTree
8161
8256
  end
8162
8257
  end
8163
8258
 
8164
- # [Array[ Ident ]] any required parameters
8259
+ # [Array[ Ident | MLHSParen ]] any required parameters
8165
8260
  attr_reader :requireds
8166
8261
 
8167
- # [Array[ [ Ident, untyped ] ]] any optional parameters and their default
8262
+ # [Array[ [ Ident, Node ] ]] any optional parameters and their default
8168
8263
  # values
8169
8264
  attr_reader :optionals
8170
8265
 
@@ -8176,11 +8271,12 @@ module SyntaxTree
8176
8271
  # parameter
8177
8272
  attr_reader :posts
8178
8273
 
8179
- # [Array[ [ Ident, nil | untyped ] ]] any keyword parameters and their
8274
+ # [Array[ [ Label, nil | Node ] ]] any keyword parameters and their
8180
8275
  # optional default values
8181
8276
  attr_reader :keywords
8182
8277
 
8183
- # [nil | :nil | KwRestParam] the optional keyword rest parameter
8278
+ # [nil | :nil | ArgsForward | KwRestParam] the optional keyword rest
8279
+ # parameter
8184
8280
  attr_reader :keyword_rest
8185
8281
 
8186
8282
  # [nil | BlockArg] the optional block parameter
@@ -8369,7 +8465,7 @@ module SyntaxTree
8369
8465
  # [LParen] the left parenthesis that opened this statement
8370
8466
  attr_reader :lparen
8371
8467
 
8372
- # [nil | untyped] the expression inside the parentheses
8468
+ # [nil | Node] the expression inside the parentheses
8373
8469
  attr_reader :contents
8374
8470
 
8375
8471
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -9218,7 +9314,7 @@ module SyntaxTree
9218
9314
  # end
9219
9315
  #
9220
9316
  class RescueEx < Node
9221
- # [untyped] the list of exceptions being rescued
9317
+ # [nil | Node] the list of exceptions being rescued
9222
9318
  attr_reader :exceptions
9223
9319
 
9224
9320
  # [nil | Field | VarField] the expression being used to capture the raised
@@ -9296,7 +9392,7 @@ module SyntaxTree
9296
9392
  # [Kw] the rescue keyword
9297
9393
  attr_reader :keyword
9298
9394
 
9299
- # [RescueEx] the exceptions being rescued
9395
+ # [nil | RescueEx] the exceptions being rescued
9300
9396
  attr_reader :exception
9301
9397
 
9302
9398
  # [Statements] the expressions to evaluate when an error is rescued
@@ -9416,10 +9512,10 @@ module SyntaxTree
9416
9512
  # expression rescue value
9417
9513
  #
9418
9514
  class RescueMod < Node
9419
- # [untyped] the expression to execute
9515
+ # [Node] the expression to execute
9420
9516
  attr_reader :statement
9421
9517
 
9422
- # [untyped] the value to use if the executed expression raises an error
9518
+ # [Node] the value to use if the executed expression raises an error
9423
9519
  attr_reader :value
9424
9520
 
9425
9521
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -9678,7 +9774,7 @@ module SyntaxTree
9678
9774
  # end
9679
9775
  #
9680
9776
  class SClass < Node
9681
- # [untyped] the target of the singleton class to enter
9777
+ # [Node] the target of the singleton class to enter
9682
9778
  attr_reader :target
9683
9779
 
9684
9780
  # [BodyStmt] the expressions to be executed
@@ -9752,23 +9848,19 @@ module SyntaxTree
9752
9848
  # propagate that onto void_stmt nodes inside the stmts in order to make sure
9753
9849
  # all comments get printed appropriately.
9754
9850
  class Statements < Node
9755
- # [SyntaxTree] the parser that is generating this node
9756
- attr_reader :parser
9757
-
9758
- # [Array[ untyped ]] the list of expressions contained within this node
9851
+ # [Array[ Node ]] the list of expressions contained within this node
9759
9852
  attr_reader :body
9760
9853
 
9761
9854
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
9762
9855
  attr_reader :comments
9763
9856
 
9764
- def initialize(parser, body:, location:)
9765
- @parser = parser
9857
+ def initialize(body:, location:)
9766
9858
  @body = body
9767
9859
  @location = location
9768
9860
  @comments = []
9769
9861
  end
9770
9862
 
9771
- def bind(start_char, start_column, end_char, end_column)
9863
+ def bind(parser, start_char, start_column, end_char, end_column)
9772
9864
  @location =
9773
9865
  Location.new(
9774
9866
  start_line: location.start_line,
@@ -9794,7 +9886,7 @@ module SyntaxTree
9794
9886
  body[0] = VoidStmt.new(location: location)
9795
9887
  end
9796
9888
 
9797
- attach_comments(start_char, end_char)
9889
+ attach_comments(parser, start_char, end_char)
9798
9890
  end
9799
9891
 
9800
9892
  def bind_end(end_char, end_column)
@@ -9826,7 +9918,6 @@ module SyntaxTree
9826
9918
  def copy(body: nil, location: nil)
9827
9919
  node =
9828
9920
  Statements.new(
9829
- parser,
9830
9921
  body: body || self.body,
9831
9922
  location: location || self.location
9832
9923
  )
@@ -9838,7 +9929,7 @@ module SyntaxTree
9838
9929
  alias deconstruct child_nodes
9839
9930
 
9840
9931
  def deconstruct_keys(_keys)
9841
- { parser: parser, body: body, location: location, comments: comments }
9932
+ { body: body, location: location, comments: comments }
9842
9933
  end
9843
9934
 
9844
9935
  def format(q)
@@ -9898,7 +9989,7 @@ module SyntaxTree
9898
9989
  # As efficiently as possible, gather up all of the comments that have been
9899
9990
  # found while this statements list was being parsed and add them into the
9900
9991
  # body.
9901
- def attach_comments(start_char, end_char)
9992
+ def attach_comments(parser, start_char, end_char)
9902
9993
  parser_comments = parser.comments
9903
9994
 
9904
9995
  comment_index = 0
@@ -9945,9 +10036,13 @@ module SyntaxTree
9945
10036
  # string
9946
10037
  attr_reader :parts
9947
10038
 
10039
+ # [Array[ Comment | EmbDoc ]] the comments attached to this node
10040
+ attr_reader :comments
10041
+
9948
10042
  def initialize(parts:, location:)
9949
10043
  @parts = parts
9950
10044
  @location = location
10045
+ @comments = []
9951
10046
  end
9952
10047
 
9953
10048
  def accept(visitor)
@@ -9974,6 +10069,33 @@ module SyntaxTree
9974
10069
  def ===(other)
9975
10070
  other.is_a?(StringContent) && ArrayMatch.call(parts, other.parts)
9976
10071
  end
10072
+
10073
+ def format(q)
10074
+ q.text(q.quote)
10075
+ q.group do
10076
+ parts.each do |part|
10077
+ if part.is_a?(TStringContent)
10078
+ value = Quotes.normalize(part.value, q.quote)
10079
+ first = true
10080
+
10081
+ value.each_line(chomp: true) do |line|
10082
+ if first
10083
+ first = false
10084
+ else
10085
+ q.breakable_return
10086
+ end
10087
+
10088
+ q.text(line)
10089
+ end
10090
+
10091
+ q.breakable_return if value.end_with?("\n")
10092
+ else
10093
+ q.format(part)
10094
+ end
10095
+ end
10096
+ end
10097
+ q.text(q.quote)
10098
+ end
9977
10099
  end
9978
10100
 
9979
10101
  # StringConcat represents concatenating two strings together using a backward
@@ -9983,7 +10105,8 @@ module SyntaxTree
9983
10105
  # "second"
9984
10106
  #
9985
10107
  class StringConcat < Node
9986
- # [StringConcat | StringLiteral] the left side of the concatenation
10108
+ # [Heredoc | StringConcat | StringLiteral] the left side of the
10109
+ # concatenation
9987
10110
  attr_reader :left
9988
10111
 
9989
10112
  # [StringLiteral] the right side of the concatenation
@@ -10180,7 +10303,7 @@ module SyntaxTree
10180
10303
  # string literal
10181
10304
  attr_reader :parts
10182
10305
 
10183
- # [String] which quote was used by the string literal
10306
+ # [nil | String] which quote was used by the string literal
10184
10307
  attr_reader :quote
10185
10308
 
10186
10309
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -10425,8 +10548,8 @@ module SyntaxTree
10425
10548
  # :symbol
10426
10549
  #
10427
10550
  class SymbolLiteral < Node
10428
- # [Backtick | Const | CVar | GVar | Ident | IVar | Kw | Op] the value of the
10429
- # symbol
10551
+ # [Backtick | Const | CVar | GVar | Ident | IVar | Kw | Op | TStringContent]
10552
+ # the value of the symbol
10430
10553
  attr_reader :value
10431
10554
 
10432
10555
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -10465,6 +10588,7 @@ module SyntaxTree
10465
10588
 
10466
10589
  def format(q)
10467
10590
  q.text(":")
10591
+ q.text("\\") if value.comments.any?
10468
10592
  q.format(value)
10469
10593
  end
10470
10594
 
@@ -10934,7 +11058,7 @@ module SyntaxTree
10934
11058
  # not value
10935
11059
  #
10936
11060
  class Not < Node
10937
- # [nil | untyped] the statement on which to operate
11061
+ # [nil | Node] the statement on which to operate
10938
11062
  attr_reader :statement
10939
11063
 
10940
11064
  # [boolean] whether or not parentheses were used
@@ -11021,7 +11145,7 @@ module SyntaxTree
11021
11145
  # [String] the operator being used
11022
11146
  attr_reader :operator
11023
11147
 
11024
- # [untyped] the statement on which to operate
11148
+ # [Node] the statement on which to operate
11025
11149
  attr_reader :statement
11026
11150
 
11027
11151
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -11165,7 +11289,7 @@ module SyntaxTree
11165
11289
  # end
11166
11290
  #
11167
11291
  class UnlessNode < Node
11168
- # [untyped] the expression to be checked
11292
+ # [Node] the expression to be checked
11169
11293
  attr_reader :predicate
11170
11294
 
11171
11295
  # [Statements] the expressions to be executed
@@ -11311,7 +11435,7 @@ module SyntaxTree
11311
11435
  # end
11312
11436
  #
11313
11437
  class UntilNode < Node
11314
- # [untyped] the expression to be checked
11438
+ # [Node] the expression to be checked
11315
11439
  attr_reader :predicate
11316
11440
 
11317
11441
  # [Statements] the expressions to be executed
@@ -11379,7 +11503,7 @@ module SyntaxTree
11379
11503
  #
11380
11504
  # In the example above, the VarField node represents the +variable+ token.
11381
11505
  class VarField < Node
11382
- # [nil | Const | CVar | GVar | Ident | IVar] the target of this node
11506
+ # [nil | :nil | Const | CVar | GVar | Ident | IVar] the target of this node
11383
11507
  attr_reader :value
11384
11508
 
11385
11509
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -11490,8 +11614,9 @@ module SyntaxTree
11490
11614
  #
11491
11615
  # To be clear, this method should just not exist. It's not good. It's a
11492
11616
  # place of shame. But it's necessary for now, so I'm keeping it.
11493
- def pin(parent)
11494
- replace = PinnedVarRef.new(value: value, location: location)
11617
+ def pin(parent, pin)
11618
+ replace =
11619
+ PinnedVarRef.new(value: value, location: pin.location.to(location))
11495
11620
 
11496
11621
  parent
11497
11622
  .deconstruct_keys([])
@@ -11517,7 +11642,7 @@ module SyntaxTree
11517
11642
  # This can be a plain local variable like the example above. It can also be a
11518
11643
  # a class variable, a global variable, or an instance variable.
11519
11644
  class PinnedVarRef < Node
11520
- # [VarRef] the value of this node
11645
+ # [Const | CVar | GVar | Ident | IVar] the value of this node
11521
11646
  attr_reader :value
11522
11647
 
11523
11648
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
@@ -11631,9 +11756,6 @@ module SyntaxTree
11631
11756
  # ;;
11632
11757
  #
11633
11758
  class VoidStmt < Node
11634
- # [Location] the location of this node
11635
- attr_reader :location
11636
-
11637
11759
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
11638
11760
  attr_reader :comments
11639
11761
 
@@ -11794,7 +11916,7 @@ module SyntaxTree
11794
11916
  # end
11795
11917
  #
11796
11918
  class WhileNode < Node
11797
- # [untyped] the expression to be checked
11919
+ # [Node] the expression to be checked
11798
11920
  attr_reader :predicate
11799
11921
 
11800
11922
  # [Statements] the expressions to be executed