fix(tools): complete the Literal parseability attribution and the soft-keyword positions
pyScalar's docstring named only the two code points CPython refuses anywhere in source. A bare quote, a trailing odd backslash, and a bare LF/CR break the Literal line just as fatally, and JSON.stringify is what covers those too. The argument also leaned on an unstated coincidence: every escape JSON.stringify can emit is a Python escape for the same character, which is why the emitted text both parses and decodes back to the declared value. Say both, and assert the second class. "statement head" does not describe `case`, whose clause block is not a statement. Split the positions three ways. Add the mode 'both' by python assembly, pinning the mode-by-language matrix rather than leaving it to the shared code path.
This commit is contained in:
@@ -29,9 +29,10 @@ const IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/
|
||||
* every tool and field without collisions.
|
||||
* Soft keywords (``match``, ``case``, ``type``, ``_`` — the language
|
||||
* reference's whole set) are deliberately ABSENT: each is special in exactly
|
||||
* one syntactic position — a statement head, or a ``match`` pattern for ``_``
|
||||
* — so ``match: str`` as a field and ``async def match(...)`` as a method are
|
||||
* both legal, and including
|
||||
* one syntactic position — a statement head (``match``, ``type``), a ``match``
|
||||
* statement's clause head (``case``), or a pattern (``_``) — so ``match: str``
|
||||
* as a field and ``async def match(...)`` as a method are both legal, and
|
||||
* including
|
||||
* them would needlessly degrade common search/regex tool fields to
|
||||
* ``dict[str, Any]``. Underscore-leading names are handled separately, not
|
||||
* here: a non-dunder ``__token`` name-mangles, a dunder present on
|
||||
@@ -262,13 +263,21 @@ function childClassName(base: string, segment: string): string {
|
||||
* by a JS parser back into the same double.
|
||||
*
|
||||
* `JSON.stringify` is also what keeps this path's output parseable, and it is
|
||||
* the only thing that does: it escapes both code points CPython refuses in
|
||||
* source — NUL among the C0 controls, and unpaired surrogates under ES2019
|
||||
* well-formed stringification, which the engines range guarantees. The
|
||||
* the only thing that does. It covers both classes of hazard: the two code
|
||||
* points CPython refuses anywhere in source — NUL among the C0 controls, and
|
||||
* unpaired surrogates under ES2019 well-formed stringification, which the
|
||||
* engines range guarantees — and the ones that break this line in particular,
|
||||
* a bare `"` closing the literal early, a trailing odd backslash eating the
|
||||
* closing quote, and a bare LF/CR ending it before its terminator. The
|
||||
* `description` path carries {@link UNPRINTABLE} and {@link LONE_SURROGATE}
|
||||
* because nothing quotes it. DEL and the C1 controls do reach a `Literal[...]`
|
||||
* raw — legal but invisible, byte-for-byte as in the TS flavor; escaping them
|
||||
* is a both-flavors change.
|
||||
* because nothing quotes it, and folds newlines in {@link describe}.
|
||||
*
|
||||
* That leans on a coincidence worth naming: every escape `JSON.stringify` can
|
||||
* emit (`\"`, `\\`, `\b`, `\f`, `\n`, `\r`, `\t`, `\uXXXX`) is also a Python
|
||||
* escape denoting the same character, so the emitted `Literal[...]` both
|
||||
* parses and decodes back to the value the schema declared. DEL and the C1
|
||||
* controls do reach it raw — legal but invisible, byte-for-byte as in the TS
|
||||
* flavor; escaping them is a both-flavors change.
|
||||
*/
|
||||
function pyScalar(value: JsonSchemaScalar): string {
|
||||
if (value === true) return 'True'
|
||||
|
||||
Reference in New Issue
Block a user