Skip to content

Commit da57f98

Browse files
committed
Improve the performance of requesting completions within a massive array literal
1 parent 1191e2e commit da57f98

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

src/services/utilities.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1158,6 +1158,35 @@ namespace ts {
11581158
}
11591159
}
11601160

1161+
/**
1162+
* Psuedo-binary searches the list of children for the first element whose end position exceeds the input position
1163+
* Returns `undefined` if no element satisfies the condition, or the index of the satisfying element otherwise.
1164+
* This could probably be written using our `binarySeach` helper, but the `keyComparator` would be hairy enough
1165+
* that it's probably worth just writing out the algorithm in full.
1166+
* @param {number} start - Start search index, inclusive
1167+
* @param {number} end - End search index, inclusive
1168+
*/
1169+
function searchChildrenSlice(position: number, children: Node[], start = 0, end = children.length - 1): number | undefined {
1170+
const pivot = Math.floor((end - start)/2) + start;
1171+
if (!children[pivot]) {
1172+
return undefined;
1173+
}
1174+
if (position < children[pivot].end) {
1175+
// first element whose end position is greater than the input position
1176+
if (!children[pivot - 1] || position >= children[pivot - 1].end) {
1177+
return pivot;
1178+
}
1179+
if (pivot === start) {
1180+
return undefined;
1181+
}
1182+
return searchChildrenSlice(position, children, start, pivot - 1);
1183+
}
1184+
if (pivot === end) {
1185+
return undefined;
1186+
}
1187+
return searchChildrenSlice(position, children, pivot + 1, end);
1188+
}
1189+
11611190
/**
11621191
* Finds the rightmost token satisfying `token.end <= position`,
11631192
* excluding `JsxText` tokens containing only whitespace.
@@ -1173,7 +1202,8 @@ namespace ts {
11731202
}
11741203

11751204
const children = n.getChildren(sourceFile);
1176-
for (let i = 0; i < children.length; i++) {
1205+
const i = searchChildrenSlice(position, children);
1206+
if (typeof i !== "undefined") {
11771207
const child = children[i];
11781208
// Note that the span of a node's tokens is [node.getStart(...), node.end).
11791209
// Given that `position < child.end` and child has constituent tokens, we distinguish these cases:

tests/cases/fourslash/excessivelyLargeArrayLiteralCompletions.ts

Lines changed: 19 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)