Skip to content

Commit ec80c8c

Browse files
authored
Type nodes for JSDoc (#1013)
1 parent cf0c2c5 commit ec80c8c

File tree

207 files changed

+1118
-1722
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

207 files changed

+1118
-1722
lines changed

internal/ast/ast.go

Lines changed: 70 additions & 44 deletions
Large diffs are not rendered by default.

internal/ast/utilities.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,7 @@ func isDeclarationStatementKind(kind Kind) bool {
656656
KindExportDeclaration,
657657
KindExportAssignment,
658658
KindJSExportAssignment,
659+
KindCommonJSExport,
659660
KindNamespaceExportDeclaration:
660661
return true
661662
}
@@ -863,6 +864,15 @@ func WalkUpParenthesizedTypes(node *TypeNode) *Node {
863864
return node
864865
}
865866

867+
func GetEffectiveTypeParent(parent *Node) *Node {
868+
if IsInJSFile(parent) && parent.Kind == KindJSDocTypeExpression {
869+
if host := parent.AsJSDocTypeExpression().Host; host != nil {
870+
parent = host
871+
}
872+
}
873+
return parent
874+
}
875+
866876
// Walks up the parents of a node to find the containing SourceFile
867877
func GetSourceFileOfNode(node *Node) *SourceFile {
868878
for node != nil {
@@ -3403,6 +3413,7 @@ func ReplaceModifiers(factory *NodeFactory, node *Node, modifierArray *ModifierL
34033413
return factory.UpdateExportAssignment(
34043414
node.AsExportAssignment(),
34053415
modifierArray,
3416+
node.Type(),
34063417
node.Expression(),
34073418
)
34083419
case KindExportDeclaration:

internal/binder/binder.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1653,7 +1653,7 @@ func (b *Binder) bindChildren(node *ast.Node) {
16531653
b.inAssignmentPattern = saveInAssignmentPattern
16541654
b.bindEachChild(node)
16551655
case ast.KindJSExportAssignment, ast.KindCommonJSExport:
1656-
return // Reparsed nodes do not double-bind children, which are not reparsed
1656+
// Reparsed nodes do not double-bind children, which are not reparsed
16571657
default:
16581658
b.bindEachChild(node)
16591659
}
@@ -2214,9 +2214,11 @@ func (b *Binder) bindDestructuringAssignmentFlow(node *ast.Node) {
22142214
b.bind(expr.Right)
22152215
b.inAssignmentPattern = true
22162216
b.bind(expr.Left)
2217+
b.bind(expr.Type)
22172218
} else {
22182219
b.inAssignmentPattern = true
22192220
b.bind(expr.Left)
2221+
b.bind(expr.Type)
22202222
b.inAssignmentPattern = false
22212223
b.bind(expr.OperatorToken)
22222224
b.bind(expr.Right)
@@ -2245,6 +2247,7 @@ func (b *Binder) bindBinaryExpressionFlow(node *ast.Node) {
22452247
}
22462248
} else {
22472249
b.bind(expr.Left)
2250+
b.bind(expr.Type)
22482251
if operator == ast.KindCommaToken {
22492252
b.maybeBindExpressionFlowIfCall(node)
22502253
}

internal/checker/checker.go

Lines changed: 67 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2896,11 +2896,12 @@ func (c *Checker) checkTypePredicate(node *ast.Node) {
28962896
}
28972897

28982898
func (c *Checker) getTypePredicateParent(node *ast.Node) *ast.SignatureDeclaration {
2899-
switch node.Parent.Kind {
2899+
parent := ast.GetEffectiveTypeParent(node.Parent)
2900+
switch parent.Kind {
29002901
case ast.KindArrowFunction, ast.KindCallSignature, ast.KindFunctionDeclaration, ast.KindFunctionExpression, ast.KindFunctionType,
29012902
ast.KindMethodDeclaration, ast.KindMethodSignature:
2902-
if node == node.Parent.Type() {
2903-
return node.Parent
2903+
if node == parent.Type() {
2904+
return parent
29042905
}
29052906
}
29062907
return nil
@@ -5377,6 +5378,11 @@ func (c *Checker) checkExportAssignment(node *ast.Node) {
53775378
c.error(node, diagnostics.ESM_syntax_is_not_allowed_in_a_CommonJS_module_when_verbatimModuleSyntax_is_enabled)
53785379
}
53795380
c.checkExternalModuleExports(container)
5381+
if typeNode := node.Type(); typeNode != nil && node.Kind == ast.KindExportAssignment {
5382+
t := c.getTypeFromTypeNode(typeNode)
5383+
initializerType := c.checkExpressionCached(node.Expression())
5384+
c.checkTypeAssignableToAndOptionallyElaborate(initializerType, t, node.Expression(), node.Expression(), nil /*headMessage*/, nil)
5385+
}
53805386
if (node.Flags&ast.NodeFlagsAmbient != 0) && !ast.IsEntityNameExpression(node.Expression()) {
53815387
c.grammarErrorOnNode(node.Expression(), diagnostics.The_expression_of_an_export_assignment_must_be_an_identifier_or_qualified_name_in_an_ambient_context)
53825388
}
@@ -12579,18 +12585,11 @@ func (c *Checker) checkObjectLiteral(node *ast.Node, checkMode CheckMode) *Type
1257912585
}
1258012586
if ast.IsPropertyAssignment(memberDecl) || ast.IsShorthandPropertyAssignment(memberDecl) || ast.IsObjectLiteralMethod(memberDecl) {
1258112587
var t *Type
12582-
switch {
12583-
case memberDecl.Kind == ast.KindPropertyAssignment:
12588+
switch memberDecl.Kind {
12589+
case ast.KindPropertyAssignment:
1258412590
t = c.checkPropertyAssignment(memberDecl, checkMode)
12585-
case memberDecl.Kind == ast.KindShorthandPropertyAssignment:
12586-
var expr *ast.Node
12587-
if !inDestructuringPattern {
12588-
expr = memberDecl.AsShorthandPropertyAssignment().ObjectAssignmentInitializer
12589-
}
12590-
if expr == nil {
12591-
expr = memberDecl.Name()
12592-
}
12593-
t = c.checkExpressionForMutableLocation(expr, checkMode)
12591+
case ast.KindShorthandPropertyAssignment:
12592+
t = c.checkShorthandPropertyAssignment(memberDecl, inDestructuringPattern, checkMode)
1259412593
default:
1259512594
t = c.checkObjectLiteralMethod(memberDecl, checkMode)
1259612595
}
@@ -13025,7 +13024,30 @@ func (c *Checker) checkPropertyAssignment(node *ast.Node, checkMode CheckMode) *
1302513024
if ast.IsComputedPropertyName(node.Name()) {
1302613025
c.checkComputedPropertyName(node.Name())
1302713026
}
13028-
return c.checkExpressionForMutableLocation(node.Initializer(), checkMode)
13027+
initializerType := c.checkExpressionForMutableLocation(node.Initializer(), checkMode)
13028+
if node.Type() != nil {
13029+
t := c.getTypeFromTypeNode(node.Type())
13030+
c.checkTypeAssignableToAndOptionallyElaborate(initializerType, t, node, node.Initializer(), nil /*headMessage*/, nil)
13031+
return t
13032+
}
13033+
return initializerType
13034+
}
13035+
13036+
func (c *Checker) checkShorthandPropertyAssignment(node *ast.Node, inDestructuringPattern bool, checkMode CheckMode) *Type {
13037+
var expr *ast.Node
13038+
if !inDestructuringPattern {
13039+
expr = node.AsShorthandPropertyAssignment().ObjectAssignmentInitializer
13040+
}
13041+
if expr == nil {
13042+
expr = node.Name()
13043+
}
13044+
expressionType := c.checkExpressionForMutableLocation(expr, checkMode)
13045+
if node.Type() != nil {
13046+
t := c.getTypeFromTypeNode(node.Type())
13047+
c.checkTypeAssignableToAndOptionallyElaborate(expressionType, t, node, expr, nil /*headMessage*/, nil)
13048+
return t
13049+
}
13050+
return expressionType
1302913051
}
1303013052

1303113053
func (c *Checker) isInPropertyInitializerOrClassStaticBlock(node *ast.Node) bool {
@@ -15683,11 +15705,15 @@ func (c *Checker) getTypeOfVariableOrParameterOrPropertyWorker(symbol *ast.Symbo
1568315705
case ast.KindPropertyAssignment:
1568415706
result = c.checkPropertyAssignment(declaration, CheckModeNormal)
1568515707
case ast.KindShorthandPropertyAssignment:
15686-
result = c.checkExpressionForMutableLocation(declaration.Name(), CheckModeNormal)
15708+
result = c.checkShorthandPropertyAssignment(declaration, true /*inDestructuringPattern*/, CheckModeNormal)
1568715709
case ast.KindMethodDeclaration:
1568815710
result = c.checkObjectLiteralMethod(declaration, CheckModeNormal)
1568915711
case ast.KindExportAssignment, ast.KindJSExportAssignment:
15690-
result = c.widenTypeForVariableLikeDeclaration(c.checkExpressionCached(declaration.AsExportAssignment().Expression), declaration, false /*reportErrors*/)
15712+
if declaration.Type() != nil {
15713+
result = c.getTypeFromTypeNode(declaration.Type())
15714+
} else {
15715+
result = c.widenTypeForVariableLikeDeclaration(c.checkExpressionCached(declaration.AsExportAssignment().Expression), declaration, false /*reportErrors*/)
15716+
}
1569115717
case ast.KindBinaryExpression:
1569215718
result = c.getWidenedTypeForAssignmentDeclaration(symbol)
1569315719
case ast.KindJsxAttribute:
@@ -17114,23 +17140,28 @@ const (
1711417140
func (c *Checker) getWidenedTypeForAssignmentDeclaration(symbol *ast.Symbol) *Type {
1711517141
var t *Type
1711617142
kind, location := c.isConstructorDeclaredThisProperty(symbol)
17117-
if kind == thisAssignmentDeclarationTyped {
17143+
switch kind {
17144+
case thisAssignmentDeclarationTyped:
1711817145
if location == nil {
1711917146
panic("location should not be nil when this assignment has a type.")
1712017147
}
1712117148
t = c.getTypeFromTypeNode(location)
17122-
} else if kind == thisAssignmentDeclarationConstructor {
17149+
case thisAssignmentDeclarationConstructor:
1712317150
if location == nil {
1712417151
panic("constructor should not be nil when this assignment is in a constructor.")
1712517152
}
1712617153
t = c.getFlowTypeInConstructor(symbol, location)
17127-
} else if kind == thisAssignmentDeclarationMethod {
17154+
case thisAssignmentDeclarationMethod:
1712817155
t = c.getTypeOfPropertyInBaseClass(symbol)
1712917156
}
1713017157
if t == nil {
1713117158
var types []*Type
1713217159
for _, declaration := range symbol.Declarations {
1713317160
if ast.IsBinaryExpression(declaration) {
17161+
if declaration.Type() != nil {
17162+
t = c.getTypeFromTypeNode(declaration.Type())
17163+
break
17164+
}
1713417165
types = core.AppendIfUnique(types, c.checkExpressionForMutableLocation(declaration.AsBinaryExpression().Right, CheckModeNormal))
1713517166
}
1713617167
}
@@ -17139,7 +17170,9 @@ func (c *Checker) getWidenedTypeForAssignmentDeclaration(symbol *ast.Symbol) *Ty
1713917170
types = core.AppendIfUnique(types, c.undefinedOrMissingType)
1714017171
}
1714117172
}
17142-
t = c.getWidenedType(c.getUnionType(types))
17173+
if t == nil {
17174+
t = c.getWidenedType(c.getUnionType(types))
17175+
}
1714317176
}
1714417177
// report an all-nullable or empty union as an implicit any in JS files
1714517178
if symbol.ValueDeclaration != nil && ast.IsInJSFile(symbol.ValueDeclaration) &&
@@ -17160,7 +17193,7 @@ func (c *Checker) isConstructorDeclaredThisProperty(symbol *ast.Symbol) (thisAss
1716017193
if kind, ok := c.thisExpandoKinds[symbol]; ok {
1716117194
location, ok2 := c.thisExpandoLocations[symbol]
1716217195
if !ok2 {
17163-
panic("ctor should be cached whenever this expando location is cached")
17196+
panic("location should be cached whenever this expando symbol is cached")
1716417197
}
1716517198
return kind, location
1716617199
}
@@ -17174,9 +17207,8 @@ func (c *Checker) isConstructorDeclaredThisProperty(symbol *ast.Symbol) (thisAss
1717417207
bin := declaration.AsBinaryExpression()
1717517208
if ast.GetAssignmentDeclarationKind(bin) == ast.JSDeclarationKindThisProperty &&
1717617209
(bin.Left.Kind != ast.KindElementAccessExpression || ast.IsStringOrNumericLiteralLike(bin.Left.AsElementAccessExpression().ArgumentExpression)) {
17177-
// TODO: if bin.Type() != nil, use bin.Type()
17178-
if bin.Right.Kind == ast.KindTypeAssertionExpression {
17179-
typeAnnotation = bin.Right.AsTypeAssertion().Type
17210+
if bin.Type != nil {
17211+
typeAnnotation = bin.Type
1718017212
}
1718117213
} else {
1718217214
allThis = false
@@ -21796,6 +21828,7 @@ func (c *Checker) getTypeFromTypeOperatorNode(node *ast.Node) *Type {
2179621828
}
2179721829

2179821830
func (c *Checker) getESSymbolLikeTypeForNode(node *ast.Node) *Type {
21831+
node = ast.GetEffectiveTypeParent(node)
2179921832
if isValidESSymbolDeclaration(node) {
2180021833
symbol := c.getSymbolOfNode(node)
2180121834
if symbol != nil {
@@ -27665,7 +27698,7 @@ func (c *Checker) getContextualType(node *ast.Node, contextFlags ContextFlags) *
2766527698
return c.getContextualType(parent, contextFlags)
2766627699
case ast.KindSatisfiesExpression:
2766727700
return c.getTypeFromTypeNode(parent.AsSatisfiesExpression().Type)
27668-
case ast.KindExportAssignment:
27701+
case ast.KindExportAssignment, ast.KindJSExportAssignment, ast.KindCommonJSExport:
2766927702
return c.tryGetTypeFromTypeNode(parent)
2767027703
case ast.KindJsxExpression:
2767127704
return c.getContextualTypeForJsxExpression(parent, contextFlags)
@@ -28075,11 +28108,15 @@ func (c *Checker) getContextualTypeForDecorator(decorator *ast.Node) *Type {
2807528108

2807628109
func (c *Checker) getContextualTypeForBinaryOperand(node *ast.Node, contextFlags ContextFlags) *Type {
2807728110
binary := node.Parent.AsBinaryExpression()
28111+
if t := binary.Type; t != nil {
28112+
return c.getTypeFromTypeNode(t)
28113+
}
2807828114
switch binary.OperatorToken.Kind {
2807928115
case ast.KindEqualsToken, ast.KindAmpersandAmpersandEqualsToken, ast.KindBarBarEqualsToken, ast.KindQuestionQuestionEqualsToken:
2808028116
// In an assignment expression, the right operand is contextually typed by the type of the left operand
2808128117
// unless it's an assignment declaration.
28082-
if node == binary.Right {
28118+
kind := ast.GetAssignmentDeclarationKind(binary)
28119+
if node == binary.Right && kind != ast.JSDeclarationKindModuleExports && kind != ast.JSDeclarationKindExportsProperty {
2808328120
return c.getContextualTypeForAssignmentExpression(binary)
2808428121
}
2808528122
case ast.KindBarBarToken, ast.KindQuestionQuestionToken:
@@ -28171,6 +28208,9 @@ func (c *Checker) getContextualTypeForAssignmentExpression(binary *ast.BinaryExp
2817128208
}
2817228209

2817328210
func (c *Checker) getContextualTypeForObjectLiteralElement(element *ast.Node, contextFlags ContextFlags) *Type {
28211+
if t := element.Type(); t != nil && !ast.IsObjectLiteralMethod(element) {
28212+
return c.getTypeFromTypeNode(t)
28213+
}
2817428214
objectLiteral := element.Parent
2817528215
t := c.getApparentTypeOfContextualType(objectLiteral, contextFlags)
2817628216
if t != nil {

internal/checker/grammarchecks.go

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,14 +1377,7 @@ func (c *Checker) checkGrammarTypeOperatorNode(node *ast.TypeOperatorNode) bool
13771377
if innerType.Kind != ast.KindSymbolKeyword {
13781378
return c.grammarErrorOnNode(innerType, diagnostics.X_0_expected, scanner.TokenToString(ast.KindSymbolKeyword))
13791379
}
1380-
parent := ast.WalkUpParenthesizedTypes(node.Parent)
1381-
// !!!
1382-
// if ast.IsInJSFile(parent) && isJSDocTypeExpression(parent) {
1383-
// host := getJSDocHost(parent)
1384-
// if host != nil {
1385-
// parent = getSingleVariableOfVariableStatement(host) || host
1386-
// }
1387-
// }
1380+
parent := ast.GetEffectiveTypeParent(ast.WalkUpParenthesizedTypes(node.Parent))
13881381
switch parent.Kind {
13891382
case ast.KindVariableDeclaration:
13901383
decl := parent.AsVariableDeclaration()

internal/parser/jsdoc.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@ const (
2626
propertyLikeParseCallbackParameter
2727
)
2828

29-
func (p *Parser) withJSDoc(node *ast.Node, hasJSDoc bool) {
29+
func (p *Parser) withJSDoc(node *ast.Node, hasJSDoc bool) []*ast.Node {
3030
if !hasJSDoc {
31-
return
31+
return nil
3232
}
3333

3434
if p.jsdocCache == nil {
@@ -60,7 +60,9 @@ func (p *Parser) withJSDoc(node *ast.Node, hasJSDoc bool) {
6060
p.reparseTags(node, jsdoc)
6161
}
6262
p.jsdocCache[node] = jsdoc
63+
return jsdoc
6364
}
65+
return nil
6466
}
6567

6668
func (p *Parser) parseJSDocTypeExpression(mayOmitBraces bool) *ast.Node {

internal/parser/parser.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1396,8 +1396,8 @@ func (p *Parser) parseExpressionOrLabeledStatement() *ast.Statement {
13961396
}
13971397
result := p.factory.NewExpressionStatement(expression)
13981398
p.finishNode(result, pos)
1399-
p.withJSDoc(result, hasJSDoc && !hasParen)
1400-
p.reparseCommonJS(result)
1399+
jsdoc := p.withJSDoc(result, hasJSDoc && !hasParen)
1400+
p.reparseCommonJS(result, jsdoc)
14011401
return result
14021402
}
14031403

@@ -2378,7 +2378,7 @@ func (p *Parser) parseExportAssignment(pos int, hasJSDoc bool, modifiers *ast.Mo
23782378
p.parseSemicolon()
23792379
p.contextFlags = saveContextFlags
23802380
p.statementHasAwaitIdentifier = saveHasAwaitIdentifier
2381-
result := p.factory.NewExportAssignment(modifiers, isExportEquals, expression)
2381+
result := p.factory.NewExportAssignment(modifiers, isExportEquals, nil /*typeNode*/, expression)
23822382
p.finishNode(result, pos)
23832383
p.withJSDoc(result, hasJSDoc)
23842384
return result
@@ -4592,7 +4592,7 @@ func (p *Parser) makeAsExpression(left *ast.Expression, right *ast.TypeNode) *as
45924592
}
45934593

45944594
func (p *Parser) makeBinaryExpression(left *ast.Expression, operatorToken *ast.Node, right *ast.Expression, pos int) *ast.Node {
4595-
result := p.factory.NewBinaryExpression(left, operatorToken, right)
4595+
result := p.factory.NewBinaryExpression(nil /*modifiers*/, left, nil /*typeNode*/, operatorToken, right)
45964596
p.finishNode(result, pos)
45974597
return result
45984598
}
@@ -4734,7 +4734,7 @@ func (p *Parser) parseJsxElementOrSelfClosingElementOrFragment(inExpressionConte
47344734
operatorToken := p.factory.NewToken(ast.KindCommaToken)
47354735
operatorToken.Loc = core.NewTextRange(invalidElement.Pos(), invalidElement.Pos())
47364736
p.parseErrorAt(scanner.SkipTrivia(p.sourceText, topBadPos), invalidElement.End(), diagnostics.JSX_expressions_must_have_one_parent_element)
4737-
result = p.factory.NewBinaryExpression(result, operatorToken, invalidElement)
4737+
result = p.factory.NewBinaryExpression(nil /*modifiers*/, result, nil /*typeNode*/, operatorToken, invalidElement)
47384738
p.finishNode(result, pos)
47394739
}
47404740
return result
@@ -5644,11 +5644,11 @@ func (p *Parser) parseObjectLiteralElement() *ast.Node {
56445644
if equalsToken != nil {
56455645
initializer = doInContext(p, ast.NodeFlagsDisallowInContext, false, (*Parser).parseAssignmentExpressionOrHigher)
56465646
}
5647-
node = p.factory.NewShorthandPropertyAssignment(modifiers, name, postfixToken, equalsToken, initializer)
5647+
node = p.factory.NewShorthandPropertyAssignment(modifiers, name, postfixToken, nil /*typeNode*/, equalsToken, initializer)
56485648
} else {
56495649
p.parseExpected(ast.KindColonToken)
56505650
initializer := doInContext(p, ast.NodeFlagsDisallowInContext, false, (*Parser).parseAssignmentExpressionOrHigher)
5651-
node = p.factory.NewPropertyAssignment(modifiers, name, postfixToken, initializer)
5651+
node = p.factory.NewPropertyAssignment(modifiers, name, postfixToken, nil /*typeNode*/, initializer)
56525652
}
56535653
p.finishNode(node, pos)
56545654
p.withJSDoc(node, hasJSDoc)

0 commit comments

Comments
 (0)