Skip to content

Commit 8f0e49f

Browse files
authored
Follow up from the implements/extends PR (#1154)
1 parent ca4757d commit 8f0e49f

File tree

12 files changed

+109
-80
lines changed

12 files changed

+109
-80
lines changed

internal/ast/utilities.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,6 +1557,16 @@ func IsDottedName(node *Node) bool {
15571557
return false
15581558
}
15591559

1560+
func HasSamePropertyAccessName(node1, node2 *Node) bool {
1561+
if node1.Kind == KindIdentifier && node2.Kind == KindIdentifier {
1562+
return node1.Text() == node2.Text()
1563+
} else if node1.Kind == KindPropertyAccessExpression && node2.Kind == KindPropertyAccessExpression {
1564+
return node1.AsPropertyAccessExpression().Name().Text() == node2.AsPropertyAccessExpression().Name().Text() &&
1565+
HasSamePropertyAccessName(node1.AsPropertyAccessExpression().Expression, node2.AsPropertyAccessExpression().Expression)
1566+
}
1567+
return false
1568+
}
1569+
15601570
func IsAmbientModule(node *Node) bool {
15611571
return IsModuleDeclaration(node) && (node.AsModuleDeclaration().Name().Kind == KindStringLiteral || IsGlobalScopeAugmentation(node))
15621572
}

internal/binder/binder.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -537,9 +537,7 @@ func (b *Binder) combineFlowLists(head *ast.FlowList, tail *ast.FlowList) *ast.F
537537
}
538538

539539
func (b *Binder) newSingleDeclaration(declaration *ast.Node) []*ast.Node {
540-
nodes := b.singleDeclarationsPool.NewSlice(1)
541-
nodes[0] = declaration
542-
return nodes
540+
return b.singleDeclarationsPool.NewSlice1(declaration)
543541
}
544542

