@@ -21,6 +21,7 @@ namespace ts {
21
21
getChildCount ( sourceFile ?: SourceFile ) : number ;
22
22
getChildAt ( index : number , sourceFile ?: SourceFile ) : Node ;
23
23
getChildren ( sourceFile ?: SourceFile ) : Node [ ] ;
24
+ getNonJsDocCommentChildren ?( sourceFile ?: SourceFile ) : Node [ ] ;
24
25
getStart ( sourceFile ?: SourceFile , includeJsDocComment ?: boolean ) : number ;
25
26
getFullStart ( ) : number ;
26
27
getEnd ( ) : number ;
@@ -196,6 +197,7 @@ namespace ts {
196
197
public parent : Node ;
197
198
public jsDocComments : JSDocComment [ ] ;
198
199
private _children : Node [ ] ;
200
+ private _nonJsDocCommentChildren : Node [ ] ;
199
201
200
202
constructor ( kind : SyntaxKind , pos : number , end : number ) {
201
203
this . pos = pos ;
@@ -273,20 +275,22 @@ namespace ts {
273
275
}
274
276
275
277
private createChildren ( sourceFile ?: SourceFile ) {
276
- let children : Node [ ] ;
278
+ let jsDocCommentChildren : Node [ ] ;
279
+ let nonJsDocCommentChildren : Node [ ] ;
277
280
if ( this . kind >= SyntaxKind . FirstNode ) {
278
281
scanner . setText ( ( sourceFile || this . getSourceFile ( ) ) . text ) ;
279
- children = [ ] ;
282
+ jsDocCommentChildren = [ ] ;
283
+ nonJsDocCommentChildren = [ ] ;
280
284
let pos = this . pos ;
281
285
const useJSDocScanner = this . kind >= SyntaxKind . FirstJSDocTagNode && this . kind <= SyntaxKind . LastJSDocTagNode ;
282
- const processNode = ( node : Node ) => {
286
+ const processNode = ( node : Node , children = nonJsDocCommentChildren ) => {
283
287
if ( pos < node . pos ) {
284
288
pos = this . addSyntheticNodes ( children , pos , node . pos , useJSDocScanner ) ;
285
289
}
286
290
children . push ( node ) ;
287
291
pos = node . end ;
288
292
} ;
289
- const processNodes = ( nodes : NodeArray < Node > ) => {
293
+ const processNodes = ( nodes : NodeArray < Node > , children = nonJsDocCommentChildren ) => {
290
294
if ( pos < nodes . pos ) {
291
295
pos = this . addSyntheticNodes ( children , pos , nodes . pos , useJSDocScanner ) ;
292
296
}
@@ -296,16 +300,21 @@ namespace ts {
296
300
// jsDocComments need to be the first children
297
301
if ( this . jsDocComments ) {
298
302
for ( const jsDocComment of this . jsDocComments ) {
299
- processNode ( jsDocComment ) ;
303
+ processNode ( jsDocComment , jsDocCommentChildren ) ;
300
304
}
301
305
}
306
+ // For syntactic classifications, all trivia are classcified together, including jsdoc comments.
307
+ // For that to work, the jsdoc comments should still be the leading trivia of the first child.
308
+ // Restoring the scanner position ensures that.
309
+ pos = this . pos ;
302
310
forEachChild ( this , processNode , processNodes ) ;
303
311
if ( pos < this . end ) {
304
- this . addSyntheticNodes ( children , pos , this . end ) ;
312
+ this . addSyntheticNodes ( nonJsDocCommentChildren , pos , this . end ) ;
305
313
}
306
314
scanner . setText ( undefined ) ;
307
315
}
308
- this . _children = children || emptyArray ;
316
+ this . _nonJsDocCommentChildren = nonJsDocCommentChildren || emptyArray ;
317
+ this . _children = concatenate ( jsDocCommentChildren , this . _nonJsDocCommentChildren ) ;
309
318
}
310
319
311
320
public getChildCount ( sourceFile ?: SourceFile ) : number {
@@ -323,6 +332,18 @@ namespace ts {
323
332
return this . _children ;
324
333
}
325
334
335
+ public getNonJsDocCommentChildren ( sourceFile ?: SourceFile ) : Node [ ] {
336
+ // If the cached children were cleared, that means some node before the current node has changed.
337
+ // so even if we have a cached nonJsDocCommentChildren, it would be outdated as well.
338
+ if ( ! this . _children ) {
339
+ this . createChildren ( sourceFile ) ;
340
+ }
341
+ // If the node has cached children but not nonJsDocCommentChildren, it means the children is not created
342
+ // via calling the "createChildren" method, so it can only be a SyntaxList. As SyntaxList cannot have jsDocCommentChildren
343
+ // anyways, we can just return its children.
344
+ return this . _nonJsDocCommentChildren ? this . _nonJsDocCommentChildren : this . _children ;
345
+ }
346
+
326
347
public getFirstToken ( sourceFile ?: SourceFile ) : Node {
327
348
const children = this . getChildren ( sourceFile ) ;
328
349
if ( ! children . length ) {
@@ -7725,7 +7746,7 @@ namespace ts {
7725
7746
if ( decodedTextSpanIntersectsWith ( spanStart , spanLength , element . pos , element . getFullWidth ( ) ) ) {
7726
7747
checkForClassificationCancellation ( element . kind ) ;
7727
7748
7728
- const children = element . getChildren ( sourceFile ) ;
7749
+ const children = element . getNonJsDocCommentChildren ? element . getNonJsDocCommentChildren ( sourceFile ) : element . getChildren ( sourceFile ) ;
7729
7750
for ( let i = 0 , n = children . length ; i < n ; i ++ ) {
7730
7751
const child = children [ i ] ;
7731
7752
if ( ! tryClassifyNode ( child ) ) {
0 commit comments