Skip to content

Commit 4dc7e59

Browse files
authored
Merge pull request #40953 from weswigham/improve-completions-large-literal-perf
Improve the performance of requesting completions within a massive array literal
2 parents 21ea557 + d6af322 commit 4dc7e59

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

src/compiler/core.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,7 +1195,7 @@ namespace ts {
11951195
* @param keyComparer A callback used to compare two keys in a sorted array.
11961196
* @param offset An offset into `array` at which to start the search.
11971197
*/
1198-
export function binarySearchKey<T, U>(array: readonly T[], key: U, keySelector: (v: T) => U, keyComparer: Comparer<U>, offset?: number): number {
1198+
export function binarySearchKey<T, U>(array: readonly T[], key: U, keySelector: (v: T, i: number) => U, keyComparer: Comparer<U>, offset?: number): number {
11991199
if (!some(array)) {
12001200
return -1;
12011201
}
@@ -1204,7 +1204,7 @@ namespace ts {
12041204
let high = array.length - 1;
12051205
while (low <= high) {
12061206
const middle = low + ((high - low) >> 1);
1207-
const midKey = keySelector(array[middle]);
1207+
const midKey = keySelector(array[middle], middle);
12081208
switch (keyComparer(midKey, key)) {
12091209
case Comparison.LessThan:
12101210
low = middle + 1;

src/services/utilities.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1173,7 +1173,21 @@ namespace ts {
11731173
}
11741174

11751175
const children = n.getChildren(sourceFile);
1176-
for (let i = 0; i < children.length; i++) {
1176+
const i = binarySearchKey(children, position, (_, i) => i, (middle, _) => {
1177+
// This last callback is more of a selector than a comparator -
1178+
// `EqualTo` causes the `middle` result to be returned
1179+
// `GreaterThan` causes recursion on the left of the middle
1180+
// `LessThan` causes recursion on the right of the middle
1181+
if (position < children[middle].end) {
1182+
// first element whose end position is greater than the input position
1183+
if (!children[middle - 1] || position >= children[middle - 1].end) {
1184+
return Comparison.EqualTo;
1185+
}
1186+
return Comparison.GreaterThan;
1187+
}
1188+
return Comparison.LessThan;
1189+
});
1190+
if (i >= 0 && children[i]) {
11771191
const child = children[i];
11781192
// Note that the span of a node's tokens is [node.getStart(...), node.end).
11791193
// 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)