Repository navigation
fix(65020): recover nested JSDoc @property after unparseable type - #65029
Closed
Timur Vural (timurzvural) wants to merge 1 commit into
Closed
Timur Vural (timurzvural) wants to merge 1 commit into
Timur Vural (timurzvural) wants to merge 1 commit into
Conversation
When a braced JSDoc type fails to parse (e.g. removed Closure function(...) syntax), skip leftover tokens through the closing } so the property name still parses. That keeps later nested @Property tags under the same object instead of aborting the nested type literal. Also treat a missing nested property name as a recoverable child rather than end-of-nesting. Adds a compiler regression for microsoft#65020 and a parser unit test. Updates typedefTagWrapping baselines where function(...) typedef names are now recovered (typed as Function). AI assistance disclosure: authored with Cursor Agent.
Author
|
Closing: #65020 is already closed, so this PR is being withdrawn. |
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
JSDoc recovery can misinterpret quoted literals, skip subsequent tags, and incorrectly nest valid unnamed parameters, producing incorrect properties and parameter types.
3 open issues
What changed in this PR
This PR addresses #65020 by improving JSDoc error recovery in the native TypeScript parser so an unsupported type does not discard later nested properties.
Changes:
- Adds recovery for leftover parenthesized type syntax and missing child-tag names.
- Adds parser and compiler regression tests for nested property preservation.
- Updates baselines to reflect recovered property and typedef names while retaining the syntax error.
| File | Description |
|---|---|
tsc/testdata/tests/cases/compiler/jsdocNestedPropertyRecoveryAfterBadType.ts |
Checks that nested property names remain available through keyof. |
tsc/testdata/baselines/reference/conformance/typedefTagWrapping.types |
Records recovered typedefs resolving to Function. |
tsc/testdata/baselines/reference/conformance/typedefTagWrapping.errors.txt |
Removes cascading errors for recovered typedef names. |
tsc/testdata/baselines/reference/compiler/jsdocNestedPropertyRecoveryAfterBadType.types |
Records preserved nested property keys. |
tsc/testdata/baselines/reference/compiler/jsdocNestedPropertyRecoveryAfterBadType.symbols |
Adds symbol expectations for the regression case. |
tsc/testdata/baselines/reference/compiler/jsdocNestedPropertyRecoveryAfterBadType.errors.txt |
Expects only the unsupported-type syntax error. |
tsc/internal/parser/parser_test.go |
Adds an assertion that later nested properties survive parsing. |
tsc/internal/parser/jsdoc.go |
Implements type-expression and missing-name recovery. |
Review effort: Balanced
Comment on lines
+149
to
+151
| case ast.KindOpenBraceToken, ast.KindOpenParenToken, ast.KindOpenBracketToken: | ||
| depth++ | ||
| p.nextTokenJSDoc() |
Comment on lines
+139
to
+160
| depth := 0 | ||
| for p.token != ast.KindAtToken && p.token != ast.KindEndOfFile { | ||
| switch p.token { | ||
| case ast.KindCloseBraceToken: | ||
| if depth == 0 { | ||
| p.nextTokenJSDoc() | ||
| return | ||
| } | ||
| depth-- | ||
| p.nextTokenJSDoc() | ||
| case ast.KindOpenBraceToken, ast.KindOpenParenToken, ast.KindOpenBracketToken: | ||
| depth++ | ||
| p.nextTokenJSDoc() | ||
| case ast.KindCloseParenToken, ast.KindCloseBracketToken: | ||
| if depth > 0 { | ||
| depth-- | ||
| } | ||
| p.nextTokenJSDoc() | ||
| default: | ||
| p.nextTokenJSDoc() | ||
| } | ||
| } |
Comment on lines
+1241
to
+1242
| if !ast.NodeIsMissing(childName) && | ||
| (ast.IsIdentifier(childName) || !textsEqual(name, childName.AsQualifiedName().Left)) { |
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.

Bug
When a nested JSDoc
@propertyhas a type that does not parse (commonly a removed Closurefunction(string)=form), every nested@propertyafter it is dropped from the typedef. Flat properties recover; nested ones do not. This worked in 6.0.3 and broke in 7.x after Closurefunction(...)types were removed and recovery became insufficient.Root cause
{function(string)=}, the parser treatedfunctionas a name and left(...)before}, so the property name never parsed.parseChildParameterOrPropertyTag, a child whose name did not match (including a missing name) aborted the nested type literal, so later matching nested tags were never collected.Fix
parseJSDocTypeExpressionCloseBrace: if}is missing and the next token is(, skip leftovers (with brace/paren/bracket depth) through the closing}so the tag name still parses. Only start this recovery at(so unrelated missing-}cases keep the following name in place.parseChildParameterOrPropertyTag, keep a missing-name property/parameter child nested instead of treating it as end-of-nesting.Tests
TestJSDocNestedPropertyRecoveryAfterBadTypeasserting nestedArgs.onCancelis keptjsdocNestedPropertyRecoveryAfterBadType.ts(+ baselines): only TS1005 on the Closure type;check.tshas 0 errors andonCancelremains inkeyof Sig['Args']typedefTagWrappingerror/types baselines wherefunction(...)typedef names are now recovered (typed asFunction)Fixes #65020
Related: similar open #65022
AI assistance disclosure
This PR was authored with assistance from Cursor Agent. I have read and understand the change and am prepared to discuss and revise it in review.