22
33/* @internal */
44namespace ts {
5+ export const emptyArray : never [ ] = [ ] as never [ ] ;
6+
57 export const externalHelpersModuleNameText = "tslib" ;
68
79 export interface ReferencePathMatchResult {
@@ -1445,39 +1447,37 @@ namespace ts {
14451447 ( < JSDocFunctionType > node ) . parameters [ 0 ] . type . kind === SyntaxKind . JSDocConstructorType ;
14461448 }
14471449
1448- export function getCommentsFromJSDoc ( node : Node ) : string [ ] {
1449- return map ( getJSDocs ( node ) , doc => doc . comment ) ;
1450- }
1451-
1452- export function hasJSDocParameterTags ( node : FunctionLikeDeclaration | SignatureDeclaration ) {
1453- const parameterTags = getJSDocTags ( node , SyntaxKind . JSDocParameterTag ) ;
1454- return parameterTags && parameterTags . length > 0 ;
1450+ export function hasJSDocParameterTags ( node : FunctionLikeDeclaration | SignatureDeclaration ) : boolean {
1451+ return ! ! getFirstJSDocTag ( node , SyntaxKind . JSDocParameterTag ) ;
14551452 }
14561453
1457- function getJSDocTags ( node : Node , kind : SyntaxKind ) : JSDocTag [ ] {
1458- return flatMap ( getJSDocs ( node ) , doc =>
1459- doc . kind === SyntaxKind . JSDocComment
1460- ? filter ( ( doc as JSDoc ) . tags , tag => tag . kind === kind )
1461- : doc . kind === kind && doc ) ;
1454+ function getFirstJSDocTag ( node : Node , kind : SyntaxKind ) : JSDocTag | undefined {
1455+ const tags = getJSDocTags ( node ) ;
1456+ return find ( tags , doc => doc . kind === kind ) ;
14621457 }
14631458
1464- function getFirstJSDocTag ( node : Node , kind : SyntaxKind ) : JSDocTag {
1465- return node && firstOrUndefined ( getJSDocTags ( node , kind ) ) ;
1466- }
1467-
1468- export function getJSDocs ( node : Node ) : ( JSDoc | JSDocTag ) [ ] {
1459+ export function getAllJSDocs ( node : Node ) : ( JSDoc | JSDocTag ) [ ] {
14691460 if ( isJSDocTypedefTag ( node ) ) {
14701461 return [ node . parent ] ;
14711462 }
1463+ return getJSDocCommentsAndTags ( node ) ;
1464+ }
14721465
1473- let cache : ( JSDoc | JSDocTag ) [ ] = node . jsDocCache ;
1474- if ( ! cache ) {
1475- getJSDocsWorker ( node ) ;
1476- node . jsDocCache = cache ;
1466+ export function getJSDocTags ( node : Node ) : JSDocTag [ ] | undefined {
1467+ let tags = node . jsDocCache ;
1468+ // If cache is 'null', that means we did the work of searching for JSDoc tags and came up with nothing.
1469+ if ( tags === undefined ) {
1470+ node . jsDocCache = tags = flatMap ( getJSDocCommentsAndTags ( node ) , j => isJSDoc ( j ) ? j . tags : j ) ;
14771471 }
1478- return cache ;
1472+ return tags ;
1473+ }
1474+
1475+ function getJSDocCommentsAndTags ( node : Node ) : ( JSDoc | JSDocTag ) [ ] {
1476+ let result : Array < JSDoc | JSDocTag > | undefined ;
1477+ getJSDocCommentsAndTagsWorker ( node ) ;
1478+ return result || emptyArray ;
14791479
1480- function getJSDocsWorker ( node : Node ) {
1480+ function getJSDocCommentsAndTagsWorker ( node : Node ) : void {
14811481 const parent = node . parent ;
14821482 // Try to recognize this pattern when node is initializer of variable declaration and JSDoc comments are on containing variable statement.
14831483 // /**
@@ -1496,7 +1496,7 @@ namespace ts {
14961496 isVariableOfVariableDeclarationStatement ? parent . parent :
14971497 undefined ;
14981498 if ( variableStatementNode ) {
1499- getJSDocsWorker ( variableStatementNode ) ;
1499+ getJSDocCommentsAndTagsWorker ( variableStatementNode ) ;
15001500 }
15011501
15021502 // Also recognize when the node is the RHS of an assignment expression
@@ -1506,43 +1506,51 @@ namespace ts {
15061506 ( parent as BinaryExpression ) . operatorToken . kind === SyntaxKind . EqualsToken &&
15071507 parent . parent . kind === SyntaxKind . ExpressionStatement ;
15081508 if ( isSourceOfAssignmentExpressionStatement ) {
1509- getJSDocsWorker ( parent . parent ) ;
1509+ getJSDocCommentsAndTagsWorker ( parent . parent ) ;
15101510 }
15111511
15121512 const isModuleDeclaration = node . kind === SyntaxKind . ModuleDeclaration &&
15131513 parent && parent . kind === SyntaxKind . ModuleDeclaration ;
15141514 const isPropertyAssignmentExpression = parent && parent . kind === SyntaxKind . PropertyAssignment ;
15151515 if ( isModuleDeclaration || isPropertyAssignmentExpression ) {
1516- getJSDocsWorker ( parent ) ;
1516+ getJSDocCommentsAndTagsWorker ( parent ) ;
15171517 }
15181518
15191519 // Pull parameter comments from declaring function as well
15201520 if ( node . kind === SyntaxKind . Parameter ) {
1521- cache = concatenate ( cache , getJSDocParameterTags ( node as ParameterDeclaration ) ) ;
1521+ result = addRange ( result , getJSDocParameterTags ( node as ParameterDeclaration ) ) ;
15221522 }
15231523
15241524 if ( isVariableLike ( node ) && node . initializer ) {
1525- cache = concatenate ( cache , node . initializer . jsDoc ) ;
1525+ result = addRange ( result , node . initializer . jsDoc ) ;
15261526 }
15271527
1528- cache = concatenate ( cache , node . jsDoc ) ;
1528+ result = addRange ( result , node . jsDoc ) ;
15291529 }
15301530 }
15311531
1532- export function getJSDocParameterTags ( param : ParameterDeclaration ) : JSDocParameterTag [ ] {
1532+ export function getJSDocParameterTags ( param : ParameterDeclaration ) : JSDocParameterTag [ ] | undefined {
15331533 const func = param . parent ;
1534- const tags = getJSDocTags ( func , SyntaxKind . JSDocParameterTag ) as JSDocParameterTag [ ] ;
1534+ const tags = getJSDocTags ( func ) ;
1535+ if ( ! tags ) return undefined ;
1536+
15351537 if ( ! param . name ) {
15361538 // this is an anonymous jsdoc param from a `function(type1, type2): type3` specification
1537- const i = func . parameters . indexOf ( param ) ;
1538- const paramTags = filter ( tags , tag => tag . kind === SyntaxKind . JSDocParameterTag ) ;
1539- if ( paramTags && 0 <= i && i < paramTags . length ) {
1540- return [ paramTags [ i ] ] ;
1539+ const paramIndex = func . parameters . indexOf ( param ) ;
1540+ Debug . assert ( paramIndex !== - 1 ) ;
1541+ let curParamIndex = 0 ;
1542+ for ( const tag of tags ) {
1543+ if ( isJSDocParameterTag ( tag ) ) {
1544+ if ( curParamIndex === paramIndex ) {
1545+ return [ tag ] ;
1546+ }
1547+ curParamIndex ++ ;
1548+ }
15411549 }
15421550 }
15431551 else if ( param . name . kind === SyntaxKind . Identifier ) {
15441552 const name = ( param . name as Identifier ) . text ;
1545- return filter ( tags , tag => tag . kind === SyntaxKind . JSDocParameterTag && tag . name . text === name ) ;
1553+ return tags . filter ( ( tag ) : tag is JSDocParameterTag => isJSDocParameterTag ( tag ) && tag . name . text === name ) as JSDocParameterTag [ ] ;
15461554 }
15471555 else {
15481556 // TODO: it's a destructured parameter, so it should look up an "object type" series of multiple lines
0 commit comments