545543
func setFlowNodeReferenced(flow *ast.FlowNode) {

internal/checker/grammarchecks.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -779,7 +779,7 @@ func (c *Checker) checkGrammarFunctionLikeDeclaration(node *ast.Node) bool {
779779

780780
func (c *Checker) checkGrammarClassLikeDeclaration(node *ast.Node) bool {
781781
file := ast.GetSourceFileOfNode(node)
782-
return c.checkGrammarClassDeclarationHeritageClauses(node) || c.checkGrammarTypeParameterList(node.ClassLikeData().TypeParameters, file)
782+
return c.checkGrammarClassDeclarationHeritageClauses(node, file) || c.checkGrammarTypeParameterList(node.ClassLikeData().TypeParameters, file)
783783
}
784784

785785
func (c *Checker) checkGrammarArrowFunction(node *ast.Node, file *ast.SourceFile) bool {
@@ -907,7 +907,7 @@ func (c *Checker) checkGrammarExpressionWithTypeArguments(node *ast.Node /*Union
907907
return c.checkGrammarTypeArguments(node, exprWithTypeArgs.TypeArguments)
908908
}
909909

910-
func (c *Checker) checkGrammarClassDeclarationHeritageClauses(node *ast.ClassLikeDeclaration) bool {
910+
func (c *Checker) checkGrammarClassDeclarationHeritageClauses(node *ast.ClassLikeDeclaration, file *ast.SourceFile) bool {
911911
seenExtendsClause := false
912912
seenImplementsClause := false
913913

@@ -930,6 +930,19 @@ func (c *Checker) checkGrammarClassDeclarationHeritageClauses(node *ast.ClassLik
930930
return c.grammarErrorOnFirstToken(typeNodes[1], diagnostics.Classes_can_only_extend_a_single_class)
931931
}
932932

933+
for _, j := range node.JSDoc(file) {
934+
for _, tag := range j.AsJSDoc().Tags.Nodes {
935+
if tag.Kind == ast.KindJSDocAugmentsTag {
936+
target := typeNodes[0].AsExpressionWithTypeArguments()
937+
source := tag.AsJSDocAugmentsTag().ClassName.AsExpressionWithTypeArguments()
938+
if !ast.HasSamePropertyAccessName(target.Expression, source.Expression) &&
939+
target.Expression.Kind == ast.KindIdentifier &&
940+
source.Expression.Kind == ast.KindIdentifier {
941+
return c.grammarErrorOnNode(tag.AsJSDocAugmentsTag().ClassName, diagnostics.JSDoc_0_1_does_not_match_the_extends_2_clause, tag.AsJSDocAugmentsTag().TagName.Text(), source.Expression.Text(), target.Expression.Text())
942+
}
943+
}
944+
}
945+
}
933946
seenExtendsClause = true
934947
} else {
935948
if heritageClause.Token != ast.KindImplementsKeyword {

internal/core/pool.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ func (p *Pool[T]) NewSlice(size int) []T {
4343
return slice
4444
}
4545

46+
func (p *Pool[T]) NewSlice1(t T) []T {
47+
slice := p.NewSlice(1)
48+
slice[0] = t
49+
return slice
50+
}
51+
4652
func nextPoolSize(size int) int {
4753
// This compiles down branch-free.
4854
size = max(size, 1)

internal/parser/parser.go

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2162,9 +2162,7 @@ func (p *Parser) parseModuleOrNamespaceDeclaration(pos int, hasJSDoc bool, modif
21622162
implicitExport := p.factory.NewModifier(ast.KindExportKeyword)
21632163
implicitExport.Loc = core.NewTextRange(p.nodePos(), p.nodePos())
21642164
implicitExport.Flags = ast.NodeFlagsReparsed
2165-
nodes := p.nodeSlicePool.NewSlice(1)
2166-
nodes[0] = implicitExport
2167-
implicitModifiers := p.newModifierList(implicitExport.Loc, nodes)
2165+
implicitModifiers := p.newModifierList(implicitExport.Loc, p.nodeSlicePool.NewSlice1(implicitExport))
21682166
body = p.parseModuleOrNamespaceDeclaration(p.nodePos(), false /*hasJSDoc*/, implicitModifiers, true /*nested*/, keyword)
21692167
} else {
21702168
body = p.parseModuleBlock()
@@ -3804,9 +3802,7 @@ func (p *Parser) parseModifiersForConstructorType() *ast.ModifierList {
38043802
modifier := p.factory.NewModifier(p.token)
38053803
p.nextToken()
38063804
p.finishNode(modifier, pos)
3807-
nodes := p.nodeSlicePool.NewSlice(1)
3808-
nodes[0] = modifier
3809-
return p.newModifierList(modifier.Loc, nodes)
3805+
return p.newModifierList(modifier.Loc, p.nodeSlicePool.NewSlice1(modifier))
38103806
}
38113807
return nil
38123808
}
@@ -4455,9 +4451,7 @@ func (p *Parser) parseModifiersForArrowFunction() *ast.ModifierList {
44554451
p.nextToken()
44564452
modifier := p.factory.NewModifier(ast.KindAsyncKeyword)
44574453
p.finishNode(modifier, pos)
4458-
nodes := p.nodeSlicePool.NewSlice(1)
4459-
nodes[0] = modifier
4460-
return p.newModifierList(modifier.Loc, nodes)
4454+
return p.newModifierList(modifier.Loc, p.nodeSlicePool.NewSlice1(modifier))
44614455
}
44624456
return nil
44634457
}

internal/parser/reparser.go

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,11 @@ func (p *Parser) reparseCommonJS(node *ast.Node, jsdoc []*ast.Node) {
1919
case ast.JSDeclarationKindModuleExports:
2020
export = p.factory.NewJSExportAssignment(nil, bin.Right)
2121
case ast.JSDeclarationKindExportsProperty:
22-
nodes := p.nodeSlicePool.NewSlice(1)
23-
nodes[0] = p.factory.NewModifier(ast.KindExportKeyword)
24-
nodes[0].Flags = ast.NodeFlagsReparsed
25-
nodes[0].Loc = bin.Loc
22+
mod := p.factory.NewModifier(ast.KindExportKeyword)
23+
mod.Flags = p.contextFlags | ast.NodeFlagsReparsed
24+
mod.Loc = bin.Loc
2625
// TODO: Name can sometimes be a string literal, so downstream code needs to handle this
27-
export = p.factory.NewCommonJSExport(p.newModifierList(bin.Loc, nodes), ast.GetElementOrPropertyAccessName(bin.Left), nil /*typeNode*/, bin.Right)
26+
export = p.factory.NewCommonJSExport(p.newModifierList(bin.Loc, p.nodeSlicePool.NewSlice1(mod)), ast.GetElementOrPropertyAccessName(bin.Left), nil /*typeNode*/, bin.Right)
2827
}
2928
if export != nil {
3029
export.Flags = ast.NodeFlagsReparsed
@@ -66,9 +65,7 @@ func (p *Parser) reparseUnhosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Nod
6665
export := p.factory.NewModifier(ast.KindExportKeyword)
6766
export.Loc = tag.Loc
6867
export.Flags = p.contextFlags | ast.NodeFlagsReparsed
69-
nodes := p.nodeSlicePool.NewSlice(1)
70-
nodes[0] = export
71-
modifiers := p.newModifierList(export.Loc, nodes)
68+
modifiers := p.newModifierList(export.Loc, p.nodeSlicePool.NewSlice1(export))
7269

7370
typeParameters := p.gatherTypeParameters(jsDoc)
7471

@@ -283,18 +280,15 @@ func (p *Parser) reparseHosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Node)
283280
return
284281
}
285282
}
286-
types := p.nodeSlicePool.NewSlice(1)
287-
types[0] = implementsTag.ClassName
288283
implementsTag.ClassName.Flags |= ast.NodeFlagsReparsed
289-
typesList := p.newNodeList(implementsTag.ClassName.Loc, types)
284+
typesList := p.newNodeList(implementsTag.ClassName.Loc, p.nodeSlicePool.NewSlice1(implementsTag.ClassName))
290285

