Commit d07e330
authored
* Fold ASCII in the last-resort schema scan, and make its tests able to fail
Follow-up to #3297, which merged at the head I had pushed rather than the one
I had finished. Three commits did not make it, and one of them is a real fix
rather than polish, so this lands them.
THE FIX. `detectSchemaVersion`'s fallback uppercases the first 2000 bytes and
looks for `IFC5` / `IFC4X3` / `IFC4` / `IFC2X3` as substrings.
`'ı'.toUpperCase()` is `'I'`, so a FILE_DESCRIPTION mentioning `ıFC5` selects
IFC5 for a file that never said so. Still live on main at source-header.ts:294.
Same fold #3297 removed from the record scan, one function further down the
same file. The scan is deliberately loose -- it only runs when no FILE_SCHEMA
identifier resolves, and it already matches `IFC4` inside ordinary prose --
but loose is not a reason to accept a fold ISO 10303-21 does not use. A copy
is fine here where it was not in the record scan, because nothing takes
offsets from it.
THE TESTS THAT COULD NOT FAIL. My first two tests for this did not exercise
the fold at all: one asserted the trailing IFC4 default, which passes for any
implementation that fails to match, and the other fed input already
upper-case. An identity mutant on the helper was killed by ZERO tests across
the whole parser suite. There is now a case that drives the direction the fold
exists for, lower-case `ifc4x3` in prose, plus one for the subtler mutant that
DROPS non-ASCII rather than passing it through: deleting a character joins the
fragments either side, so `IFCı5` becomes `IFC5`, a match built from a
character that was never in the word.
Off-by-one bounds on the fold survive and are left alone deliberately. The
output is consumed only by `.includes()` on tokens whose letters are i, f, c
and x, so neither `a` nor `z` can appear in a match and nothing through the
public surface can distinguish them.
A FALSE CLAIM, replacing a stale one. #3297 rewrote a comment in
`schema-version-detection.test.ts` that wrongly said `detectSchemaVersion` is
module-private, and replaced it with a different wrong claim: that
`buildStep()` can never reach the last-resort scan. It always emits a
FILE_SCHEMA record but not always a RESOLVABLE one, and the `IFC2X2` case
falls through to the scan. Proven by putting a throw at the top of the scan
and watching only that test go red.
Also: `schema_detect.rs` uses the crate's SPDX one-line header like every
sibling, both changeset fences declare a language, and the changeset says the
`ıFC5` input falls through to the IFC4 default rather than "no longer selects
a schema", since `detectSchemaVersion` always returns one.
Verified by exit code: parser 849, rust export 0, typecheck 0, lint 0,
module-size 0. Mutation-verified: restoring `toUpperCase()` reddens the new
test and only it.
* Drop the license-header change, and say what the fold gives up
Preflight came back clean on the fix itself and raised two small things.
The SPDX header swap on `schema_detect.rs` has nothing to do with the ASCII
fold, so it is out. It was a CodeRabbit suggestion I took on the original
branch, and it is defensible -- 52 of 54 files in `rust/export/src` already
use the one-line form -- but `LICENSE_HEADER.md` still documents the block
comment as required for `.rs`, and `scripts/add-license-headers.mjs` matches
only that form. So the repo has an in-flight migration with a stale doc and a
stale script, and quietly adding one more file to the wrong side of it in a
parser fix is not the way to settle that. Filing it separately.
The changeset now says what the fold costs rather than only what it fixes: a
Turkish-locale `ıfc4x3` in free header prose used to resolve and no longer
does. It is the same character as the false positive being removed, pointed
the other way, and a reader of release notes should see both. ISO 10303-21
tokens are ASCII and this scan only runs for a file that declares no
resolvable schema, so the trade is worth making, but it is a trade.
Also `source-header.test.ts`'s own docstring claimed the file is direct
coverage for `parseSourceHeader`. It now tests `detectSchemaVersion` too, and
the sibling comment in `schema-version-detection.test.ts` -- rewritten in this
same work -- points at it for exactly that. The two now agree.
Verified by exit code: parser 849, typecheck 0, lint 0, module-size 0.
* Two corrections to what #3297 shipped, both found by the CLI after it merged
Neither blocked that merge; both are mine.
A DOC THAT SURVIVED ITS OWN MECHANISM. `find_unquoted`'s comment sends the
reader to `last_comment_close` for the linearity argument and describes the
closer search as HOISTED. I replaced that design mid-branch with a deferred
search and a `no_closer` memo on `Lex`, and deleted the function, but the
comment two files away still described the old shape. `grep -rn "fn
last_comment_close" rust/export/src/` returns nothing.
That is exactly the failure #3284 is about, committed by the fix for it: a
comment invalidated at a distance by a refactor, still confidently describing
a mechanism that no longer exists. Now it names the memo and says why the memo
is what makes the bound hold.
AN ASSERTION THAT COULD NOT TELL TWO ANSWERS APART.
assert!(h.is_none() || h.unwrap().schema_identifiers.is_empty());
passes whether the reader REJECTS the malformed `FILE_SCHEMA\u{00A0}(...)` or
ACCEPTS it and returns an empty list. The comment directly above claims the
first. So the test agreed with itself either way, and if the reader ever began
accepting that record it would still be green.
It returns None today, so that is what is pinned now. Mutation-verified rather
than assumed: teaching `skip_trivia` to treat 0xC2, the UTF-8 lead byte of
U+00A0, as whitespace makes the reader accept the record, and the tightened
assertion reddens where the old one did not.
This also gives the PR a new head event, which it needs for a second reason:
`gh run list --branch fix/3284-followup-ascii-fold` returned NOTHING, so
test.yml never fired when the branch was pushed and the PR opened. Seven lanes
registered, none of them a test lane, and the required aggregate absent. Same
shape as #3294, on my own PR, which is what #3313 exists to catch.
Verified by exit code: cargo test -p ifc-lite-export 0.
1 parent 073d9c6 commit d07e330
6 files changed
Lines changed: 99 additions & 16 deletions
File tree
- .changeset
- packages/parser
- src
- test
- rust/export
- src
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
| 12 | + | |
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
| 20 | + | |
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
259 | 259 | | |
260 | 260 | | |
261 | 261 | | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
262 | 272 | | |
263 | 273 | | |
264 | 274 | | |
| |||
291 | 301 | | |
292 | 302 | | |
293 | 303 | | |
294 | | - | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
295 | 312 | | |
296 | 313 | | |
297 | 314 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
| 6 | + | |
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
29 | 36 | | |
30 | 37 | | |
31 | 38 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
7 | 9 | | |
8 | 10 | | |
9 | 11 | | |
| |||
17 | 19 | | |
18 | 20 | | |
19 | 21 | | |
20 | | - | |
| 22 | + | |
21 | 23 | | |
22 | 24 | | |
23 | 25 | | |
| |||
534 | 536 | | |
535 | 537 | | |
536 | 538 | | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
35 | 35 | | |
36 | 36 | | |
37 | 37 | | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
42 | 44 | | |
43 | 45 | | |
44 | 46 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
111 | 111 | | |
112 | 112 | | |
113 | 113 | | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
114 | 119 | | |
115 | | - | |
116 | | - | |
| 120 | + | |
117 | 121 | | |
0 commit comments