Fix JSDoc @enum so the tagged name is a type as well as a value - #64004
Fix JSDoc @enum so the tagged name is a type as well as a value#64004Xia Chao (bun-unsafe) wants to merge 1 commit into
Conversation
6382a8b to
0e478d7
Compare
There was a problem hiding this comment.
Pull request overview
Adds first-class JSDoc @enum type support and Closure-style function type parsing.
Changes:
- Adds
JSDocEnumTagAST, parser, encoder, checker, and emit support. - Synthesizes type aliases alongside enum values.
- Updates compiler and fourslash baselines.
Reviewed changes
Copilot reviewed 28 out of 33 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
tsc/internal/parser/jsdoc.go |
Parses enum tags and function types. |
tsc/internal/parser/parser.go |
Recognizes JSDoc function(...) types. |
tsc/internal/parser/reparser.go |
Synthesizes enum type aliases. |
tsc/internal/checker/checker.go |
Classifies enum tags in type space. |
tsc/internal/checker/emitresolver.go |
Handles enum-tag visibility. |
tsc/internal/ast/ast.go |
Integrates enum-tag accessors. |
tsc/internal/ast/ast_generated.go |
Adds generated enum-tag nodes. |
tsc/internal/ast/kind_generated.go |
Adds the enum-tag syntax kind. |
tsc/internal/ast/kind_stringer_generated.go |
Updates generated kind strings. |
tsc/internal/ast/utilities.go |
Enables enum-tag comments. |
tsc/internal/api/encoder/encoder_generated.go |
Encodes enum-tag children. |
tsc/internal/api/encoder/decoder_generated.go |
Decodes enum-tag children. |
tools/scripts/tsc/ast.json |
Defines the enum-tag AST schema. |
smartSelection_JSDocTags9.baseline |
Updates JSDoc selection output. |
typedefTagWrapping.types |
Records parsed function return types. |
typedefTagWrapping.errors.txt |
Removes obsolete parse errors. |
jsDeclarationsEnumTag(target=es2015).types |
Records enum aliases’ resolved types. |
jsDeclarationsEnumTag(target=es2015).symbols |
Records merged symbols. |
jsDeclarationsEnumTag(target=es2015).js |
Records emitted type aliases. |
jsDeclarationsEnumTag(target=es2015).errors.txt |
Removes value-only type errors. |
enumTagUseBeforeDefCrash.types |
Records the enum’s aliased type. |
enumTagUseBeforeDefCrash.symbols |
Records its merged symbol. |
enumTagUseBeforeDefCrash.errors.txt |
Removes the former type error. |
enumTagOnExports.symbols |
Records CommonJS merged symbols. |
enumTagImported.types |
Records imported enum types. |
enumTagImported.symbols |
Records imported merged symbols. |
enumTagImported.errors.txt |
Removes import/type errors. |
enumTagCircularReference.symbols |
Records the circular alias symbol. |
enumTagCircularReference.errors.txt |
Adds the circular-alias diagnostic. |
enumTag.types |
Records local enum alias types. |
enumTag.symbols |
Records local merged symbols. |
enumTag.errors.txt |
Removes value-only type errors. |
jsFileESModuleWithEnumTag.symbols |
Records merged ES-module symbols. |
Files not reviewed (5)
- tsc/internal/api/encoder/decoder_generated.go: Generated file
- tsc/internal/api/encoder/encoder_generated.go: Generated file
- tsc/internal/ast/ast_generated.go: Generated file
- tsc/internal/ast/kind_generated.go: Generated file
- tsc/internal/ast/kind_stringer_generated.go: Generated file
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
| case ast.KindElementAccessExpression: | ||
| arg := expr.AsElementAccessExpression().ArgumentExpression | ||
| if ast.IsIdentifier(arg) { | ||
| return arg |
There was a problem hiding this comment.
Thanks. The identifier check matches Strada nameForNamelessJSDocTypedef (element access only when the argument is an identifier).
Static exports["E"] / numeric literals are a reasonable follow-up (GetElementOrPropertyAccessName + identifier). I left that out of this PR so the @enum const/export case stays reviewable.
| switch expr.Kind { | ||
| case ast.KindPropertyAccessExpression: | ||
| return expr.AsPropertyAccessExpression().Name() |
There was a problem hiding this comment.
Thanks. This is a real remaining @enum hole: we only take the innermost name, so Host.UserMetrics.Action does not become a qualified type. jsEnumCrossFileExport.ts still reports TS2749.
This PR is scoped to a declaration-named const/export (export const E / .d.ts consumers). Wrapping the full static path like dotted @typedef is a follow-up. I can do it in this PR if you want it here.
|
@microsoft-github-policy-service agree |
|
Everything you're adding back was intentionally removed https://github.com/microsoft/TypeScript/blob/main/tsc/CHANGES.md |
|
You're right — I missed that I'll close this PR. Sorry for the noise. |
|
Why did you choose to work on this? Does this personally affect you? |
|
I was comparing 6.x vs 7 declaration emit on a small JSDoc fixture ( |
Fixes #64003
JSDoc
@enumon aconstobject did not introduce a type. The name was value-only, so@param {E}in the same file andconst n: E = E.Aagainst the emitted.d.tsboth reported TS2749.This parses
@enum, reparses a type alias named after the host declaration, and merges it with the value. Declaration emit then includesexport type E = …next to the existingconst. JSDocfunction(number): numberis parsed as a function type so@enum {function(number): number}prints a valid signature (this also clears the old parse errors on{function(string): boolean}intypedefTagWrapping).Emit is
export type E = Tplusexport declare const E: { … }, not the 6.xnamespaceshape. The type+value contract is what consumers need (Ein type position,E.Aas a value).Tests:
jsDeclarationsEnumTag,enumTag*,jsFileESModuleWithEnumTag,typedefTagWrapping,smartSelection_JSDocTags9.I used Copilot while writing this patch. I read the change, ran the tests above, and I will handle review myself.