Skip to content

Fix lint findings and check indexed access in src/ (D1, D3) - #22

Merged
mkarlesky merged 1 commit into
next_versionfrom
lint/fixes
Oct 23, 2026
Merged

mkarlesky merged 1 commit into
next_versionfrom
lint/fixes

Conversation

@mkarlesky

Copy link
Copy Markdown
Member

This PR applies approved decisions D1 (compiler strictness) and D3 (lint triage) from the findings report.

Stacked on #21.

Results:

  • Lint: 121 findings down to 9. All 9 are the engine's synchronous I/O and sequential discovery, which PR C converts to async (D2).
  • Tests: 254 unit (+3) and 4 integration, all passing.
  • Coverage: unchanged at 68.5% of statements. This PR adds no coverage work; that's PR C.

D1: noUncheckedIndexedAccess for src/

The flag is on in tsconfig.json; tests keep their own config. All 34 compile errors are resolved:

  • Mandatory regex groups go through a captured() helper, with a comment on why each is guaranteed.
  • Fixed-length values become tuples.
  • Real guards remain where an index can be missing.

The flag also removes the seven false alarms in which the linter called real runtime guards impossible.

It found a real bug. matchToProblem() checked group indexes against the array length, but a custom pattern's optional file group that didn't participate is undefined at an in-range index. That value reached path.normalize(), which threw, and the whole pattern's results were dropped. Two failing tests came first.

D3: lint triage

Fixes:

  • SingleFlight dropped a rejection whose reason was undefined. It now records outcomes as a flag. A failing test came first.
  • reparse() could reject unhandled. It runs from watchers and editor events without being awaited; it now catches and logs its own failures. The deliberate fire-and-forget refresh() calls are marked void.
  • runPlan's untyped new Map() made the whole selection any. It's now typed.
  • Untyped input is typed honestly. normalizePatterns() and readCppUnitReport() take unknown and narrow it, instead of trusting types that user JSON and parsed XML don't guarantee. Their shape checks are now meaningful to the compiler.
  • Type escapes removed.
    • CeedlingRunner keeps the state it shares with its exit callback in one object, and its non-null assertions are gone.
    • The controller passes the TestController to its item builders instead of using this.controller!.
    • resolveLaunchConfig() returns a typed DebugConfiguration.
    • dispose() callbacks use block bodies.
  • Smaller fixes: util.format for interpolated errors, import type, removal of redundant assertions and of the async on activate(), removal of the dead ProblemMatchingPattern re-export, and binary-search line lookup in discovery.

Marked inline with reasons:

  • sequential awaits that are deliberate (the run plan, clean and clobber, SingleFlight);
  • the synchronous /proc snapshot taken on cancellation;
  • Unity's verbatim regex escape;
  • split()'s undefined pieces, which the library typing hides;
  • one TypeScript control-flow false positive.

Tuning: require-await is off for test doubles.

🤖 Generated with Claude Code

Turns on noUncheckedIndexedAccess for src/ (tsconfig.json only; tests keep their config).
Index reads, destructured elements, and regex groups are now checked. Mandatory regex groups
go through a captured() helper. The flag found a real bug: matchToProblem passed a
non-participating optional file group, undefined despite an in-range index, to
path.normalize, which threw and dropped every result of that problem-matching pattern.

Other fixes:
- SingleFlight swallowed a rejection whose reason was undefined. Outcomes are now flagged.
- reparse() could reject unhandled from watcher and editor events. It now reports its own
  failures, and fire-and-forget refresh() calls are marked void.
- runPlan's selection map was implicitly any; it is now typed.
- normalizePatterns() and readCppUnitReport() take unknown and narrow it, instead of
  trusting types that user JSON and parsed XML don't guarantee.
- ProcessRunner keeps callback-shared state in one object. The non-null assertions are
  gone, and the controller passes the TestController to its item builders.
- Error interpolation uses util.format. Type-only imports are marked. Redundant assertions,
  the async-without-await activate(), and the unused ProblemMatchingPattern re-export are
  removed. Discovery's line lookup is a binary search.

Deliberate patterns are marked inline with reasons: sequential awaits, /proc's synchronous
snapshot, a Unity-verbatim regex escape, split()'s undefined pieces, and a TypeScript
control-flow false positive. require-await is off for test doubles.

Lint goes from 121 findings to 9. The 9 remaining are the engine's sync I/O and sequential
discovery, which the async performance work addresses.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mkarlesky
mkarlesky changed the base branch from tooling/lint-coverage to next_version October 23, 2026 19:21
@mkarlesky
mkarlesky merged commit d94c1cb into next_version Oct 23, 2026
3 checks passed
@mkarlesky
mkarlesky deleted the lint/fixes branch October 23, 2026 19:21
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.

1 participant