port to oxc#638
Draft
nathanwhit wants to merge 30 commits into
Draft
Conversation
#-private property and method definitions were not treated as private (only TS `private` accessibility was), so they leaked into the public API type inference and produced spurious missing-explicit-type errors. Also emit the collapsed `#private` placeholder as `#private!: unknown` without `declare` (declare is invalid on a private identifier, TS18019) to match upstream.
… logical exprs as leavable
- Destructured (object/array) params with a leavable default (`{a} = {}`)
were always flagged missing-explicit-type because the default lives in
`FormalParameter.initializer` (not an `AssignmentPattern`) and the
object/array pattern arms ignored it.
- `||`/`&&`/`??` (`LogicalExpression`) were treated as non-leavable; SWC
models these as binary expressions, so they're leavable when both
operands are. Fixes spurious missing-explicit-return-type on arrows like
`() => a === b || c === d`.
`is_private_member` only recognized the TS `private` keyword for class methods/properties, not `#`-private members (unlike auto-accessors). As a result the range finder traced the types referenced by `#`-private members, pulling non-exported internal types into the public API surface and emitting spurious diagnostics for them.
… params The dependency analyzer skipped two kinds of type references, so the symbols/types they referenced were dropped from the fast-check output (causing TS2304 'cannot find name' at type-check time): - a variable declarator's explicit type annotation (`const x: T`) was never visited (only the initializer was, and only when there was no annotation). - a function/method/constructor rest parameter's type (`...args: T`) was never visited (only `params.items`, not `params.rest`).
A public function/method parameter without a type annotation keeps its (leavable) default value in the output, so the values it references are dependencies. The dep analyzer only visited the parameter's pattern, so defaults referencing non-exported values (e.g. `isNode = isAstNode`) had those values dropped from the output, causing TS2304 at type-check time.
…ures Extend the rest-parameter dependency handling to the remaining param-visiting sites that only looked at `params.items`: arrow functions and TS call/construct/method signatures. Their rest-param types (`(...args: T) => ...`) are kept in the output and so are dependencies.
A parameter with both a type annotation and a default (`p: T = expr`) kept the default in the emitted signature, which (a) diverged from the upstream output and (b) referenced the default's value, dropping it from the output and causing TS2304 at type-check time. Match upstream: drop the default, marking the parameter optional when it can be trailing-optional, otherwise widening its type to `T | undefined`.
The default-export symbol for `export default someIdent` used the identifier's span rather than the full statement span, so the transform's public-range check never matched and the `export default` statement was dropped from the output (the referenced binding was kept), producing TS1192 'no default export' for importers. Use the full statement span.
The OXC port's `CommentsMut` kept every comment, whereas the swc-based deno_graph prunes leading comments down to JSDoc block comments and `@ts-*` line comments. As a result `@deno-types="npm:@types/..."` pragmas survived into the fast check emit. When such an emit is type-checked as a root, the pragma pulls in a second `@types/react` instance whose `ForwardRefExoticComponent` (a `unique symbol $$typeof`) no longer unifies with the one seen through the dependency graph, producing spurious `TS2344` errors (e.g. `React.ElementRef<typeof Primitive.div>` across the radix-ui-fork / bureaudouble React packages). Filter comments in `CommentsMut::new` to match swc: keep only `@ts-*` line comments and `/** */` JSDoc blocks. Regenerated the 8 fast_check spec snapshots, which now match the swc repo output.
oxc_codegen only emits comments at statement/declaration boundaries, not
on interior nodes like function parameters (confirmed still true on the
latest oxc 0.134). So an error-suppression directive written inside a
signature, e.g.
function f(a: number, // @ts-ignore: ...
b?: Foo<T, U>): T[]
was dropped from the fast check emit, resurfacing the error it suppressed
(the `edouardmisset/utils` TS2304 cluster).
Re-anchor `@ts-ignore` / `@ts-expect-error` line comments that sit interior
to a top-level statement onto that statement's start, so codegen emits them
as a leading comment. The emitted signature is collapsed to one line, so
the directive still suppresses the same error. Directives inside a
function/method body are left untouched: the body is replaced with
`{} as never`, so codegen already drops them and hoisting would produce
spurious TS2578 "unused directive" errors.
…mes, scope @ts hoist to params Three related fast check emit fixes surfaced by the ecosystem corpus: * Constructor parameter properties with a default (`constructor(public r = 0)`) were hoisted to a class field without a type (`declare r;`), making them implicitly `any` (TS7008). Infer the field type from the default initializer, matching the existing AssignmentPattern handling. (iz7n/std, gfx/canvas) * Expando namespace members named with a reserved word (`alias.for = ...`) were emitted as `export var for = ...`, which is a syntax error. `is_valid_js_ident` now rejects reserved keywords, so such members are dropped like swc does. (decorators/alias) * Restrict the interior `@ts-ignore`/`@ts-expect-error` hoist (added for the edouardmisset cluster) to directives inside a parameter list. Hoisting a class-member directive to the class statement would either miss the line it guards or become an unused-directive error (TS2578). Regenerated the type_assertion fast_check spec, which now carries the inferred parameter-property type (matching the swc output).
`expr as const` is kept verbatim in the fast check output, so identifiers it
references are dependencies. OXC represents it as a `TSAsExpression` with a
`const` type (swc uses a distinct `TsConstAssertion`), and our dep visitor
only walked the type annotation, dropping the value's references. As a result
a referenced binding (`const foo = ...; export const bar = { foo } as const`)
was pruned, producing a dangling shorthand reference (TS18004).
Walk the value expression when the assertion type is `const`. (marvinh/foo)
A typed destructured parameter (`{ x }: T = default` / `[x]: T = default`)
kept its runtime default in the emit. When the default referenced a pruned
binding (`{ components = empty }: Options = { components: empty }`), the
reference dangled (TS2304). Matching swc, always replace the default of a
*typed* destructured param with a `{} as never` / `[] as never` placeholder
(keeping the param optional); only an untyped param relies on a leavable
default to avoid requiring an explicit type.
Regenerated functions / class_params_initializers fast_check specs, whose
typed destructured defaults now read `= {} as never` like the swc output.
(bureaudouble/html-parse-stringify)
Decorators are runtime-only and aren't part of the fast check type surface. Class-level decorators were already cleared, but method/property/accessor decorators (and constructor parameter decorators) were left in the emit. When a decorator's import was pruned as unused, the dangling reference failed type checking (e.g. `@HostListener(...)` → TS2304). Clear member and parameter decorators too, matching swc. Regenerated basic / cache__basic fast_check specs, which no longer carry the `@dec` method/parameter decorators (matching the swc output). (lenicdev/ng-hcaptcha)
….134 Updates the deno_ast dependency to one built on oxc 0.134 and uses its new `scope_analysis` (oxc_semantic) output to make symbol resolution scope-aware. oxc 0.134: - toolchain bumped to 1.96 (oxc_transformer uses stabilized `if let` guards) - string-literal value type `Atom` -> `Str` - the newer codegen emits interior (class member) comments, fixing a class of dropped `@ts-ignore`/`@ts-expect-error` directives (e.g. gfx/canvas) Scope-aware resolution: - `Id`'s discriminator is now the resolved oxc `SymbolId` (the swc `SyntaxContext` equivalent) instead of always `0`, threaded through `to_id`, the dep analyzer, the transformer's expando handling, and `EsModuleInfo`. This fixes declaration merging across scopes (e.g. a `type X` + `namespace X` pair reused under multiple parents), which previously dropped a merged declaration (agent/openai TS2694). - Unresolved references (which oxc_semantic leaves symbol-less, e.g. the root of `X.prototype.y` type names) fall back to matching a uniquely named declaration. Regenerated symbols specs (Id discriminators now reflect symbol ids) and the ref_obj_type fast_check spec (interior JSDoc now emitted).
Re-blesses the ecosystem fast-check corpus after the emit fixes, oxc 0.134 update, and scope-aware symbol resolution. Net effect vs the prior corpus: ~39 previously-failing TYPE CHECK packages now pass, 0 EMIT regressions. The only remaining type-check failures introduced are halvardm/sqlx (2 versions): a `@ts-ignore` written inside an `extends` clause's type arguments. oxc codegen emits interior comments on class members now but not yet inside type-argument lists, so that directive is still dropped. Tracked as a known codegen limitation.
These versions couldn't be re-blessed locally earlier because the JSR mirror
was incomplete (missing source files), so their committed expectations were
stale swc-era output. They still fail type checking on a pre-existing
`Cannot find namespace 'JSX'` (no DOM/JSX lib); the emit shape just matches
the oxc port now (e.g. object rest params kept as `{ ...props }`). CI (with a
complete mirror) caught the drift; this captures the correct deterministic
output.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Based on denoland/deno_ast#331