/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ import { EventEmitter, Event, Disposable } from 'vscode'; export function filterEvent(event: Event, filter: (e: T) => boolean): Event { return (listener, thisArgs = null, disposables?) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables); } export function onceEvent(event: Event): Event { return (listener, thisArgs = null, disposables?) => { const result = event(e => { result.dispose(); return listener.call(thisArgs, e); }, null, disposables); return result; }; } export interface PromiseAdapter { ( value: T, resolve: (value: U | PromiseLike) => void, reject: (reason: any) => void ): any; } const passthrough = (value: any, resolve: (value?: any) => void) => resolve(value); /** * Return a promise that resolves with the next emitted event, or with some future * event as decided by an adapter. * * If specified, the adapter is a function that will be called with * `(event, resolve, reject)`. It will be called once per event until it resolves or * rejects. * * The default adapter is the passthrough function `(value, resolve) => resolve(value)`. * * @param event the event * @param adapter controls resolution of the returned promise * @returns a promise that resolves or rejects as specified by the adapter */ export function promiseFromEvent( event: Event, adapter: PromiseAdapter = passthrough): { promise: Promise, cancel: EventEmitter } { let subscription: Disposable; let cancel = new EventEmitter(); return { promise: new Promise((resolve, reject) => { cancel.event(_ => reject()); subscription = event((value: T) => { try { Promise.resolve(adapter(value, resolve, reject)) .catch(reject); } catch (error) { reject(error); } }); }).then( (result: U) => { subscription.dispose(); return result; }, error => { subscription.dispose(); throw error; } ), cancel }; } export function arrayEquals(one: ReadonlyArray | undefined, other: ReadonlyArray | undefined, itemEquals: (a: T, b: T) => boolean = (a, b) => a === b): boolean { if (one === other) { return true; } if (!one || !other) { return false; } if (one.length !== other.length) { return false; } for (let i = 0, len = one.length; i < len; i++) { if (!itemEquals(one[i], other[i])) { return false; } } return true; }