Moves out Comparator logic from inline completions to arrays.ts.

This commit is contained in:
Henning Dieterichs 2021-12-08 12:41:52 +01:00
parent 258ca4f8a2
commit e3544ad159
No known key found for this signature in database
GPG key ID: 771381EFFDB9EC06
4 changed files with 60 additions and 22 deletions

View file

@ -625,6 +625,46 @@ export function maxIndex<T>(array: readonly T[], fn: (value: T) => number): numb
return maxIdx;
}
/**
* A comparator `c` defines a total order `<=` on `T` as following:
* `c(a, b) <= 0` iff `a` <= `b`.
* We also have `c(a, b) == 0` iff `c(b, a) == 0`.
*/
export type Comparator<T> = (a: T, b: T) => number;
export function compareBy<TItem, TCompareBy>(selector: (item: TItem) => TCompareBy, comparator: Comparator<TCompareBy>): Comparator<TItem> {
return (a, b) => comparator(selector(a), selector(b));
}
/**
* The natural order on numbers.
*/
export const numberComparator: Comparator<number> = (a, b) => a - b;
/**
* Returns the first item that is equal to or greater than every other item.
*/
export function findMaxBy<T>(items: readonly T[], comparator: Comparator<T>): T | undefined {
if (items.length === 0) {
return undefined;
}
let min = items[0];
for (const item of items) {
if (comparator(item, min) > 0) {
min = item;
}
}
return min;
}
/**
* Returns the first item that is equal to or less than every other item.
*/
export function findMinBy<T>(items: readonly T[], comparator: Comparator<T>): T | undefined {
return findMaxBy(items, (a, b) => -comparator(a, b));
}
export class ArrayQueue<T> {
private firstIdx = 0;
private lastIdx = this.items.length - 1;

View file

@ -354,6 +354,24 @@ suite('Arrays', () => {
assert.strictEqual(arrays.maxIndex(array, value => value === 'b' ? 5 : 0), 1);
});
test('findMaxBy', () => {
const array = [{ v: 3 }, { v: 5 }, { v: 2 }, { v: 2 }, { v: 2 }, { v: 5 }];
assert.strictEqual(
array.indexOf(arrays.findMaxBy(array, arrays.compareBy(v => v.v, arrays.numberComparator))!),
1
);
});
test('findMinBy', () => {
const array = [{ v: 3 }, { v: 5 }, { v: 2 }, { v: 2 }, { v: 2 }, { v: 5 }];
assert.strictEqual(
array.indexOf(arrays.findMinBy(array, arrays.compareBy(v => v.v, arrays.numberComparator))!),
2
);
});
suite('ArrayQueue', () => {
suite('takeWhile/takeFromEndWhile', () => {
test('TakeWhile 1', () => {

View file

@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { compareBy, findMaxBy, numberComparator } from 'vs/base/common/arrays';
import { RunOnceScheduler } from 'vs/base/common/async';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
@ -16,7 +17,6 @@ import { CompletionItem } from 'vs/editor/contrib/suggest/suggest';
import { SuggestController } from 'vs/editor/contrib/suggest/suggestController';
import { minimizeInlineCompletion } from './inlineCompletionsModel';
import { NormalizedInlineCompletion, normalizedInlineCompletionsEquals } from './inlineCompletionToGhostText';
import { compareBy, compareByNumber, findMaxBy } from './utils';
export interface SuggestWidgetState {
/**
@ -108,7 +108,7 @@ export class SuggestWidgetInlineCompletionProvider extends Disposable {
const result = findMaxBy(
candidates,
compareBy(s => s!.prefixLength, compareByNumber())
compareBy(s => s!.prefixLength, numberComparator)
);
return result ? result.index : - 1;
}

View file

@ -11,23 +11,3 @@ export function createDisposableRef<T>(object: T, disposable?: IDisposable): IRe
dispose: () => disposable?.dispose(),
};
}
export type Comparator<T> = (a: T, b: T) => number;
export function compareBy<TItem, TCompareBy>(selector: (item: TItem) => TCompareBy, comparator: Comparator<TCompareBy>): Comparator<TItem> {
return (a, b) => comparator(selector(a), selector(b));
}
export function compareByNumber(): Comparator<number> {
return (a, b) => a - b;
}
export function findMaxBy<T>(items: T[], comparator: Comparator<T>): T | undefined {
let min: T | undefined = undefined;
for (const item of items) {
if (min === undefined || comparator(item, min) > 0) {
min = item;
}
}
return min;
}