diff --git a/CHANGELOG.md b/CHANGELOG.md index 51d4c21..7591b10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +- prune the backlog of completed items and record the TS 7 LSP shutdown + workaround in development/testing.md + ## [0.7.1] - 2026-09-23 - upgrade dependencies diff --git a/backlog.tasks b/backlog.tasks index 83a08ae..d4e1650 100644 --- a/backlog.tasks +++ b/backlog.tasks @@ -6,17 +6,6 @@ Backlog and tracking for tiny-pattern-ts. Managed in vscode-todotasks format. Setup: ☐ Split off template into separate package => pi --session 01a07dde-7050-7054-bb36-1606d7eb2bc3 @low -✔ straighten oxc rules @done - ✔ oxc forbids ternary => remove oxc rule @done - ✔ oxc wants comments to start comments with a capital letter => remove oxc rule @done - ✔ there already exists a /* */ block comment in primitive.ts, => change to multi-line comment @done - -✔ Remove example code files and its documentation and its exports from index.ts @high @done - ✔ remove src/match.ts and its documentation @high @done - ✔ remove src/pattern.ts and its documentation @high @done - ✔ remove src/index.test.ts and its documentation @high @done - ✔ exports from `src/index.ts` should only be the public API surface @done - v1.0: ☐ API surface is stable and fully typed @@ -27,55 +16,12 @@ v1.0: ☐ Achieve 100% branch coverage on `src/primitive-union.ts` ☐ Achieve 100% branch coverage on `src/index.ts` -Testing: -✔ Cover autocomplete with real completion test cases in the suite @medium @done - → `src/util/__tests__/lsp-completion.ts` (`#test-utils/…`) is the helper; the suite asserts its labels (see development/testing.md § Autocomplete) - → wire it into `node --test` so a test asserts the offered labels - → note: `Parameters[0]` resolves only the *last* overload; use `@ts-expect-error` call sites for factory negatives, not `not.toExtend>` -✔ Drive the LSP completion helper through the LSP protocol library instead of a hand-rolled JSON-RPC client @medium @done - ✔ Add `vscode-languageserver-protocol` and record the tooling decision @done - ✔ Rewrite `src/util/__tests__/lsp-completion.ts` onto `createMessageConnection` and typed requests @done - ✔ Update `development/testing.md § Autocomplete` for the new client @done - ✔ Run `npm run verify` and check the task off @done -✘ Test a literal union widened with `(string & {})` — `"red" | "green" | "yellow" | (string & {})` @medium @cancelled - → broad universes are rejected; the rejection is covered by the broad-universe gate tests -✔ Type hole when using broad types like string as a universe @high @done - → decided: broad universes are rejected at the factory, so the exhaustive overload can always be proven - → value/stringification collisions (`true | "true"`, `1 | "1"`) are rejected too; handler params are typed by `Member` - → see development/library.md § Supported universes - Matcher: -✔ Clean up: adopt the 3-overload matcher (`src/prototype-ac2.ts`) and delete the prototypes @high @done - → `getMatcher` / `getMatcherW`, each with overloads `ExhaustiveLoose` → `Fallback` → `Handlers` (order is load-bearing) - → fold into `src/primitive.ts` / the public API; drop `src/prototype*.ts` -✔ `_` should receive only the unhandled `T` keys, not all of `T` @medium @done - → the fallback is now a second argument: `(handlers, (s) => …)`, `s: Exclude` -✔ A fallback for an already-exhaustive handler map must be a compile error @medium @done - → rejected by an F-bounded constraint on `Handled` (checked *after* inference); a conditional in the fallback parameter is evaluated too early and breaks contextual typing -✔ Implement matcher with similar API like matcher from primitive.ts @high @done - → `getTaggedUnionMatcher` / `getTaggedUnionMatcherW`, curried on the discriminant key - → fallback is the second argument; `_` removed -✔ Rename `primitive` to `primitive-union` and `getMatcher` to `getPrimitiveMatcher` @medium @done - → `src/primitive.ts` / `src/primitive.test.ts` → `primitive-union.*` - → `getMatcherW` → `getPrimitiveMatcherW` for symmetry with the tagged-union pair - → update `src/index.ts`, `development/library.md` and any README references - → shipped as `getPrimitiveUnionMatcher` / `getPrimitiveUnionMatcherW`; kept `Union` for symmetry with the tagged-union pair ☐ when using a union type as a property, the current behavior of tagged union matcher is to pass never to handler parameters → new matcher function needed or can be fixed in tagged union matcher ☐ optional discriminant (`{ type?: "x" }`) is the same hole: the boolean/nullish change now admits the `undefined` tag, so the factory accepts the key, but `Extract>` still passes `never` to both the `x` and `undefined` handlers -Bugs: -✔ TS 7 LSP server logs `context canceled` on stderr at shutdown @done - → `handleExit` returns `io.EOF`, cancelling the background context while `Session.updateWatches` is still in flight; the bare error is flushed to stderr and the server exits 1 - → close stdin after `shutdown` instead of sending `exit`; the server exits cleanly (code 0, no output), kill kept as a fallback -Enhancements: -✔ Allow boolean literals in primitive union patterns (e.g. `true: () => "yes"`) @medium @done - ✔ Are there other primitive types that should be supported in union patterns? (e.g. `bigint`, `symbol`) @medium @done - → added boolean, null and undefined; rejected `symbol` (compile-time brand, nothing at runtime) and `bigint` (not a property key) -✔ Allow boolean, null and undefined discriminant values in tagged-union patterns @medium @done - → moved the `PatternKey` / `PatternParam` projection to `matcher-shared.ts` and keyed the tagged-union handler map through it; see development/library.md § Tagged-union matcher - Documentation: ☐ Bring README.md back to its previous form — synopsis and examples restored, in the correct place → previous section order: title, tagline, Synopsis, Description, Requirements, Examples, API, License, Contributing @@ -84,12 +30,8 @@ Documentation: ☐ Add comparison section vs. other TS pattern-matching libs in Readme.md ☐ Write migration guide for users coming from discriminated unions ☐ Create backlog tasks for implementation -✔ Document the matcher design paths in `development/` — union vs overload merge, inferred universe (`NoInfer`), conditional `RequireKeys`, cases-first — and why each was abandoned @done ☐ Validate code fences in Markdown (start with README.md) — compile the TypeScript examples against `src/` so the docs cannot drift from the API -Workflow: -✔ Resolve the finish/push tension: `create:finish` leaves `main` ahead of its upstream while `create:branch` refuses until `main` matches upstream — decide whether `finish` should push or `branch` should compare only `BEHIND` (see development/workflow.md) @done - Maintenance: ☐ Serve CI coverage over a tiny self-hosted webserver (replace the zip artifact) @low ☐ Explore serving coverage for non-tag pushes (e.g. `main/coverage`, PR previews) @low diff --git a/development/testing.md b/development/testing.md index 2eee22e..9125cbe 100644 --- a/development/testing.md +++ b/development/testing.md @@ -198,6 +198,11 @@ the CLI is for manual inspection. delay is needed. - The server answers some requests with a string id (`client/registerCapability`); the client must tolerate `string | number` ids or the server stalls. +- `LspSession.close()` sends `shutdown` and then closes stdin instead of + sending `exit`. The TS 7 Go server's `handleExit` returns `io.EOF`, cancelling + the background context while a watch update is still in flight, and logs a + bare `context canceled` before exiting 1; EOF on stdin exits 0 with no output. + The kill stays as a fallback for a server that does not exit. ## Known issues