Skip to content

Commit

Permalink
Merge pull request #40953 from weswigham/improve-completions-large-li…
Browse files Browse the repository at this point in the history
…teral-perf

Improve the performance of requesting completions within a massive array literal
  • Loading branch information
weswigham authored Oct 7, 2020
2 parents 21ea557 + d6af322 commit 4dc7e59
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 3 deletions.
4 changes: 2 additions & 2 deletions src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1195,7 +1195,7 @@ namespace ts {
* @param keyComparer A callback used to compare two keys in a sorted array.
* @param offset An offset into `array` at which to start the search.
*/
export function binarySearchKey<T, U>(array: readonly T[], key: U, keySelector: (v: T) => U, keyComparer: Comparer<U>, offset?: number): number {
export function binarySearchKey<T, U>(array: readonly T[], key: U, keySelector: (v: T, i: number) => U, keyComparer: Comparer<U>, offset?: number): number {
if (!some(array)) {
return -1;
}
Expand All @@ -1204,7 +1204,7 @@ namespace ts {
let high = array.length - 1;
while (low <= high) {
const middle = low + ((high - low) >> 1);
const midKey = keySelector(array[middle]);
const midKey = keySelector(array[middle], middle);
switch (keyComparer(midKey, key)) {
case Comparison.LessThan:
low = middle + 1;
Expand Down
16 changes: 15 additions & 1 deletion src/services/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1173,7 +1173,21 @@ namespace ts {
}

const children = n.getChildren(sourceFile);
for (let i = 0; i < children.length; i++) {
const i = binarySearchKey(children, position, (_, i) => i, (middle, _) => {
// This last callback is more of a selector than a comparator -
// `EqualTo` causes the `middle` result to be returned
// `GreaterThan` causes recursion on the left of the middle
// `LessThan` causes recursion on the right of the middle
if (position < children[middle].end) {
// first element whose end position is greater than the input position
if (!children[middle - 1] || position >= children[middle - 1].end) {
return Comparison.EqualTo;
}
return Comparison.GreaterThan;
}
return Comparison.LessThan;
});
if (i >= 0 && children[i]) {
const child = children[i];
// Note that the span of a node's tokens is [node.getStart(...), node.end).
// Given that `position < child.end` and child has constituent tokens, we distinguish these cases:
Expand Down
19 changes: 19 additions & 0 deletions tests/cases/fourslash/excessivelyLargeArrayLiteralCompletions.ts

Large diffs are not rendered by default.

0 comments on commit 4dc7e59

Please sign in to comment.