Skip to content

Commit

Permalink
fix #7269: complete support vscode.workspace.fs API
Browse files Browse the repository at this point in the history
Signed-off-by: Anton Kosyakov <[email protected]>
  • Loading branch information
akosyakov committed May 27, 2020
1 parent 99a7aa3 commit f9a5153
Show file tree
Hide file tree
Showing 31 changed files with 3,582 additions and 766 deletions.
92 changes: 92 additions & 0 deletions packages/languages/src/common/language-selector/strings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,23 @@ function doEqualsIgnoreCase(a: string, b: string, stopAt = a.length): boolean {
return true;
}

/**
* @returns the length of the common prefix of the two strings.
*/
export function commonPrefixLength(a: string, b: string): number {

let i: number;
const len = Math.min(a.length, b.length);

for (i = 0; i < len; i++) {
if (a.charCodeAt(i) !== b.charCodeAt(i)) {
return i;
}
}

return len;
}

/**
* Escapes regular expression characters in a given string
*/
Expand Down Expand Up @@ -125,3 +142,78 @@ export function escapeInvisibleChars(value: string): string {
export function unescapeInvisibleChars(value: string): string {
return value.replace(/\\n/g, '\n').replace(/\\r/g, '\r');
}

export function compare(a: string, b: string): number {
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
return 0;
}
}

export function compareSubstring(a: string, b: string, aStart: number = 0, aEnd: number = a.length, bStart: number = 0, bEnd: number = b.length): number {
for (; aStart < aEnd && bStart < bEnd; aStart++, bStart++) {
const codeA = a.charCodeAt(aStart);
const codeB = b.charCodeAt(bStart);
if (codeA < codeB) {
return -1;
} else if (codeA > codeB) {
return 1;
}
}
const aLen = aEnd - aStart;
const bLen = bEnd - bStart;
if (aLen < bLen) {
return -1;
} else if (aLen > bLen) {
return 1;
}
return 0;
}

export function compareIgnoreCase(a: string, b: string): number {
return compareSubstringIgnoreCase(a, b, 0, a.length, 0, b.length);
}

export function compareSubstringIgnoreCase(a: string, b: string, aStart: number = 0, aEnd: number = a.length, bStart: number = 0, bEnd: number = b.length): number {

for (; aStart < aEnd && bStart < bEnd; aStart++, bStart++) {

const codeA = a.charCodeAt(aStart);
const codeB = b.charCodeAt(bStart);

if (codeA === codeB) {
// equal
continue;
}

const diff = codeA - codeB;
if (diff === 32 && isUpperAsciiLetter(codeB)) { // codeB =[65-90] && codeA =[97-122]
continue;

} else if (diff === -32 && isUpperAsciiLetter(codeA)) { // codeB =[97-122] && codeA =[65-90]
continue;
}

if (isLowerAsciiLetter(codeA) && isLowerAsciiLetter(codeB)) {
//
return diff;

} else {
return compareSubstring(a.toLowerCase(), b.toLowerCase(), aStart, aEnd, bStart, bEnd);
}
}

const aLen = aEnd - aStart;
const bLen = bEnd - bStart;

if (aLen < bLen) {
return -1;
} else if (aLen > bLen) {
return 1;
}

return 0;
}
35 changes: 35 additions & 0 deletions packages/plugin-ext/src/common/arrays.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/********************************************************************************
* Copyright (C) 2020 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

/**
* @returns New array with all falsy values removed. The original array IS NOT modified.
*/
export function coalesce<T>(array: ReadonlyArray<T | undefined | null>): T[] {
return <T[]>array.filter(e => !!e);
}

/**
* @returns True if the provided object is an array and has at least one element.
*/
export function isNonEmptyArray<T>(obj: T[] | undefined | null): obj is T[];
export function isNonEmptyArray<T>(obj: readonly T[] | undefined | null): obj is readonly T[];
export function isNonEmptyArray<T>(obj: T[] | readonly T[] | undefined | null): obj is T[] | readonly T[] {
return Array.isArray(obj) && obj.length > 0;
}
87 changes: 87 additions & 0 deletions packages/plugin-ext/src/common/buffer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
const hasBuffer = (typeof Buffer !== 'undefined');
const hasTextEncoder = (typeof TextEncoder !== 'undefined');

