Skip to content

Rename SymbolNode#value_loc to SymbolNode#content_loc - #4215

Open
Earlopain wants to merge 1 commit into
ruby:mainfrom
Earlopain:rename-content-to-value
Open

Earlopain wants to merge 1 commit into
ruby:mainfrom
Earlopain:rename-content-to-value

Conversation

@Earlopain

Copy link
Copy Markdown
Collaborator

Currently there are 43 matches for name: value and only 4 for name: content in config.yml
RationalNode/ImaginaryNode also have value from node extensions.

(of course, most of the 43 are not for literals but for child nodes like in the RHS of a = 1)

The one I particularly care about is StringNode because I often handle SymbolNode and StringNode the same way but I have to write different code becaues the fields are not named the same. This allows to ducktype them and I don't have to keep in mind when to use content vs value. value for a literal also sounds better to me.

Same as in #4060, keep the previous names around.

@Earlopain
Earlopain force-pushed the rename-content-to-value branch from fc643c4 to 0235374 Compare August 27, 2026 13:00
@eregon

eregon commented Aug 27, 2026

Copy link
Copy Markdown
Member

Wouldn't you want unescaped instead of content for those? (depending on the situation)
I would expect unescaped if aliased to value, e.g. Integer#value parses the number, "unescaping it" for something like 1_000_000.

require 'prism'

code = <<'RUBY'
"a\nb"
RUBY

node = Prism.parse(code).value.statements.body[0]

pp node
p node.content
p node.unescaped

gives:

$ ruby test_string_node.rb
@ StringNode (location: (1,0)-(1,6))
├── flags: newline
├── opening_loc: (1,0)-(1,1) = "\""
├── content_loc: (1,1)-(1,5) = "a\\nb"
├── closing_loc: (1,5)-(1,6) = "\""
└── unescaped: "a\nb"
"a\\nb" # content
"a\nb" # unescaped

@eregon

eregon commented Aug 27, 2026

Copy link
Copy Markdown
Member

SymbolNode does indeed name content as value though, and has unescaped too:

code = <<'RUBY'
:"a\nb"
RUBY

@ SymbolNode (location: (1,0)-(1,7))
├── flags: newline, static_literal, forced_us_ascii_encoding
├── opening_loc: (1,0)-(1,2) = ":\""
├── value_loc: (1,2)-(1,6) = "a\\nb"
├── closing_loc: (1,6)-(1,7) = "\""
└── unescaped: "a\nb"
"a\\nb" # value
"a\nb" # unescaped

@eregon

eregon commented Aug 27, 2026

Copy link
Copy Markdown
Member

Or IOW, I would expect SomeLiteralNode value to return an instance of Literal, e.g. IntegerNode#value returns an Integer, FloatNode#value a Float, etc.
That's however not the case currently for SymbolNode#value which returns an escaped String, and not an unescaped Symbol.

(apologies for the many comments, just trying to explain my thoughts on this)

@Earlopain

Copy link
Copy Markdown
Collaborator Author

That did not cross my mind. Yes, I would want the unescaped one and have probably not done so many times when I should have for correctness.

Let me update this to a different approach. However I'm not so convinced anymore since the distinction between value/content is not immediatly obvious when both are present.

@Earlopain
Earlopain marked this pull request as draft August 27, 2026 19:39
@kddnewton

Copy link
Copy Markdown
Collaborator

Yeah I'm very hesitant on this. If I were to call value on a SymbolNode, I would expect it to be the actual value of the symbol. For a string, I would expect it to be the unescaped string. Same for all other literals. Honestly I'm not too keen on this PR because it's a fair amount of churn (most clients working with Prism will touch symbols/strings) and I'm not sure it's getting us closer to a specific goal.

@Earlopain

Copy link
Copy Markdown
Collaborator Author

Not sure I'm following. What should .value be for :"a\nb" be in your mind? With the newline resolved, or just as written (so with a literal backslash + n)

@eregon

eregon commented Aug 27, 2026

Copy link
Copy Markdown
Member

Not sure I'm following. What should .value be for :"a\nb" be in your mind? With the newline resolved, or just as written (so with a literal backslash + n)

I believe Kevin means with the newline resolved, since it would be a Symbol object corresponding to the source.
Basically I think value for a literal node should be the same, so to speak, as eval(node.slice).
It's the case for most literals, but not SymbolNode (returns an escaped String instead), StringNode, XStringNode, RegularExpressionNode, MatchLastLineNode (no value method), and maybe a few more.

I'd imagine changing SymbolNode#value to return a Symbol instead of a String is tough for compatibility.

@Earlopain
Earlopain force-pushed the rename-content-to-value branch from 0235374 to f92d9b5 Compare September 15, 2026 12:54
@Earlopain Earlopain changed the title Rename content fields to value Rename SymbolNode#value_loc to SymbolNode#content_loc Sep 15, 2026
@Earlopain
Earlopain force-pushed the rename-content-to-value branch from f92d9b5 to 1c8aca6 Compare September 15, 2026 12:55
Makes it consistent with nodes that contain text, like `StringNode`
For those, `value` returns the literal. But we can't make it return a symbol for backwards compatibility.
@Earlopain
Earlopain force-pushed the rename-content-to-value branch from 1c8aca6 to 7c1e135 Compare September 15, 2026 12:57
@Earlopain

Copy link
Copy Markdown
Collaborator Author

So I've just renamed SymbolNode value_loc to content_loc. With #4220 that is similar enough for typechecking.

And yeah, impossible to return a symbol for backwards compatibility. Now it's just like #4060

@Earlopain
Earlopain marked this pull request as ready for review September 15, 2026 12:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants