@@ -412,12 +412,12 @@ namespace ts {
412
412
case SyntaxKind . JSDocParameterTag :
413
413
case SyntaxKind . JSDocPropertyTag :
414
414
if ( ( node as JSDocPropertyLikeTag ) . isNameFirst ) {
415
- return visitNode ( cbNode , ( < JSDocPropertyLikeTag > node ) . fullName ) ||
415
+ return visitNode ( cbNode , ( < JSDocPropertyLikeTag > node ) . name ) ||
416
416
visitNode ( cbNode , ( < JSDocPropertyLikeTag > node ) . typeExpression ) ;
417
417
}
418
418
else {
419
419
return visitNode ( cbNode , ( < JSDocPropertyLikeTag > node ) . typeExpression ) ||
420
- visitNode ( cbNode , ( < JSDocPropertyLikeTag > node ) . fullName ) ;
420
+ visitNode ( cbNode , ( < JSDocPropertyLikeTag > node ) . name ) ;
421
421
}
422
422
case SyntaxKind . JSDocReturnTag :
423
423
return visitNode ( cbNode , ( < JSDocReturnTag > node ) . typeExpression ) ;
@@ -438,7 +438,10 @@ namespace ts {
438
438
visitNode ( cbNode , ( < JSDocTypedefTag > node ) . typeExpression ) ;
439
439
}
440
440
case SyntaxKind . JSDocTypeLiteral :
441
- return visitNodes ( cbNode , cbNodes , ( < JSDocTypeLiteral > node ) . jsDocPropertyTags ) ;
441
+ for ( const tag of ( node as JSDocTypeLiteral ) . jsDocPropertyTags ) {
442
+ visitNode ( cbNode , tag ) ;
443
+ }
444
+ return ;
442
445
case SyntaxKind . PartiallyEmittedExpression :
443
446
return visitNode ( cbNode , ( < PartiallyEmittedExpression > node ) . expression ) ;
444
447
}
@@ -1943,14 +1946,18 @@ namespace ts {
1943
1946
break ;
1944
1947
}
1945
1948
dotPos = scanner . getStartPos ( ) ;
1946
- const node : QualifiedName = < QualifiedName > createNode ( SyntaxKind . QualifiedName , entity . pos ) ;
1947
- node . left = entity ;
1948
- node . right = parseRightSideOfDot ( allowReservedWords ) ;
1949
- entity = finishNode ( node ) ;
1949
+ entity = createQualifiedName ( entity , parseRightSideOfDot ( allowReservedWords ) ) ;
1950
1950
}
1951
1951
return entity ;
1952
1952
}
1953
1953
1954
+ function createQualifiedName ( entity : EntityName , name : Identifier ) : QualifiedName {
1955
+ const node = createNode ( SyntaxKind . QualifiedName , entity . pos ) as QualifiedName ;
1956
+ node . left = entity ;
1957
+ node . right = name ;
1958
+ return finishNode ( node ) ;
1959
+ }
1960
+
1954
1961
function parseRightSideOfDot ( allowIdentifierNames : boolean ) : Identifier {
1955
1962
// Technically a keyword is valid here as all identifiers and keywords are identifier names.
1956
1963
// However, often we'll encounter this in error situations when the identifier or keyword
@@ -6473,10 +6480,10 @@ namespace ts {
6473
6480
} ) ;
6474
6481
}
6475
6482
6476
- function parseBracketNameInPropertyAndParamTag ( ) : { fullName : EntityName , isBracketed : boolean } {
6483
+ function parseBracketNameInPropertyAndParamTag ( ) : { name : EntityName , isBracketed : boolean } {
6477
6484
// Looking for something like '[foo]', 'foo', '[foo.bar]' or 'foo.bar'
6478
6485
const isBracketed = parseOptional ( SyntaxKind . OpenBracketToken ) ;
6479
- const fullName = parseJSDocEntityName ( /*createIfMissing*/ true ) ;
6486
+ const name = parseJSDocEntityName ( ) ;
6480
6487
if ( isBracketed ) {
6481
6488
skipWhitespace ( ) ;
6482
6489
@@ -6488,68 +6495,68 @@ namespace ts {
6488
6495
parseExpected ( SyntaxKind . CloseBracketToken ) ;
6489
6496
}
6490
6497
6491
- return { fullName , isBracketed } ;
6498
+ return { name , isBracketed } ;
6492
6499
}
6493
6500
6494
6501
function isObjectOrObjectArrayTypeReference ( node : TypeNode ) : boolean {
6495
- return node . kind === SyntaxKind . ObjectKeyword ||
6496
- isTypeReferenceNode ( node ) && ts . isIdentifier ( node . typeName ) && node . typeName . text === "Object" ||
6497
- node . kind === SyntaxKind . ArrayType && isObjectOrObjectArrayTypeReference ( ( node as ArrayTypeNode ) . elementType ) ;
6502
+ switch ( node . kind ) {
6503
+ case SyntaxKind . ObjectKeyword :
6504
+ return true ;
6505
+ case SyntaxKind . ArrayType :
6506
+ return isObjectOrObjectArrayTypeReference ( ( node as ArrayTypeNode ) . elementType ) ;
6507
+ default :
6508
+ return isTypeReferenceNode ( node ) && ts . isIdentifier ( node . typeName ) && node . typeName . text === "Object" ;
6509
+ }
6498
6510
}
6499
6511
6500
6512
function parseParameterOrPropertyTag ( atToken : AtToken , tagName : Identifier , target : PropertyLikeParse . Parameter ) : JSDocParameterTag ;
6501
6513
function parseParameterOrPropertyTag ( atToken : AtToken , tagName : Identifier , target : PropertyLikeParse . Property ) : JSDocPropertyTag ;
6502
6514
function parseParameterOrPropertyTag ( atToken : AtToken , tagName : Identifier , target : PropertyLikeParse ) : JSDocPropertyLikeTag {
6503
6515
let typeExpression = tryParseTypeExpression ( ) ;
6516
+ let isNameFirst = ! typeExpression ;
6504
6517
skipWhitespace ( ) ;
6505
6518
6506
- const { fullName , isBracketed } = parseBracketNameInPropertyAndParamTag ( ) ;
6519
+ const { name , isBracketed } = parseBracketNameInPropertyAndParamTag ( ) ;
6507
6520
skipWhitespace ( ) ;
6508
6521
6509
- let preName : EntityName , postName : EntityName ;
6510
- if ( typeExpression ) {
6511
- postName = fullName ;
6512
- }
6513
- else {
6514
- preName = fullName ;
6522
+ if ( isNameFirst ) {
6515
6523
typeExpression = tryParseTypeExpression ( ) ;
6516
6524
}
6517
6525
6518
- const result : JSDocPropertyLikeTag = target ?
6526
+ const result : JSDocPropertyLikeTag = target === PropertyLikeParse . Parameter ?
6519
6527
< JSDocParameterTag > createNode ( SyntaxKind . JSDocParameterTag , atToken . pos ) :
6520
6528
< JSDocPropertyTag > createNode ( SyntaxKind . JSDocPropertyTag , atToken . pos ) ;
6521
- const nestedTypeLiteral = parseNestedTypeLiteral ( typeExpression , fullName ) ;
6529
+ const nestedTypeLiteral = parseNestedTypeLiteral ( typeExpression , name ) ;
6522
6530
if ( nestedTypeLiteral ) {
6523
6531
typeExpression = nestedTypeLiteral ;
6532
+ isNameFirst = true ;
6524
6533
}
6525
6534
result . atToken = atToken ;
6526
6535
result . tagName = tagName ;
6527
6536
result . typeExpression = typeExpression ;
6528
- if ( typeExpression ) {
6529
- result . type = typeExpression . type ;
6530
- }
6531
- result . fullName = postName || preName ;
6532
- result . name = ts . isIdentifier ( result . fullName ) ? result . fullName : result . fullName . right ;
6533
- result . isNameFirst = ! ! nestedTypeLiteral || ( postName ? false : ! ! preName ) ;
6537
+ result . name = name ;
6538
+ result . isNameFirst = isNameFirst ;
6534
6539
result . isBracketed = isBracketed ;
6535
6540
return finishNode ( result ) ;
6536
6541
6537
6542
}
6538
6543
6539
- function parseNestedTypeLiteral ( typeExpression : JSDocTypeExpression , fullName : EntityName ) {
6544
+ function parseNestedTypeLiteral ( typeExpression : JSDocTypeExpression , name : EntityName ) {
6540
6545
if ( typeExpression && isObjectOrObjectArrayTypeReference ( typeExpression . type ) ) {
6541
6546
const typeLiteralExpression = < JSDocTypeExpression > createNode ( SyntaxKind . JSDocTypeExpression , scanner . getTokenPos ( ) ) ;
6542
- let child : JSDocPropertyLikeTag | false ;
6547
+ let child : JSDocParameterTag | false ;
6543
6548
let jsdocTypeLiteral : JSDocTypeLiteral ;
6544
6549
const start = scanner . getStartPos ( ) ;
6545
- while ( child = tryParse ( ( ) => parseChildParameterOrPropertyTag ( PropertyLikeParse . Parameter , fullName ) ) ) {
6546
- if ( ! jsdocTypeLiteral ) {
6547
- jsdocTypeLiteral = < JSDocTypeLiteral > createNode ( SyntaxKind . JSDocTypeLiteral , start ) ;
6548
- jsdocTypeLiteral . jsDocPropertyTags = [ ] as MutableNodeArray < JSDocPropertyTag > ;
6550
+ let children : JSDocParameterTag [ ] ;
6551
+ while ( child = tryParse ( ( ) => parseChildParameterOrPropertyTag ( PropertyLikeParse . Parameter , name ) ) ) {
6552
+ if ( ! children ) {
6553
+ children = [ ] ;
6549
6554
}
6550
- ( jsdocTypeLiteral . jsDocPropertyTags as MutableNodeArray < JSDocPropertyTag > ) . push ( child as JSDocPropertyTag ) ;
6555
+ children . push ( child ) ;
6551
6556
}
6552
- if ( jsdocTypeLiteral ) {
6557
+ if ( children ) {
6558
+ jsdocTypeLiteral = < JSDocTypeLiteral > createNode ( SyntaxKind . JSDocTypeLiteral , start ) ;
6559
+ jsdocTypeLiteral . jsDocPropertyTags = children ;
6553
6560
if ( typeExpression . type . kind === SyntaxKind . ArrayType ) {
6554
6561
jsdocTypeLiteral . isArrayType = true ;
6555
6562
}
@@ -6678,61 +6685,58 @@ namespace ts {
6678
6685
}
6679
6686
}
6680
6687
6681
- function textsEqual ( parent : EntityName , name : EntityName ) : boolean {
6682
- while ( ! ts . isIdentifier ( parent ) || ! ts . isIdentifier ( name ) ) {
6683
- if ( ! ts . isIdentifier ( parent ) && ! ts . isIdentifier ( name ) && parent . right . text === name . right . text ) {
6684
- parent = parent . left ;
6685
- name = name . left ;
6688
+ function textsEqual ( a : EntityName , b : EntityName ) : boolean {
6689
+ while ( ! ts . isIdentifier ( a ) || ! ts . isIdentifier ( b ) ) {
6690
+ if ( ! ts . isIdentifier ( a ) && ! ts . isIdentifier ( b ) && a . right . text === b . right . text ) {
6691
+ a = a . left ;
6692
+ b = b . left ;
6686
6693
}
6687
6694
else {
6688
6695
return false ;
6689
6696
}
6690
6697
}
6691
- return parent . text === name . text ;
6698
+ return a . text === b . text ;
6692
6699
}
6693
6700
6694
6701
function parseChildParameterOrPropertyTag ( target : PropertyLikeParse . Property ) : JSDocTypeTag | JSDocPropertyTag | false ;
6695
- function parseChildParameterOrPropertyTag ( target : PropertyLikeParse . Parameter , fullName : EntityName ) : JSDocPropertyTag | JSDocParameterTag | false ;
6696
- function parseChildParameterOrPropertyTag ( target : PropertyLikeParse , fullName ?: EntityName ) : JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false {
6697
- let resumePos = scanner . getStartPos ( ) ;
6702
+ function parseChildParameterOrPropertyTag ( target : PropertyLikeParse . Parameter , name : EntityName ) : JSDocParameterTag | false ;
6703
+ function parseChildParameterOrPropertyTag ( target : PropertyLikeParse , name ?: EntityName ) : JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false {
6698
6704
let canParseTag = true ;
6699
6705
let seenAsterisk = false ;
6700
- while ( token ( ) !== SyntaxKind . EndOfFileToken ) {
6706
+ while ( true ) {
6701
6707
nextJSDocToken ( ) ;
6702
6708
switch ( token ( ) ) {
6703
- case SyntaxKind . AtToken :
6704
- if ( canParseTag ) {
6705
- const child = tryParseChildTag ( target ) ;
6706
- if ( child && child . kind === SyntaxKind . JSDocParameterTag &&
6707
- ( ts . isIdentifier ( child . fullName ) || ! textsEqual ( fullName , child . fullName . left ) ) ) {
6708
- break ;
6709
+ case SyntaxKind . AtToken :
6710
+ if ( canParseTag ) {
6711
+ const child = tryParseChildTag ( target ) ;
6712
+ if ( child && child . kind === SyntaxKind . JSDocParameterTag &&
6713
+ ( ts . isIdentifier ( child . name ) || ! textsEqual ( name , child . name . left ) ) ) {
6714
+ return false ;
6715
+ }
6716
+ return child ;
6709
6717
}
6710
- return child ;
6711
- }
6712
- seenAsterisk = false ;
6713
- break ;
6714
- case SyntaxKind . NewLineTrivia :
6715
- resumePos = scanner . getStartPos ( ) - 1 ;
6716
- canParseTag = true ;
6717
- seenAsterisk = false ;
6718
- break ;
6719
- case SyntaxKind . AsteriskToken :
6720
- if ( seenAsterisk ) {
6718
+ seenAsterisk = false ;
6719
+ break ;
6720
+ case SyntaxKind . NewLineTrivia :
6721
+ canParseTag = true ;
6722
+ seenAsterisk = false ;
6723
+ break ;
6724
+ case SyntaxKind . AsteriskToken :
6725
+ if ( seenAsterisk ) {
6726
+ canParseTag = false ;
6727
+ }
6728
+ seenAsterisk = true ;
6729
+ break ;
6730
+ case SyntaxKind . Identifier :
6721
6731
canParseTag = false ;
6722
- }
6723
- seenAsterisk = true ;
6724
- break ;
6725
- case SyntaxKind . Identifier :
6726
- canParseTag = false ;
6727
- break ;
6728
- case SyntaxKind . EndOfFileToken :
6729
- break ;
6732
+ break ;
6733
+ case SyntaxKind . EndOfFileToken :
6734
+ return false ;
6730
6735
}
6731
6736
}
6732
- scanner . setTextPos ( resumePos ) ;
6733
6737
}
6734
6738
6735
- function tryParseChildTag ( target : PropertyLikeParse , alreadyHasTypeTag ?: boolean ) : JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false {
6739
+ function tryParseChildTag ( target : PropertyLikeParse ) : JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false {
6736
6740
Debug . assert ( token ( ) === SyntaxKind . AtToken ) ;
6737
6741
const atToken = < AtToken > createNode ( SyntaxKind . AtToken , scanner . getStartPos ( ) ) ;
6738
6742
atToken . end = scanner . getTextPos ( ) ;
@@ -6745,7 +6749,7 @@ namespace ts {
6745
6749
}
6746
6750
switch ( tagName . text ) {
6747
6751
case "type" :
6748
- return ! alreadyHasTypeTag && target === PropertyLikeParse . Property && parseTypeTag ( atToken , tagName ) ;
6752
+ return target === PropertyLikeParse . Property && parseTypeTag ( atToken , tagName ) ;
6749
6753
case "prop" :
6750
6754
case "property" :
6751
6755
return target === PropertyLikeParse . Property && parseParameterOrPropertyTag ( atToken , tagName , target ) ;
@@ -6801,22 +6805,20 @@ namespace ts {
6801
6805
return currentToken = scanner . scanJSDocToken ( ) ;
6802
6806
}
6803
6807
6804
- function parseJSDocEntityName ( createIfMissing = false ) : EntityName {
6805
- let entity : EntityName = parseJSDocIdentifierName ( createIfMissing ) ;
6808
+ function parseJSDocEntityName ( ) : EntityName {
6809
+ let entity : EntityName = parseJSDocIdentifierName ( /* createIfMissing*/ true ) ;
6806
6810
if ( parseOptional ( SyntaxKind . OpenBracketToken ) ) {
6807
6811
parseExpected ( SyntaxKind . CloseBracketToken ) ;
6808
6812
// Note that y[] is accepted as an entity name, but the postfix brackets are not saved for checking.
6809
6813
// Technically usejsdoc.org requires them for specifying a property of a type equivalent to Array<{ x: ...}>
6810
6814
// but it's not worth it to enforce that restriction.
6811
6815
}
6812
6816
while ( parseOptional ( SyntaxKind . DotToken ) ) {
6813
- const node : QualifiedName = createNode ( SyntaxKind . QualifiedName , entity . pos ) as QualifiedName ;
6814
- node . left = entity ;
6815
- node . right = parseJSDocIdentifierName ( createIfMissing ) ;
6817
+ const name = parseJSDocIdentifierName ( /*createIfMissing*/ true ) ;
6816
6818
if ( parseOptional ( SyntaxKind . OpenBracketToken ) ) {
6817
6819
parseExpected ( SyntaxKind . CloseBracketToken ) ;
6818
6820
}
6819
- entity = finishNode ( node ) ;
6821
+ entity = createQualifiedName ( entity , name ) ;
6820
6822
}
6821
6823
return entity ;
6822
6824
}
0 commit comments