Merge from vscode 2f984aad710215f4e4684a035bb02f55d1a9e2cc (#9819)

This commit is contained in:
Anthony Dresser
2020-04-01 00:44:39 -07:00
committed by GitHub
parent 0e27aaa61f
commit 0bfbdc62ed
247 changed files with 5402 additions and 3311 deletions

View File

@@ -472,17 +472,6 @@ export function range(arg: number, to?: number): number[] {
return result;
}
/**
* @deprecated ES6: use `Array.fill`
*/
export function fill<T>(num: number, value: T, arr: T[] = []): T[] {
for (let i = 0; i < num; i++) {
arr[i] = value;
}
return arr;
}
export function index<T>(array: ReadonlyArray<T>, indexer: (t: T) => string): { [key: string]: T; };
export function index<T, R>(array: ReadonlyArray<T>, indexer: (t: T) => string, merger?: (t: T, r: R) => R): { [key: string]: R; };
export function index<T, R>(array: ReadonlyArray<T>, indexer: (t: T) => string, merger: (t: T, r: R) => R = t => t as any): { [key: string]: R; } {

View File

@@ -94,8 +94,14 @@ export class VSBuffer {
return new VSBuffer(this.buffer.subarray(start!/*bad lib.d.ts*/, end));
}
set(array: VSBuffer, offset?: number): void {
this.buffer.set(array.buffer, offset);
set(array: VSBuffer, offset?: number): void;
set(array: Uint8Array, offset?: number): void;
set(array: VSBuffer | Uint8Array, offset?: number): void {
if (array instanceof VSBuffer) {
this.buffer.set(array.buffer, offset);
} else {
this.buffer.set(array, offset);
}
}
readUInt32BE(offset: number): number {
@@ -106,6 +112,14 @@ export class VSBuffer {
writeUInt32BE(this.buffer, value, offset);
}
readUInt32LE(offset: number): number {
return readUInt32LE(this.buffer, offset);
}
writeUInt32LE(value: number, offset: number): void {
writeUInt32LE(this.buffer, value, offset);
}
readUInt8(offset: number): number {
return readUInt8(this.buffer, offset);
}
@@ -117,15 +131,15 @@ export class VSBuffer {
export function readUInt16LE(source: Uint8Array, offset: number): number {
return (
source[offset]
+ source[offset + 1] * 2 ** 8
((source[offset + 0] << 0) >>> 0) |
((source[offset + 1] << 8) >>> 0)
);
}
export function writeUInt16LE(destination: Uint8Array, value: number, offset: number): void {
destination[offset] = value;
destination[offset + 0] = (value & 0b11111111);
value = value >>> 8;
destination[offset + 1] = value;
destination[offset + 1] = (value & 0b11111111);
}
export function readUInt32BE(source: Uint8Array, offset: number): number {
@@ -147,6 +161,25 @@ export function writeUInt32BE(destination: Uint8Array, value: number, offset: nu
destination[offset] = value;
}
export function readUInt32LE(source: Uint8Array, offset: number): number {
return (
((source[offset + 0] << 0) >>> 0) |
((source[offset + 1] << 8) >>> 0) |
((source[offset + 2] << 16) >>> 0) |
((source[offset + 3] << 24) >>> 0)
);
}
export function writeUInt32LE(destination: Uint8Array, value: number, offset: number): void {
destination[offset + 0] = (value & 0b11111111);
value = value >>> 8;
destination[offset + 1] = (value & 0b11111111);
value = value >>> 8;
destination[offset + 2] = (value & 0b11111111);
value = value >>> 8;
destination[offset + 3] = (value & 0b11111111);
}
export function readUInt8(source: Uint8Array, offset: number): number {
return source[offset];
}

View File

@@ -3,7 +3,6 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as strings from 'vs/base/common/strings';
import { sep } from 'vs/base/common/path';
import { IdleValue } from 'vs/base/common/async';
@@ -133,8 +132,8 @@ export function compareAnything(one: string, other: string, lookFor: string): nu
}
// Sort suffix matches over non suffix matches
const elementASuffixMatch = strings.endsWith(elementAName, lookFor);
const elementBSuffixMatch = strings.endsWith(elementBName, lookFor);
const elementASuffixMatch = elementAName.endsWith(lookFor);
const elementBSuffixMatch = elementBName.endsWith(lookFor);
if (elementASuffixMatch !== elementBSuffixMatch) {
return elementASuffixMatch ? -1 : 1;
}
@@ -154,8 +153,8 @@ export function compareByPrefix(one: string, other: string, lookFor: string): nu
const elementBName = other.toLowerCase();
// Sort prefix matches over non prefix matches
const elementAPrefixMatch = strings.startsWith(elementAName, lookFor);
const elementBPrefixMatch = strings.startsWith(elementBName, lookFor);
const elementAPrefixMatch = elementAName.startsWith(lookFor);
const elementBPrefixMatch = elementBName.startsWith(lookFor);
if (elementAPrefixMatch !== elementBPrefixMatch) {
return elementAPrefixMatch ? -1 : 1;
}

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { isWindows } from 'vs/base/common/platform';
import { startsWithIgnoreCase, equalsIgnoreCase, endsWith, rtrim } from 'vs/base/common/strings';
import { startsWithIgnoreCase, equalsIgnoreCase, rtrim } from 'vs/base/common/strings';
import { CharCode } from 'vs/base/common/charCode';
import { sep, posix, isAbsolute, join, normalize } from 'vs/base/common/path';
@@ -235,7 +235,7 @@ export function isWindowsDriveLetter(char0: number): boolean {
export function sanitizeFilePath(candidate: string, cwd: string): string {
// Special case: allow to open a drive letter without trailing backslash
if (isWindows && endsWith(candidate, ':')) {
if (isWindows && candidate.endsWith(':')) {
candidate += sep;
}
@@ -252,7 +252,7 @@ export function sanitizeFilePath(candidate: string, cwd: string): string {
candidate = rtrim(candidate, sep);
// Special case: allow to open drive root ('C:\')
if (endsWith(candidate, ':')) {
if (candidate.endsWith(':')) {
candidate += sep;
}

View File

@@ -25,15 +25,15 @@ export function score(target: string, query: IPreparedQuery, fuzzy: boolean): Sc
return scoreMultiple(target, query.values, fuzzy);
}
return scoreSingle(target, query.value, query.valueLowercase, fuzzy);
return scoreSingle(target, query.normalized, query.normalizedLowercase, fuzzy);
}
function scoreMultiple(target: string, query: IPreparedQueryPiece[], fuzzy: boolean): Score {
let totalScore = NO_MATCH;
const totalPositions: number[] = [];
for (const { value, valueLowercase } of query) {
const [scoreValue, positions] = scoreSingle(target, value, valueLowercase, fuzzy);
for (const { normalized, normalizedLowercase } of query) {
const [scoreValue, positions] = scoreSingle(target, normalized, normalizedLowercase, fuzzy);
if (scoreValue === NO_MATCH) {
// if a single query value does not match, return with
// no score entirely, we require all queries to match
@@ -338,11 +338,26 @@ const LABEL_CAMELCASE_SCORE = 1 << 16;
const LABEL_SCORE_THRESHOLD = 1 << 15;
export interface IPreparedQueryPiece {
/**
* The original query as provided as input.
*/
original: string;
originalLowercase: string;
value: string;
valueLowercase: string;
/**
* Original normalized to platform separators:
* - Windows: \
* - Posix: /
*/
pathNormalized: string;
/**
* In addition to the normalized path, will have
* whitespace and wildcards removed.
*/
normalized: string;
normalizedLowercase: string;
}
export interface IPreparedQuery extends IPreparedQueryPiece {
@@ -364,17 +379,21 @@ export function prepareQuery(original: string): IPreparedQuery {
}
const originalLowercase = original.toLowerCase();
const value = prepareQueryValue(original);
const valueLowercase = value.toLowerCase();
const containsPathSeparator = value.indexOf(sep) >= 0;
const { pathNormalized, normalized, normalizedLowercase } = normalizeQuery(original);
const containsPathSeparator = pathNormalized.indexOf(sep) >= 0;
let values: IPreparedQueryPiece[] | undefined = undefined;
const originalSplit = original.split(MULTIPL_QUERY_VALUES_SEPARATOR);
if (originalSplit.length > 1) {
for (const originalPiece of originalSplit) {
const valuePiece = prepareQueryValue(originalPiece);
if (valuePiece) {
const {
pathNormalized: pathNormalizedPiece,
normalized: normalizedPiece,
normalizedLowercase: normalizedLowercasePiece
} = normalizeQuery(originalPiece);
if (normalizedPiece) {
if (!values) {
values = [];
}
@@ -382,29 +401,36 @@ export function prepareQuery(original: string): IPreparedQuery {
values.push({
original: originalPiece,
originalLowercase: originalPiece.toLowerCase(),
value: valuePiece,
valueLowercase: valuePiece.toLowerCase()
pathNormalized: pathNormalizedPiece,
normalized: normalizedPiece,
normalizedLowercase: normalizedLowercasePiece
});
}
}
}
return { original, originalLowercase, value, valueLowercase, values, containsPathSeparator };
return { original, originalLowercase, pathNormalized, normalized, normalizedLowercase, values, containsPathSeparator };
}
function prepareQueryValue(original: string): string {
let value = stripWildcards(original).replace(/\s/g, ''); // get rid of all wildcards and whitespace
function normalizeQuery(original: string): { pathNormalized: string, normalized: string, normalizedLowercase: string } {
let pathNormalized: string;
if (isWindows) {
value = value.replace(/\//g, sep); // Help Windows users to search for paths when using slash
pathNormalized = original.replace(/\//g, sep); // Help Windows users to search for paths when using slash
} else {
value = value.replace(/\\/g, sep); // Help macOS/Linux users to search for paths when using backslash
pathNormalized = original.replace(/\\/g, sep); // Help macOS/Linux users to search for paths when using backslash
}
return value;
const normalized = stripWildcards(pathNormalized).replace(/\s/g, '');
return {
pathNormalized,
normalized,
normalizedLowercase: normalized.toLowerCase()
};
}
export function scoreItem<T>(item: T, query: IPreparedQuery, fuzzy: boolean, accessor: IItemAccessor<T>, cache: ScorerCache): IItemScore {
if (!item || !query.value) {
if (!item || !query.normalized) {
return NO_ITEM_SCORE; // we need an item and query to score on at least
}
@@ -417,9 +443,9 @@ export function scoreItem<T>(item: T, query: IPreparedQuery, fuzzy: boolean, acc
let cacheHash: string;
if (description) {
cacheHash = `${label}${description}${query.value}${fuzzy}`;
cacheHash = `${label}${description}${query.normalized}${fuzzy}`;
} else {
cacheHash = `${label}${query.value}${fuzzy}`;
cacheHash = `${label}${query.normalized}${fuzzy}`;
}
const cached = cache[cacheHash];
@@ -455,7 +481,7 @@ function createMatches(offsets: undefined | number[]): IMatch[] {
function doScoreItem(label: string, description: string | undefined, path: string | undefined, query: IPreparedQuery, fuzzy: boolean): IItemScore {
// 1.) treat identity matches on full path highest
if (path && (isLinux ? query.original === path : equalsIgnoreCase(query.original, path))) {
if (path && (isLinux ? query.pathNormalized === path : equalsIgnoreCase(query.pathNormalized, path))) {
return { score: PATH_IDENTITY_SCORE, labelMatch: [{ start: 0, end: label.length }], descriptionMatch: description ? [{ start: 0, end: description.length }] : undefined };
}
@@ -464,13 +490,13 @@ function doScoreItem(label: string, description: string | undefined, path: strin
if (preferLabelMatches) {
// 2.) treat prefix matches on the label second highest
const prefixLabelMatch = matchesPrefix(query.value, label);
const prefixLabelMatch = matchesPrefix(query.normalized, label);
if (prefixLabelMatch) {
return { score: LABEL_PREFIX_SCORE, labelMatch: prefixLabelMatch };
}
// 3.) treat camelcase matches on the label third highest
const camelcaseLabelMatch = matchesCamelCase(query.value, label);
const camelcaseLabelMatch = matchesCamelCase(query.normalized, label);
if (camelcaseLabelMatch) {
return { score: LABEL_CAMELCASE_SCORE, labelMatch: camelcaseLabelMatch };
}
@@ -702,17 +728,17 @@ function fallbackCompare<T>(itemA: T, itemB: T, query: IPreparedQuery, accessor:
// compare by label
if (labelA !== labelB) {
return compareAnything(labelA, labelB, query.value);
return compareAnything(labelA, labelB, query.normalized);
}
// compare by description
if (descriptionA && descriptionB && descriptionA !== descriptionB) {
return compareAnything(descriptionA, descriptionB, query.value);
return compareAnything(descriptionA, descriptionB, query.normalized);
}
// compare by path
if (pathA && pathB && pathA !== pathB) {
return compareAnything(pathA, pathB, query.value);
return compareAnything(pathA, pathB, query.normalized);
}
// equal

View File

@@ -302,7 +302,7 @@ function parsePattern(arg1: string | IRelativePattern, options: IGlobOptions): P
if (T1.test(pattern)) { // common pattern: **/*.txt just need endsWith check
const base = pattern.substr(4); // '**/*'.length === 4
parsedPattern = function (path, basename) {
return typeof path === 'string' && strings.endsWith(path, base) ? pattern : null;
return typeof path === 'string' && path.endsWith(base) ? pattern : null;
};
} else if (match = T2.exec(trimForExclusions(pattern, options))) { // common pattern: **/some.txt just need basename check
parsedPattern = trivia2(match[1], pattern);
@@ -339,7 +339,7 @@ function wrapRelativePattern(parsedPattern: ParsedStringPattern, arg2: string |
}
function trimForExclusions(pattern: string, options: IGlobOptions): string {
return options.trimForExclusions && strings.endsWith(pattern, '/**') ? pattern.substr(0, pattern.length - 2) : pattern; // dropping **, tailing / is dropped later
return options.trimForExclusions && pattern.endsWith('/**') ? pattern.substr(0, pattern.length - 2) : pattern; // dropping **, tailing / is dropped later
}
// common pattern: **/some.txt just need basename check
@@ -353,7 +353,7 @@ function trivia2(base: string, originalPattern: string): ParsedStringPattern {
if (basename) {
return basename === base ? originalPattern : null;
}
return path === base || strings.endsWith(path, slashBase) || strings.endsWith(path, backslashBase) ? originalPattern : null;
return path === base || path.endsWith(slashBase) || path.endsWith(backslashBase) ? originalPattern : null;
};
const basenames = [base];
parsedPattern.basenames = basenames;
@@ -398,7 +398,7 @@ function trivia4and5(path: string, pattern: string, matchPathEnds: boolean): Par
const nativePath = paths.sep !== paths.posix.sep ? path.replace(ALL_FORWARD_SLASHES, paths.sep) : path;
const nativePathEnd = paths.sep + nativePath;
const parsedPattern: ParsedStringPattern = matchPathEnds ? function (path, basename) {
return typeof path === 'string' && (path === nativePath || strings.endsWith(path, nativePathEnd)) ? pattern : null;
return typeof path === 'string' && (path === nativePath || path.endsWith(nativePathEnd)) ? pattern : null;
} : function (path, basename) {
return typeof path === 'string' && path === nativePath ? pattern : null;
};

View File

@@ -5,7 +5,7 @@
import { URI } from 'vs/base/common/uri';
import { posix, normalize, win32, sep } from 'vs/base/common/path';
import { endsWith, startsWithIgnoreCase, rtrim, startsWith } from 'vs/base/common/strings';
import { startsWithIgnoreCase, rtrim } from 'vs/base/common/strings';
import { Schemas } from 'vs/base/common/network';
import { isLinux, isWindows, isMacintosh } from 'vs/base/common/platform';
import { isEqual, basename, relativePath } from 'vs/base/common/resources';
@@ -117,7 +117,7 @@ export function tildify(path: string, userHome: string): string {
}
// Linux: case sensitive, macOS: case insensitive
if (isLinux ? startsWith(path, normalizedUserHome) : startsWithIgnoreCase(path, normalizedUserHome)) {
if (isLinux ? path.startsWith(normalizedUserHome) : startsWithIgnoreCase(path, normalizedUserHome)) {
path = `~/${path.substr(normalizedUserHome.length)}`;
}
@@ -210,7 +210,7 @@ export function shorten(paths: string[], pathSeparator: string = sep): string[]
// Adding separator as prefix for subpath, such that 'endsWith(src, trgt)' considers subpath as directory name instead of plain string.
// prefix is not added when either subpath is root directory or path[otherPathIndex] does not have multiple directories.
const subpathWithSep: string = (start > 0 && paths[otherPathIndex].indexOf(pathSeparator) > -1) ? pathSeparator + subpath : subpath;
const isOtherPathEnding: boolean = endsWith(paths[otherPathIndex], subpathWithSep);
const isOtherPathEnding: boolean = paths[otherPathIndex].endsWith(subpathWithSep);
match = !isSubpathEnding || isOtherPathEnding;
}
@@ -221,7 +221,7 @@ export function shorten(paths: string[], pathSeparator: string = sep): string[]
let result = '';
// preserve disk drive or root prefix
if (endsWith(segments[0], ':') || prefix !== '') {
if (segments[0].endsWith(':') || prefix !== '') {
if (start === 1) {
// extend subpath to include disk drive prefix
start = 0;

View File

@@ -56,32 +56,6 @@ export function setToString<K>(set: Set<K>): string {
return `Set(${set.size}) {${entries.join(', ')}}`;
}
/**
* @deprecated ES6: use `...Map.entries()`
*/
export function mapToSerializable(map: Map<string, string>): [string, string][] {
const serializable: [string, string][] = [];
map.forEach((value, key) => {
serializable.push([key, value]);
});
return serializable;
}
/**
* @deprecated ES6: use `new Map([[key1, value1],[key2, value2]])`
*/
export function serializableToMap(serializable: [string, string][]): Map<string, string> {
const items = new Map<string, string>();
for (const [key, value] of serializable) {
items.set(key, value);
}
return items;
}
export interface IKeyIterator {
reset(key: string): this;
next(): this;

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { basename, posix, extname } from 'vs/base/common/path';
import { endsWith, startsWithUTF8BOM, startsWith } from 'vs/base/common/strings';
import { startsWithUTF8BOM } from 'vs/base/common/strings';
import { coalesce } from 'vs/base/common/arrays';
import { match } from 'vs/base/common/glob';
import { URI } from 'vs/base/common/uri';
@@ -185,7 +185,7 @@ function guessMimeTypeByPath(path: string, filename: string, associations: IText
// Longest extension match
if (association.extension) {
if (!extensionMatch || association.extension.length > extensionMatch.extension!.length) {
if (endsWith(filename, association.extensionLowercase!)) {
if (filename.endsWith(association.extensionLowercase!)) {
extensionMatch = association;
}
}
@@ -259,11 +259,11 @@ export function suggestFilename(mode: string | undefined, prefix: string): strin
.map(assoc => assoc.extension);
const extensionsWithDotFirst = coalesce(extensions)
.filter(assoc => startsWith(assoc, '.'));
.filter(assoc => assoc.startsWith('.'));
if (extensionsWithDotFirst.length > 0) {
const candidateExtension = extensionsWithDotFirst[0];
if (endsWith(prefix, candidateExtension)) {
if (prefix.endsWith(candidateExtension)) {
// do not add the prefix if it already exists
// https://github.com/microsoft/vscode/issues/83603
return prefix;

View File

@@ -588,11 +588,11 @@ function _makeFsPath(uri: URI, keepDriveLetterCasing: boolean): string {
&& (uri.path.charCodeAt(1) >= CharCode.A && uri.path.charCodeAt(1) <= CharCode.Z || uri.path.charCodeAt(1) >= CharCode.a && uri.path.charCodeAt(1) <= CharCode.z)
&& uri.path.charCodeAt(2) === CharCode.Colon
) {
// windows drive letter: file:///c:/far/boo
if (!keepDriveLetterCasing) {
// windows drive letter: file:///c:/far/boo
value = uri.path[1].toLowerCase() + uri.path.substr(2);
} else {
value = uri.path.substr(1, 2);
value = uri.path.substr(1);
}
} else {
// other path