summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Newton <[email protected]>2024-12-20 16:52:10 -0500
committergit <[email protected]>2025-01-12 18:41:42 +0000
commit14b9098459b88f94e316ccc9274693e74565739e (patch)
tree3f0d66e89ab1e4599cc549159eee3db88fd5e0d7
parent48749afe61fedcfd59cbd2fcc134c55f5ccef7f8 (diff)
[ruby/prism] Frozen strings in the AST
https://github.com/ruby/prism/commit/8d9d429155
-rw-r--r--lib/prism/translation/parser/compiler.rb2
-rw-r--r--lib/prism/translation/ruby_parser.rb7
-rw-r--r--prism/templates/ext/prism/api_node.c.erb2
-rw-r--r--prism/templates/lib/prism/serialize.rb.erb4
-rw-r--r--test/prism/encoding/regular_expression_encoding_test.rb4
-rw-r--r--test/prism/result/string_test.rb32
6 files changed, 42 insertions, 9 deletions
diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb
index e6ffa39d9d..26c5c174f4 100644
--- a/lib/prism/translation/parser/compiler.rb
+++ b/lib/prism/translation/parser/compiler.rb
@@ -2049,7 +2049,7 @@ module Prism
location = appendee.loc
location = location.with_expression(location.expression.join(child.loc.expression))
- children[-1] = appendee.updated(:str, [appendee.children.first << child.children.first], location: location)
+ children[-1] = appendee.updated(:str, ["#{appendee.children.first}#{child.children.first}"], location: location)
else
children << child
end
diff --git a/lib/prism/translation/ruby_parser.rb b/lib/prism/translation/ruby_parser.rb
index 465b693470..7fb533048c 100644
--- a/lib/prism/translation/ruby_parser.rb
+++ b/lib/prism/translation/ruby_parser.rb
@@ -929,9 +929,9 @@ module Prism
if result == :space
# continue
elsif result.is_a?(String)
- results[0] << result
+ results[0] = "#{results[0]}#{result}"
elsif result.is_a?(Array) && result[0] == :str
- results[0] << result[1]
+ results[0] = "#{results[0]}#{result[1]}"
else
results << result
state = :interpolated_content
@@ -940,7 +940,7 @@ module Prism
if result == :space
# continue
elsif visited[index - 1] != :space && result.is_a?(Array) && result[0] == :str && results[-1][0] == :str && (results[-1].line_max == result.line)
- results[-1][1] << result[1]
+ results[-1][1] = "#{results[-1][1]}#{result[1]}"
results[-1].line_max = result.line_max
else
results << result
@@ -1440,6 +1440,7 @@ module Prism
unescaped = node.unescaped
if node.forced_binary_encoding?
+ unescaped = unescaped.dup
unescaped.force_encoding(Encoding::BINARY)
end
diff --git a/prism/templates/ext/prism/api_node.c.erb b/prism/templates/ext/prism/api_node.c.erb
index 03615b0ae2..777ebfa8fc 100644
--- a/prism/templates/ext/prism/api_node.c.erb
+++ b/prism/templates/ext/prism/api_node.c.erb
@@ -34,7 +34,7 @@ pm_token_new(const pm_parser_t *parser, const pm_token_t *token, rb_encoding *en
static VALUE
pm_string_new(const pm_string_t *string, rb_encoding *encoding) {
- return rb_enc_str_new((const char *) pm_string_source(string), pm_string_length(string), encoding);
+ return rb_obj_freeze(rb_enc_str_new((const char *) pm_string_source(string), pm_string_length(string), encoding));
}
VALUE
diff --git a/prism/templates/lib/prism/serialize.rb.erb b/prism/templates/lib/prism/serialize.rb.erb
index 01c0a6cb2d..d40aa881e7 100644
--- a/prism/templates/lib/prism/serialize.rb.erb
+++ b/prism/templates/lib/prism/serialize.rb.erb
@@ -241,14 +241,14 @@ module Prism
end
def load_embedded_string
- io.read(load_varuint).force_encoding(encoding)
+ io.read(load_varuint).force_encoding(encoding).freeze
end
def load_string
type = io.getbyte
case type
when 1
- input.byteslice(load_varuint, load_varuint).force_encoding(encoding)
+ input.byteslice(load_varuint, load_varuint).force_encoding(encoding).freeze
when 2
load_embedded_string
else
diff --git a/test/prism/encoding/regular_expression_encoding_test.rb b/test/prism/encoding/regular_expression_encoding_test.rb
index 5d062fe59a..e2daae1d7f 100644
--- a/test/prism/encoding/regular_expression_encoding_test.rb
+++ b/test/prism/encoding/regular_expression_encoding_test.rb
@@ -119,8 +119,8 @@ module Prism
if expected.is_a?(Array) && actual.is_a?(Array)
if expected.last.start_with?("/.../n has a non escaped non ASCII character in non ASCII-8BIT script:") &&
actual.last.start_with?("/.../n has a non escaped non ASCII character in non ASCII-8BIT script:")
- expected.last.clear
- actual.last.clear
+ expected.pop
+ actual.pop
end
end
diff --git a/test/prism/result/string_test.rb b/test/prism/result/string_test.rb
new file mode 100644
index 0000000000..48c7f592eb
--- /dev/null
+++ b/test/prism/result/string_test.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class StringTest < TestCase
+ def test_regular_expression_node_unescaped_frozen
+ node = Prism.parse_statement("/foo/")
+ assert_predicate node.unescaped, :frozen?
+ end
+
+ def test_source_file_node_filepath_frozen
+ node = Prism.parse_statement("__FILE__")
+ assert_predicate node.filepath, :frozen?
+ end
+
+ def test_string_node_unescaped_frozen
+ node = Prism.parse_statement('"foo"')
+ assert_predicate node.unescaped, :frozen?
+ end
+
+ def test_symbol_node_unescaped_frozen
+ node = Prism.parse_statement(":foo")
+ assert_predicate node.unescaped, :frozen?
+ end
+
+ def test_xstring_node_unescaped_frozen
+ node = Prism.parse_statement("`foo`")
+ assert_predicate node.unescaped, :frozen?
+ end
+ end
+end