Skip to content

Commit 14b9098

Browse files
kddnewtonmatzbot
authored andcommitted
[ruby/prism] Frozen strings in the AST
ruby/prism@8d9d429155
1 parent 48749af commit 14b9098

File tree

6 files changed

+42
-9
lines changed

6 files changed

+42
-9
lines changed

lib/prism/translation/parser/compiler.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -2049,7 +2049,7 @@ def visit_heredoc(node)
20492049
location = appendee.loc
20502050
location = location.with_expression(location.expression.join(child.loc.expression))
20512051

2052-
children[-1] = appendee.updated(:str, [appendee.children.first << child.children.first], location: location)
2052+
children[-1] = appendee.updated(:str, ["#{appendee.children.first}#{child.children.first}"], location: location)
20532053
else
20542054
children << child
20552055
end

lib/prism/translation/ruby_parser.rb

+4-3
Original file line numberDiff line numberDiff line change
@@ -929,9 +929,9 @@ def visit_interpolated_x_string_node(node)
929929
if result == :space
930930
# continue
931931
elsif result.is_a?(String)
932-
results[0] << result
932+
results[0] = "#{results[0]}#{result}"
933933
elsif result.is_a?(Array) && result[0] == :str
934-
results[0] << result[1]
934+
results[0] = "#{results[0]}#{result[1]}"
935935
else
936936
results << result
937937
state = :interpolated_content
@@ -940,7 +940,7 @@ def visit_interpolated_x_string_node(node)
940940
if result == :space
941941
# continue
942942
elsif visited[index - 1] != :space && result.is_a?(Array) && result[0] == :str && results[-1][0] == :str && (results[-1].line_max == result.line)
943-
results[-1][1] << result[1]
943+
results[-1][1] = "#{results[-1][1]}#{result[1]}"
944944
results[-1].line_max = result.line_max
945945
else
946946
results << result
@@ -1440,6 +1440,7 @@ def visit_string_node(node)
14401440
unescaped = node.unescaped
14411441

14421442
if node.forced_binary_encoding?
1443+
unescaped = unescaped.dup
14431444
unescaped.force_encoding(Encoding::BINARY)
14441445
end
14451446

prism/templates/ext/prism/api_node.c.erb

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pm_token_new(const pm_parser_t *parser, const pm_token_t *token, rb_encoding *en
3434

3535
static VALUE
3636
pm_string_new(const pm_string_t *string, rb_encoding *encoding) {
37-
return rb_enc_str_new((const char *) pm_string_source(string), pm_string_length(string), encoding);
37+
return rb_obj_freeze(rb_enc_str_new((const char *) pm_string_source(string), pm_string_length(string), encoding));
3838
}
3939

4040
VALUE

prism/templates/lib/prism/serialize.rb.erb

+2-2
Original file line numberDiff line numberDiff line change
@@ -241,14 +241,14 @@ module Prism
241241
end
242242

243243
def load_embedded_string
244-
io.read(load_varuint).force_encoding(encoding)
244+
io.read(load_varuint).force_encoding(encoding).freeze
245245
end
246246

247247
def load_string
248248
type = io.getbyte
249249
case type
250250
when 1
251-
input.byteslice(load_varuint, load_varuint).force_encoding(encoding)
251+
input.byteslice(load_varuint, load_varuint).force_encoding(encoding).freeze
252252
when 2
253253
load_embedded_string
254254
else

test/prism/encoding/regular_expression_encoding_test.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ def assert_regular_expression_encoding_flags(encoding, regexps)
119119
if expected.is_a?(Array) && actual.is_a?(Array)
120120
if expected.last.start_with?("/.../n has a non escaped non ASCII character in non ASCII-8BIT script:") &&
121121
actual.last.start_with?("/.../n has a non escaped non ASCII character in non ASCII-8BIT script:")
122-
expected.last.clear
123-
actual.last.clear
122+
expected.pop
123+
actual.pop
124124
end
125125
end
126126

test/prism/result/string_test.rb

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# frozen_string_literal: true
2+
3+
require_relative "../test_helper"
4+
5+
module Prism
6+
class StringTest < TestCase
7+
def test_regular_expression_node_unescaped_frozen
8+
node = Prism.parse_statement("/foo/")
9+
assert_predicate node.unescaped, :frozen?
10+
end
11+
12+
def test_source_file_node_filepath_frozen
13+
node = Prism.parse_statement("__FILE__")
14+
assert_predicate node.filepath, :frozen?
15+
end
16+
17+
def test_string_node_unescaped_frozen
18+
node = Prism.parse_statement('"foo"')
19+
assert_predicate node.unescaped, :frozen?
20+
end
21+
22+
def test_symbol_node_unescaped_frozen
23+
node = Prism.parse_statement(":foo")
24+
assert_predicate node.unescaped, :frozen?
25+
end
26+
27+
def test_xstring_node_unescaped_frozen
28+
node = Prism.parse_statement("`foo`")
29+
assert_predicate node.unescaped, :frozen?
30+
end
31+
end
32+
end

0 commit comments

Comments
 (0)