Skip to content

[finding] The 15 gates that parse with ts.createSourceFile never read parseDiagnostics — a file with a syntax error is walked as a recovered partial AST and scores clean #10133

Description

@os-steve

Filed unassigned, found while implementing #10123. Nothing is red today. This is the
same defect class as #10123a file the gate could not read scores as a file with
nothing to report
— one parser over.

Measured

ts.createSourceFile() is error-tolerant by design: it never throws on a syntax error,
it returns a SourceFile built by error recovery and records what went wrong in
parseDiagnostics. Every gate in this repo that walks TypeScript uses it, and a sweep
of scripts/ finds no gate reading parseDiagnostics (grep -rn "parseDiagnostics" scripts/ returns nothing).

The recovery is partial, and how much it loses depends on the break. Counting
x as any sites in a 3-site file, with the repo's own typescript:

clean : asAny=3 parseDiagnostics=0 statements=3
break at top : asAny=2 parseDiagnostics=1 statements=3
break inside body : asAny=2 parseDiagnostics=3 statements=2
unterminated tpl : asAny=0 parseDiagnostics=1 statements=1

The last row is the interesting one: one unterminated template literal takes the whole
file from 3 sites to 0, and the walker cannot tell that from a clean file. The gate
prints its green line.

The 15 gates on this parser today:

check-driver-memory-census.mjs check-org-identifier.mjs
check-durability-degradation-log-level.mjs check-resume-authority-declared.mjs
check-engine-double-contract.mjs check-route-envelope.mjs
check-filter-alias-parity.mjs check-startup-registry-verdict.mjs
check-init-service-contract.mjs check-tenant-chokepoint.mjs
check-kernel-hook-pairs.mjs check-verify-stand-in-erasure.mjs
check-meta-type-normalized.mjs check-where-matcher-conformance.mjs
check-wildcard-fallthrough.mjs

check-verify-stand-in-erasure.mjs is worth naming: lint.yml calls it "the third and
narrowest member" of the two ESLint ratchets #10123 fixed, so the family whose hole was
just closed has a third member with the same hole through a different parser.

Why it matters, and why it is not urgent

Same argument as #10123: the failure mode is a quiet green, on gates that exist because
something else cannot see what they see. It is latent for the same reason — the tree
parses today, and pnpm lint fails loudly on a file that does not — so the exposure is
the window between a file breaking and lint being run, plus any file lint does not cover.

Direction (not a decision)

The cheap shape mirrors #10123: after createSourceFile, refuse when
sf.parseDiagnostics is non-empty, naming the file and the first diagnostic. Two things
a card here has to decide rather than assume:

Refs: #10123 (the same class, ESLint side, where this was found) · #9367 (the precedent
for a class-wide defect across source-scanning gates).

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions