Escapes a backslash inside a quoted object key - #214
Merged
Conversation
format_object_key/1 escaped the quote character of the style it was writing but never the escape character itself - the same defect px-v3b had just fixed one screen above it, in the same visitor. An object key carrying a backslash rendered it unescaped, so the source parsed back to a different key with the backslash silently gone, and a key ending in one rendered an unterminated literal that did not parse at all. A quoted key is read by the same lexer string rule as a literal, so it always owed the same escaping. Both quoted clauses now route through escape_within/2, the helper px-v3b introduced, rather than growing a second implementation: two escape paths in one writer is how this defect outlived the first fix. The identifier style is untouched - the parser only produces it for a bare identifier, which carries neither a quote nor a backslash. The corpus the escaping is tested over moves to Predicator.EscapeCorpus in test_helper.exs, matching this repo's test-support pattern, so the literal suite and the new object-key suite enumerate the same awkward cases from one place instead of drifting apart. Refs: px-0tz
Codecov Report✅ All modified and coverable lines are covered by tests.
🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes px-0tz.
The defect
format_object_key/1inStringVisitorescaped the quote character of thestyle it was writing but never the escape character itself - the same defect
px-v3b fixed for string literals one screen above it, in the same visitor, and
deliberately left in place here because a quoted object key sits outside that
bead's acceptance criteria.
A quoted key is read by the same lexer string rule as a literal
(
parse_object_key/1inparser.exconsumes a STRING token), so it alwaysowed the same escaping. Before this branch, on
main:{'a\b': 1}rendered with the backslash unescaped, so parsing it backyielded the key
ab- a silent data loss with no warning.{'\': 1}, an unterminated literalthat does not parse at all.
quote landed one character early.
The fix
Both quoted clauses now route through
escape_within/2, the shared helperpx-v3b introduced, rather than growing a second implementation. Two escape
paths in one writer is how this defect outlived the first fix, so the bead
asked for the helper specifically.
The
:identifierclause is untouched. The parser only ever produces it for abare identifier, which by construction carries neither a quote nor a
backslash, and quoting one on the writer's own initiative would switch a style
the writer is required to render as asked for (the px-v3b operator ruling).
Tests
test/predicator/visitors/string_visitor_object_key_escape_test.exspins theround trip for a corpus enumerated from the characters the lexer treats
specially, not transcribed from examples: 129 keys x 2 quote styles = 258
cases, plus the named cases the bead calls out and a guard that the identifier
style still renders bare.
Confirmed red before the fix (4 failures, including both the lone-backslash
and backslash-before-quote cases) and green after.
Provenance
Two files the bead did not name were forced by the change and are included:
test/test_helper.exsandtest/predicator/visitors/string_visitor_escape_test.exs. The new suiteneeds the same awkward-value corpus as the px-v3b literal suite, and a
second copy of the enumeration tripped
Credo.Check.Design.DuplicatedCodeon the full gate. The corpus moves to
Predicator.EscapeCorpusintest_helper.exs- this repo's established test-support pattern, alongsidePredicator.SpanSlicingandPredicator.ASTShape- and both suites readit. No behavior in either suite changed; the literal suite runs over the
same values it did before.
No new public surface. No ISA movement, no corpus regeneration, no version
bump.
Changelog
changelog.d/px-0tz.md, aFixedentry: user-visible, since a callerdecompiling an object with a quoted key was losing data.
Gate
mix qualitygreen on this HEAD (rebase was a no-op;mainisd952dd0):format, compile with warnings-as-errors, deps, Credo clean, 2,895 tests at
95.5% coverage, Dialyzer clean.