Merge from vscode 817eb6b0c720a4ecbc13c020afbbebfed667aa09 (#7356)

This commit is contained in:
Anthony Dresser
2019-09-24 21:36:17 -07:00
committed by GitHub
parent a29ae4d3b9
commit 6a6048d40f
541 changed files with 7045 additions and 7287 deletions

View File

@@ -11,6 +11,7 @@ export function getPathFromAmdModule(requirefn: typeof require, relativePath: st
/**
* Reference a resource that might be inlined.
* Do not inline icons that will be used by the native mac touchbar.
* Do not rename this method unless you adopt the build scripts.
*/
export function registerAndGetAmdImageURL(absolutePath: string): string {

View File

@@ -372,6 +372,12 @@ export function distinctES6<T>(array: ReadonlyArray<T>): T[] {
});
}
export function fromSet<T>(set: Set<T>): T[] {
const result: T[] = [];
set.forEach(o => result.push(o));
return result;
}
export function uniqueFilter<T>(keyFn: (t: T) => string): (t: T) => boolean {
const seen: { [key: string]: boolean; } = Object.create(null);
@@ -418,6 +424,12 @@ export function first<T>(array: ReadonlyArray<T>, fn: (item: T) => boolean, notF
return index < 0 ? notFoundValue : array[index];
}
export function firstOrDefault<T, NotFound = T>(array: ReadonlyArray<T>, notFoundValue: NotFound): T | NotFound;
export function firstOrDefault<T>(array: ReadonlyArray<T>): T | undefined;
export function firstOrDefault<T, NotFound = T>(array: ReadonlyArray<T>, notFoundValue?: NotFound): T | NotFound | undefined {
return array.length > 0 ? array[0] : notFoundValue;
}
export function commonPrefixLength<T>(one: ReadonlyArray<T>, other: ReadonlyArray<T>, equals: (a: T, b: T) => boolean = (a, b) => a === b): number {
let result = 0;

View File

@@ -97,6 +97,12 @@ export function fromMap<T>(original: Map<string, T>): IStringDictionary<T> {
return result;
}
export function mapValues<V>(map: Map<any, V>): V[] {
const result: V[] = [];
map.forEach(v => result.push(v));
return result;
}
export class SetMap<K, V> {
private map = new Map<K, Set<V>>();

View File

@@ -24,40 +24,64 @@ export function createDecorator(mapFn: (fn: Function, key: string) => Function):
};
}
export function memoize(target: any, key: string, descriptor: any) {
let fnKey: string | null = null;
let fn: Function | null = null;
let memoizeId = 0;
export function createMemoizer() {
const memoizeKeyPrefix = `$memoize${memoizeId++}`;
let self: any = undefined;
if (typeof descriptor.value === 'function') {
fnKey = 'value';
fn = descriptor.value;
const result = function memoize(target: any, key: string, descriptor: any) {
let fnKey: string | null = null;
let fn: Function | null = null;
if (fn!.length !== 0) {
console.warn('Memoize should only be used in functions with zero parameters');
}
} else if (typeof descriptor.get === 'function') {
fnKey = 'get';
fn = descriptor.get;
}
if (typeof descriptor.value === 'function') {
fnKey = 'value';
fn = descriptor.value;
if (!fn) {
throw new Error('not supported');
}
const memoizeKey = `$memoize$${key}`;
descriptor[fnKey!] = function (...args: any[]) {
if (!this.hasOwnProperty(memoizeKey)) {
Object.defineProperty(this, memoizeKey, {
configurable: false,
enumerable: false,
writable: false,
value: fn!.apply(this, args)
});
if (fn!.length !== 0) {
console.warn('Memoize should only be used in functions with zero parameters');
}
} else if (typeof descriptor.get === 'function') {
fnKey = 'get';
fn = descriptor.get;
}
return this[memoizeKey];
if (!fn) {
throw new Error('not supported');
}
const memoizeKey = `${memoizeKeyPrefix}:${key}`;
descriptor[fnKey!] = function (...args: any[]) {
self = this;
if (!this.hasOwnProperty(memoizeKey)) {
Object.defineProperty(this, memoizeKey, {
configurable: true,
enumerable: false,
writable: true,
value: fn!.apply(this, args)
});
}
return this[memoizeKey];
};
};
result.clear = () => {
if (typeof self === 'undefined') {
return;
}
Object.getOwnPropertyNames(self).forEach(property => {
if (property.indexOf(memoizeKeyPrefix) === 0) {
delete self[property];
}
});
};
return result;
}
export function memoize(target: any, key: string, descriptor: any) {
return createMemoizer()(target, key, descriptor);
}
export interface IDebouceReducer<T> {
@@ -87,4 +111,4 @@ export function debounce<T>(delay: number, reducer?: IDebouceReducer<T>, initial
}, delay);
};
});
}
}

