prism 0.26.0 → 0.28.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 +45 -1
- data/Makefile +3 -2
- data/config.yml +305 -20
- data/docs/configuration.md +1 -0
- data/ext/prism/api_node.c +884 -879
- data/ext/prism/extconf.rb +23 -4
- data/ext/prism/extension.c +16 -9
- data/ext/prism/extension.h +1 -1
- data/include/prism/ast.h +298 -9
- data/include/prism/diagnostic.h +15 -5
- data/include/prism/options.h +2 -2
- data/include/prism/parser.h +10 -0
- data/include/prism/static_literals.h +8 -6
- data/include/prism/version.h +2 -2
- data/lib/prism/dot_visitor.rb +22 -6
- data/lib/prism/dsl.rb +8 -8
- data/lib/prism/ffi.rb +4 -4
- data/lib/prism/inspect_visitor.rb +2156 -0
- data/lib/prism/lex_compat.rb +18 -1
- data/lib/prism/mutation_compiler.rb +2 -2
- data/lib/prism/node.rb +2345 -1964
- data/lib/prism/node_ext.rb +34 -5
- data/lib/prism/parse_result/newlines.rb +0 -2
- data/lib/prism/parse_result.rb +137 -13
- data/lib/prism/pattern.rb +12 -6
- data/lib/prism/polyfill/byteindex.rb +13 -0
- data/lib/prism/polyfill/unpack1.rb +14 -0
- data/lib/prism/reflection.rb +21 -31
- data/lib/prism/serialize.rb +27 -17
- data/lib/prism/translation/parser/compiler.rb +34 -15
- data/lib/prism/translation/parser.rb +6 -6
- data/lib/prism/translation/ripper.rb +72 -68
- data/lib/prism/translation/ruby_parser.rb +69 -31
- data/lib/prism.rb +3 -2
- data/prism.gemspec +36 -38
- data/rbi/prism/compiler.rbi +3 -5
- data/rbi/prism/inspect_visitor.rbi +12 -0
- data/rbi/prism/node.rbi +359 -321
- data/rbi/prism/parse_result.rbi +85 -34
- data/rbi/prism/reflection.rbi +7 -13
- data/rbi/prism/translation/ripper.rbi +1 -11
- data/rbi/prism.rbi +9 -9
- data/sig/prism/dsl.rbs +3 -3
- data/sig/prism/inspect_visitor.rbs +22 -0
- data/sig/prism/node.rbs +68 -48
- data/sig/prism/parse_result.rbs +42 -10
- data/sig/prism/reflection.rbs +2 -8
- data/sig/prism/serialize.rbs +2 -3
- data/sig/prism.rbs +9 -9
- data/src/diagnostic.c +44 -24
- data/src/node.c +41 -16
- data/src/options.c +2 -2
- data/src/prettyprint.c +61 -18
- data/src/prism.c +623 -188
- data/src/serialize.c +5 -2
- data/src/static_literals.c +120 -34
- data/src/token_type.c +4 -4
- data/src/util/pm_integer.c +9 -2
- metadata +7 -9
- data/lib/prism/node_inspector.rb +0 -68
- data/lib/prism/polyfill/string.rb +0 -12
- data/rbi/prism/desugar_compiler.rbi +0 -5
- data/rbi/prism/mutation_compiler.rbi +0 -5
- data/rbi/prism/translation/parser/compiler.rbi +0 -13
- data/rbi/prism/translation/ripper/ripper_compiler.rbi +0 -5
- data/rbi/prism/translation/ruby_parser.rbi +0 -11
@@ -483,13 +483,13 @@ module Prism
|
|
483
483
|
if node.parent.nil?
|
484
484
|
builder.const_global(
|
485
485
|
token(node.delimiter_loc),
|
486
|
-
[node.
|
486
|
+
[node.name, srange(node.name_loc)]
|
487
487
|
)
|
488
488
|
else
|
489
489
|
builder.const_fetch(
|
490
490
|
visit(node.parent),
|
491
491
|
token(node.delimiter_loc),
|
492
|
-
[node.
|
492
|
+
[node.name, srange(node.name_loc)]
|
493
493
|
)
|
494
494
|
end
|
495
495
|
end
|
@@ -839,7 +839,7 @@ module Prism
|
|
839
839
|
token(node.in_loc),
|
840
840
|
pattern,
|
841
841
|
guard,
|
842
|
-
srange_find(node.pattern.location.end_offset, node.statements&.location&.start_offset
|
842
|
+
srange_find(node.pattern.location.end_offset, node.statements&.location&.start_offset, [";", "then"]),
|
843
843
|
visit(node.statements)
|
844
844
|
)
|
845
845
|
end
|
@@ -1030,6 +1030,12 @@ module Prism
|
|
1030
1030
|
end
|
1031
1031
|
end
|
1032
1032
|
|
1033
|
+
# -> { it }
|
1034
|
+
# ^^^^^^^^^
|
1035
|
+
def visit_it_parameters_node(node)
|
1036
|
+
builder.args(nil, [], nil, false)
|
1037
|
+
end
|
1038
|
+
|
1033
1039
|
# foo(bar: baz)
|
1034
1040
|
# ^^^^^^^^
|
1035
1041
|
def visit_keyword_hash_node(node)
|
@@ -1052,13 +1058,14 @@ module Prism
|
|
1052
1058
|
# ^^^^^
|
1053
1059
|
def visit_lambda_node(node)
|
1054
1060
|
parameters = node.parameters
|
1061
|
+
implicit_parameters = parameters.is_a?(NumberedParametersNode) || parameters.is_a?(ItParametersNode)
|
1055
1062
|
|
1056
1063
|
builder.block(
|
1057
1064
|
builder.call_lambda(token(node.operator_loc)),
|
1058
1065
|
[node.opening, srange(node.opening_loc)],
|
1059
1066
|
if parameters.nil?
|
1060
1067
|
builder.args(nil, [], nil, false)
|
1061
|
-
elsif
|
1068
|
+
elsif implicit_parameters
|
1062
1069
|
visit(node.parameters)
|
1063
1070
|
else
|
1064
1071
|
builder.args(
|
@@ -1068,7 +1075,7 @@ module Prism
|
|
1068
1075
|
false
|
1069
1076
|
)
|
1070
1077
|
end,
|
1071
|
-
node.body&.accept(copy_compiler(forwarding:
|
1078
|
+
node.body&.accept(copy_compiler(forwarding: implicit_parameters ? [] : find_forwarding(parameters&.parameters))),
|
1072
1079
|
[node.closing, srange(node.closing_loc)]
|
1073
1080
|
)
|
1074
1081
|
end
|
@@ -1076,7 +1083,14 @@ module Prism
|
|
1076
1083
|
# foo
|
1077
1084
|
# ^^^
|
1078
1085
|
def visit_local_variable_read_node(node)
|
1079
|
-
|
1086
|
+
name = node.name
|
1087
|
+
|
1088
|
+
# This is just a guess. parser doesn't have support for the implicit
|
1089
|
+
# `it` variable yet, so we'll probably have to visit this once it
|
1090
|
+
# does.
|
1091
|
+
name = :it if name == :"0it"
|
1092
|
+
|
1093
|
+
builder.ident([name, srange(node.location)]).updated(:lvar)
|
1080
1094
|
end
|
1081
1095
|
|
1082
1096
|
# foo = 1
|
@@ -1665,7 +1679,7 @@ module Prism
|
|
1665
1679
|
end
|
1666
1680
|
|
1667
1681
|
# until foo; bar end
|
1668
|
-
#
|
1682
|
+
# ^^^^^^^^^^^^^^^^^^
|
1669
1683
|
#
|
1670
1684
|
# bar until foo
|
1671
1685
|
# ^^^^^^^^^^^^^
|
@@ -1698,7 +1712,7 @@ module Prism
|
|
1698
1712
|
if node.then_keyword_loc
|
1699
1713
|
token(node.then_keyword_loc)
|
1700
1714
|
else
|
1701
|
-
srange_find(node.conditions.last.location.end_offset, node.statements&.location&.start_offset
|
1715
|
+
srange_find(node.conditions.last.location.end_offset, node.statements&.location&.start_offset, [";"])
|
1702
1716
|
end,
|
1703
1717
|
visit(node.statements)
|
1704
1718
|
)
|
@@ -1857,12 +1871,16 @@ module Prism
|
|
1857
1871
|
|
1858
1872
|
# Constructs a new source range by finding the given tokens between the
|
1859
1873
|
# given start offset and end offset. If the needle is not found, it
|
1860
|
-
# returns nil.
|
1874
|
+
# returns nil. Importantly it does not search past newlines or comments.
|
1875
|
+
#
|
1876
|
+
# Note that end_offset is allowed to be nil, in which case this will
|
1877
|
+
# search until the end of the string.
|
1861
1878
|
def srange_find(start_offset, end_offset, tokens)
|
1862
|
-
tokens.
|
1863
|
-
|
1864
|
-
|
1865
|
-
|
1879
|
+
if (match = source_buffer.source.byteslice(start_offset...end_offset).match(/(\s*)(#{tokens.join("|")})/))
|
1880
|
+
_, whitespace, token = *match
|
1881
|
+
token_offset = start_offset + whitespace.bytesize
|
1882
|
+
|
1883
|
+
[token, Range.new(source_buffer, offset_cache[token_offset], offset_cache[token_offset + token.bytesize])]
|
1866
1884
|
end
|
1867
1885
|
end
|
1868
1886
|
|
@@ -1875,13 +1893,14 @@ module Prism
|
|
1875
1893
|
def visit_block(call, block)
|
1876
1894
|
if block
|
1877
1895
|
parameters = block.parameters
|
1896
|
+
implicit_parameters = parameters.is_a?(NumberedParametersNode) || parameters.is_a?(ItParametersNode)
|
1878
1897
|
|
1879
1898
|
builder.block(
|
1880
1899
|
call,
|
1881
1900
|
token(block.opening_loc),
|
1882
1901
|
if parameters.nil?
|
1883
1902
|
builder.args(nil, [], nil, false)
|
1884
|
-
elsif
|
1903
|
+
elsif implicit_parameters
|
1885
1904
|
visit(parameters)
|
1886
1905
|
else
|
1887
1906
|
builder.args(
|
@@ -1896,7 +1915,7 @@ module Prism
|
|
1896
1915
|
false
|
1897
1916
|
)
|
1898
1917
|
end,
|
1899
|
-
block.body&.accept(copy_compiler(forwarding:
|
1918
|
+
block.body&.accept(copy_compiler(forwarding: implicit_parameters ? [] : find_forwarding(parameters&.parameters))),
|
1900
1919
|
token(block.closing_loc)
|
1901
1920
|
)
|
1902
1921
|
else
|
@@ -46,7 +46,7 @@ module Prism
|
|
46
46
|
source = source_buffer.source
|
47
47
|
|
48
48
|
offset_cache = build_offset_cache(source)
|
49
|
-
result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version)), offset_cache)
|
49
|
+
result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version), scopes: [[]]), offset_cache)
|
50
50
|
|
51
51
|
build_ast(result.value, offset_cache)
|
52
52
|
ensure
|
@@ -59,7 +59,7 @@ module Prism
|
|
59
59
|
source = source_buffer.source
|
60
60
|
|
61
61
|
offset_cache = build_offset_cache(source)
|
62
|
-
result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version)), offset_cache)
|
62
|
+
result = unwrap(Prism.parse(source, filepath: source_buffer.name, version: convert_for_prism(version), scopes: [[]]), offset_cache)
|
63
63
|
|
64
64
|
[
|
65
65
|
build_ast(result.value, offset_cache),
|
@@ -78,7 +78,7 @@ module Prism
|
|
78
78
|
offset_cache = build_offset_cache(source)
|
79
79
|
result =
|
80
80
|
begin
|
81
|
-
unwrap(Prism.parse_lex(source, filepath: source_buffer.name, version: convert_for_prism(version)), offset_cache)
|
81
|
+
unwrap(Prism.parse_lex(source, filepath: source_buffer.name, version: convert_for_prism(version), scopes: [[]]), offset_cache)
|
82
82
|
rescue ::Parser::SyntaxError
|
83
83
|
raise if !recover
|
84
84
|
end
|
@@ -149,17 +149,17 @@ module Prism
|
|
149
149
|
Diagnostic.new(:error, :endless_setter, {}, diagnostic_location, [])
|
150
150
|
when :embdoc_term
|
151
151
|
Diagnostic.new(:error, :embedded_document, {}, diagnostic_location, [])
|
152
|
-
when :incomplete_variable_class, :
|
152
|
+
when :incomplete_variable_class, :incomplete_variable_class_3_3
|
153
153
|
location = location.copy(length: location.length + 1)
|
154
154
|
diagnostic_location = build_range(location, offset_cache)
|
155
155
|
|
156
156
|
Diagnostic.new(:error, :cvar_name, { name: location.slice }, diagnostic_location, [])
|
157
|
-
when :incomplete_variable_instance, :
|
157
|
+
when :incomplete_variable_instance, :incomplete_variable_instance_3_3
|
158
158
|
location = location.copy(length: location.length + 1)
|
159
159
|
diagnostic_location = build_range(location, offset_cache)
|
160
160
|
|
161
161
|
Diagnostic.new(:error, :ivar_name, { name: location.slice }, diagnostic_location, [])
|
162
|
-
when :invalid_variable_global, :
|
162
|
+
when :invalid_variable_global, :invalid_variable_global_3_3
|
163
163
|
Diagnostic.new(:error, :gvar_name, { name: location.slice }, diagnostic_location, [])
|
164
164
|
when :module_in_method
|
165
165
|
Diagnostic.new(:error, :module_in_def, {}, diagnostic_location, [])
|
@@ -19,31 +19,31 @@ module Prism
|
|
19
19
|
# The main known difference is that we may omit dispatching some events in
|
20
20
|
# some cases. This impacts the following events:
|
21
21
|
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
22
|
+
# - on_assign_error
|
23
|
+
# - on_comma
|
24
|
+
# - on_ignored_nl
|
25
|
+
# - on_ignored_sp
|
26
|
+
# - on_kw
|
27
|
+
# - on_label_end
|
28
|
+
# - on_lbrace
|
29
|
+
# - on_lbracket
|
30
|
+
# - on_lparen
|
31
|
+
# - on_nl
|
32
|
+
# - on_op
|
33
|
+
# - on_operator_ambiguous
|
34
|
+
# - on_rbrace
|
35
|
+
# - on_rbracket
|
36
|
+
# - on_rparen
|
37
|
+
# - on_semicolon
|
38
|
+
# - on_sp
|
39
|
+
# - on_symbeg
|
40
|
+
# - on_tstring_beg
|
41
|
+
# - on_tstring_end
|
42
42
|
#
|
43
43
|
class Ripper < Compiler
|
44
44
|
# Parses the given Ruby program read from +src+.
|
45
45
|
# +src+ must be a String or an IO or a object with a #gets method.
|
46
|
-
def
|
46
|
+
def self.parse(src, filename = "(ripper)", lineno = 1)
|
47
47
|
new(src, filename, lineno).parse
|
48
48
|
end
|
49
49
|
|
@@ -54,22 +54,22 @@ module Prism
|
|
54
54
|
# By default, this method does not handle syntax errors in +src+,
|
55
55
|
# use the +raise_errors+ keyword to raise a SyntaxError for an error in +src+.
|
56
56
|
#
|
57
|
-
#
|
58
|
-
#
|
57
|
+
# require "ripper"
|
58
|
+
# require "pp"
|
59
59
|
#
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
66
|
-
#
|
67
|
-
#
|
68
|
-
#
|
69
|
-
#
|
70
|
-
#
|
60
|
+
# pp Ripper.lex("def m(a) nil end")
|
61
|
+
# #=> [[[1, 0], :on_kw, "def", FNAME ],
|
62
|
+
# [[1, 3], :on_sp, " ", FNAME ],
|
63
|
+
# [[1, 4], :on_ident, "m", ENDFN ],
|
64
|
+
# [[1, 5], :on_lparen, "(", BEG|LABEL],
|
65
|
+
# [[1, 6], :on_ident, "a", ARG ],
|
66
|
+
# [[1, 7], :on_rparen, ")", ENDFN ],
|
67
|
+
# [[1, 8], :on_sp, " ", BEG ],
|
68
|
+
# [[1, 9], :on_kw, "nil", END ],
|
69
|
+
# [[1, 12], :on_sp, " ", END ],
|
70
|
+
# [[1, 13], :on_kw, "end", END ]]
|
71
71
|
#
|
72
|
-
def
|
72
|
+
def self.lex(src, filename = "-", lineno = 1, raise_errors: false)
|
73
73
|
result = Prism.lex_compat(src, filepath: filename, line: lineno)
|
74
74
|
|
75
75
|
if result.failure? && raise_errors
|
@@ -368,17 +368,17 @@ module Prism
|
|
368
368
|
# returning +nil+ in such cases. Use the +raise_errors+ keyword
|
369
369
|
# to raise a SyntaxError for an error in +src+.
|
370
370
|
#
|
371
|
-
#
|
372
|
-
#
|
371
|
+
# require "ripper"
|
372
|
+
# require "pp"
|
373
373
|
#
|
374
|
-
#
|
375
|
-
#
|
376
|
-
#
|
377
|
-
#
|
378
|
-
#
|
379
|
-
#
|
374
|
+
# pp Ripper.sexp("def m(a) nil end")
|
375
|
+
# #=> [:program,
|
376
|
+
# [[:def,
|
377
|
+
# [:@ident, "m", [1, 4]],
|
378
|
+
# [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil, nil, nil, nil]],
|
379
|
+
# [:bodystmt, [[:var_ref, [:@kw, "nil", [1, 9]]]], nil, nil, nil]]]]
|
380
380
|
#
|
381
|
-
def
|
381
|
+
def self.sexp(src, filename = "-", lineno = 1, raise_errors: false)
|
382
382
|
builder = SexpBuilderPP.new(src, filename, lineno)
|
383
383
|
sexp = builder.parse
|
384
384
|
if builder.error?
|
@@ -397,23 +397,23 @@ module Prism
|
|
397
397
|
# returning +nil+ in such cases. Use the +raise_errors+ keyword
|
398
398
|
# to raise a SyntaxError for an error in +src+.
|
399
399
|
#
|
400
|
-
#
|
401
|
-
#
|
400
|
+
# require "ripper"
|
401
|
+
# require "pp"
|
402
402
|
#
|
403
|
-
#
|
404
|
-
#
|
405
|
-
#
|
406
|
-
#
|
407
|
-
#
|
408
|
-
#
|
409
|
-
#
|
410
|
-
#
|
411
|
-
#
|
412
|
-
#
|
413
|
-
#
|
414
|
-
#
|
403
|
+
# pp Ripper.sexp_raw("def m(a) nil end")
|
404
|
+
# #=> [:program,
|
405
|
+
# [:stmts_add,
|
406
|
+
# [:stmts_new],
|
407
|
+
# [:def,
|
408
|
+
# [:@ident, "m", [1, 4]],
|
409
|
+
# [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil]],
|
410
|
+
# [:bodystmt,
|
411
|
+
# [:stmts_add, [:stmts_new], [:var_ref, [:@kw, "nil", [1, 9]]]],
|
412
|
+
# nil,
|
413
|
+
# nil,
|
414
|
+
# nil]]]]
|
415
415
|
#
|
416
|
-
def
|
416
|
+
def self.sexp_raw(src, filename = "-", lineno = 1, raise_errors: false)
|
417
417
|
builder = SexpBuilder.new(src, filename, lineno)
|
418
418
|
sexp = builder.parse
|
419
419
|
if builder.error?
|
@@ -1456,16 +1456,16 @@ module Prism
|
|
1456
1456
|
# ^^^^^^^^
|
1457
1457
|
def visit_constant_path_node(node)
|
1458
1458
|
if node.parent.nil?
|
1459
|
-
bounds(node.
|
1460
|
-
child = on_const(node.
|
1459
|
+
bounds(node.name_loc)
|
1460
|
+
child = on_const(node.name.to_s)
|
1461
1461
|
|
1462
1462
|
bounds(node.location)
|
1463
1463
|
on_top_const_ref(child)
|
1464
1464
|
else
|
1465
1465
|
parent = visit(node.parent)
|
1466
1466
|
|
1467
|
-
bounds(node.
|
1468
|
-
child = on_const(node.
|
1467
|
+
bounds(node.name_loc)
|
1468
|
+
child = on_const(node.name.to_s)
|
1469
1469
|
|
1470
1470
|
bounds(node.location)
|
1471
1471
|
on_const_path_ref(parent, child)
|
@@ -1488,16 +1488,16 @@ module Prism
|
|
1488
1488
|
# Visit a constant path that is part of a write node.
|
1489
1489
|
private def visit_constant_path_write_node_target(node)
|
1490
1490
|
if node.parent.nil?
|
1491
|
-
bounds(node.
|
1492
|
-
child = on_const(node.
|
1491
|
+
bounds(node.name_loc)
|
1492
|
+
child = on_const(node.name.to_s)
|
1493
1493
|
|
1494
1494
|
bounds(node.location)
|
1495
1495
|
on_top_const_field(child)
|
1496
1496
|
else
|
1497
1497
|
parent = visit(node.parent)
|
1498
1498
|
|
1499
|
-
bounds(node.
|
1500
|
-
child = on_const(node.
|
1499
|
+
bounds(node.name_loc)
|
1500
|
+
child = on_const(node.name.to_s)
|
1501
1501
|
|
1502
1502
|
bounds(node.location)
|
1503
1503
|
on_const_path_field(parent, child)
|
@@ -3267,7 +3267,11 @@ module Prism
|
|
3267
3267
|
|
3268
3268
|
# Lazily initialize the parse result.
|
3269
3269
|
def result
|
3270
|
-
@result ||=
|
3270
|
+
@result ||=
|
3271
|
+
begin
|
3272
|
+
scopes = RUBY_VERSION >= "3.3.0" ? [] : [[]]
|
3273
|
+
Prism.parse(source, scopes: scopes)
|
3274
|
+
end
|
3271
3275
|
end
|
3272
3276
|
|
3273
3277
|
##########################################################################
|
@@ -442,9 +442,9 @@ module Prism
|
|
442
442
|
# ^^^^^^^^
|
443
443
|
def visit_constant_path_node(node)
|
444
444
|
if node.parent.nil?
|
445
|
-
s(node, :colon3, node.
|
445
|
+
s(node, :colon3, node.name)
|
446
446
|
else
|
447
|
-
s(node, :colon2, visit(node.parent), node.
|
447
|
+
s(node, :colon2, visit(node.parent), node.name)
|
448
448
|
end
|
449
449
|
end
|
450
450
|
|
@@ -805,17 +805,29 @@ module Prism
|
|
805
805
|
# if /foo #{bar}/ then end
|
806
806
|
# ^^^^^^^^^^^^
|
807
807
|
def visit_interpolated_match_last_line_node(node)
|
808
|
-
|
808
|
+
parts = visit_interpolated_parts(node.parts)
|
809
|
+
regexp =
|
810
|
+
if parts.length == 1
|
811
|
+
s(node, :lit, Regexp.new(parts.first, node.options))
|
812
|
+
else
|
813
|
+
s(node, :dregx).concat(parts).tap do |result|
|
814
|
+
options = node.options
|
815
|
+
result << options if options != 0
|
816
|
+
end
|
817
|
+
end
|
818
|
+
|
819
|
+
s(node, :match, regexp)
|
809
820
|
end
|
810
821
|
|
811
822
|
# /foo #{bar}/
|
812
823
|
# ^^^^^^^^^^^^
|
813
824
|
def visit_interpolated_regular_expression_node(node)
|
814
|
-
|
815
|
-
|
816
|
-
|
825
|
+
parts = visit_interpolated_parts(node.parts)
|
826
|
+
|
827
|
+
if parts.length == 1
|
828
|
+
s(node, :lit, Regexp.new(parts.first, node.options))
|
817
829
|
else
|
818
|
-
s(node, :dregx).concat(
|
830
|
+
s(node, :dregx).concat(parts).tap do |result|
|
819
831
|
options = node.options
|
820
832
|
result << options if options != 0
|
821
833
|
end
|
@@ -825,45 +837,71 @@ module Prism
|
|
825
837
|
# "foo #{bar}"
|
826
838
|
# ^^^^^^^^^^^^
|
827
839
|
def visit_interpolated_string_node(node)
|
828
|
-
|
829
|
-
|
830
|
-
unescaped = node.parts.map { |part| part.is_a?(StringNode) ? part.unescaped : part.statements.body.first.unescaped }.join
|
831
|
-
s(node, :str, unescaped)
|
832
|
-
else
|
833
|
-
s(node, :dstr).concat(visit_interpolated_parts(node.parts))
|
834
|
-
end
|
840
|
+
parts = visit_interpolated_parts(node.parts)
|
841
|
+
parts.length == 1 ? s(node, :str, parts.first) : s(node, :dstr).concat(parts)
|
835
842
|
end
|
836
843
|
|
837
844
|
# :"foo #{bar}"
|
838
845
|
# ^^^^^^^^^^^^^
|
839
846
|
def visit_interpolated_symbol_node(node)
|
840
|
-
|
841
|
-
|
842
|
-
s(node, :lit, unescaped.to_sym)
|
843
|
-
else
|
844
|
-
s(node, :dsym).concat(visit_interpolated_parts(node.parts))
|
845
|
-
end
|
847
|
+
parts = visit_interpolated_parts(node.parts)
|
848
|
+
parts.length == 1 ? s(node, :lit, parts.first.to_sym) : s(node, :dsym).concat(parts)
|
846
849
|
end
|
847
850
|
|
848
851
|
# `foo #{bar}`
|
849
852
|
# ^^^^^^^^^^^^
|
850
853
|
def visit_interpolated_x_string_node(node)
|
851
|
-
|
852
|
-
|
854
|
+
source = node.heredoc? ? node.parts.first : node
|
855
|
+
parts = visit_interpolated_parts(node.parts)
|
856
|
+
parts.length == 1 ? s(source, :xstr, parts.first) : s(source, :dxstr).concat(parts)
|
853
857
|
end
|
854
858
|
|
855
859
|
# Visit the interpolated content of the string-like node.
|
856
860
|
private def visit_interpolated_parts(parts)
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
+
visited = []
|
862
|
+
parts.each do |part|
|
863
|
+
result = visit(part)
|
864
|
+
|
865
|
+
if result[0] == :evstr && result[1]
|
866
|
+
if result[1][0] == :str
|
867
|
+
visited << result[1]
|
868
|
+
elsif result[1][0] == :dstr
|
869
|
+
visited.concat(result[1][1..-1])
|
870
|
+
else
|
871
|
+
visited << result
|
872
|
+
end
|
873
|
+
else
|
874
|
+
visited << result
|
875
|
+
end
|
876
|
+
end
|
877
|
+
|
878
|
+
state = :beginning #: :beginning | :string_content | :interpolated_content
|
879
|
+
|
880
|
+
visited.each_with_object([]) do |result, results|
|
881
|
+
case state
|
882
|
+
when :beginning
|
883
|
+
if result.is_a?(String)
|
884
|
+
results << result
|
885
|
+
state = :string_content
|
886
|
+
elsif result.is_a?(Array) && result[0] == :str
|
887
|
+
results << result[1]
|
888
|
+
state = :string_content
|
861
889
|
else
|
862
890
|
results << ""
|
863
|
-
results <<
|
891
|
+
results << result
|
892
|
+
state = :interpolated_content
|
893
|
+
end
|
894
|
+
when :string_content
|
895
|
+
if result.is_a?(String)
|
896
|
+
results[0] << result
|
897
|
+
elsif result.is_a?(Array) && result[0] == :str
|
898
|
+
results[0] << result[1]
|
899
|
+
else
|
900
|
+
results << result
|
901
|
+
state = :interpolated_content
|
864
902
|
end
|
865
903
|
else
|
866
|
-
results <<
|
904
|
+
results << result
|
867
905
|
end
|
868
906
|
end
|
869
907
|
end
|
@@ -1297,7 +1335,7 @@ module Prism
|
|
1297
1335
|
# __FILE__
|
1298
1336
|
# ^^^^^^^^
|
1299
1337
|
def visit_source_file_node(node)
|
1300
|
-
s(node, :str,
|
1338
|
+
s(node, :str, node.filepath)
|
1301
1339
|
end
|
1302
1340
|
|
1303
1341
|
# __LINE__
|
@@ -1498,13 +1536,13 @@ module Prism
|
|
1498
1536
|
# Parse the given source and translate it into the seattlerb/ruby_parser
|
1499
1537
|
# gem's Sexp format.
|
1500
1538
|
def parse(source, filepath = "(string)")
|
1501
|
-
translate(Prism.parse(source), filepath)
|
1539
|
+
translate(Prism.parse(source, filepath: filepath, scopes: [[]]), filepath)
|
1502
1540
|
end
|
1503
1541
|
|
1504
1542
|
# Parse the given file and translate it into the seattlerb/ruby_parser
|
1505
1543
|
# gem's Sexp format.
|
1506
1544
|
def parse_file(filepath)
|
1507
|
-
translate(Prism.parse_file(filepath), filepath)
|
1545
|
+
translate(Prism.parse_file(filepath, scopes: [[]]), filepath)
|
1508
1546
|
end
|
1509
1547
|
|
1510
1548
|
class << self
|
data/lib/prism.rb
CHANGED
@@ -18,10 +18,10 @@ module Prism
|
|
18
18
|
autoload :Dispatcher, "prism/dispatcher"
|
19
19
|
autoload :DotVisitor, "prism/dot_visitor"
|
20
20
|
autoload :DSL, "prism/dsl"
|
21
|
+
autoload :InspectVisitor, "prism/inspect_visitor"
|
21
22
|
autoload :LexCompat, "prism/lex_compat"
|
22
23
|
autoload :LexRipper, "prism/lex_compat"
|
23
24
|
autoload :MutationCompiler, "prism/mutation_compiler"
|
24
|
-
autoload :NodeInspector, "prism/node_inspector"
|
25
25
|
autoload :Pack, "prism/pack"
|
26
26
|
autoload :Pattern, "prism/pattern"
|
27
27
|
autoload :Reflection, "prism/reflection"
|
@@ -37,7 +37,7 @@ module Prism
|
|
37
37
|
private_constant :LexRipper
|
38
38
|
|
39
39
|
# :call-seq:
|
40
|
-
# Prism::lex_compat(source, **options) ->
|
40
|
+
# Prism::lex_compat(source, **options) -> LexCompat::Result
|
41
41
|
#
|
42
42
|
# Returns a parse result whose value is an array of tokens that closely
|
43
43
|
# resembles the return value of Ripper::lex. The main difference is that the
|
@@ -67,6 +67,7 @@ module Prism
|
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
|
+
require_relative "prism/polyfill/byteindex"
|
70
71
|
require_relative "prism/node"
|
71
72
|
require_relative "prism/node_ext"
|
72
73
|
require_relative "prism/parse_result"
|