From 93cbd6f34f998862ac62358aa0634569c7c1d76a Mon Sep 17 00:00:00 2001 From: Kamil Monicz Date: Mon, 2 Feb 2026 13:09:59 +0100 Subject: [PATCH] Optimize TextRangeCollection.getItemContaining --- .../src/common/textRangeCollection.ts | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/packages/pyright-internal/src/common/textRangeCollection.ts b/packages/pyright-internal/src/common/textRangeCollection.ts index 7b0d256d1043..c74c9de004cd 100644 --- a/packages/pyright-internal/src/common/textRangeCollection.ts +++ b/packages/pyright-internal/src/common/textRangeCollection.ts @@ -97,10 +97,44 @@ export class TextRangeCollection { return -1; } - return getIndexContaining(this._items, position); + return getIndexContainingDense(this._items, position); } } +// Fast path for dense, start-sorted ranges: +// binary-search for the containing item, with an early-out +// when the position falls between adjacent ranges. +function getIndexContainingDense(arr: readonly T[], position: number): number { + let min = 0; + let max = arr.length - 1; + + while (min <= max) { + const mid = min + ((max - min) >> 1); + const item = arr[mid]; + + if (TextRange.contains(item, position)) { + return mid; + } + + if (position < item.start) { + max = mid - 1; + continue; + } + + const end = TextRange.getEnd(item); + + // If the position falls between this item's end and the next item's start, + // it isn't contained in any item. + if (mid < arr.length - 1 && end <= position && position < arr[mid + 1].start) { + return -1; + } + + min = mid + 1; + } + + return -1; +} + export function getIndexContaining( arr: (T | undefined)[], position: number,