Merge from vscode 2b0b9136329c181a9e381463a1f7dc3a2d105a34 (#4880)

This commit is contained in:
Karl Burtram
2019-04-05 10:09:18 -07:00
committed by GitHub
parent 9bd7e30d18
commit cb5bcf2248
433 changed files with 8915 additions and 8361 deletions

View File

@@ -659,19 +659,6 @@ export class RunOnceWorker<T> extends RunOnceScheduler {
}
}
export function nfcall(fn: Function, ...args: any[]): Promise<any>;
export function nfcall<T>(fn: Function, ...args: any[]): Promise<T>;
export function nfcall(fn: Function, ...args: any[]): any {
return new Promise((c, e) => fn(...args, (err: any, result: any) => err ? e(err) : c(result)));
}
export function ninvoke(thisArg: any, fn: Function, ...args: any[]): Promise<any>;
export function ninvoke<T>(thisArg: any, fn: Function, ...args: any[]): Promise<T>;
export function ninvoke(thisArg: any, fn: Function, ...args: any[]): any {
return new Promise((resolve, reject) => fn.call(thisArg, ...args, (err: any, result: any) => err ? reject(err) : resolve(result)));
}
//#region -- run on idle tricks ------------
export interface IdleDeadline {

View File

@@ -6,6 +6,9 @@
declare var Buffer: any;
const hasBuffer = (typeof Buffer !== 'undefined');
let textEncoder: TextEncoder | null;
let textDecoder: TextDecoder | null;
export class VSBuffer {
public static alloc(byteLength: number): VSBuffer {
@@ -21,7 +24,14 @@ export class VSBuffer {
}
public static fromString(source: string): VSBuffer {
return new VSBuffer(Buffer.from(source));
if (hasBuffer) {
return new VSBuffer(Buffer.from(source));
} else {
if (!textEncoder) {
textEncoder = new TextEncoder();
}
return new VSBuffer(textEncoder.encode(source));
}
}
public static concat(buffers: VSBuffer[], totalLength?: number): VSBuffer {
@@ -52,7 +62,14 @@ export class VSBuffer {
}
public toString(): string {
return this.buffer.toString();
if (hasBuffer) {
return this.buffer.toString();
} else {
if (!textDecoder) {
textDecoder = new TextDecoder();
}
return textDecoder.decode(this.buffer);
}
}
public slice(start?: number, end?: number): VSBuffer {

View File

@@ -87,7 +87,12 @@ class MutableToken implements CancellationToken {
export class CancellationTokenSource {
private _token?: CancellationToken;
private _token?: CancellationToken = undefined;
private _parentListener?: IDisposable = undefined;
constructor(parent?: CancellationToken) {
this._parentListener = parent && parent.onCancellationRequested(this.cancel, this);
}
get token(): CancellationToken {
if (!this._token) {
@@ -112,6 +117,9 @@ export class CancellationTokenSource {
}
dispose(): void {
if (this._parentListener) {
this._parentListener.dispose();
}
if (!this._token) {
// ensure to initialize with an empty token if we had none
this._token = CancellationToken.None;

View File

@@ -130,7 +130,7 @@ export namespace Event {
* @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<T>(event: Event<T>, merge: (last: T | undefined, 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> {
@@ -488,7 +488,7 @@ export class Emitter<T> {
private readonly _leakageMon?: LeakageMonitor;
private _disposed: boolean = false;
private _event?: Event<T>;
private _deliveryQueue: [Listener<T>, T][];
private _deliveryQueue?: LinkedList<[Listener<T>, T]>;
protected _listeners?: LinkedList<Listener<T>>;
constructor(options?: EmitterOptions) {
@@ -570,14 +570,14 @@ export class Emitter<T> {
// the driver of this
if (!this._deliveryQueue) {
this._deliveryQueue = [];
this._deliveryQueue = new LinkedList();
}
for (let iter = this._listeners.iterator(), e = iter.next(); !e.done; e = iter.next()) {
this._deliveryQueue.push([e.value, event]);
}
while (this._deliveryQueue.length > 0) {
while (this._deliveryQueue.size > 0) {
const [listener, event] = this._deliveryQueue.shift()!;
try {
if (typeof listener === 'function') {
@@ -594,10 +594,10 @@ export class Emitter<T> {
dispose() {
if (this._listeners) {
this._listeners = undefined;
this._listeners.clear();
}
if (this._deliveryQueue) {
this._deliveryQueue.length = 0;
this._deliveryQueue.clear();
}
if (this._leakageMon) {
this._leakageMon.dispose();
@@ -606,6 +606,51 @@ export class Emitter<T> {
}
}
export class PauseableEmitter<T> extends Emitter<T> {
private _isPaused = 0;
private _eventQueue = new LinkedList<T>();
private _mergeFn?: (input: T[]) => T;
constructor(options?: EmitterOptions & { merge?: (input: T[]) => T }) {
super(options);
this._mergeFn = options && options.merge;
}
pause(): void {
this._isPaused++;
}
resume(): void {
if (this._isPaused !== 0 && --this._isPaused === 0) {
if (this._mergeFn) {
// use the merge function to create a single composite
// event. make a copy in case firing pauses this emitter
const events = this._eventQueue.toArray();
this._eventQueue.clear();
super.fire(this._mergeFn(events));
} else {
// no merging, fire each event individually and test
// that this emitter isn't paused halfway through
while (!this._isPaused && this._eventQueue.size !== 0) {
super.fire(this._eventQueue.shift()!);
}
}
}
}
fire(event: T): void {
if (this._listeners) {
if (this._isPaused !== 0) {
this._eventQueue.push(event);
} else {
super.fire(event);
}
}
}
}
export interface IWaitUntil {
waitUntil(thenable: Promise<any>): void;
}

View File

@@ -4,9 +4,9 @@
*--------------------------------------------------------------------------------------------*/
import { isWindows } from 'vs/base/common/platform';
import { startsWithIgnoreCase, equalsIgnoreCase } from 'vs/base/common/strings';
import { startsWithIgnoreCase, equalsIgnoreCase, endsWith, rtrim } from 'vs/base/common/strings';
import { CharCode } from 'vs/base/common/charCode';
import { sep, posix } from 'vs/base/common/path';
import { sep, posix, isAbsolute, join, normalize } from 'vs/base/common/path';
function isPathSeparator(code: number) {
return code === CharCode.Slash || code === CharCode.Backslash;
@@ -227,4 +227,56 @@ export function isEqualOrParent(path: string, candidate: string, ignoreCase?: bo
export function isWindowsDriveLetter(char0: number): boolean {
return char0 >= CharCode.A && char0 <= CharCode.Z || char0 >= CharCode.a && char0 <= CharCode.z;
}
export function sanitizeFilePath(candidate: string, cwd: string): string {
// Special case: allow to open a drive letter without trailing backslash
if (isWindows && endsWith(candidate, ':')) {
candidate += sep;
}
// Ensure absolute
if (!isAbsolute(candidate)) {
candidate = join(cwd, candidate);
}
// Ensure normalized
candidate = normalize(candidate);
// Ensure no trailing slash/backslash
if (isWindows) {
candidate = rtrim(candidate, sep);
// Special case: allow to open drive root ('C:\')
if (endsWith(candidate, ':')) {
candidate += sep;
}
} else {
candidate = rtrim(candidate, sep);
// Special case: allow to open root ('/')
if (!candidate) {
candidate = sep;
}
}
return candidate;
}
export function isRootOrDriveLetter(path: string): boolean {
const pathNormalized = normalize(path);
if (isWindows) {
if (path.length > 3) {
return false;
}
return isWindowsDriveLetter(pathNormalized.charCodeAt(0))
&& pathNormalized.charCodeAt(1) === CharCode.Colon
&& (path.length === 2 || pathNormalized.charCodeAt(2) === CharCode.Backslash);
}
return pathNormalized === posix.sep;
}

View File

@@ -12,7 +12,7 @@ import { CharCode } from 'vs/base/common/charCode';
import { isThenable } from 'vs/base/common/async';
export interface IExpression {
[pattern: string]: boolean | SiblingClause | any;
[pattern: string]: boolean | SiblingClause;
}
export interface IRelativePattern {
@@ -429,7 +429,7 @@ function toRegExp(pattern: string): ParsedStringPattern {
*/
export function match(pattern: string | IRelativePattern, path: string): boolean;
export function match(expression: IExpression, path: string, hasSibling?: (name: string) => boolean): string /* the matching pattern */;
export function match(arg1: string | IExpression | IRelativePattern, path: string, hasSibling?: (name: string) => boolean): any {
export function match(arg1: string | IExpression | IRelativePattern, path: string, hasSibling?: (name: string) => boolean): boolean | string | null | Promise<string | null> {
if (!arg1 || typeof path !== 'string') {
return false;
}
@@ -447,14 +447,14 @@ export function match(arg1: string | IExpression | IRelativePattern, path: strin
*/
export function parse(pattern: string | IRelativePattern, options?: IGlobOptions): ParsedPattern;
export function parse(expression: IExpression, options?: IGlobOptions): ParsedExpression;
export function parse(arg1: string | IExpression | IRelativePattern, options: IGlobOptions = {}): any {
export function parse(arg1: string | IExpression | IRelativePattern, options: IGlobOptions = {}): ParsedPattern | ParsedExpression {
if (!arg1) {
return FALSE;
}
// Glob with String
if (typeof arg1 === 'string' || isRelativePattern(arg1)) {
const parsedPattern = parsePattern(arg1 as string | IRelativePattern, options);
const parsedPattern = parsePattern(arg1, options);
if (parsedPattern === NULL) {
return FALSE;
}
@@ -512,23 +512,12 @@ function listToMap(list: string[]) {
return map;
}
export function isRelativePattern(obj: any): obj is IRelativePattern {
export function isRelativePattern(obj: unknown): obj is IRelativePattern {
const rp = obj as IRelativePattern;
return rp && typeof rp.base === 'string' && typeof rp.pattern === 'string';
}
/**
* Same as `parse`, but the ParsedExpression is guaranteed to return a Promise
*/
export function parseToAsync(expression: IExpression, options?: IGlobOptions): ParsedExpression {
const parsedExpression = parse(expression, options);
return (path: string, basename?: string, hasSibling?: (name: string) => boolean | Promise<boolean>): string | null | Promise<string | null> => {
const result = parsedExpression(path, basename, hasSibling);
return isThenable(result) ? result : Promise.resolve(result);
};
}
export function getBasenameTerms(patternOrExpression: ParsedPattern | ParsedExpression): string[] {
return (<ParsedStringPattern>patternOrExpression).allBasenames || [];
}
@@ -613,7 +602,7 @@ function parsedExpression(expression: IExpression, options: IGlobOptions): Parse
return resultExpression;
}
function parseExpressionPattern(pattern: string, value: any, options: IGlobOptions): (ParsedStringPattern | ParsedExpressionPattern) {
function parseExpressionPattern(pattern: string, value: boolean | SiblingClause, options: IGlobOptions): (ParsedStringPattern | ParsedExpressionPattern) {
if (value === false) {
return NULL; // pattern is disabled
}

View File

@@ -6,19 +6,24 @@
import { Iterator, IteratorResult, FIN } from 'vs/base/common/iterator';
class Node<E> {
static readonly Undefined = new Node<any>(undefined);
element: E;
next: Node<E> | undefined;
prev: Node<E> | undefined;
next: Node<E>;
prev: Node<E>;
constructor(element: E) {
this.element = element;
this.next = Node.Undefined;
this.prev = Node.Undefined;
}
}
export class LinkedList<E> {
private _first: Node<E> | undefined;
private _last: Node<E> | undefined;
private _first: Node<E> = Node.Undefined;
private _last: Node<E> = Node.Undefined;
private _size: number = 0;
get size(): number {
@@ -26,12 +31,12 @@ export class LinkedList<E> {
}
isEmpty(): boolean {
return !this._first;
return this._first === Node.Undefined;
}
clear(): void {
this._first = undefined;
this._last = undefined;
this._first = Node.Undefined;
this._last = Node.Undefined;
this._size = 0;
}
@@ -45,7 +50,7 @@ export class LinkedList<E> {
private _insert(element: E, atTheEnd: boolean): () => void {
const newNode = new Node(element);
if (!this._first) {
if (this._first === Node.Undefined) {
this._first = newNode;
this._last = newNode;
@@ -64,12 +69,18 @@ export class LinkedList<E> {
oldFirst.prev = newNode;
}
this._size += 1;
return this._remove.bind(this, newNode);
let didRemove = false;
return () => {
if (!didRemove) {
didRemove = true;
this._remove(newNode);
}
};
}
shift(): E | undefined {
if (!this._first) {
if (this._first === Node.Undefined) {
return undefined;
} else {
const res = this._first.element;
@@ -79,7 +90,7 @@ export class LinkedList<E> {
}
pop(): E | undefined {
if (!this._last) {
if (this._last === Node.Undefined) {
return undefined;
} else {
const res = this._last.element;
@@ -89,38 +100,30 @@ export class LinkedList<E> {
}
private _remove(node: Node<E>): void {
let candidate: Node<E> | undefined = this._first;
while (candidate instanceof Node) {
if (candidate !== node) {
candidate = candidate.next;
continue;
}
if (candidate.prev && candidate.next) {
// middle
const anchor = candidate.prev;
anchor.next = candidate.next;
candidate.next.prev = anchor;
if (node.prev !== Node.Undefined && node.next !== Node.Undefined) {
// middle
const anchor = node.prev;
anchor.next = node.next;
node.next.prev = anchor;
} else if (!candidate.prev && !candidate.next) {
// only node
this._first = undefined;
this._last = undefined;
} else if (node.prev === Node.Undefined && node.next === Node.Undefined) {
// only node
this._first = Node.Undefined;
this._last = Node.Undefined;
} else if (!candidate.next) {
// last
this._last = this._last!.prev!;
this._last.next = undefined;
} else if (node.next === Node.Undefined) {
// last
this._last = this._last!.prev!;
this._last.next = Node.Undefined;
} else if (!candidate.prev) {
// first
this._first = this._first!.next!;
this._first.prev = undefined;
}
// done
this._size -= 1;
break;
} else if (node.prev === Node.Undefined) {
// first
this._first = this._first!.next!;
this._first.prev = Node.Undefined;
}
// done
this._size -= 1;
}
iterator(): Iterator<E> {
@@ -128,7 +131,7 @@ export class LinkedList<E> {
let node = this._first;
return {
next(): IteratorResult<E> {
if (!node) {
if (node === Node.Undefined) {
return FIN;
}
@@ -145,7 +148,7 @@ export class LinkedList<E> {
toArray(): E[] {
const result: E[] = [];
for (let node = this._first; node instanceof Node; node = node.next) {
for (let node = this._first; node !== Node.Undefined; node = node.next) {
result.push(node.element);
}
return result;

View File

@@ -175,34 +175,6 @@ export function equals(one: any, other: any): boolean {
return true;
}
function arrayToHash(array: string[]): { [name: string]: true } {
const result: any = {};
for (const e of array) {
result[e] = true;
}
return result;
}
/**
* Given an array of strings, returns a function which, given a string
* returns true or false whether the string is in that array.
*/
export function createKeywordMatcher(arr: string[], caseInsensitive: boolean = false): (str: string) => boolean {
if (caseInsensitive) {
arr = arr.map(function (x) { return x.toLowerCase(); });
}
const hash = arrayToHash(arr);
if (caseInsensitive) {
return function (word) {
return hash[word.toLowerCase()] !== undefined && hash.hasOwnProperty(word.toLowerCase());
};
} else {
return function (word) {
return hash[word] !== undefined && hash.hasOwnProperty(word);
};
}
}
/**
* Calls JSON.Stringify with a replacer to break apart any circular references.
* This prevents JSON.stringify from throwing the exception

View File

@@ -87,6 +87,17 @@ export const enum TerminateResponseCode {
ProcessNotFound = 3,
}
export interface ProcessItem {
name: string;
cmd: string;
pid: number;
ppid: number;
load: number;
mem: number;
children?: ProcessItem[];
}
/**
* Sanitizes a VS Code process environment by removing all Electron/VS Code-related values.
*/

View File

@@ -159,27 +159,6 @@ export function validateConstraint(arg: any, constraint: TypeConstraint | undefi
}
}
/**
* Creates a new object of the provided class and will call the constructor with
* any additional argument supplied.
*/
export function create(ctor: Function, ...args: any[]): any {
if (isNativeClass(ctor)) {
return new (ctor as any)(...args);
} else {
const obj = Object.create(ctor.prototype);
ctor.apply(obj, args);
return obj;
}
}
// https://stackoverflow.com/a/32235645/1499159
function isNativeClass(thing: any): boolean {
return typeof thing === 'function'
&& thing.hasOwnProperty('prototype')
&& !thing.hasOwnProperty('arguments');
}
export function getAllPropertyNames(obj: object): string[] {
let res: string[] = [];
let proto = Object.getPrototypeOf(obj);
@@ -202,4 +181,4 @@ export function withNullAsUndefined<T>(x: T | null): T | undefined {
*/
export function withUndefinedAsNull<T>(x: T | undefined): T | null {
return typeof x === 'undefined' ? null : x;
}
}

View File

@@ -1,112 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export function toUint8ArrayBuffer(str: string): ArrayBuffer {
if (typeof TextEncoder !== 'undefined') {
return new TextEncoder().encode(str).buffer;
}
let i: number, len: number, length = 0, charCode = 0, trailCharCode = 0, codepoint = 0;
// First pass, for the size
for (i = 0, len = str.length; i < len; i++) {
charCode = str.charCodeAt(i);
// Surrogate pair
if (charCode >= 0xD800 && charCode < 0xDC00) {
trailCharCode = str.charCodeAt(++i);
if (!(trailCharCode >= 0xDC00 && trailCharCode < 0xE000)) {
throw new Error('Invalid char code');
}
// Code point can be obtained by subtracting 0xD800 and 0xDC00 from both char codes respectively
// and joining the 10 least significant bits from each, finally adding 0x10000.
codepoint = ((((charCode - 0xD800) & 0x3FF) << 10) | ((trailCharCode - 0xDC00) & 0x3FF)) + 0x10000;
} else {
codepoint = charCode;
}
length += byteSizeInUTF8(codepoint);
}
let result = new ArrayBuffer(length);
let view = new Uint8Array(result);
let pos = 0;
// Second pass, for the data
for (i = 0, len = str.length; i < len; i++) {
charCode = str.charCodeAt(i);
if (charCode >= 0xD800 && charCode < 0xDC00) {
trailCharCode = str.charCodeAt(++i);
codepoint = ((((charCode - 0xD800) & 0x3FF) << 10) | ((trailCharCode - 0xDC00) & 0x3FF)) + 0x10000;
} else {
codepoint = charCode;
}
pos += writeUTF8(codepoint, view, pos);
}
return result;
}
function byteSizeInUTF8(codePoint: number): number {
codePoint = codePoint >>> 0;
if (codePoint < 0x80) {
return 1;
} else if (codePoint < 0x800) {
return 2;
} else if (codePoint < 0x10000) {
return 3;
} else if (codePoint < 0x200000) {
return 4;
} else if (codePoint < 0x4000000) {
return 5;
} else if (codePoint < 0x80000000) {
return 6;
} else {
throw new Error('Code point 0x' + toHexString(codePoint) + ' not encodable in UTF8.');
}
}
function writeUTF8(codePoint: number, buffer: Uint8Array, pos: number): number {
// How many bits needed for codePoint
let byteSize = byteSizeInUTF8(codePoint);
// 0xxxxxxx
if (byteSize === 1) {
buffer[pos] = codePoint;
return 1;
}
// 110xxxxx 10xxxxxx
// 1110xxxx 10xxxxxx 10xxxxxx
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
// 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
// 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
// first byte
buffer[pos] = ((0xFC << (6 - byteSize)) | (codePoint >>> (6 * (byteSize - 1)))) & 0xFF;
// successive bytes
for (let i = 1; i < byteSize; i++) {
buffer[pos + i] = (0x80 | (0x3F & (codePoint >>> (6 * (byteSize - i - 1))))) & 0xFF;
}
return byteSize;
}
function leftPad(value: string, length: number, char: string = '0'): string {
return new Array(length - value.length + 1).join(char) + value;
}
function toHexString(value: number, bitsize: number = 32): string {
return leftPad((value >>> 0).toString(16), bitsize / 4);
}