291286
heritageClause := p.factory.NewHeritageClause(ast.KindImplementsKeyword, typesList)
292287
heritageClause.Loc = implementsTag.ClassName.Loc
293288
heritageClause.Flags = p.contextFlags | ast.NodeFlagsReparsed
294289

295290
if class.HeritageClauses == nil {
296-
heritageClauses := p.newNodeList(implementsTag.ClassName.Loc, p.nodeSlicePool.NewSlice(1))
297-
heritageClauses.Nodes[0] = heritageClause
291+
heritageClauses := p.newNodeList(implementsTag.ClassName.Loc, p.nodeSlicePool.NewSlice1(heritageClause))
298292
class.HeritageClauses = heritageClauses
299293
} else {
300294
class.HeritageClauses.Nodes = append(class.HeritageClauses.Nodes, heritageClause)
@@ -307,7 +301,7 @@ func (p *Parser) reparseHosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Node)
307301
}); extendsClause != nil && len(extendsClause.AsHeritageClause().Types.Nodes) == 1 {
308302
target := extendsClause.AsHeritageClause().Types.Nodes[0].AsExpressionWithTypeArguments()
309303
source := tag.AsJSDocAugmentsTag().ClassName.AsExpressionWithTypeArguments()
310-
if hasSamePropertyAccessName(target.Expression, source.Expression) {
304+
if ast.HasSamePropertyAccessName(target.Expression, source.Expression) {
311305
if target.TypeArguments == nil && source.TypeArguments != nil {
312306
target.TypeArguments = source.TypeArguments
313307
for _, typeArg := range source.TypeArguments.Nodes {
@@ -387,16 +381,6 @@ func (p *Parser) makeNewType(typeExpression *ast.TypeNode, host *ast.Node) *ast.
387381
return t
388382
}
389383

390-
func hasSamePropertyAccessName(node1, node2 *ast.Node) bool {
391-
if node1.Kind == ast.KindIdentifier && node2.Kind == ast.KindIdentifier {
392-
return node1.Text() == node2.Text()
393-
} else if node1.Kind == ast.KindPropertyAccessExpression && node2.Kind == ast.KindPropertyAccessExpression {
394-
return node1.AsPropertyAccessExpression().Name().Text() == node2.AsPropertyAccessExpression().Name().Text() &&
395-
hasSamePropertyAccessName(node1.AsPropertyAccessExpression().Expression, node2.AsPropertyAccessExpression().Expression)
396-
}
397-
return false
398-
}
399-
400384
func getClassLikeData(parent *ast.Node) *ast.ClassLikeBase {
401385
var class *ast.ClassLikeBase
402386
if parent.Kind == ast.KindClassDeclaration {
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
main.js(2,15): error TS8023: JSDoc '@extends Mismatch' does not match the 'extends B' clause.
2+
3+
4+
==== super.js (0 errors) ====
5+
export class B { }
6+
7+
==== main.js (1 errors) ====
8+
import { B } from './super'
9+
/** @extends {Mismatch} */
10+
~~~~~~~~
11+
!!! error TS8023: JSDoc '@extends Mismatch' does not match the 'extends B' clause.
12+
class C extends B { }
13+
14+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/a.js(2,14): error TS8023: JSDoc '@augments ' does not match the 'extends A' clause.
2+
3+
4+
==== /a.js (1 errors) ====
5+
class A { constructor() { this.x = 0; } }
6+
/** @augments */
7+
8+
!!! error TS8023: JSDoc '@augments ' does not match the 'extends A' clause.
9+
class B extends A {
10+
m() {
11+
this.x
12+
}
13+
}
14+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/b.js(4,15): error TS8023: JSDoc '@augments A' does not match the 'extends B' clause.
2+
3+
4+
==== /b.js (1 errors) ====
5+
class A {}
6+
class B {}
7+
8+
/** @augments A */
9+
~
10+
!!! error TS8023: JSDoc '@augments A' does not match the 'extends B' clause.
11+
class C extends B {}
12+

testdata/baselines/reference/submoduleAccepted/conformance/extendsTagEmit.errors.txt.diff

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,18 @@
22
+++ new.extendsTagEmit.errors.txt
33
@@= skipped -0, +0 lines =@@
44
-main.js(2,15): error TS2304: Cannot find name 'Mismatch'.
5-
-main.js(2,15): error TS8023: JSDoc '@extends Mismatch' does not match the 'extends B' clause.
6-
-
7-
-
8-
-==== super.js (0 errors) ====
9-
- export class B { }
10-
-
5+
main.js(2,15): error TS8023: JSDoc '@extends Mismatch' does not match the 'extends B' clause.
6+
7+
8+
==== super.js (0 errors) ====
9+
export class B { }
10+
1111
-==== main.js (2 errors) ====
12-
- import { B } from './super'
13-
- /** @extends {Mismatch} */
12+
+==== main.js (1 errors) ====
13+
import { B } from './super'
14+
/** @extends {Mismatch} */
1415
- ~~~~~~~~
1516
-!!! error TS2304: Cannot find name 'Mismatch'.
16-
- ~~~~~~~~
17-
-!!! error TS8023: JSDoc '@extends Mismatch' does not match the 'extends B' clause.
18-
- class C extends B { }
19-
-
20-
-
21-
+<no content>
17+
~~~~~~~~
18+
!!! error TS8023: JSDoc '@extends Mismatch' does not match the 'extends B' clause.
19+
class C extends B { }

0 commit comments

Comments
 (0)