Skip to content

Commit 450efd7

Browse files
committed
fix(2632): allow missing names in jsdoc param tags
1 parent 3cee8d9 commit 450efd7

File tree

38 files changed

+268
-168
lines changed

38 files changed

+268
-168
lines changed

internal/parser/jsdoc.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ func (p *Parser) parseTag(tags []*ast.Node, margin int) *ast.Node {
383383
start := p.scanner.TokenStart()
384384
p.nextTokenJSDoc()
385385

386-
tagName := p.parseJSDocIdentifierName(nil)
386+
tagName := p.parseJSDocIdentifierName(diagnostics.Identifier_expected)
387387
indentText := p.skipWhitespaceOrAsterisk()
388388

389389
var tag *ast.Node
@@ -670,15 +670,15 @@ func (p *Parser) tryParseTypeExpression() *ast.Node {
670670
}
671671
}
672672

673-
func (p *Parser) parseBracketNameInPropertyAndParamTag() (name *ast.EntityName, isBracketed bool) {
673+
func (p *Parser) parseBracketNameInPropertyAndParamTag(target propertyLikeParse) (name *ast.EntityName, isBracketed bool) {
674674
// Looking for something like '[foo]', 'foo', '[foo.bar]' or 'foo.bar'
675675
isBracketed = p.parseOptionalJsdoc(ast.KindOpenBracketToken)
676676
if isBracketed {
677677
p.skipWhitespace()
678678
}
679679
// a markdown-quoted name: `arg` is not legal jsdoc, but occurs in the wild
680680
isBackquoted := p.parseOptionalJsdoc(ast.KindBacktickToken)
681-
name = p.parseJSDocEntityName()
681+
name = p.parseJSDocEntityName(core.IfElse(target == propertyLikeParseParameter, nil, diagnostics.Identifier_expected))
682682
if isBackquoted {
683683
p.parseExpectedTokenJSDoc(ast.KindBacktickToken)
684684
}
@@ -715,7 +715,7 @@ func (p *Parser) parseParameterOrPropertyTag(start int, tagName *ast.IdentifierN
715715
isNameFirst := typeExpression == nil
716716
p.skipWhitespaceOrAsterisk()
717717

718-
name, isBracketed := p.parseBracketNameInPropertyAndParamTag()
718+
name, isBracketed := p.parseBracketNameInPropertyAndParamTag(target)
719719
indentText := p.skipWhitespaceOrAsterisk()
720720

721721
if isNameFirst && p.lookAhead(func(p *Parser) bool { _, ok := p.parseJSDocLinkPrefix(); return !ok }) {
@@ -846,9 +846,9 @@ func (p *Parser) parseExpressionWithTypeArgumentsForAugments() *ast.Node {
846846

847847
func (p *Parser) parsePropertyAccessEntityNameExpression() *ast.Node {
848848
pos := p.nodePos()
849-
node := p.parseJSDocIdentifierName(nil)
849+
node := p.parseJSDocIdentifierName(diagnostics.Identifier_expected)
850850
for p.parseOptional(ast.KindDotToken) {
851-
name := p.parseJSDocIdentifierName(nil)
851+
name := p.parseJSDocIdentifierName(diagnostics.Identifier_expected)
852852
node = p.finishNode(p.factory.NewPropertyAccessExpression(node, nil, name, ast.NodeFlagsNone), pos)
853853
}
854854
return node
@@ -868,7 +868,7 @@ func (p *Parser) parseThisTag(start int, tagName *ast.IdentifierNode, margin int
868868
func (p *Parser) parseTypedefTag(start int, tagName *ast.IdentifierNode, indent int, indentText string) *ast.Node {
869869
typeExpression := p.tryParseTypeExpression()
870870
p.skipWhitespaceOrAsterisk()
871-
fullName := p.parseJSDocIdentifierName(nil)
871+
fullName := p.parseJSDocIdentifierName(diagnostics.Identifier_expected)
872872
p.skipWhitespace()
873873
comment := p.parseTagComments(indent, nil)
874874

@@ -984,7 +984,7 @@ func (p *Parser) parseJSDocSignature(start int, indent int) *ast.Node {
984984
}
985985

986986
func (p *Parser) parseCallbackTag(start int, tagName *ast.IdentifierNode, indent int, indentText string) *ast.Node {
987-
fullName := p.parseJSDocIdentifierName(nil)
987+
fullName := p.parseJSDocIdentifierName(diagnostics.Identifier_expected)
988988
p.skipWhitespace()
989989
comment := p.parseTagComments(indent, nil)
990990
typeExpression := p.parseJSDocSignature(p.nodePos(), indent)
@@ -1071,7 +1071,7 @@ func (p *Parser) tryParseChildTag(target propertyLikeParse, indent int) *ast.Nod
10711071
start := p.scanner.TokenFullStart()
10721072
p.nextTokenJSDoc()
10731073

1074-
tagName := p.parseJSDocIdentifierName(nil)
1074+
tagName := p.parseJSDocIdentifierName(diagnostics.Identifier_expected)
10751075
indentText := p.skipWhitespaceOrAsterisk()
10761076
var t propertyLikeParse
10771077
switch tagName.Text() {
@@ -1164,16 +1164,16 @@ func (p *Parser) parseOptionalJsdoc(t ast.Kind) bool {
11641164
return false
11651165
}
11661166

1167-
func (p *Parser) parseJSDocEntityName() *ast.EntityName {
1168-
var entity *ast.EntityName = p.parseJSDocIdentifierName(nil)
1167+
func (p *Parser) parseJSDocEntityName(diagnosticMessage *diagnostics.Message) *ast.EntityName {
1168+
var entity *ast.EntityName = p.parseJSDocIdentifierName(diagnosticMessage)
11691169
if p.parseOptional(ast.KindOpenBracketToken) {
11701170
p.parseExpected(ast.KindCloseBracketToken)
11711171
// Note that y[] is accepted as an entity name, but the postfix brackets are not saved for checking.
11721172
// Technically usejsdoc.org requires them for specifying a property of a type equivalent to Array<{ x: ...}>
11731173
// but it's not worth it to enforce that restriction.
11741174
}
11751175
for p.parseOptional(ast.KindDotToken) {
1176-
name := p.parseJSDocIdentifierName(nil)
1176+
name := p.parseJSDocIdentifierName(diagnostics.Identifier_expected)
11771177
if p.parseOptional(ast.KindOpenBracketToken) {
11781178
p.parseExpected(ast.KindCloseBracketToken)
11791179
}
@@ -1189,8 +1189,6 @@ func (p *Parser) parseJSDocIdentifierName(diagnosticMessage *diagnostics.Message
11891189
p.parseErrorAtCurrentToken(diagnosticMessage)
11901190
} else if isReservedWord(p.token) {
11911191
p.parseErrorAtCurrentToken(diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, p.scanner.TokenText())
1192-
} else {
1193-
p.parseErrorAtCurrentToken(diagnostics.Identifier_expected)
11941192
}
11951193
return p.finishNode(p.newIdentifier(""), p.nodePos())
11961194
}

internal/parser/reparser.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,8 @@ func findMatchingParameter(fun *ast.Node, parameterTag *ast.JSDocParameterTag, j
585585
}
586586
for parameterIndex, parameter := range fun.Parameters() {
587587
if parameter.Name().Kind == ast.KindIdentifier {
588-
if parameterTag.Name().Kind == ast.KindIdentifier && parameter.Name().Text() == parameterTag.Name().Text() {
588+
if parameterTag.Name().Kind == ast.KindIdentifier &&
589+
((parameter.Name().Text() == parameterTag.Name().Text()) || (parameterIndex == tagIndex && len(parameterTag.Name().Text()) == 0)) {
589590
return parameter.AsParameterDeclaration(), true
590591
}
591592
} else if parameterIndex == tagIndex {
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
a.js(5,14): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
2+
3+
4+
==== a.js (1 errors) ====
5+
/**
6+
* @param {(x: string) => string}
7+
*/
8+
function foo(f) {
9+
return f(123);
10+
~~~
11+
!!! error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
12+
}
13+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//// [tests/cases/conformance/jsdoc/jsdocParamTagNoName.ts] ////
2+
3+
=== a.js ===
4+
/**
5+
* @param {(x: string) => string}
6+
*/
7+
function foo(f) {
8+
>foo : Symbol(foo, Decl(a.js, 0, 0))
9+
>f : Symbol(f, Decl(a.js, 3, 13))
10+
11+
return f(123);
12+
>f : Symbol(f, Decl(a.js, 3, 13))
13+
}
14+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//// [tests/cases/conformance/jsdoc/jsdocParamTagNoName.ts] ////
2+
3+
=== a.js ===
4+
/**
5+
* @param {(x: string) => string}
6+
*/
7+
function foo(f) {
8+
>foo : (f: (x: string) => string) => string
9+
>f : (x: string) => string
10+
11+
return f(123);
12+
>f(123) : string
13+
>f : (x: string) => string
14+
>123 : 123
15+
}
16+

testdata/baselines/reference/submodule/conformance/jsDeclarationsMissingTypeParameters.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ function w() { return null; }
4949
declare function x(y?: Array | undefined): void;
5050
/** @param {function (Array)} func Invoked
5151
*/
52-
declare function y(func: any): void;
52+
declare function y(func: function): void;
5353
/**
5454
* @return {(Array.<> | null)} list of devices
5555
*/

testdata/baselines/reference/submodule/conformance/jsDeclarationsMissingTypeParameters.js.diff

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
/** @param {function (Array)} func Invoked
1010
*/
1111
-declare function y(func: (arg0: any[]) => any): void;
12-
+declare function y(func: any): void;
12+
+declare function y(func: function): void;
1313
/**
1414
* @return {(Array.<> | null)} list of devices
1515
*/

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ function x(y) { }
1212
/** @param {function (Array)} func Invoked
1313
*/
1414
function y(func) { return; }
15-
>y : (func: any) => void
16-
>func : any
15+
>y : (func: function) => void
16+
>func : function
1717

1818
/**
1919
* @return {(Array.<> | null)} list of devices

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
function y(func) { return; }
1515
->y : (func: (arg0: any[]) => any) => void
1616
->func : (arg0: any[]) => any
17-
+>y : (func: any) => void
18-
+>func : any
17+
+>y : (func: function) => void
18+
+>func : function
1919

2020
/**
2121
* @return {(Array.<> | null)} list of devices

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1+
bug38550.js(3,14): error TS2552: Cannot find name 'function'. Did you mean 'Function'?
12
bug38550.js(3,22): error TS1005: '}' expected.
23

34

4-
==== bug38550.js (1 errors) ====
5+
==== bug38550.js (2 errors) ====
56
export class Clazz {
67
/**
78
* @param {function(this:Object, ...*):*} functionDeclaration
9+
~~~~~~~~
10+
!!! error TS2552: Cannot find name 'function'. Did you mean 'Function'?
11+
!!! related TS2728 lib.es5.d.ts:--:--: 'Function' is declared here.
812
~
913
!!! error TS1005: '}' expected.
1014
*/

0 commit comments

Comments
 (0)