Merge VS Code 1.31.1 (#4283)

This commit is contained in:
Matt Irvine
2019-03-15 13:09:45 -07:00
committed by GitHub
parent 7d31575149
commit 86bac90001
1716 changed files with 53308 additions and 48375 deletions

View File

@@ -19,9 +19,348 @@ export interface Event<T> {
export namespace Event {
const _disposable = { dispose() { } };
export const None: Event<any> = function () { return _disposable; };
/**
* Given an event, returns another event which only fires once.
*/
export function once<T>(event: Event<T>): Event<T> {
return (listener, thisArgs = null, disposables?) => {
// we need this, in case the event fires during the listener call
let didFire = false;
const result = event(e => {
if (didFire) {
return;
} else if (result) {
result.dispose();
} else {
didFire = true;
}
return listener.call(thisArgs, e);
}, null, disposables);
if (didFire) {
result.dispose();
}
return result;
};
}
/**
* Given an event and a `map` function, returns another event which maps each element
* throught the mapping function.
*/
export function map<I, O>(event: Event<I>, map: (i: I) => O): Event<O> {
return (listener, thisArgs = null, disposables?) => event(i => listener.call(thisArgs, map(i)), null, disposables);
}
/**
* Given an event and an `each` function, returns another identical event and calls
* the `each` function per each element.
*/
export function forEach<I>(event: Event<I>, each: (i: I) => void): Event<I> {
return (listener, thisArgs = null, disposables?) => event(i => { each(i); listener.call(thisArgs, i); }, null, disposables);
}
/**
* Given an event and a `filter` function, returns another event which emits those
* elements for which the `filter` function returns `true`.
*/
export function filter<T>(event: Event<T>, filter: (e: T) => boolean): Event<T>;
export function filter<T, R>(event: Event<T | R>, filter: (e: T | R) => e is R): Event<R>;
export function filter<T>(event: Event<T>, filter: (e: T) => boolean): Event<T> {
return (listener, thisArgs = null, disposables?) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables);
}
/**
* Given an event, returns the same event but typed as `Event<void>`.
*/
export function signal<T>(event: Event<T>): Event<void> {
return event as Event<any> as Event<void>;
}
/**
* Given a collection of events, returns a single event which emits
* whenever any of the provided events emit.
*/
export function any<T>(...events: Event<T>[]): Event<T> {
return (listener, thisArgs = null, disposables?) => combinedDisposable(events.map(event => event(e => listener.call(thisArgs, e), null, disposables)));
}
/**
* Given an event and a `merge` function, returns another event which maps each element
* and the cummulative result throught the `merge` function. Similar to `map`, but with memory.
*/
export function reduce<I, O>(event: Event<I>, merge: (last: O | undefined, event: I) => O, initial?: O): Event<O> {
let output: O | undefined = initial;
return map<I, O>(event, e => {
output = merge(output, e);
return output;
});
}
/**
* Debounces the provided event, given a `merge` function.
*
* @param event The input event.
* @param merge The reducing function.
* @param delay The debouncing delay in millis.
* @param leading Whether the event should fire in the leading phase of the timeout.
* @param leakWarningThreshold The leak warning threshold override.
*/
export function debounce<T>(event: Event<T>, merge: (last: T, event: T) => T, delay?: number, leading?: boolean, leakWarningThreshold?: number): Event<T>;
export function debounce<I, O>(event: Event<I>, merge: (last: O | undefined, event: I) => O, delay?: number, leading?: boolean, leakWarningThreshold?: number): Event<O>;
export function debounce<I, O>(event: Event<I>, merge: (last: O | undefined, event: I) => O, delay: number = 100, leading = false, leakWarningThreshold?: number): Event<O> {
let subscription: IDisposable;
let output: O | undefined = undefined;
let handle: any = undefined;
let numDebouncedCalls = 0;
const emitter = new Emitter<O>({
leakWarningThreshold,
onFirstListenerAdd() {
subscription = event(cur => {
numDebouncedCalls++;
output = merge(output, cur);
if (leading && !handle) {
emitter.fire(output);
}
clearTimeout(handle);
handle = setTimeout(() => {
let _output = output;
output = undefined;
handle = undefined;
if (!leading || numDebouncedCalls > 1) {
emitter.fire(_output!);
}
numDebouncedCalls = 0;
}, delay);
});
},
onLastListenerRemove() {
subscription.dispose();
}
});
return emitter.event;
}
/**
* Given an event, it returns another event which fires only once and as soon as
* the input event emits. The event data is the number of millis it took for the
* event to fire.
*/
export function stopwatch<T>(event: Event<T>): Event<number> {
const start = new Date().getTime();
return map(once(event), _ => new Date().getTime() - start);
}
/**
* Given an event, it returns another event which fires only when the event
* element changes.
*/
export function latch<T>(event: Event<T>): Event<T> {
let firstCall = true;
let cache: T;
return filter(event, value => {
let shouldEmit = firstCall || value !== cache;
firstCall = false;
cache = value;
return shouldEmit;
});
}
/**
* Buffers the provided event until a first listener comes
* along, at which point fire all the events at once and
* pipe the event from then on.
*
* ```typescript
* const emitter = new Emitter<number>();
* const event = emitter.event;
* const bufferedEvent = buffer(event);
*
* emitter.fire(1);
* emitter.fire(2);
* emitter.fire(3);
* // nothing...
*
* const listener = bufferedEvent(num => console.log(num));
* // 1, 2, 3
*
* emitter.fire(4);
* // 4
* ```
*/
export function buffer<T>(event: Event<T>, nextTick = false, _buffer: T[] = []): Event<T> {
let buffer: T[] | null = _buffer.slice();
let listener: IDisposable | null = event(e => {
if (buffer) {
buffer.push(e);
} else {
emitter.fire(e);
}
});
const flush = () => {
if (buffer) {
buffer.forEach(e => emitter.fire(e));
}
buffer = null;
};
const emitter = new Emitter<T>({
onFirstListenerAdd() {
if (!listener) {
listener = event(e => emitter.fire(e));
}
},
onFirstListenerDidAdd() {
if (buffer) {
if (nextTick) {
setTimeout(flush);
} else {
flush();
}
}
},
onLastListenerRemove() {
if (listener) {
listener.dispose();
}
listener = null;
}
});
return emitter.event;
}
/**
* Similar to `buffer` but it buffers indefinitely and repeats
* the buffered events to every new listener.
*/
export function echo<T>(event: Event<T>, nextTick = false, buffer: T[] = []): Event<T> {
buffer = buffer.slice();
event(e => {
buffer.push(e);
emitter.fire(e);
});
const flush = (listener: (e: T) => any, thisArgs?: any) => buffer.forEach(e => listener.call(thisArgs, e));
const emitter = new Emitter<T>({
onListenerDidAdd(emitter, listener: (e: T) => any, thisArgs?: any) {
if (nextTick) {
setTimeout(() => flush(listener, thisArgs));
} else {
flush(listener, thisArgs);
}
}
});
return emitter.event;
}
export interface IChainableEvent<T> {
event: Event<T>;
map<O>(fn: (i: T) => O): IChainableEvent<O>;
forEach(fn: (i: T) => void): IChainableEvent<T>;
filter(fn: (e: T) => boolean): IChainableEvent<T>;
reduce<R>(merge: (last: R | undefined, event: T) => R, initial?: R): IChainableEvent<R>;
latch(): IChainableEvent<T>;
on(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]): IDisposable;
once(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]): IDisposable;
}
class ChainableEvent<T> implements IChainableEvent<T> {
get event(): Event<T> { return this._event; }
constructor(private _event: Event<T>) { }
map<O>(fn: (i: T) => O): IChainableEvent<O> {
return new ChainableEvent(map(this._event, fn));
}
forEach(fn: (i: T) => void): IChainableEvent<T> {
return new ChainableEvent(forEach(this._event, fn));
}
filter(fn: (e: T) => boolean): IChainableEvent<T> {
return new ChainableEvent(filter(this._event, fn));
}
reduce<R>(merge: (last: R | undefined, event: T) => R, initial?: R): IChainableEvent<R> {
return new ChainableEvent(reduce(this._event, merge, initial));
}
latch(): IChainableEvent<T> {
return new ChainableEvent(latch(this._event));
}
on(listener: (e: T) => any, thisArgs: any, disposables: IDisposable[]) {
return this._event(listener, thisArgs, disposables);
}
once(listener: (e: T) => any, thisArgs: any, disposables: IDisposable[]) {
return once(this._event)(listener, thisArgs, disposables);
}
}
export function chain<T>(event: Event<T>): IChainableEvent<T> {
return new ChainableEvent(event);
}
export interface NodeEventEmitter {
on(event: string | symbol, listener: Function): this;
removeListener(event: string | symbol, listener: Function): this;
}
export function fromNodeEventEmitter<T>(emitter: NodeEventEmitter, eventName: string, map: (...args: any[]) => T = id => id): Event<T> {
const fn = (...args: any[]) => result.fire(map(...args));
const onFirstListenerAdd = () => emitter.on(eventName, fn);
const onLastListenerRemove = () => emitter.removeListener(eventName, fn);
const result = new Emitter<T>({ onFirstListenerAdd, onLastListenerRemove });
return result.event;
}
export function fromPromise<T = any>(promise: Promise<T>): Event<undefined> {
const emitter = new Emitter<undefined>();
let shouldEmit = false;
promise
.then(undefined, () => null)
.then(() => {
if (!shouldEmit) {
setTimeout(() => emitter.fire(undefined), 0);
} else {
emitter.fire(undefined);
}
});
shouldEmit = true;
return emitter.event;
}
export function toPromise<T>(event: Event<T>): Promise<T> {
return new Promise(c => once(event)(c));
}
}
type Listener = [Function, any] | Function;
type Listener<T> = [(e: T) => void, any] | ((e: T) => void);
export interface EmitterOptions {
onFirstListenerAdd?: Function;
@@ -80,7 +419,7 @@ class LeakageMonitor {
if (this._warnCountdown <= 0) {
// only warn on first exceed and then every time the limit
// is exceeded by 50% again
this._warnCountdown = threshold * .5;
this._warnCountdown = threshold * 0.5;
// find most frequent listener and print warning
let topStack: string;
@@ -128,12 +467,12 @@ export class Emitter<T> {
private static readonly _noop = function () { };
private readonly _options: EmitterOptions | undefined;
private readonly _leakageMon: LeakageMonitor | undefined;
private readonly _options?: EmitterOptions;
private readonly _leakageMon?: LeakageMonitor;
private _disposed: boolean = false;
private _event: Event<T> | undefined;
private _deliveryQueue: [Listener, (T | undefined)][] | undefined;
protected _listeners: LinkedList<Listener> | undefined;
private _event?: Event<T>;
private _deliveryQueue: [Listener<T>, T][];
protected _listeners?: LinkedList<Listener<T>>;
constructor(options?: EmitterOptions) {
this._options = options;
@@ -207,7 +546,7 @@ export class Emitter<T> {
* To be kept private to fire an event to
* subscribers
*/
fire(event?: T): any {
fire(event: T): void {
if (this._listeners) {
// put all [listener,event]-pairs into delivery queue
// then emit all event. an inner/nested event might be
@@ -251,14 +590,14 @@ export class Emitter<T> {
}
export interface IWaitUntil {
waitUntil(thenable: Thenable<any>): void;
waitUntil(thenable: Promise<any>): void;
}
export class AsyncEmitter<T extends IWaitUntil> extends Emitter<T> {
private _asyncDeliveryQueue: [Listener, T, Thenable<any>[]][];
private _asyncDeliveryQueue: [Listener<T>, T, Promise<any>[]][];
async fireAsync(eventFn: (thenables: Thenable<any>[], listener: Function) => T): Promise<void> {
async fireAsync(eventFn: (thenables: Promise<any>[], listener: Function) => T): Promise<void> {
if (!this._listeners) {
return;
}
@@ -271,7 +610,7 @@ export class AsyncEmitter<T extends IWaitUntil> extends Emitter<T> {
}
for (let iter = this._listeners.iterator(), e = iter.next(); !e.done; e = iter.next()) {
let thenables: Thenable<void>[] = [];
let thenables: Promise<void>[] = [];
this._asyncDeliveryQueue.push([e.value, eventFn(thenables, typeof e.value === 'function' ? e.value : e.value[0]), thenables]);
}
@@ -359,98 +698,6 @@ export class EventMultiplexer<T> implements IDisposable {
}
}
export function fromPromise<T =any>(promise: Thenable<T>): Event<T> {
const emitter = new Emitter<T>();
let shouldEmit = false;
promise
.then(undefined, () => null)
.then(() => {
if (!shouldEmit) {
setTimeout(() => emitter.fire(), 0);
} else {
emitter.fire();
}
});
shouldEmit = true;
return emitter.event;
}
export function toPromise<T>(event: Event<T>): Thenable<T> {
return new Promise(c => once(event)(c));
}
export function once<T>(event: Event<T>): Event<T> {
return (listener, thisArgs = null, disposables?) => {
// we need this, in case the event fires during the listener call
let didFire = false;
const result = event(e => {
if (didFire) {
return;
} else if (result) {
result.dispose();
} else {
didFire = true;
}
return listener.call(thisArgs, e);
}, null, disposables);
if (didFire) {
result.dispose();
}
return result;
};
}
export function anyEvent<T>(...events: Event<T>[]): Event<T> {
return (listener, thisArgs = null, disposables?) => combinedDisposable(events.map(event => event(e => listener.call(thisArgs, e), null, disposables)));
}
export function debounceEvent<T>(event: Event<T>, merger: (last: T, event: T) => T, delay?: number, leading?: boolean, leakWarningThreshold?: number): Event<T>;
export function debounceEvent<I, O>(event: Event<I>, merger: (last: O | undefined, event: I) => O, delay?: number, leading?: boolean, leakWarningThreshold?: number): Event<O>;
export function debounceEvent<I, O>(event: Event<I>, merger: (last: O | undefined, event: I) => O, delay: number = 100, leading = false, leakWarningThreshold?: number): Event<O> {
let subscription: IDisposable;
let output: O | undefined = undefined;
let handle: any = undefined;
let numDebouncedCalls = 0;
const emitter = new Emitter<O>({
leakWarningThreshold,
onFirstListenerAdd() {
subscription = event(cur => {
numDebouncedCalls++;
output = merger(output, cur);
if (leading && !handle) {
emitter.fire(output);
}
clearTimeout(handle);
handle = setTimeout(() => {
let _output = output;
output = undefined;
handle = undefined;
if (!leading || numDebouncedCalls > 1) {
emitter.fire(_output);
}
numDebouncedCalls = 0;
}, delay);
});
},
onLastListenerRemove() {
subscription.dispose();
}
});
return emitter.event;
}
/**
* The EventBufferer is useful in situations in which you want
* to delay firing your events during some code.
@@ -485,12 +732,12 @@ export class EventBufferer {
} else {
listener.call(thisArgs, i);
}
}, void 0, disposables);
}, undefined, disposables);
};
}
bufferEvents<R = void>(fn: () => R): R {
const buffer: Function[] = [];
const buffer: Array<() => R> = [];
this.buffers.push(buffer);
const r = fn();
this.buffers.pop();
@@ -499,169 +746,12 @@ export class EventBufferer {
}
}
export interface IChainableEvent<T> {
event: Event<T>;
map<O>(fn: (i: T) => O): IChainableEvent<O>;
forEach(fn: (i: T) => void): IChainableEvent<T>;
filter(fn: (e: T) => boolean): IChainableEvent<T>;
latch(): IChainableEvent<T>;
on(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]): IDisposable;
once(listener: (e: T) => any, thisArgs?: any, disposables?: IDisposable[]): IDisposable;
}
export function mapEvent<I, O>(event: Event<I>, map: (i: I) => O): Event<O> {
return (listener, thisArgs = null, disposables?) => event(i => listener.call(thisArgs, map(i)), null, disposables);
}
export function forEach<I>(event: Event<I>, each: (i: I) => void): Event<I> {
return (listener, thisArgs = null, disposables?) => event(i => { each(i); listener.call(thisArgs, i); }, null, disposables);
}
export function filterEvent<T>(event: Event<T>, filter: (e: T) => boolean): Event<T>;
export function filterEvent<T, R>(event: Event<T | R>, filter: (e: T | R) => e is R): Event<R>;
export function filterEvent<T>(event: Event<T>, filter: (e: T) => boolean): Event<T> {
return (listener, thisArgs = null, disposables?) => event(e => filter(e) && listener.call(thisArgs, e), null, disposables);
}
export function signalEvent<T>(event: Event<T>): Event<void> {
return event as Event<any> as Event<void>;
}
class ChainableEvent<T> implements IChainableEvent<T> {
get event(): Event<T> { return this._event; }
constructor(private _event: Event<T>) { }
map<O>(fn: (i: T) => O): IChainableEvent<O> {
return new ChainableEvent(mapEvent(this._event, fn));
}
forEach(fn: (i: T) => void): IChainableEvent<T> {
return new ChainableEvent(forEach(this._event, fn));
}
filter(fn: (e: T) => boolean): IChainableEvent<T> {
return new ChainableEvent(filterEvent(this._event, fn));
}
latch(): IChainableEvent<T> {
return new ChainableEvent(latch(this._event));
}
on(listener: (e: T) => any, thisArgs: any, disposables: IDisposable[]) {
return this._event(listener, thisArgs, disposables);
}
once(listener: (e: T) => any, thisArgs: any, disposables: IDisposable[]) {
return once(this._event)(listener, thisArgs, disposables);
}
}
export function chain<T>(event: Event<T>): IChainableEvent<T> {
return new ChainableEvent(event);
}
export function stopwatch<T>(event: Event<T>): Event<number> {
const start = new Date().getTime();
return mapEvent(once(event), _ => new Date().getTime() - start);
}
/**
* Buffers the provided event until a first listener comes
* along, at which point fire all the events at once and
* pipe the event from then on.
*
* ```typescript
* const emitter = new Emitter<number>();
* const event = emitter.event;
* const bufferedEvent = buffer(event);
*
* emitter.fire(1);
* emitter.fire(2);
* emitter.fire(3);
* // nothing...
*
* const listener = bufferedEvent(num => console.log(num));
* // 1, 2, 3
*
* emitter.fire(4);
* // 4
* ```
* A Relay is an event forwarder which functions as a replugabble event pipe.
* Once created, you can connect an input event to it and it will simply forward
* events from that input event through its own `event` property. The `input`
* can be changed at any point in time.
*/
export function buffer<T>(event: Event<T>, nextTick = false, _buffer: T[] = []): Event<T> {
let buffer: T[] | null = _buffer.slice();
let listener: IDisposable | null = event(e => {
if (buffer) {
buffer.push(e);
} else {
emitter.fire(e);
}
});
const flush = () => {
if (buffer) {
buffer.forEach(e => emitter.fire(e));
}
buffer = null;
};
const emitter = new Emitter<T>({
onFirstListenerAdd() {
if (!listener) {
listener = event(e => emitter.fire(e));
}
},
onFirstListenerDidAdd() {
if (buffer) {
if (nextTick) {
setTimeout(flush);
} else {
flush();
}
}
},
onLastListenerRemove() {
if (listener) {
listener.dispose();
}
listener = null;
}
});
return emitter.event;
}
/**
* Similar to `buffer` but it buffers indefinitely and repeats
* the buffered events to every new listener.
*/
export function echo<T>(event: Event<T>, nextTick = false, buffer: T[] = []): Event<T> {
buffer = buffer.slice();
event(e => {
buffer.push(e);
emitter.fire(e);
});
const flush = (listener: (e: T) => any, thisArgs?: any) => buffer.forEach(e => listener.call(thisArgs, e));
const emitter = new Emitter<T>({
onListenerDidAdd(emitter, listener: (e: T) => any, thisArgs?: any) {
if (nextTick) {
setTimeout(() => flush(listener, thisArgs));
} else {
flush(listener, thisArgs);
}
}
});
return emitter.event;
}
export class Relay<T> implements IDisposable {
private listening = false;
@@ -695,29 +785,3 @@ export class Relay<T> implements IDisposable {
this.emitter.dispose();
}
}
export interface NodeEventEmitter {
on(event: string | symbol, listener: Function): this;
removeListener(event: string | symbol, listener: Function): this;
}
export function fromNodeEventEmitter<T>(emitter: NodeEventEmitter, eventName: string, map: (...args: any[]) => T = id => id): Event<T> {
const fn = (...args: any[]) => result.fire(map(...args));
const onFirstListenerAdd = () => emitter.on(eventName, fn);
const onLastListenerRemove = () => emitter.removeListener(eventName, fn);
const result = new Emitter<T>({ onFirstListenerAdd, onLastListenerRemove });
return result.event;
}
export function latch<T>(event: Event<T>): Event<T> {
let firstCall = true;
let cache: T;
return filterEvent(event, value => {
let shouldEmit = firstCall || value !== cache;
firstCall = false;
cache = value;
return shouldEmit;
});
}