prism 0.30.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -1
- data/README.md +3 -1
- data/config.yml +185 -126
- data/docs/serialization.md +3 -0
- data/ext/prism/api_node.c +2843 -2085
- data/ext/prism/extconf.rb +1 -1
- data/ext/prism/extension.c +35 -25
- data/ext/prism/extension.h +2 -2
- data/include/prism/ast.h +1048 -69
- data/include/prism/defines.h +9 -0
- data/include/prism/diagnostic.h +11 -3
- data/include/prism/options.h +55 -1
- data/include/prism/parser.h +27 -3
- data/include/prism/regexp.h +2 -1
- data/include/prism/util/pm_integer.h +6 -6
- data/include/prism/util/pm_newline_list.h +11 -0
- data/include/prism/util/pm_string.h +1 -0
- data/include/prism/version.h +3 -3
- data/lib/prism/desugar_compiler.rb +111 -74
- data/lib/prism/dispatcher.rb +2 -1
- data/lib/prism/dot_visitor.rb +21 -31
- data/lib/prism/dsl.rb +656 -471
- data/lib/prism/ffi.rb +3 -0
- data/lib/prism/inspect_visitor.rb +285 -57
- data/lib/prism/mutation_compiler.rb +5 -5
- data/lib/prism/node.rb +2282 -4754
- data/lib/prism/node_ext.rb +72 -11
- data/lib/prism/parse_result/errors.rb +65 -0
- data/lib/prism/parse_result/newlines.rb +28 -28
- data/lib/prism/parse_result.rb +25 -2
- data/lib/prism/reflection.rb +7 -7
- data/lib/prism/serialize.rb +468 -610
- data/lib/prism/translation/parser/compiler.rb +18 -18
- data/lib/prism/translation/parser/lexer.rb +1 -1
- data/lib/prism/translation/parser.rb +3 -3
- data/lib/prism/translation/ripper.rb +14 -14
- data/lib/prism/translation/ruby_parser.rb +43 -7
- data/prism.gemspec +3 -1
- data/rbi/prism/dsl.rbi +521 -0
- data/rbi/prism/node.rbi +1456 -5616
- data/rbi/prism.rbi +16 -16
- data/sig/prism/dsl.rbs +189 -305
- data/sig/prism/node.rbs +702 -603
- data/sig/prism/parse_result.rbs +2 -0
- data/src/diagnostic.c +22 -6
- data/src/node.c +277 -284
- data/src/options.c +18 -0
- data/src/prettyprint.c +99 -108
- data/src/prism.c +1282 -760
- data/src/regexp.c +72 -4
- data/src/serialize.c +165 -50
- data/src/token_type.c +2 -2
- data/src/util/pm_integer.c +14 -14
- data/src/util/pm_newline_list.c +29 -0
- data/src/util/pm_string.c +9 -5
- metadata +4 -2
data/lib/prism/node_ext.rb
CHANGED
@@ -21,7 +21,10 @@ module Prism
|
|
21
21
|
# Returns a numeric value that represents the flags that were used to create
|
22
22
|
# the regular expression.
|
23
23
|
def options
|
24
|
-
o =
|
24
|
+
o = 0
|
25
|
+
o |= Regexp::IGNORECASE if flags.anybits?(RegularExpressionFlags::IGNORE_CASE)
|
26
|
+
o |= Regexp::EXTENDED if flags.anybits?(RegularExpressionFlags::EXTENDED)
|
27
|
+
o |= Regexp::MULTILINE if flags.anybits?(RegularExpressionFlags::MULTI_LINE)
|
25
28
|
o |= Regexp::FIXEDENCODING if flags.anybits?(RegularExpressionFlags::EUC_JP | RegularExpressionFlags::WINDOWS_31J | RegularExpressionFlags::UTF_8)
|
26
29
|
o |= Regexp::NOENCODING if flags.anybits?(RegularExpressionFlags::ASCII_8BIT)
|
27
30
|
o
|
@@ -69,11 +72,12 @@ module Prism
|
|
69
72
|
def to_interpolated
|
70
73
|
InterpolatedStringNode.new(
|
71
74
|
source,
|
75
|
+
-1,
|
76
|
+
location,
|
72
77
|
frozen? ? InterpolatedStringNodeFlags::FROZEN : 0,
|
73
78
|
opening_loc,
|
74
|
-
[copy(
|
75
|
-
closing_loc
|
76
|
-
location
|
79
|
+
[copy(location: content_loc, opening_loc: nil, closing_loc: nil)],
|
80
|
+
closing_loc
|
77
81
|
)
|
78
82
|
end
|
79
83
|
end
|
@@ -86,10 +90,12 @@ module Prism
|
|
86
90
|
def to_interpolated
|
87
91
|
InterpolatedXStringNode.new(
|
88
92
|
source,
|
93
|
+
-1,
|
94
|
+
location,
|
95
|
+
flags,
|
89
96
|
opening_loc,
|
90
|
-
[StringNode.new(source, 0, nil, content_loc, nil, unescaped
|
91
|
-
closing_loc
|
92
|
-
location
|
97
|
+
[StringNode.new(source, node_id, content_loc, 0, nil, content_loc, nil, unescaped)],
|
98
|
+
closing_loc
|
93
99
|
)
|
94
100
|
end
|
95
101
|
end
|
@@ -115,9 +121,9 @@ module Prism
|
|
115
121
|
deprecated("value", "numerator", "denominator")
|
116
122
|
|
117
123
|
if denominator == 1
|
118
|
-
IntegerNode.new(source,
|
124
|
+
IntegerNode.new(source, -1, location.chop, flags, numerator)
|
119
125
|
else
|
120
|
-
FloatNode.new(source, numerator.to_f / denominator
|
126
|
+
FloatNode.new(source, -1, location.chop, 0, numerator.to_f / denominator)
|
121
127
|
end
|
122
128
|
end
|
123
129
|
end
|
@@ -195,7 +201,12 @@ module Prism
|
|
195
201
|
# continue to supply that API.
|
196
202
|
def child
|
197
203
|
deprecated("name", "name_loc")
|
198
|
-
|
204
|
+
|
205
|
+
if name
|
206
|
+
ConstantReadNode.new(source, -1, name_loc, 0, name)
|
207
|
+
else
|
208
|
+
MissingNode.new(source, -1, location, 0)
|
209
|
+
end
|
199
210
|
end
|
200
211
|
end
|
201
212
|
|
@@ -231,7 +242,12 @@ module Prism
|
|
231
242
|
# continue to supply that API.
|
232
243
|
def child
|
233
244
|
deprecated("name", "name_loc")
|
234
|
-
|
245
|
+
|
246
|
+
if name
|
247
|
+
ConstantReadNode.new(source, -1, name_loc, 0, name)
|
248
|
+
else
|
249
|
+
MissingNode.new(source, -1, location, 0)
|
250
|
+
end
|
235
251
|
end
|
236
252
|
end
|
237
253
|
|
@@ -444,4 +460,49 @@ module Prism
|
|
444
460
|
binary_operator_loc
|
445
461
|
end
|
446
462
|
end
|
463
|
+
|
464
|
+
class CaseMatchNode < Node
|
465
|
+
# Returns the else clause of the case match node. This method is deprecated
|
466
|
+
# in favor of #else_clause.
|
467
|
+
def consequent
|
468
|
+
deprecated("else_clause")
|
469
|
+
else_clause
|
470
|
+
end
|
471
|
+
end
|
472
|
+
|
473
|
+
class CaseNode < Node
|
474
|
+
# Returns the else clause of the case node. This method is deprecated in
|
475
|
+
# favor of #else_clause.
|
476
|
+
def consequent
|
477
|
+
deprecated("else_clause")
|
478
|
+
else_clause
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
482
|
+
class IfNode < Node
|
483
|
+
# Returns the subsequent if/elsif/else clause of the if node. This method is
|
484
|
+
# deprecated in favor of #subsequent.
|
485
|
+
def consequent
|
486
|
+
deprecated("subsequent")
|
487
|
+
subsequent
|
488
|
+
end
|
489
|
+
end
|
490
|
+
|
491
|
+
class RescueNode < Node
|
492
|
+
# Returns the subsequent rescue clause of the rescue node. This method is
|
493
|
+
# deprecated in favor of #subsequent.
|
494
|
+
def consequent
|
495
|
+
deprecated("subsequent")
|
496
|
+
subsequent
|
497
|
+
end
|
498
|
+
end
|
499
|
+
|
500
|
+
class UnlessNode < Node
|
501
|
+
# Returns the else clause of the unless node. This method is deprecated in
|
502
|
+
# favor of #else_clause.
|
503
|
+
def consequent
|
504
|
+
deprecated("else_clause")
|
505
|
+
else_clause
|
506
|
+
end
|
507
|
+
end
|
447
508
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "stringio"
|
4
|
+
|
5
|
+
module Prism
|
6
|
+
class ParseResult < Result
|
7
|
+
# An object to represent the set of errors on a parse result. This object
|
8
|
+
# can be used to format the errors in a human-readable way.
|
9
|
+
class Errors
|
10
|
+
# The parse result that contains the errors.
|
11
|
+
attr_reader :parse_result
|
12
|
+
|
13
|
+
# Initialize a new set of errors from the given parse result.
|
14
|
+
def initialize(parse_result)
|
15
|
+
@parse_result = parse_result
|
16
|
+
end
|
17
|
+
|
18
|
+
# Formats the errors in a human-readable way and return them as a string.
|
19
|
+
def format
|
20
|
+
error_lines = {}
|
21
|
+
parse_result.errors.each do |error|
|
22
|
+
location = error.location
|
23
|
+
(location.start_line..location.end_line).each do |line|
|
24
|
+
error_lines[line] ||= []
|
25
|
+
error_lines[line] << error
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
source_lines = parse_result.source.source.lines
|
30
|
+
source_lines << "" if error_lines.key?(source_lines.size + 1)
|
31
|
+
|
32
|
+
io = StringIO.new
|
33
|
+
source_lines.each.with_index(1) do |line, line_number|
|
34
|
+
io.puts(line)
|
35
|
+
|
36
|
+
(error_lines.delete(line_number) || []).each do |error|
|
37
|
+
location = error.location
|
38
|
+
|
39
|
+
case line_number
|
40
|
+
when location.start_line
|
41
|
+
io.print(" " * location.start_column + "^")
|
42
|
+
|
43
|
+
if location.start_line == location.end_line
|
44
|
+
if location.start_column != location.end_column
|
45
|
+
io.print("~" * (location.end_column - location.start_column - 1))
|
46
|
+
end
|
47
|
+
|
48
|
+
io.puts(" " + error.message)
|
49
|
+
else
|
50
|
+
io.puts("~" * (line.bytesize - location.start_column))
|
51
|
+
end
|
52
|
+
when location.end_line
|
53
|
+
io.puts("~" * location.end_column + " " + error.message)
|
54
|
+
else
|
55
|
+
io.puts("~" * line.bytesize)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
io.puts
|
61
|
+
io.string
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -45,7 +45,7 @@ module Prism
|
|
45
45
|
|
46
46
|
# Mark if/unless nodes as newlines.
|
47
47
|
def visit_if_node(node)
|
48
|
-
node.
|
48
|
+
node.newline_flag!(@lines)
|
49
49
|
super(node)
|
50
50
|
end
|
51
51
|
|
@@ -54,7 +54,7 @@ module Prism
|
|
54
54
|
# Permit statements lists to mark newlines within themselves.
|
55
55
|
def visit_statements_node(node)
|
56
56
|
node.body.each do |child|
|
57
|
-
child.
|
57
|
+
child.newline_flag!(@lines)
|
58
58
|
end
|
59
59
|
super(node)
|
60
60
|
end
|
@@ -62,93 +62,93 @@ module Prism
|
|
62
62
|
end
|
63
63
|
|
64
64
|
class Node
|
65
|
-
def
|
66
|
-
@
|
65
|
+
def newline_flag? # :nodoc:
|
66
|
+
@newline_flag ? true : false
|
67
67
|
end
|
68
68
|
|
69
|
-
def
|
69
|
+
def newline_flag!(lines) # :nodoc:
|
70
70
|
line = location.start_line
|
71
71
|
unless lines[line]
|
72
72
|
lines[line] = true
|
73
|
-
@
|
73
|
+
@newline_flag = true
|
74
74
|
end
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
78
|
class BeginNode < Node
|
79
|
-
def
|
79
|
+
def newline_flag!(lines) # :nodoc:
|
80
80
|
# Never mark BeginNode with a newline flag, mark children instead.
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
84
84
|
class ParenthesesNode < Node
|
85
|
-
def
|
85
|
+
def newline_flag!(lines) # :nodoc:
|
86
86
|
# Never mark ParenthesesNode with a newline flag, mark children instead.
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
90
90
|
class IfNode < Node
|
91
|
-
def
|
92
|
-
predicate.
|
91
|
+
def newline_flag!(lines) # :nodoc:
|
92
|
+
predicate.newline_flag!(lines)
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
96
|
class UnlessNode < Node
|
97
|
-
def
|
98
|
-
predicate.
|
97
|
+
def newline_flag!(lines) # :nodoc:
|
98
|
+
predicate.newline_flag!(lines)
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
102
102
|
class UntilNode < Node
|
103
|
-
def
|
104
|
-
predicate.
|
103
|
+
def newline_flag!(lines) # :nodoc:
|
104
|
+
predicate.newline_flag!(lines)
|
105
105
|
end
|
106
106
|
end
|
107
107
|
|
108
108
|
class WhileNode < Node
|
109
|
-
def
|
110
|
-
predicate.
|
109
|
+
def newline_flag!(lines) # :nodoc:
|
110
|
+
predicate.newline_flag!(lines)
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
114
|
class RescueModifierNode < Node
|
115
|
-
def
|
116
|
-
expression.
|
115
|
+
def newline_flag!(lines) # :nodoc:
|
116
|
+
expression.newline_flag!(lines)
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
120
120
|
class InterpolatedMatchLastLineNode < Node
|
121
|
-
def
|
121
|
+
def newline_flag!(lines) # :nodoc:
|
122
122
|
first = parts.first
|
123
|
-
first.
|
123
|
+
first.newline_flag!(lines) if first
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
127
127
|
class InterpolatedRegularExpressionNode < Node
|
128
|
-
def
|
128
|
+
def newline_flag!(lines) # :nodoc:
|
129
129
|
first = parts.first
|
130
|
-
first.
|
130
|
+
first.newline_flag!(lines) if first
|
131
131
|
end
|
132
132
|
end
|
133
133
|
|
134
134
|
class InterpolatedStringNode < Node
|
135
|
-
def
|
135
|
+
def newline_flag!(lines) # :nodoc:
|
136
136
|
first = parts.first
|
137
|
-
first.
|
137
|
+
first.newline_flag!(lines) if first
|
138
138
|
end
|
139
139
|
end
|
140
140
|
|
141
141
|
class InterpolatedSymbolNode < Node
|
142
|
-
def
|
142
|
+
def newline_flag!(lines) # :nodoc:
|
143
143
|
first = parts.first
|
144
|
-
first.
|
144
|
+
first.newline_flag!(lines) if first
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
148
148
|
class InterpolatedXStringNode < Node
|
149
|
-
def
|
149
|
+
def newline_flag!(lines) # :nodoc:
|
150
150
|
first = parts.first
|
151
|
-
first.
|
151
|
+
first.newline_flag!(lines) if first
|
152
152
|
end
|
153
153
|
end
|
154
154
|
end
|
data/lib/prism/parse_result.rb
CHANGED
@@ -10,7 +10,11 @@ module Prism
|
|
10
10
|
# specialized and more performant `ASCIISource` if no multibyte characters
|
11
11
|
# are present in the source code.
|
12
12
|
def self.for(source, start_line = 1, offsets = [])
|
13
|
-
source.ascii_only?
|
13
|
+
if source.ascii_only?
|
14
|
+
ASCIISource.new(source, start_line, offsets)
|
15
|
+
else
|
16
|
+
new(source, start_line, offsets)
|
17
|
+
end
|
14
18
|
end
|
15
19
|
|
16
20
|
# The source code that this source object represents.
|
@@ -87,7 +91,12 @@ module Prism
|
|
87
91
|
# encodings, it is not captured here.
|
88
92
|
def code_units_offset(byte_offset, encoding)
|
89
93
|
byteslice = (source.byteslice(0, byte_offset) or raise).encode(encoding)
|
90
|
-
|
94
|
+
|
95
|
+
if encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE
|
96
|
+
byteslice.bytesize / 2
|
97
|
+
else
|
98
|
+
byteslice.length
|
99
|
+
end
|
91
100
|
end
|
92
101
|
|
93
102
|
# Returns the column number in code units for the given encoding for the
|
@@ -575,9 +584,11 @@ module Prism
|
|
575
584
|
# This is a result specific to the `parse` and `parse_file` methods.
|
576
585
|
class ParseResult < Result
|
577
586
|
autoload :Comments, "prism/parse_result/comments"
|
587
|
+
autoload :Errors, "prism/parse_result/errors"
|
578
588
|
autoload :Newlines, "prism/parse_result/newlines"
|
579
589
|
|
580
590
|
private_constant :Comments
|
591
|
+
private_constant :Errors
|
581
592
|
private_constant :Newlines
|
582
593
|
|
583
594
|
# The syntax tree that was parsed from the source code.
|
@@ -604,6 +615,12 @@ module Prism
|
|
604
615
|
def mark_newlines!
|
605
616
|
value.accept(Newlines.new(source.offsets.size)) # steep:ignore
|
606
617
|
end
|
618
|
+
|
619
|
+
# Returns a string representation of the syntax tree with the errors
|
620
|
+
# displayed inline.
|
621
|
+
def errors_format
|
622
|
+
Errors.new(self).format
|
623
|
+
end
|
607
624
|
end
|
608
625
|
|
609
626
|
# This is a result specific to the `lex` and `lex_file` methods.
|
@@ -694,5 +711,11 @@ module Prism
|
|
694
711
|
other.type == type &&
|
695
712
|
other.value == value
|
696
713
|
end
|
714
|
+
|
715
|
+
# Returns a string representation of this token.
|
716
|
+
def inspect
|
717
|
+
location
|
718
|
+
super
|
719
|
+
end
|
697
720
|
end
|
698
721
|
end
|
data/lib/prism/reflection.rb
CHANGED
@@ -112,7 +112,7 @@ module Prism
|
|
112
112
|
when :and_node
|
113
113
|
[NodeField.new(:left), NodeField.new(:right), LocationField.new(:operator_loc)]
|
114
114
|
when :arguments_node
|
115
|
-
[FlagsField.new(:flags, [:contains_keywords?, :contains_keyword_splat?]), NodeListField.new(:arguments)]
|
115
|
+
[FlagsField.new(:flags, [:contains_keywords?, :contains_keyword_splat?, :contains_splat?]), NodeListField.new(:arguments)]
|
116
116
|
when :array_node
|
117
117
|
[FlagsField.new(:flags, [:contains_splat?]), NodeListField.new(:elements), OptionalLocationField.new(:opening_loc), OptionalLocationField.new(:closing_loc)]
|
118
118
|
when :array_pattern_node
|
@@ -150,9 +150,9 @@ module Prism
|
|
150
150
|
when :capture_pattern_node
|
151
151
|
[NodeField.new(:value), NodeField.new(:target), LocationField.new(:operator_loc)]
|
152
152
|
when :case_match_node
|
153
|
-
[OptionalNodeField.new(:predicate), NodeListField.new(:conditions), OptionalNodeField.new(:
|
153
|
+
[OptionalNodeField.new(:predicate), NodeListField.new(:conditions), OptionalNodeField.new(:else_clause), LocationField.new(:case_keyword_loc), LocationField.new(:end_keyword_loc)]
|
154
154
|
when :case_node
|
155
|
-
[OptionalNodeField.new(:predicate), NodeListField.new(:conditions), OptionalNodeField.new(:
|
155
|
+
[OptionalNodeField.new(:predicate), NodeListField.new(:conditions), OptionalNodeField.new(:else_clause), LocationField.new(:case_keyword_loc), LocationField.new(:end_keyword_loc)]
|
156
156
|
when :class_node
|
157
157
|
[ConstantListField.new(:locals), LocationField.new(:class_keyword_loc), NodeField.new(:constant_path), OptionalLocationField.new(:inheritance_operator_loc), OptionalNodeField.new(:superclass), OptionalNodeField.new(:body), LocationField.new(:end_keyword_loc), ConstantField.new(:name)]
|
158
158
|
when :class_variable_and_write_node
|
@@ -236,7 +236,7 @@ module Prism
|
|
236
236
|
when :hash_pattern_node
|
237
237
|
[OptionalNodeField.new(:constant), NodeListField.new(:elements), OptionalNodeField.new(:rest), OptionalLocationField.new(:opening_loc), OptionalLocationField.new(:closing_loc)]
|
238
238
|
when :if_node
|
239
|
-
[OptionalLocationField.new(:if_keyword_loc), NodeField.new(:predicate), OptionalLocationField.new(:then_keyword_loc), OptionalNodeField.new(:statements), OptionalNodeField.new(:
|
239
|
+
[OptionalLocationField.new(:if_keyword_loc), NodeField.new(:predicate), OptionalLocationField.new(:then_keyword_loc), OptionalNodeField.new(:statements), OptionalNodeField.new(:subsequent), OptionalLocationField.new(:end_keyword_loc)]
|
240
240
|
when :imaginary_node
|
241
241
|
[NodeField.new(:numeric)]
|
242
242
|
when :implicit_node
|
@@ -360,13 +360,13 @@ module Prism
|
|
360
360
|
when :rescue_modifier_node
|
361
361
|
[NodeField.new(:expression), LocationField.new(:keyword_loc), NodeField.new(:rescue_expression)]
|
362
362
|
when :rescue_node
|
363
|
-
[LocationField.new(:keyword_loc), NodeListField.new(:exceptions), OptionalLocationField.new(:operator_loc), OptionalNodeField.new(:reference), OptionalNodeField.new(:statements), OptionalNodeField.new(:
|
363
|
+
[LocationField.new(:keyword_loc), NodeListField.new(:exceptions), OptionalLocationField.new(:operator_loc), OptionalNodeField.new(:reference), OptionalNodeField.new(:statements), OptionalNodeField.new(:subsequent)]
|
364
364
|
when :rest_parameter_node
|
365
365
|
[FlagsField.new(:flags, [:repeated_parameter?]), OptionalConstantField.new(:name), OptionalLocationField.new(:name_loc), LocationField.new(:operator_loc)]
|
366
366
|
when :retry_node
|
367
367
|
[]
|
368
368
|
when :return_node
|
369
|
-
[
|
369
|
+
[LocationField.new(:keyword_loc), OptionalNodeField.new(:arguments)]
|
370
370
|
when :self_node
|
371
371
|
[]
|
372
372
|
when :shareable_constant_node
|
@@ -394,7 +394,7 @@ module Prism
|
|
394
394
|
when :undef_node
|
395
395
|
[NodeListField.new(:names), LocationField.new(:keyword_loc)]
|
396
396
|
when :unless_node
|
397
|
-
[LocationField.new(:keyword_loc), NodeField.new(:predicate), OptionalLocationField.new(:then_keyword_loc), OptionalNodeField.new(:statements), OptionalNodeField.new(:
|
397
|
+
[LocationField.new(:keyword_loc), NodeField.new(:predicate), OptionalLocationField.new(:then_keyword_loc), OptionalNodeField.new(:statements), OptionalNodeField.new(:else_clause), OptionalLocationField.new(:end_keyword_loc)]
|
398
398
|
when :until_node
|
399
399
|
[FlagsField.new(:flags, [:begin_modifier?]), LocationField.new(:keyword_loc), OptionalLocationField.new(:closing_loc), NodeField.new(:predicate), OptionalNodeField.new(:statements)]
|
400
400
|
when :when_node
|