Skip to content

Commit 92c21db

Browse files
authored
Reparse fixes (#2372)
1 parent 06abb77 commit 92c21db

14 files changed

+48
-77
lines changed

internal/ast/ast.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11001,7 +11001,6 @@ func (node *SourceFile) GetOrCreateToken(
1100111001
) *TokenNode {
1100211002
node.tokenCacheMu.Lock()
1100311003
defer node.tokenCacheMu.Unlock()
11004-
1100511004
loc := core.NewTextRange(pos, end)
1100611005
if node.tokenCache == nil {
1100711006
node.tokenCache = make(map[core.TextRange]*Node)
@@ -11014,7 +11013,9 @@ func (node *SourceFile) GetOrCreateToken(
1101411013
}
1101511014
return token
1101611015
}
11017-
11016+
if parent.Flags&NodeFlagsReparsed != 0 {
11017+
panic(fmt.Sprintf("Cannot create token from reparsed node of kind %v", parent.Kind))
11018+
}
1101811019
token := createToken(kind, node, pos, end, flags)
1101911020
token.Loc = loc
1102011021
token.Parent = parent

internal/astnav/tokens.go

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,6 @@ func getTokenAtPosition(
6565
// `left` tracks the lower boundary of the node/token that could be returned,
6666
// and is eventually the scanner's start position, if the scanner is used.
6767
left := 0
68-
// `allowReparsed` is set when we're navigating inside an AsExpression or
69-
// SatisfiesExpression, which allows visiting their reparsed children to reach
70-
// the actual identifier from JSDoc type assertions.
71-
allowReparsed := false
7268

7369
testNode := func(node *ast.Node) int {
7470
if node.Kind != ast.KindEndOfFile && node.End() == position && includePrecedingTokenAtEndPosition != nil {
@@ -92,15 +88,8 @@ func getTokenAtPosition(
9288
// We can't abort visiting children, so once a match is found, we set `next`
9389
// and do nothing on subsequent visits.
9490
if node != nil && next == nil {
95-
// Skip reparsed nodes unless:
96-
// 1. The node itself is AsExpression or SatisfiesExpression, OR
97-
// 2. We're already inside an AsExpression or SatisfiesExpression (allowReparsed=true)
98-
// These are special cases where reparsed nodes from JSDoc type assertions
99-
// should still be navigable to reach identifiers.
100-
isSpecialReparsed := node.Flags&ast.NodeFlagsReparsed != 0 &&
101-
(node.Kind == ast.KindAsExpression || node.Kind == ast.KindSatisfiesExpression)
102-
103-
if node.Flags&ast.NodeFlagsReparsed == 0 || isSpecialReparsed || allowReparsed {
91+
// Skip reparsed nodes
92+
if node.Flags&ast.NodeFlagsReparsed == 0 {
10493
result := testNode(node)
10594
switch result {
10695
case -1:
@@ -211,11 +200,6 @@ func getTokenAtPosition(
211200
current = next
212201
left = current.Pos()
213202
next = nil
214-
// When navigating into AsExpression or SatisfiesExpression, allow visiting
215-
// their reparsed children to reach identifiers from JSDoc type assertions.
216-
if current.Kind == ast.KindAsExpression || current.Kind == ast.KindSatisfiesExpression {
217-
allowReparsed = true
218-
}
219203
}
220204
}
221205

internal/checker/checker.go

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10408,18 +10408,15 @@ func (c *Checker) getInstantiationExpressionType(exprType *Type, node *ast.Node)
1040810408
}
1040910409

1041010410
func (c *Checker) checkSatisfiesExpression(node *ast.Node) *Type {
10411-
c.checkSourceElement(node.Type())
10412-
return c.checkSatisfiesExpressionWorker(node.Expression(), node.Type(), CheckModeNormal)
10413-
}
10414-
10415-
func (c *Checker) checkSatisfiesExpressionWorker(expression *ast.Node, target *ast.Node, checkMode CheckMode) *Type {
10416-
exprType := c.checkExpressionEx(expression, checkMode)
10417-
targetType := c.getTypeFromTypeNode(target)
10411+
typeNode := node.Type()
10412+
c.checkSourceElement(typeNode)
10413+
exprType := c.checkExpression(node.Expression())
10414+
targetType := c.getTypeFromTypeNode(typeNode)
1041810415
if c.isErrorType(targetType) {
1041910416
return targetType
1042010417
}
10421-
errorNode := ast.FindAncestor(target.Parent, func(n *ast.Node) bool { return ast.IsSatisfiesExpression(n) })
10422-
c.checkTypeAssignableToAndOptionallyElaborate(exprType, targetType, errorNode, expression, diagnostics.Type_0_does_not_satisfy_the_expected_type_1, nil)
10418+
errorNode := core.IfElse(typeNode.Flags&ast.NodeFlagsReparsed != 0, typeNode, node)
10419+
c.checkTypeAssignableToAndOptionallyElaborate(exprType, targetType, errorNode, node.Expression(), diagnostics.Type_0_does_not_satisfy_the_expected_type_1, nil)
1042310420
return exprType
1042410421
}
1042510422

@@ -11935,14 +11932,15 @@ func (c *Checker) checkAssertion(node *ast.Node, checkMode CheckMode) *Type {
1193511932
}
1193611933

1193711934
func (c *Checker) checkAssertionDeferred(node *ast.Node) {
11935+
typeNode := node.Type()
1193811936
exprType := c.getRegularTypeOfObjectLiteral(c.getBaseTypeOfLiteralType(c.assertionLinks.Get(node).exprType))
11939-
targetType := c.getTypeFromTypeNode(node.Type())
11937+
targetType := c.getTypeFromTypeNode(typeNode)
1194011938
if !c.isErrorType(targetType) {
1194111939
widenedType := c.getWidenedType(exprType)
1194211940
if !c.isTypeComparableTo(targetType, widenedType) {
1194311941
errNode := node
11944-
if node.Flags&ast.NodeFlagsReparsed != 0 {
11945-
errNode = node.Type()
11942+
if typeNode.Flags&ast.NodeFlagsReparsed != 0 {
11943+
errNode = typeNode
1194611944
}
1194711945
c.checkTypeComparableTo(exprType, targetType, errNode, diagnostics.Conversion_of_type_0_to_type_1_may_be_a_mistake_because_neither_type_sufficiently_overlaps_with_the_other_If_this_was_intentional_convert_the_expression_to_unknown_first)
1194811946
}

internal/ls/folding.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,7 @@ func (l *LanguageService) addRegionOutliningSpans(sourceFile *ast.SourceFile) []
109109
}
110110

111111
func visitNode(ctx context.Context, n *ast.Node, depthRemaining int, sourceFile *ast.SourceFile, l *LanguageService) []*lsproto.FoldingRange {
112-
if depthRemaining == 0 {
113-
return nil
114-
}
115-
if ctx.Err() != nil {
112+
if n.Flags&ast.NodeFlagsReparsed != 0 || depthRemaining == 0 || ctx.Err() != nil {
116113
return nil
117114
}
118115
foldingRange := make([]*lsproto.FoldingRange, 0, 40)

internal/parser/reparser.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ func (p *Parser) reparseHosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Node)
314314
if parent.Expression() != nil && tag.TypeExpression() != nil {
315315
parent.AsMutable().SetExpression(p.makeNewCast(
316316
p.factory.DeepCloneReparse(tag.TypeExpression().Type()),
317-
p.factory.DeepCloneReparse(parent.Expression()),
317+
parent.Expression(),
318318
true /*isAssertion*/))
319319
p.finishMutatedNode(parent)
320320
return
@@ -335,7 +335,7 @@ func (p *Parser) reparseHosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Node)
335335
if declaration.Initializer() != nil && tag.TypeExpression() != nil {
336336
declaration.AsMutable().SetInitializer(p.makeNewCast(
337337
p.factory.DeepCloneReparse(tag.TypeExpression().Type()),
338-
p.factory.DeepCloneReparse(declaration.Initializer()),
338+
declaration.Initializer(),
339339
false /*isAssertion*/))
340340
p.finishMutatedNode(declaration)
341341
break
@@ -348,7 +348,7 @@ func (p *Parser) reparseHosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Node)
348348
if parent.Initializer() != nil && tag.TypeExpression() != nil {
349349
parent.AsMutable().SetInitializer(p.makeNewCast(
350350
p.factory.DeepCloneReparse(tag.TypeExpression().Type()),
351-
p.factory.DeepCloneReparse(parent.Initializer()),
351+
parent.Initializer(),
352352
false /*isAssertion*/))
353353
p.finishMutatedNode(parent)
354354
}
@@ -357,7 +357,7 @@ func (p *Parser) reparseHosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Node)
357357
if shorthand.ObjectAssignmentInitializer != nil && tag.AsJSDocSatisfiesTag().TypeExpression != nil {
358358
shorthand.ObjectAssignmentInitializer = p.makeNewCast(
359359
p.factory.DeepCloneReparse(tag.AsJSDocSatisfiesTag().TypeExpression.Type()),
360-
p.factory.DeepCloneReparse(shorthand.ObjectAssignmentInitializer),
360+
shorthand.ObjectAssignmentInitializer,
361361
false /*isAssertion*/)
362362
p.finishMutatedNode(parent)
363363
}
@@ -366,7 +366,7 @@ func (p *Parser) reparseHosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Node)
366366
if parent.Expression() != nil && tag.TypeExpression() != nil {
367367
parent.AsMutable().SetExpression(p.makeNewCast(
368368
p.factory.DeepCloneReparse(tag.TypeExpression().Type()),
369-
p.factory.DeepCloneReparse(parent.Expression()),
369+
parent.Expression(),
370370
false /*isAssertion*/))
371371
p.finishMutatedNode(parent)
372372
}
@@ -376,7 +376,7 @@ func (p *Parser) reparseHosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Node)
376376
if kind := ast.GetAssignmentDeclarationKind(bin); kind != ast.JSDeclarationKindNone && tag.TypeExpression() != nil {
377377
bin.Right = p.makeNewCast(
378378
p.factory.DeepCloneReparse(tag.TypeExpression().Type()),
379-
p.factory.DeepCloneReparse(bin.Right),
379+
bin.Right,
380380
false /*isAssertion*/)
381381
p.finishMutatedNode(bin.AsNode())
382382
}
@@ -602,7 +602,7 @@ func (p *Parser) makeNewCast(t *ast.TypeNode, e *ast.Node, isAssertion bool) *as
602602
} else {
603603
assert = p.factory.NewSatisfiesExpression(e, t)
604604
}
605-
p.finishReparsedNode(assert, e)
605+
p.finishNodeWithEnd(assert, e.Pos(), e.End())
606606
return assert
607607
}
608608

internal/testutil/tsbaseline/type_symbol_baseline.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,7 @@ func (walker *typeWriterWalker) writeTypeOrSymbol(node *ast.Node, isSymbolWalk b
354354
// Don't try to get the type of something that's already a type.
355355
// Exception for `T` in `type T = something` because that may evaluate to some interesting type.
356356
if ast.IsPartOfTypeNode(node) ||
357+
(node.Kind == ast.KindAsExpression || node.Kind == ast.KindSatisfiesExpression) && node.Type().Flags&ast.NodeFlagsReparsed != 0 ||
357358
ast.IsIdentifier(node) &&
358359
(ast.GetMeaningFromDeclaration(node.Parent)&ast.SemanticMeaningValue) == 0 &&
359360
!(ast.IsTypeOrJSTypeAliasDeclaration(node.Parent) && node == node.Parent.Name()) {

testdata/baselines/reference/submodule/conformance/checkJsdocSatisfiesTag1.errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/a.js(21,44): error TS2353: Object literal may only specify known properties, and 'b' does not exist in type 'T1'.
2-
/a.js(22,38): error TS2741: Property 'a' is missing in type '{}' but required in type 'T1'.
2+
/a.js(22,28): error TS2741: Property 'a' is missing in type '{}' but required in type 'T1'.
33
/a.js(31,49): error TS2353: Object literal may only specify known properties, and 'b' does not exist in type 'T4'.
44

55

@@ -28,7 +28,7 @@
2828
~
2929
!!! error TS2353: Object literal may only specify known properties, and 'b' does not exist in type 'T1'.
3030
const t3 = /** @satisfies {T1} */ ({});
31-
~
31+
~~
3232
!!! error TS2741: Property 'a' is missing in type '{}' but required in type 'T1'.
3333
!!! related TS2728 /a.js:3:23: 'a' is declared here.
3434

testdata/baselines/reference/submodule/conformance/checkJsdocSatisfiesTag1.errors.txt.diff

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/a.js(21,44): error TS2353: Object literal may only specify known properties, and 'b' does not exist in type 'T1'.
55
-/a.js(22,17): error TS1360: Type '{}' does not satisfy the expected type 'T1'.
66
- Property 'a' is missing in type '{}' but required in type 'T1'.
7-
+/a.js(22,38): error TS2741: Property 'a' is missing in type '{}' but required in type 'T1'.
7+
+/a.js(22,28): error TS2741: Property 'a' is missing in type '{}' but required in type 'T1'.
88
/a.js(31,49): error TS2353: Object literal may only specify known properties, and 'b' does not exist in type 'T4'.
99

1010

@@ -16,7 +16,7 @@
1616
-!!! error TS1360: Type '{}' does not satisfy the expected type 'T1'.
1717
-!!! error TS1360: Property 'a' is missing in type '{}' but required in type 'T1'.
1818
-!!! related TS2728 /a.js:3:4: 'a' is declared here.
19-
+ ~
19+
+ ~~
2020
+!!! error TS2741: Property 'a' is missing in type '{}' but required in type 'T1'.
2121
+!!! related TS2728 /a.js:3:23: 'a' is declared here.
2222

testdata/baselines/reference/submodule/conformance/checkJsdocSatisfiesTag11.types

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
const t1 = { a: 1 };
1919
>t1 : { a: number; }
2020
>{ a: 1 } : { a: number; }
21-
>{ a: 1 } : { a: number; }
2221
>a : number
2322
>1 : 1
2423

testdata/baselines/reference/submodule/conformance/checkJsdocSatisfiesTag11.types.diff

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)