Skip to content

Commit d24afc2

Browse files
committed
Return non-JsDocComment children
... to make syntactic classification work
1 parent 09bc2e6 commit d24afc2

File tree

1 file changed

+29
-8
lines changed

1 file changed

+29
-8
lines changed

src/services/services.ts

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace ts {
2121
getChildCount(sourceFile?: SourceFile): number;
2222
getChildAt(index: number, sourceFile?: SourceFile): Node;
2323
getChildren(sourceFile?: SourceFile): Node[];
24+
getNonJsDocCommentChildren?(sourceFile?: SourceFile): Node[];
2425
getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number;
2526
getFullStart(): number;
2627
getEnd(): number;
@@ -196,6 +197,7 @@ namespace ts {
196197
public parent: Node;
197198
public jsDocComments: JSDocComment[];
198199
private _children: Node[];
200+
private _nonJsDocCommentChildren: Node[];
199201

200202
constructor(kind: SyntaxKind, pos: number, end: number) {
201203
this.pos = pos;
@@ -273,20 +275,22 @@ namespace ts {
273275
}
274276

275277
private createChildren(sourceFile?: SourceFile) {
276-
let children: Node[];
278+
let jsDocCommentChildren: Node[];
279+
let nonJsDocCommentChildren: Node[];
277280
if (this.kind >= SyntaxKind.FirstNode) {
278281
scanner.setText((sourceFile || this.getSourceFile()).text);
279-
children = [];
282+
jsDocCommentChildren = [];
283+
nonJsDocCommentChildren = [];
280284
let pos = this.pos;
281285
const useJSDocScanner = this.kind >= SyntaxKind.FirstJSDocTagNode && this.kind <= SyntaxKind.LastJSDocTagNode;
282-
const processNode = (node: Node) => {
286+
const processNode = (node: Node, children = nonJsDocCommentChildren) => {
283287
if (pos < node.pos) {
284288
pos = this.addSyntheticNodes(children, pos, node.pos, useJSDocScanner);
285289
}
286290
children.push(node);
287291
pos = node.end;
288292
};
289-
const processNodes = (nodes: NodeArray<Node>) => {
293+
const processNodes = (nodes: NodeArray<Node>, children = nonJsDocCommentChildren) => {
290294
if (pos < nodes.pos) {
291295
pos = this.addSyntheticNodes(children, pos, nodes.pos, useJSDocScanner);
292296
}
@@ -296,16 +300,21 @@ namespace ts {
296300
// jsDocComments need to be the first children
297301
if (this.jsDocComments) {
298302
for (const jsDocComment of this.jsDocComments) {
299-
processNode(jsDocComment);
303+
processNode(jsDocComment, jsDocCommentChildren);
300304
}
301305
}
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;
302310
forEachChild(this, processNode, processNodes);
303311
if (pos < this.end) {
304-
this.addSyntheticNodes(children, pos, this.end);
312+
this.addSyntheticNodes(nonJsDocCommentChildren, pos, this.end);
305313
}
306314
scanner.setText(undefined);
307315
}
308-
this._children = children || emptyArray;
316+
this._nonJsDocCommentChildren = nonJsDocCommentChildren || emptyArray;
317+
this._children = concatenate(jsDocCommentChildren, this._nonJsDocCommentChildren);
309318
}
310319

311320
public getChildCount(sourceFile?: SourceFile): number {
@@ -323,6 +332,18 @@ namespace ts {
323332
return this._children;
324333
}
325334

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+
326347
public getFirstToken(sourceFile?: SourceFile): Node {
327348
const children = this.getChildren(sourceFile);
328349
if (!children.length) {
@@ -7725,7 +7746,7 @@ namespace ts {
77257746
if (decodedTextSpanIntersectsWith(spanStart, spanLength, element.pos, element.getFullWidth())) {
77267747
checkForClassificationCancellation(element.kind);
77277748

7728-
const children = element.getChildren(sourceFile);
7749+
const children = element.getNonJsDocCommentChildren ? element.getNonJsDocCommentChildren(sourceFile) : element.getChildren(sourceFile);
77297750
for (let i = 0, n = children.length; i < n; i++) {
77307751
const child = children[i];
77317752
if (!tryClassifyNode(child)) {

0 commit comments

Comments
 (0)