View File

@@ -451,7 +451,7 @@ class LeakageMonitor {
* Sample:
class Document {
private _onDidChange = new Emitter<(value:string)=>any>();
private readonly _onDidChange = new Emitter<(value:string)=>any>();
public onDidChange = this._onDidChange.event;
@@ -808,7 +808,7 @@ export class Relay<T> implements IDisposable {
private inputEvent: Event<T> = Event.None;
private inputEventListener: IDisposable = Disposable.None;
private emitter = new Emitter<T>({
private readonly emitter = new Emitter<T>({
onFirstListenerDidAdd: () => {
this.listening = true;
this.inputEventListener = this.inputEvent(this.emitter.fire, this.emitter);

View File

@@ -11,7 +11,7 @@ export class HistoryNavigator<T> implements INavigator<T> {
private _limit: number;
private _navigator!: ArrayNavigator<T>;
constructor(history: T[] = [], limit: number = 10) {
constructor(history: readonly T[] = [], limit: number = 10) {
this._initialize(history);
this._limit = limit;
this._onChange();
@@ -62,7 +62,8 @@ export class HistoryNavigator<T> implements INavigator<T> {
private _onChange() {
this._reduceToLimit();
this._navigator = new ArrayNavigator(this._elements, 0, this._elements.length, this._elements.length);
const elements = this._elements;
this._navigator = new ArrayNavigator(elements, 0, elements.length, elements.length);
}
private _reduceToLimit() {
@@ -72,7 +73,7 @@ export class HistoryNavigator<T> implements INavigator<T> {
}
}
private _initialize(history: T[]): void {
private _initialize(history: readonly T[]): void {
this._history = new Set();
for (const entry of history) {
this._history.add(entry);

View File

@@ -18,6 +18,22 @@ export interface Iterator<T> {
next(): IteratorResult<T>;
}
interface NativeIteratorYieldResult<TYield> {
done?: false;
value: TYield;
}
interface NativeIteratorReturnResult<TReturn> {
done: true;
value: TReturn;
}
type NativeIteratorResult<T, TReturn = any> = NativeIteratorYieldResult<T> | NativeIteratorReturnResult<TReturn>;
export interface NativeIterator<T> {
next(): NativeIteratorResult<T>;
}
export module Iterator {
const _empty: Iterator<any> = {
next() {
@@ -56,6 +72,20 @@ export module Iterator {
};
}
export function fromNativeIterator<T>(it: NativeIterator<T>): Iterator<T> {
return {
next(): IteratorResult<T> {
const result = it.next();
if (result.done) {
return FIN;
}
return { done: false, value: result.value };
}
};
}
export function from<T>(elements: Iterator<T> | T[] | undefined): Iterator<T> {
if (!elements) {
return Iterator.empty();
@@ -160,12 +190,12 @@ export interface INextIterator<T> {
export class ArrayIterator<T> implements INextIterator<T> {
private items: T[];
private readonly items: readonly T[];
protected start: number;
protected end: number;
protected index: number;
constructor(items: T[], start: number = 0, end: number = items.length, index = start - 1) {
constructor(items: readonly T[], start: number = 0, end: number = items.length, index = start - 1) {
this.items = items;
this.start = start;
this.end = end;
@@ -193,7 +223,7 @@ export class ArrayIterator<T> implements INextIterator<T> {
export class ArrayNavigator<T> extends ArrayIterator<T> implements INavigator<T> {
constructor(items: T[], start: number = 0, end: number = items.length, index = start - 1) {
constructor(items: readonly T[], start: number = 0, end: number = items.length, index = start - 1) {
super(items, start, end, index);
}

View File

@@ -61,7 +61,7 @@ export interface IJSONSchema {
markdownDescription?: string; // VSCode extension
doNotSuggest?: boolean; // VSCode extension
allowComments?: boolean; // VSCode extension
allowsTrailingCommas?: boolean; // VSCode extension
allowTrailingCommas?: boolean; // VSCode extension
}
export interface IJSONSchemaMap {

View File

@@ -0,0 +1,191 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { memoize } from 'vs/base/common/decorators';
import * as paths from 'vs/base/common/path';
import { Iterator } from 'vs/base/common/iterator';
import { relativePath, joinPath } from 'vs/base/common/resources';
import { URI } from 'vs/base/common/uri';
import { mapValues } from 'vs/base/common/collections';
export interface ILeafNode<T, C = void> {
readonly uri: URI;
readonly relativePath: string;
readonly name: string;
readonly element: T;
readonly context: C;
}
export interface IBranchNode<T, C = void> {
readonly uri: URI;
readonly relativePath: string;
readonly name: string;
readonly size: number;
readonly children: Iterator<INode<T, C>>;
readonly parent: IBranchNode<T, C> | undefined;
readonly context: C;
get(childName: string): INode<T, C> | undefined;
}
export type INode<T, C> = IBranchNode<T, C> | ILeafNode<T, C>;
// Internals
class Node<C> {
@memoize
get name(): string { return paths.posix.basename(this.relativePath); }
constructor(readonly uri: URI, readonly relativePath: string, readonly context: C) { }
}
class BranchNode<T, C> extends Node<C> implements IBranchNode<T, C> {
private _children = new Map<string, BranchNode<T, C> | LeafNode<T, C>>();
get size(): number {
return this._children.size;
}
get children(): Iterator<BranchNode<T, C> | LeafNode<T, C>> {
return Iterator.fromArray(mapValues(this._children));
}
constructor(uri: URI, relativePath: string, context: C, readonly parent: IBranchNode<T, C> | undefined = undefined) {
super(uri, relativePath, context);
}
get(path: string): BranchNode<T, C> | LeafNode<T, C> | undefined {
return this._children.get(path);
}
set(path: string, child: BranchNode<T, C> | LeafNode<T, C>): void {
this._children.set(path, child);
}
delete(path: string): void {
this._children.delete(path);
}
}
class LeafNode<T, C> extends Node<C> implements ILeafNode<T, C> {
constructor(uri: URI, path: string, context: C, readonly element: T) {
super(uri, path, context);
}
}
function collect<T, C>(node: INode<T, C>, result: T[]): T[] {
if (ResourceTree.isBranchNode(node)) {
Iterator.forEach(node.children, child => collect(child, result));
} else {
result.push(node.element);
}
return result;
}
export class ResourceTree<T extends NonNullable<any>, C> {
readonly root: BranchNode<T, C>;
static isBranchNode<T, C>(obj: any): obj is IBranchNode<T, C> {
return obj instanceof BranchNode;
}
static getRoot<T, C>(node: IBranchNode<T, C>): IBranchNode<T, C> {
while (node.parent) {
node = node.parent;
}
return node;
}
static collect<T, C>(node: INode<T, C>): T[] {
return collect(node, []);
}
constructor(context: C, rootURI: URI = URI.file('/')) {
this.root = new BranchNode(rootURI, '', context);
}
add(uri: URI, element: T): void {
const key = relativePath(this.root.uri, uri) || uri.fsPath;
const parts = key.split(/[\\\/]/).filter(p => !!p);
let node = this.root;
let path = '';
for (let i = 0; i < parts.length; i++) {
const name = parts[i];
path = path + '/' + name;
let child = node.get(name);
if (!child) {
if (i < parts.length - 1) {
child = new BranchNode(joinPath(this.root.uri, path), path, this.root.context, node);
node.set(name, child);
} else {
child = new LeafNode(uri, path, this.root.context, element);
node.set(name, child);
return;
}
}
if (!(child instanceof BranchNode)) {
if (i < parts.length - 1) {
throw new Error('Inconsistent tree: can\'t override leaf with branch.');
}
// replace
node.set(name, new LeafNode(uri, path, this.root.context, element));
return;
} else if (i === parts.length - 1) {
throw new Error('Inconsistent tree: can\'t override branch with leaf.');
}
node = child;
}
}
delete(uri: URI): T | undefined {
const key = relativePath(this.root.uri, uri) || uri.fsPath;
const parts = key.split(/[\\\/]/).filter(p => !!p);
return this._delete(this.root, parts, 0);
}
private _delete(node: BranchNode<T, C>, parts: string[], index: number): T | undefined {
const name = parts[index];
const child = node.get(name);
if (!child) {
return undefined;
}
// not at end
if (index < parts.length - 1) {
if (child instanceof BranchNode) {
const result = this._delete(child, parts, index + 1);
if (typeof result !== 'undefined' && child.size === 0) {
node.delete(name);
}
return result;
} else {
throw new Error('Inconsistent tree: Expected a branch, found a leaf instead.');
}
}
//at end
if (child instanceof BranchNode) {
// TODO: maybe we can allow this
throw new Error('Inconsistent tree: Expected a leaf, found a branch instead.');
}
node.delete(name);
return child.element;
}
}

View File

@@ -24,11 +24,11 @@ export class Sequence<T> implements ISequence<T>, ISpliceable<T> {
readonly elements: T[] = [];
private _onDidSplice = new Emitter<ISplice<T>>();
private readonly _onDidSplice = new Emitter<ISplice<T>>();
readonly onDidSplice: Event<ISplice<T>> = this._onDidSplice.event;
splice(start: number, deleteCount: number, toInsert: T[] = []): void {
this.elements.splice(start, deleteCount, ...toInsert);
this._onDidSplice.fire({ start, deleteCount, toInsert });
}
}
}