Skip to content

Commit

Permalink
Don't cache child lists for tokens (#58233)
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielRosenwasser committed Apr 19, 2024
1 parent aedd1b1 commit e8f2225
Show file tree
Hide file tree
Showing 8 changed files with 21 additions and 19 deletions.
14 changes: 10 additions & 4 deletions src/compiler/factory/nodeChildren.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { Node } from "../_namespaces/ts";
import {
emptyArray,
isNodeKind,
Node,
} from "../_namespaces/ts";

const nodeChildren = new WeakMap<Node, Node[] | undefined>();
const nodeChildren = new WeakMap<Node, readonly Node[] | undefined>();

/** @internal */
export function getNodeChildren(node: Node): Node[] | undefined {
export function getNodeChildren(node: Node): readonly Node[] | undefined {
if (!isNodeKind(node.kind)) return emptyArray;

return nodeChildren.get(node);
}

/** @internal */
export function setNodeChildren(node: Node, children: Node[]): Node[] {
export function setNodeChildren(node: Node, children: readonly Node[]): readonly Node[] {
nodeChildren.set(node, children);
return children;
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/factory/nodeFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6209,7 +6209,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
}

// @api
function createSyntaxList(children: Node[]) {
function createSyntaxList(children: readonly Node[]) {
const node = createBaseNode<SyntaxList>(SyntaxKind.SyntaxList);
setNodeChildren(node, children);
return node;
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9006,7 +9006,7 @@ export interface NodeFactory {
// Synthetic Nodes
//
/** @internal */ createSyntheticExpression(type: Type, isSpread?: boolean, tupleNameSource?: ParameterDeclaration | NamedTupleMember): SyntheticExpression;
/** @internal */ createSyntaxList(children: Node[]): SyntaxList;
/** @internal */ createSyntaxList(children: readonly Node[]): SyntaxList;

//
// Transformation nodes
Expand Down
8 changes: 2 additions & 6 deletions src/services/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ class NodeObject<TKind extends SyntaxKind> implements Node {
return this.getChildren(sourceFile)[index];
}

public getChildren(sourceFile?: SourceFileLike): Node[] {
public getChildren(sourceFile?: SourceFileLike): readonly Node[] {
this.assertHasRealPosition("Node without a real position cannot be scanned and thus has no token nodes - use forEachChild and collect the result if that's fine");
return getNodeChildren(this) ?? setNodeChildren(this, createChildren(this, sourceFile));
}
Expand Down Expand Up @@ -473,11 +473,7 @@ class NodeObject<TKind extends SyntaxKind> implements Node {
}
}

function createChildren(node: Node, sourceFile: SourceFileLike | undefined): Node[] {
if (!isNodeKind(node.kind)) {
return emptyArray;
}

function createChildren(node: Node, sourceFile: SourceFileLike | undefined): readonly Node[] {
const children: Node[] = [];

if (isJSDocCommentContainingNode(node)) {
Expand Down
6 changes: 3 additions & 3 deletions src/services/smartSelection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ function getSelectionChildren(node: Node): readonly Node[] {
* Groups sibling nodes together into their own SyntaxList if they
* a) are adjacent, AND b) match a predicate function.
*/
function groupChildren(children: Node[], groupOn: (child: Node) => boolean): Node[] {
function groupChildren(children: readonly Node[], groupOn: (child: Node) => boolean): Node[] {
const result: Node[] = [];
let group: Node[] | undefined;
for (const child of children) {
Expand Down Expand Up @@ -315,7 +315,7 @@ function groupChildren(children: Node[], groupOn: (child: Node) => boolean): Nod
* @param separateTrailingSemicolon If the last token is a semicolon, it will be returned as a separate
* child rather than be included in the right-hand group.
*/
function splitChildren(children: Node[], pivotOn: (child: Node) => boolean, separateTrailingSemicolon = true): Node[] {
function splitChildren(children: readonly Node[], pivotOn: (child: Node) => boolean, separateTrailingSemicolon = true): readonly Node[] {
if (children.length < 2) {
return children;
}
Expand All @@ -336,7 +336,7 @@ function splitChildren(children: Node[], pivotOn: (child: Node) => boolean, sepa
return separateLastToken ? result.concat(lastToken) : result;
}

function createSyntaxList(children: Node[]): SyntaxList {
function createSyntaxList(children: readonly Node[]): SyntaxList {
Debug.assertGreaterThanOrEqual(children.length, 1);
return setTextRangePosEnd(parseNodeFactory.createSyntaxList(children), children[0].pos, last(children).end);
}
Expand Down
4 changes: 2 additions & 2 deletions src/services/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ declare module "../compiler/types" {
getSourceFile(): SourceFile;
getChildCount(sourceFile?: SourceFile): number;
getChildAt(index: number, sourceFile?: SourceFile): Node;
getChildren(sourceFile?: SourceFile): Node[];
getChildren(sourceFile?: SourceFile): readonly Node[];
/** @internal */
getChildren(sourceFile?: SourceFileLike): Node[]; // eslint-disable-line @typescript-eslint/unified-signatures
getChildren(sourceFile?: SourceFileLike): readonly Node[]; // eslint-disable-line @typescript-eslint/unified-signatures
getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number;
/** @internal */
getStart(sourceFile?: SourceFileLike, includeJsDocComment?: boolean): number; // eslint-disable-line @typescript-eslint/unified-signatures
Expand Down
2 changes: 1 addition & 1 deletion src/services/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1830,7 +1830,7 @@ function findRightmostToken(n: Node, sourceFile: SourceFileLike): Node | undefin
/**
* Finds the rightmost child to the left of `children[exclusiveStartPosition]` which is a non-all-whitespace token or has constituent tokens.
*/
function findRightmostChildNodeWithTokens(children: Node[], exclusiveStartPosition: number, sourceFile: SourceFileLike, parentKind: SyntaxKind): Node | undefined {
function findRightmostChildNodeWithTokens(children: readonly Node[], exclusiveStartPosition: number, sourceFile: SourceFileLike, parentKind: SyntaxKind): Node | undefined {
for (let i = exclusiveStartPosition - 1; i >= 0; i--) {
const child = children[i];

Expand Down
2 changes: 1 addition & 1 deletion tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4215,7 +4215,7 @@ declare namespace ts {
getSourceFile(): SourceFile;
getChildCount(sourceFile?: SourceFile): number;
getChildAt(index: number, sourceFile?: SourceFile): Node;
getChildren(sourceFile?: SourceFile): Node[];
getChildren(sourceFile?: SourceFile): readonly Node[];
getStart(sourceFile?: SourceFile, includeJsDocComment?: boolean): number;
getFullStart(): number;
getEnd(): number;
Expand Down

0 comments on commit e8f2225

Please sign in to comment.