prism 0.29.0 → 0.30.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -1
- data/CONTRIBUTING.md +0 -4
- data/README.md +1 -0
- data/config.yml +66 -9
- data/docs/fuzzing.md +1 -1
- data/docs/ripper_translation.md +22 -0
- data/ext/prism/api_node.c +30 -12
- data/ext/prism/extension.c +107 -372
- data/ext/prism/extension.h +1 -1
- data/include/prism/ast.h +138 -70
- data/include/prism/diagnostic.h +7 -2
- data/include/prism/node.h +0 -21
- data/include/prism/parser.h +23 -25
- data/include/prism/regexp.h +17 -8
- data/include/prism/static_literals.h +3 -2
- data/include/prism/util/pm_char.h +1 -2
- data/include/prism/util/pm_constant_pool.h +0 -8
- data/include/prism/util/pm_integer.h +16 -9
- data/include/prism/util/pm_string.h +0 -8
- data/include/prism/version.h +2 -2
- data/include/prism.h +0 -11
- data/lib/prism/compiler.rb +3 -0
- data/lib/prism/dispatcher.rb +14 -0
- data/lib/prism/dot_visitor.rb +22 -3
- data/lib/prism/dsl.rb +7 -2
- data/lib/prism/ffi.rb +24 -3
- data/lib/prism/inspect_visitor.rb +10 -8
- data/lib/prism/mutation_compiler.rb +6 -1
- data/lib/prism/node.rb +166 -241
- data/lib/prism/node_ext.rb +21 -5
- data/lib/prism/parse_result/comments.rb +0 -7
- data/lib/prism/parse_result/newlines.rb +101 -11
- data/lib/prism/parse_result.rb +17 -0
- data/lib/prism/reflection.rb +3 -1
- data/lib/prism/serialize.rb +80 -67
- data/lib/prism/translation/parser/compiler.rb +134 -114
- data/lib/prism/translation/parser.rb +6 -1
- data/lib/prism/translation/ripper.rb +8 -6
- data/lib/prism/translation/ruby_parser.rb +23 -5
- data/lib/prism/visitor.rb +3 -0
- data/lib/prism.rb +0 -4
- data/prism.gemspec +1 -4
- data/rbi/prism/node.rbi +63 -6
- data/rbi/prism/visitor.rbi +3 -0
- data/rbi/prism.rbi +6 -0
- data/sig/prism/dsl.rbs +4 -1
- data/sig/prism/mutation_compiler.rbs +1 -0
- data/sig/prism/node.rbs +28 -4
- data/sig/prism/visitor.rbs +1 -0
- data/sig/prism.rbs +21 -0
- data/src/diagnostic.c +27 -17
- data/src/node.c +408 -1666
- data/src/prettyprint.c +49 -6
- data/src/prism.c +958 -991
- data/src/regexp.c +133 -68
- data/src/serialize.c +6 -1
- data/src/static_literals.c +63 -84
- data/src/token_type.c +2 -2
- data/src/util/pm_constant_pool.c +0 -8
- data/src/util/pm_integer.c +39 -11
- data/src/util/pm_string.c +0 -12
- data/src/util/pm_strpbrk.c +32 -6
- metadata +2 -5
- data/include/prism/util/pm_string_list.h +0 -44
- data/lib/prism/debug.rb +0 -249
- data/src/util/pm_string_list.c +0 -28
@@ -90,7 +90,11 @@ module Prism
|
|
90
90
|
end
|
91
91
|
|
92
92
|
if node.constant
|
93
|
-
|
93
|
+
if visited.empty?
|
94
|
+
builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(token(node.opening_loc), visited, token(node.closing_loc)), token(node.closing_loc))
|
95
|
+
else
|
96
|
+
builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(nil, visited, nil), token(node.closing_loc))
|
97
|
+
end
|
94
98
|
else
|
95
99
|
builder.array_pattern(token(node.opening_loc), visited, token(node.closing_loc))
|
96
100
|
end
|
@@ -105,38 +109,46 @@ module Prism
|
|
105
109
|
# { a: 1 }
|
106
110
|
# ^^^^
|
107
111
|
def visit_assoc_node(node)
|
112
|
+
key = node.key
|
113
|
+
|
108
114
|
if in_pattern
|
109
115
|
if node.value.is_a?(ImplicitNode)
|
110
|
-
if
|
111
|
-
|
116
|
+
if key.is_a?(SymbolNode)
|
117
|
+
if key.opening.nil?
|
118
|
+
builder.match_hash_var([key.unescaped, srange(key.location)])
|
119
|
+
else
|
120
|
+
builder.match_hash_var_from_str(token(key.opening_loc), [builder.string_internal([key.unescaped, srange(key.value_loc)])], token(key.closing_loc))
|
121
|
+
end
|
112
122
|
else
|
113
|
-
builder.match_hash_var_from_str(token(
|
123
|
+
builder.match_hash_var_from_str(token(key.opening_loc), visit_all(key.parts), token(key.closing_loc))
|
114
124
|
end
|
125
|
+
elsif key.opening.nil?
|
126
|
+
builder.pair_keyword([key.unescaped, srange(key.location)], visit(node.value))
|
115
127
|
else
|
116
|
-
builder.
|
128
|
+
builder.pair_quoted(token(key.opening_loc), [builder.string_internal([key.unescaped, srange(key.value_loc)])], token(key.closing_loc), visit(node.value))
|
117
129
|
end
|
118
130
|
elsif node.value.is_a?(ImplicitNode)
|
119
131
|
if (value = node.value.value).is_a?(LocalVariableReadNode)
|
120
132
|
builder.pair_keyword(
|
121
|
-
[
|
122
|
-
builder.ident([value.name, srange(
|
133
|
+
[key.unescaped, srange(key)],
|
134
|
+
builder.ident([value.name, srange(key.value_loc)]).updated(:lvar)
|
123
135
|
)
|
124
136
|
else
|
125
|
-
builder.pair_label([
|
137
|
+
builder.pair_label([key.unescaped, srange(key.location)])
|
126
138
|
end
|
127
139
|
elsif node.operator_loc
|
128
|
-
builder.pair(visit(
|
129
|
-
elsif
|
130
|
-
builder.pair_keyword([
|
140
|
+
builder.pair(visit(key), token(node.operator_loc), visit(node.value))
|
141
|
+
elsif key.is_a?(SymbolNode) && key.opening_loc.nil?
|
142
|
+
builder.pair_keyword([key.unescaped, srange(key.location)], visit(node.value))
|
131
143
|
else
|
132
144
|
parts =
|
133
|
-
if
|
134
|
-
[builder.string_internal([
|
145
|
+
if key.is_a?(SymbolNode)
|
146
|
+
[builder.string_internal([key.unescaped, srange(key.value_loc)])]
|
135
147
|
else
|
136
|
-
visit_all(
|
148
|
+
visit_all(key.parts)
|
137
149
|
end
|
138
150
|
|
139
|
-
builder.pair_quoted(token(
|
151
|
+
builder.pair_quoted(token(key.opening_loc), parts, token(key.closing_loc), visit(node.value))
|
140
152
|
end
|
141
153
|
end
|
142
154
|
|
@@ -146,7 +158,9 @@ module Prism
|
|
146
158
|
# { **foo }
|
147
159
|
# ^^^^^
|
148
160
|
def visit_assoc_splat_node(node)
|
149
|
-
if
|
161
|
+
if in_pattern
|
162
|
+
builder.match_rest(token(node.operator_loc), token(node.value&.location))
|
163
|
+
elsif node.value.nil? && forwarding.include?(:**)
|
150
164
|
builder.forwarded_kwrestarg(token(node.operator_loc))
|
151
165
|
else
|
152
166
|
builder.kwsplat(token(node.operator_loc), visit(node.value))
|
@@ -881,7 +895,7 @@ module Prism
|
|
881
895
|
# 1i
|
882
896
|
# ^^
|
883
897
|
def visit_imaginary_node(node)
|
884
|
-
visit_numeric(node, builder.complex([
|
898
|
+
visit_numeric(node, builder.complex([Complex(0, node.numeric.value), srange(node.location)]))
|
885
899
|
end
|
886
900
|
|
887
901
|
# { foo: }
|
@@ -1064,36 +1078,7 @@ module Prism
|
|
1064
1078
|
# ^^^^^^^^^^^^
|
1065
1079
|
def visit_interpolated_string_node(node)
|
1066
1080
|
if node.heredoc?
|
1067
|
-
children, closing
|
1068
|
-
opening = token(node.opening_loc)
|
1069
|
-
|
1070
|
-
start_offset = node.opening_loc.end_offset + 1
|
1071
|
-
end_offset = node.parts.first.location.start_offset
|
1072
|
-
|
1073
|
-
# In the below case, the offsets should be the same:
|
1074
|
-
#
|
1075
|
-
# <<~HEREDOC
|
1076
|
-
# a #{b}
|
1077
|
-
# HEREDOC
|
1078
|
-
#
|
1079
|
-
# But in this case, the end_offset would be greater than the start_offset:
|
1080
|
-
#
|
1081
|
-
# <<~HEREDOC
|
1082
|
-
# #{b}
|
1083
|
-
# HEREDOC
|
1084
|
-
#
|
1085
|
-
# So we need to make sure the result node's heredoc range is correct, without updating the children
|
1086
|
-
result = if start_offset < end_offset
|
1087
|
-
# We need to add a padding string to ensure that the heredoc has correct range for its body
|
1088
|
-
padding_string_node = builder.string_internal(["", srange_offsets(start_offset, end_offset)])
|
1089
|
-
node_with_correct_location = builder.string_compose(opening, [padding_string_node, *children], closing)
|
1090
|
-
# But the padding string should not be included in the final AST, so we need to update the result's children
|
1091
|
-
node_with_correct_location.updated(:dstr, children)
|
1092
|
-
else
|
1093
|
-
builder.string_compose(opening, children, closing)
|
1094
|
-
end
|
1095
|
-
|
1096
|
-
return result
|
1081
|
+
return visit_heredoc(node) { |children, closing| builder.string_compose(token(node.opening_loc), children, closing) }
|
1097
1082
|
end
|
1098
1083
|
|
1099
1084
|
parts = if node.parts.one? { |part| part.type == :string_node }
|
@@ -1137,8 +1122,7 @@ module Prism
|
|
1137
1122
|
# ^^^^^^^^^^^^
|
1138
1123
|
def visit_interpolated_x_string_node(node)
|
1139
1124
|
if node.heredoc?
|
1140
|
-
children, closing
|
1141
|
-
builder.xstring_compose(token(node.opening_loc), children, closing)
|
1125
|
+
visit_heredoc(node) { |children, closing| builder.xstring_compose(token(node.opening_loc), children, closing) }
|
1142
1126
|
else
|
1143
1127
|
builder.xstring_compose(
|
1144
1128
|
token(node.opening_loc),
|
@@ -1148,6 +1132,12 @@ module Prism
|
|
1148
1132
|
end
|
1149
1133
|
end
|
1150
1134
|
|
1135
|
+
# -> { it }
|
1136
|
+
# ^^
|
1137
|
+
def visit_it_local_variable_read_node(node)
|
1138
|
+
builder.ident([:it, srange(node.location)]).updated(:lvar)
|
1139
|
+
end
|
1140
|
+
|
1151
1141
|
# -> { it }
|
1152
1142
|
# ^^^^^^^^^
|
1153
1143
|
def visit_it_parameters_node(node)
|
@@ -1201,14 +1191,7 @@ module Prism
|
|
1201
1191
|
# foo
|
1202
1192
|
# ^^^
|
1203
1193
|
def visit_local_variable_read_node(node)
|
1204
|
-
name
|
1205
|
-
|
1206
|
-
# This is just a guess. parser doesn't have support for the implicit
|
1207
|
-
# `it` variable yet, so we'll probably have to visit this once it
|
1208
|
-
# does.
|
1209
|
-
name = :it if name == :"0it"
|
1210
|
-
|
1211
|
-
builder.ident([name, srange(node.location)]).updated(:lvar)
|
1194
|
+
builder.ident([node.name, srange(node.location)]).updated(:lvar)
|
1212
1195
|
end
|
1213
1196
|
|
1214
1197
|
# foo = 1
|
@@ -1312,13 +1295,9 @@ module Prism
|
|
1312
1295
|
# foo, bar = baz
|
1313
1296
|
# ^^^^^^^^
|
1314
1297
|
def visit_multi_target_node(node)
|
1315
|
-
elements = [*node.lefts]
|
1316
|
-
elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
|
1317
|
-
elements.concat(node.rights)
|
1318
|
-
|
1319
1298
|
builder.multi_lhs(
|
1320
1299
|
token(node.lparen_loc),
|
1321
|
-
visit_all(
|
1300
|
+
visit_all(multi_target_elements(node)),
|
1322
1301
|
token(node.rparen_loc)
|
1323
1302
|
)
|
1324
1303
|
end
|
@@ -1326,9 +1305,11 @@ module Prism
|
|
1326
1305
|
# foo, bar = baz
|
1327
1306
|
# ^^^^^^^^^^^^^^
|
1328
1307
|
def visit_multi_write_node(node)
|
1329
|
-
elements =
|
1330
|
-
|
1331
|
-
elements.
|
1308
|
+
elements = multi_target_elements(node)
|
1309
|
+
|
1310
|
+
if elements.length == 1 && elements.first.is_a?(MultiTargetNode)
|
1311
|
+
elements = multi_target_elements(elements.first)
|
1312
|
+
end
|
1332
1313
|
|
1333
1314
|
builder.multi_assign(
|
1334
1315
|
builder.multi_lhs(
|
@@ -1409,12 +1390,12 @@ module Prism
|
|
1409
1390
|
|
1410
1391
|
if node.requireds.any?
|
1411
1392
|
node.requireds.each do |required|
|
1412
|
-
|
1413
|
-
|
1414
|
-
|
1415
|
-
|
1416
|
-
|
1417
|
-
|
1393
|
+
params <<
|
1394
|
+
if required.is_a?(RequiredParameterNode)
|
1395
|
+
visit(required)
|
1396
|
+
else
|
1397
|
+
required.accept(copy_compiler(in_destructure: true))
|
1398
|
+
end
|
1418
1399
|
end
|
1419
1400
|
end
|
1420
1401
|
|
@@ -1423,12 +1404,12 @@ module Prism
|
|
1423
1404
|
|
1424
1405
|
if node.posts.any?
|
1425
1406
|
node.posts.each do |post|
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1430
|
-
|
1431
|
-
|
1407
|
+
params <<
|
1408
|
+
if post.is_a?(RequiredParameterNode)
|
1409
|
+
visit(post)
|
1410
|
+
else
|
1411
|
+
post.accept(copy_compiler(in_destructure: true))
|
1412
|
+
end
|
1432
1413
|
end
|
1433
1414
|
end
|
1434
1415
|
|
@@ -1514,7 +1495,7 @@ module Prism
|
|
1514
1495
|
# 1r
|
1515
1496
|
# ^^
|
1516
1497
|
def visit_rational_node(node)
|
1517
|
-
visit_numeric(node, builder.rational([
|
1498
|
+
visit_numeric(node, builder.rational([node.value, srange(node.location)]))
|
1518
1499
|
end
|
1519
1500
|
|
1520
1501
|
# redo
|
@@ -1526,9 +1507,20 @@ module Prism
|
|
1526
1507
|
# /foo/
|
1527
1508
|
# ^^^^^
|
1528
1509
|
def visit_regular_expression_node(node)
|
1510
|
+
content = node.content
|
1511
|
+
parts =
|
1512
|
+
if content.include?("\n")
|
1513
|
+
offset = node.content_loc.start_offset
|
1514
|
+
content.lines.map do |line|
|
1515
|
+
builder.string_internal([line, srange_offsets(offset, offset += line.bytesize)])
|
1516
|
+
end
|
1517
|
+
else
|
1518
|
+
[builder.string_internal(token(node.content_loc))]
|
1519
|
+
end
|
1520
|
+
|
1529
1521
|
builder.regexp_compose(
|
1530
1522
|
token(node.opening_loc),
|
1531
|
-
|
1523
|
+
parts,
|
1532
1524
|
[node.closing[0], srange_offsets(node.closing_loc.start_offset, node.closing_loc.start_offset + 1)],
|
1533
1525
|
builder.regexp_options([node.closing[1..], srange_offsets(node.closing_loc.start_offset + 1, node.closing_loc.end_offset)])
|
1534
1526
|
)
|
@@ -1674,10 +1666,11 @@ module Prism
|
|
1674
1666
|
# ^^^^^
|
1675
1667
|
def visit_string_node(node)
|
1676
1668
|
if node.heredoc?
|
1677
|
-
children, closing
|
1678
|
-
builder.string_compose(token(node.opening_loc), children, closing)
|
1669
|
+
visit_heredoc(node.to_interpolated) { |children, closing| builder.string_compose(token(node.opening_loc), children, closing) }
|
1679
1670
|
elsif node.opening == "?"
|
1680
1671
|
builder.character([node.unescaped, srange(node.location)])
|
1672
|
+
elsif node.opening&.start_with?("%") && node.unescaped.empty?
|
1673
|
+
builder.string_compose(token(node.opening_loc), [], token(node.closing_loc))
|
1681
1674
|
else
|
1682
1675
|
content_lines = node.content.lines
|
1683
1676
|
unescaped_lines = node.unescaped.lines
|
@@ -1877,8 +1870,7 @@ module Prism
|
|
1877
1870
|
# ^^^^^
|
1878
1871
|
def visit_x_string_node(node)
|
1879
1872
|
if node.heredoc?
|
1880
|
-
children, closing
|
1881
|
-
builder.xstring_compose(token(node.opening_loc), children, closing)
|
1873
|
+
visit_heredoc(node.to_interpolated) { |children, closing| builder.xstring_compose(token(node.opening_loc), children, closing) }
|
1882
1874
|
else
|
1883
1875
|
parts = if node.unescaped.lines.one?
|
1884
1876
|
[builder.string_internal([node.unescaped, srange(node.content_loc)])]
|
@@ -1940,10 +1932,12 @@ module Prism
|
|
1940
1932
|
forwarding
|
1941
1933
|
end
|
1942
1934
|
|
1943
|
-
#
|
1944
|
-
|
1945
|
-
|
1946
|
-
|
1935
|
+
# Returns the set of targets for a MultiTargetNode or a MultiWriteNode.
|
1936
|
+
def multi_target_elements(node)
|
1937
|
+
elements = [*node.lefts]
|
1938
|
+
elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
|
1939
|
+
elements.concat(node.rights)
|
1940
|
+
elements
|
1947
1941
|
end
|
1948
1942
|
|
1949
1943
|
# Negate the value of a numeric node. This is a special case where you
|
@@ -1955,7 +1949,9 @@ module Prism
|
|
1955
1949
|
case receiver.type
|
1956
1950
|
when :integer_node, :float_node
|
1957
1951
|
receiver.copy(value: -receiver.value, location: message_loc.join(receiver.location))
|
1958
|
-
when :rational_node
|
1952
|
+
when :rational_node
|
1953
|
+
receiver.copy(numerator: -receiver.numerator, location: message_loc.join(receiver.location))
|
1954
|
+
when :imaginary_node
|
1959
1955
|
receiver.copy(numeric: numeric_negate(message_loc, receiver.numeric), location: message_loc.join(receiver.location))
|
1960
1956
|
end
|
1961
1957
|
end
|
@@ -1974,16 +1970,6 @@ module Prism
|
|
1974
1970
|
parameters.block.nil?
|
1975
1971
|
end
|
1976
1972
|
|
1977
|
-
# Because we have mutated the AST to allow for newlines in the middle of
|
1978
|
-
# a rational, we need to manually handle the value here.
|
1979
|
-
def rational_value(node)
|
1980
|
-
if node.numeric.is_a?(IntegerNode)
|
1981
|
-
Rational(node.numeric.value)
|
1982
|
-
else
|
1983
|
-
Rational(node.slice.gsub(/\s/, "").chomp("r"))
|
1984
|
-
end
|
1985
|
-
end
|
1986
|
-
|
1987
1973
|
# Locations in the parser gem AST are generated using this class. We
|
1988
1974
|
# store a reference to its constant to make it slightly faster to look
|
1989
1975
|
# up.
|
@@ -2006,7 +1992,7 @@ module Prism
|
|
2006
1992
|
# Note that end_offset is allowed to be nil, in which case this will
|
2007
1993
|
# search until the end of the string.
|
2008
1994
|
def srange_find(start_offset, end_offset, tokens)
|
2009
|
-
if (match = source_buffer.source.byteslice(start_offset...end_offset).match(
|
1995
|
+
if (match = source_buffer.source.byteslice(start_offset...end_offset).match(/\A(\s*)(#{tokens.join("|")})/))
|
2010
1996
|
_, whitespace, token = *match
|
2011
1997
|
token_offset = start_offset + whitespace.bytesize
|
2012
1998
|
|
@@ -2037,7 +2023,8 @@ module Prism
|
|
2037
2023
|
token(parameters.opening_loc),
|
2038
2024
|
if procarg0?(parameters.parameters)
|
2039
2025
|
parameter = parameters.parameters.requireds.first
|
2040
|
-
|
2026
|
+
visited = parameter.is_a?(RequiredParameterNode) ? visit(parameter) : parameter.accept(copy_compiler(in_destructure: true))
|
2027
|
+
[builder.procarg0(visited)].concat(visit_all(parameters.locals))
|
2041
2028
|
else
|
2042
2029
|
visit(parameters)
|
2043
2030
|
end,
|
@@ -2053,29 +2040,55 @@ module Prism
|
|
2053
2040
|
end
|
2054
2041
|
end
|
2055
2042
|
|
2043
|
+
# The parser gem automatically converts \r\n to \n, meaning our offsets
|
2044
|
+
# need to be adjusted to always subtract 1 from the length.
|
2045
|
+
def chomped_bytesize(line)
|
2046
|
+
chomped = line.chomp
|
2047
|
+
chomped.bytesize + (chomped == line ? 0 : 1)
|
2048
|
+
end
|
2049
|
+
|
2056
2050
|
# Visit a heredoc that can be either a string or an xstring.
|
2057
2051
|
def visit_heredoc(node)
|
2058
2052
|
children = Array.new
|
2053
|
+
indented = false
|
2054
|
+
|
2055
|
+
# If this is a dedenting heredoc, then we need to insert the opening
|
2056
|
+
# content into the children as well.
|
2057
|
+
if node.opening.start_with?("<<~") && node.parts.length > 0 && !node.parts.first.is_a?(StringNode)
|
2058
|
+
location = node.parts.first.location
|
2059
|
+
location = location.copy(start_offset: location.start_offset - location.start_line_slice.bytesize)
|
2060
|
+
children << builder.string_internal(token(location))
|
2061
|
+
indented = true
|
2062
|
+
end
|
2063
|
+
|
2059
2064
|
node.parts.each do |part|
|
2060
2065
|
pushing =
|
2061
2066
|
if part.is_a?(StringNode) && part.unescaped.include?("\n")
|
2062
|
-
unescaped = part.unescaped.lines
|
2063
|
-
escaped = part.content.lines
|
2067
|
+
unescaped = part.unescaped.lines
|
2068
|
+
escaped = part.content.lines
|
2064
2069
|
|
2065
|
-
escaped_lengths =
|
2066
|
-
|
2067
|
-
|
2068
|
-
|
2069
|
-
|
2070
|
+
escaped_lengths = []
|
2071
|
+
normalized_lengths = []
|
2072
|
+
|
2073
|
+
if node.opening.end_with?("'")
|
2074
|
+
escaped.each do |line|
|
2075
|
+
escaped_lengths << line.bytesize
|
2076
|
+
normalized_lengths << chomped_bytesize(line)
|
2070
2077
|
end
|
2078
|
+
else
|
2079
|
+
escaped
|
2080
|
+
.chunk_while { |before, after| before.match?(/(?<!\\)\\\r?\n$/) }
|
2081
|
+
.each do |lines|
|
2082
|
+
escaped_lengths << lines.sum(&:bytesize)
|
2083
|
+
normalized_lengths << lines.sum { |line| chomped_bytesize(line) }
|
2084
|
+
end
|
2085
|
+
end
|
2071
2086
|
|
2072
2087
|
start_offset = part.location.start_offset
|
2073
|
-
end_offset = nil
|
2074
2088
|
|
2075
|
-
unescaped.
|
2076
|
-
|
2077
|
-
|
2078
|
-
start_offset = end_offset
|
2089
|
+
unescaped.map.with_index do |unescaped_line, index|
|
2090
|
+
inner_part = builder.string_internal([unescaped_line, srange_offsets(start_offset, start_offset + normalized_lengths.fetch(index, 0))])
|
2091
|
+
start_offset += escaped_lengths.fetch(index, 0)
|
2079
2092
|
inner_part
|
2080
2093
|
end
|
2081
2094
|
else
|
@@ -2086,7 +2099,12 @@ module Prism
|
|
2086
2099
|
if child.type == :str && child.children.last == ""
|
2087
2100
|
# nothing
|
2088
2101
|
elsif child.type == :str && children.last && children.last.type == :str && !children.last.children.first.end_with?("\n")
|
2089
|
-
|
2102
|
+
appendee = children[-1]
|
2103
|
+
|
2104
|
+
location = appendee.loc
|
2105
|
+
location = location.with_expression(location.expression.join(child.loc.expression))
|
2106
|
+
|
2107
|
+
children[-1] = appendee.updated(:str, [appendee.children.first << child.children.first], location: location)
|
2090
2108
|
else
|
2091
2109
|
children << child
|
2092
2110
|
end
|
@@ -2095,8 +2113,10 @@ module Prism
|
|
2095
2113
|
|
2096
2114
|
closing = node.closing
|
2097
2115
|
closing_t = [closing.chomp, srange_offsets(node.closing_loc.start_offset, node.closing_loc.end_offset - (closing[/\s+$/]&.length || 0))]
|
2116
|
+
composed = yield children, closing_t
|
2098
2117
|
|
2099
|
-
|
2118
|
+
composed = composed.updated(nil, children[1..-1]) if indented
|
2119
|
+
composed
|
2100
2120
|
end
|
2101
2121
|
|
2102
2122
|
# Visit a numeric node and account for the optional sign.
|
@@ -2217,6 +2217,13 @@ module Prism
|
|
2217
2217
|
end
|
2218
2218
|
end
|
2219
2219
|
|
2220
|
+
# -> { it }
|
2221
|
+
# ^^
|
2222
|
+
def visit_it_local_variable_read_node(node)
|
2223
|
+
bounds(node.location)
|
2224
|
+
on_vcall(on_ident(node.slice))
|
2225
|
+
end
|
2226
|
+
|
2220
2227
|
# -> { it }
|
2221
2228
|
# ^^^^^^^^^
|
2222
2229
|
def visit_it_parameters_node(node)
|
@@ -2312,12 +2319,7 @@ module Prism
|
|
2312
2319
|
# ^^^
|
2313
2320
|
def visit_local_variable_read_node(node)
|
2314
2321
|
bounds(node.location)
|
2315
|
-
|
2316
|
-
if node.name == :"0it"
|
2317
|
-
on_vcall(on_ident(node.slice))
|
2318
|
-
else
|
2319
|
-
on_var_ref(on_ident(node.slice))
|
2320
|
-
end
|
2322
|
+
on_var_ref(on_ident(node.slice))
|
2321
2323
|
end
|
2322
2324
|
|
2323
2325
|
# foo = 1
|
@@ -1,6 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
begin
|
4
|
+
require "ruby_parser"
|
5
|
+
rescue LoadError
|
6
|
+
warn(%q{Error: Unable to load ruby_parser. Add `gem "ruby_parser"` to your Gemfile.})
|
7
|
+
exit(1)
|
8
|
+
end
|
4
9
|
|
5
10
|
module Prism
|
6
11
|
module Translation
|
@@ -480,9 +485,9 @@ module Prism
|
|
480
485
|
def visit_constant_path_target_node(node)
|
481
486
|
inner =
|
482
487
|
if node.parent.nil?
|
483
|
-
s(node, :colon3, node.
|
488
|
+
s(node, :colon3, node.name)
|
484
489
|
else
|
485
|
-
s(node, :colon2, visit(node.parent), node.
|
490
|
+
s(node, :colon2, visit(node.parent), node.name)
|
486
491
|
end
|
487
492
|
|
488
493
|
s(node, :const, inner)
|
@@ -870,6 +875,8 @@ module Prism
|
|
870
875
|
else
|
871
876
|
visited << result
|
872
877
|
end
|
878
|
+
elsif result[0] == :dstr
|
879
|
+
visited.concat(result[1..-1])
|
873
880
|
else
|
874
881
|
visited << result
|
875
882
|
end
|
@@ -900,12 +907,23 @@ module Prism
|
|
900
907
|
results << result
|
901
908
|
state = :interpolated_content
|
902
909
|
end
|
903
|
-
|
904
|
-
results
|
910
|
+
when :interpolated_content
|
911
|
+
if result.is_a?(Array) && result[0] == :str && results[-1][0] == :str && (results[-1].line_max == result.line)
|
912
|
+
results[-1][1] << result[1]
|
913
|
+
results[-1].line_max = result.line_max
|
914
|
+
else
|
915
|
+
results << result
|
916
|
+
end
|
905
917
|
end
|
906
918
|
end
|
907
919
|
end
|
908
920
|
|
921
|
+
# -> { it }
|
922
|
+
# ^^
|
923
|
+
def visit_it_local_variable_read_node(node)
|
924
|
+
s(node, :call, nil, :it)
|
925
|
+
end
|
926
|
+
|
909
927
|
# foo(bar: baz)
|
910
928
|
# ^^^^^^^^
|
911
929
|
def visit_keyword_hash_node(node)
|
data/lib/prism/visitor.rb
CHANGED
@@ -313,6 +313,9 @@ module Prism
|
|
313
313
|
# Visit a InterpolatedXStringNode node
|
314
314
|
alias visit_interpolated_x_string_node visit_child_nodes
|
315
315
|
|
316
|
+
# Visit a ItLocalVariableReadNode node
|
317
|
+
alias visit_it_local_variable_read_node visit_child_nodes
|
318
|
+
|
316
319
|
# Visit a ItParametersNode node
|
317
320
|
alias visit_it_parameters_node visit_child_nodes
|
318
321
|
|
data/lib/prism.rb
CHANGED
@@ -13,7 +13,6 @@ module Prism
|
|
13
13
|
|
14
14
|
autoload :BasicVisitor, "prism/visitor"
|
15
15
|
autoload :Compiler, "prism/compiler"
|
16
|
-
autoload :Debug, "prism/debug"
|
17
16
|
autoload :DesugarCompiler, "prism/desugar_compiler"
|
18
17
|
autoload :Dispatcher, "prism/dispatcher"
|
19
18
|
autoload :DotVisitor, "prism/dot_visitor"
|
@@ -32,7 +31,6 @@ module Prism
|
|
32
31
|
# Some of these constants are not meant to be exposed, so marking them as
|
33
32
|
# private here.
|
34
33
|
|
35
|
-
private_constant :Debug
|
36
34
|
private_constant :LexCompat
|
37
35
|
private_constant :LexRipper
|
38
36
|
|
@@ -71,8 +69,6 @@ require_relative "prism/polyfill/byteindex"
|
|
71
69
|
require_relative "prism/node"
|
72
70
|
require_relative "prism/node_ext"
|
73
71
|
require_relative "prism/parse_result"
|
74
|
-
require_relative "prism/parse_result/comments"
|
75
|
-
require_relative "prism/parse_result/newlines"
|
76
72
|
|
77
73
|
# This is a Ruby implementation of the prism parser. If we're running on CRuby
|
78
74
|
# and we haven't explicitly set the PRISM_FFI_BACKEND environment variable, then
|
data/prism.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
4
|
spec.name = "prism"
|
5
|
-
spec.version = "0.
|
5
|
+
spec.version = "0.30.0"
|
6
6
|
spec.authors = ["Shopify"]
|
7
7
|
spec.email = ["ruby@shopify.com"]
|
8
8
|
|
@@ -65,12 +65,10 @@ Gem::Specification.new do |spec|
|
|
65
65
|
"include/prism/util/pm_newline_list.h",
|
66
66
|
"include/prism/util/pm_strncasecmp.h",
|
67
67
|
"include/prism/util/pm_string.h",
|
68
|
-
"include/prism/util/pm_string_list.h",
|
69
68
|
"include/prism/util/pm_strpbrk.h",
|
70
69
|
"include/prism/version.h",
|
71
70
|
"lib/prism.rb",
|
72
71
|
"lib/prism/compiler.rb",
|
73
|
-
"lib/prism/debug.rb",
|
74
72
|
"lib/prism/desugar_compiler.rb",
|
75
73
|
"lib/prism/dispatcher.rb",
|
76
74
|
"lib/prism/dot_visitor.rb",
|
@@ -149,7 +147,6 @@ Gem::Specification.new do |spec|
|
|
149
147
|
"src/util/pm_list.c",
|
150
148
|
"src/util/pm_memchr.c",
|
151
149
|
"src/util/pm_newline_list.c",
|
152
|
-
"src/util/pm_string_list.c",
|
153
150
|
"src/util/pm_string.c",
|
154
151
|
"src/util/pm_strncasecmp.c",
|
155
152
|
"src/util/pm_strpbrk.c"
|