export class VSBuffer {

static alloc(byteLength: number): VSBuffer {
if (hasBuffer) {
return new VSBuffer(Buffer.allocUnsafe(byteLength));
} else {
return new VSBuffer(new Uint8Array(byteLength));
}
}

static wrap(actual: Uint8Array): VSBuffer {
if (hasBuffer && !(Buffer.isBuffer(actual))) {
// https://nodejs.org/dist/latest-v10.x/docs/api/buffer.html#buffer_class_method_buffer_from_arraybuffer_byteoffset_length
// Create a zero-copy Buffer wrapper around the ArrayBuffer pointed to by the Uint8Array
actual = Buffer.from(actual.buffer, actual.byteOffset, actual.byteLength);
}
return new VSBuffer(actual);
}

static fromString(source: string): VSBuffer {
if (hasBuffer) {
return new VSBuffer(Buffer.from(source));
} else if (hasTextEncoder) {
if (!textEncoder) {
textEncoder = new TextEncoder();
}
return new VSBuffer(textEncoder.encode(source));
} else {
return new VSBuffer(strings.encodeUTF8(source));
}
}

readonly buffer: Uint8Array;
readonly byteLength: number;

private constructor(buffer: Uint8Array) {
this.buffer = buffer;
this.byteLength = this.buffer.byteLength;
}

toString(): string {
if (hasBuffer) {
return this.buffer.toString();
} else if (hasTextDecoder) {
if (!textDecoder) {
textDecoder = new TextDecoder();
}
return textDecoder.decode(this.buffer);
} else {
return strings.decodeUTF8(this.buffer);
}
}

slice(start?: number, end?: number): VSBuffer {
// IMPORTANT: use subarray instead of slice because TypedArray#slice
// creates shallow copy and NodeBuffer#slice doesn't. The use of subarray
// ensures the same, performant, behaviour.
return new VSBuffer(this.buffer.subarray(start, end));
}

}

export interface VSBufferReadable {

read(): VSBuffer | null;

}

export function bufferToReadable(buffer: VSBuffer): VSBufferReadable {
let consumed = false;

return {
read: () => {
if (consumed) {
return null;
}

consumed = true;

return buffer;
}
};
}

72 changes: 72 additions & 0 deletions packages/plugin-ext/src/common/character-classifier.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/********************************************************************************
* Copyright (C) 2020 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { toUint8 } from './uint';

/**
* A fast character classifier that uses a compact array for ASCII values.
*/
export class CharacterClassifier<T extends number> {
/**
* Maintain a compact (fully initialized ASCII map for quickly classifying ASCII characters - used more often in code).
*/
protected _asciiMap: Uint8Array;

/**
* The entire map (sparse array).
*/
protected _map: Map<number, number>;

protected _defaultValue: number;

constructor(_defaultValue: T) {
const defaultValue = toUint8(_defaultValue);

this._defaultValue = defaultValue;
this._asciiMap = CharacterClassifier._createAsciiMap(defaultValue);
this._map = new Map<number, number>();
}

private static _createAsciiMap(defaultValue: number): Uint8Array {
const asciiMap: Uint8Array = new Uint8Array(256);
for (let i = 0; i < 256; i++) {
asciiMap[i] = defaultValue;
}
return asciiMap;
}

public set(charCode: number, _value: T): void {
const value = toUint8(_value);

if (charCode >= 0 && charCode < 256) {
this._asciiMap[charCode] = value;
} else {
this._map.set(charCode, value);
}
}

public get(charCode: number): T {
if (charCode >= 0 && charCode < 256) {
return <T>this._asciiMap[charCode];
} else {
return <T>(this._map.get(charCode) || this._defaultValue);
}
}
}
Loading

0 comments on commit f9a5153

Please sign in to comment.