[ruby/prism] Frozen strings in the AST

8d9d429155
This commit is contained in:
Kevin Newton 2024-12-20 16:52:10 -05:00 committed by git
parent 48749afe61
commit 14b9098459
6 changed files with 42 additions and 9 deletions

View file

@ -2049,7 +2049,7 @@ module Prism
location = appendee.loc location = appendee.loc
location = location.with_expression(location.expression.join(child.loc.expression)) 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 else
children << child children << child
end end

View file

@ -929,9 +929,9 @@ module Prism
if result == :space if result == :space
# continue # continue
elsif result.is_a?(String) elsif result.is_a?(String)
results[0] << result results[0] = "#{results[0]}#{result}"
elsif result.is_a?(Array) && result[0] == :str elsif result.is_a?(Array) && result[0] == :str
results[0] << result[1] results[0] = "#{results[0]}#{result[1]}"
else else
results << result results << result
state = :interpolated_content state = :interpolated_content
@ -940,7 +940,7 @@ module Prism
if result == :space if result == :space
# continue # continue
elsif visited[index - 1] != :space && result.is_a?(Array) && result[0] == :str && results[-1][0] == :str && (results[-1].line_max == result.line) 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 results[-1].line_max = result.line_max
else else
results << result results << result
@ -1440,6 +1440,7 @@ module Prism
unescaped = node.unescaped unescaped = node.unescaped
if node.forced_binary_encoding? if node.forced_binary_encoding?
unescaped = unescaped.dup
unescaped.force_encoding(Encoding::BINARY) unescaped.force_encoding(Encoding::BINARY)
end end

View file

@ -34,7 +34,7 @@ pm_token_new(const pm_parser_t *parser, const pm_token_t *token, rb_encoding *en
static VALUE static VALUE
pm_string_new(const pm_string_t *string, rb_encoding *encoding) { 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 VALUE

View file

@ -241,14 +241,14 @@ module Prism
end end
def load_embedded_string def load_embedded_string
io.read(load_varuint).force_encoding(encoding) io.read(load_varuint).force_encoding(encoding).freeze
end end
def load_string def load_string
type = io.getbyte type = io.getbyte
case type case type
when 1 when 1
input.byteslice(load_varuint, load_varuint).force_encoding(encoding) input.byteslice(load_varuint, load_varuint).force_encoding(encoding).freeze
when 2 when 2
load_embedded_string load_embedded_string
else else

View file

@ -119,8 +119,8 @@ module Prism
if expected.is_a?(Array) && actual.is_a?(Array) 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:") && 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:") actual.last.start_with?("/.../n has a non escaped non ASCII character in non ASCII-8BIT script:")
expected.last.clear expected.pop
actual.last.clear actual.pop
end end
end end

View file

@ -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