Merge from vscode 10492ba146318412cbee8b76a8c630f226914734

This commit is contained in:
ADS Merger
2020-04-08 06:33:38 +00:00
parent fca2344c2e
commit 1868a7d370
339 changed files with 3795 additions and 3146 deletions

View File

@@ -19,6 +19,10 @@ export function fromNow(date: number | Date, appendAgoLabel?: boolean): string {
}
const seconds = Math.round((new Date().getTime() - date) / 1000);
if (seconds < -30) {
return localize('date.fromNow.in', 'in {0}', fromNow(new Date().getTime() + seconds * 1000, false));
}
if (seconds < 30) {
return localize('date.fromNow.now', 'now');
}

View File

@@ -559,6 +559,8 @@ export function fuzzyScore(pattern: string, patternLow: string, patternStart: nu
let patternPos = patternStart;
let wordPos = wordStart;
let hasStrongFirstMatch = false;
// There will be a match, fill in tables
for (row = 1, patternPos = patternStart; patternPos < patternLen; row++, patternPos++) {
@@ -566,6 +568,10 @@ export function fuzzyScore(pattern: string, patternLow: string, patternStart: nu
const score = _doScore(pattern, patternLow, patternPos, patternStart, word, wordLow, wordPos);
if (patternPos === patternStart && score > 1) {
hasStrongFirstMatch = true;
}
_scores[row][column] = score;
const diag = _table[row - 1][column - 1] + (score > 1 ? 1 : score);
@@ -604,6 +610,10 @@ export function fuzzyScore(pattern: string, patternLow: string, patternStart: nu
printTables(pattern, patternStart, word, wordStart);
}
if (!hasStrongFirstMatch && !firstMatchCanBeWeak) {
return undefined;
}
_matchesCount = 0;
_topScore = -100;
_wordStart = wordStart;

View File

@@ -526,15 +526,45 @@ function createMatches(offsets: number[] | undefined): IMatch[] {
}
function normalizeMatches(matches: IMatch[]): IMatch[] {
const positions = new Set<number>();
for (const match of matches) {
for (let i = match.start; i < match.end; i++) {
positions.add(i);
// sort matches by start to be able to normalize
const sortedMatches = matches.sort((matchA, matchB) => {
return matchA.start - matchB.start;
});
// merge matches that overlap
const normalizedMatches: IMatch[] = [];
let currentMatch: IMatch | undefined = undefined;
for (const match of sortedMatches) {
// if we have no current match or the matches
// do not overlap, we take it as is and remember
// it for future merging
if (!currentMatch || !matchOverlaps(currentMatch, match)) {
currentMatch = match;
normalizedMatches.push(match);
}
// otherwise we merge the matches
else {
currentMatch.start = Math.min(currentMatch.start, match.start);
currentMatch.end = Math.max(currentMatch.end, match.end);
}
}
return createMatches(Array.from(positions.values()).sort((a, b) => a - b));
return normalizedMatches;
}
function matchOverlaps(matchA: IMatch, matchB: IMatch): boolean {
if (matchA.end < matchB.start) {
return false; // A ends before B starts
}
if (matchB.end < matchA.start) {
return false; // B ends before A starts
}
return true;
}
//#endregion

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { INavigator, ArrayNavigator } from 'vs/base/common/iterator';
import { INavigator, ArrayNavigator } from 'vs/base/common/navigator';
export class HistoryNavigator<T> implements INavigator<T> {
@@ -45,10 +45,6 @@ export class HistoryNavigator<T> implements INavigator<T> {
return this._navigator.current();
}
public parent(): null {
return null;
}
public first(): T | null {
return this._navigator.first();
}

View File

@@ -3,39 +3,17 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export interface IteratorDefinedResult<T> {
readonly done: false;
readonly value: T;
}
export interface IteratorUndefinedResult {
readonly done: true;
readonly value: undefined;
}
export const FIN: IteratorUndefinedResult = { done: true, value: undefined };
export type IteratorResult<T> = IteratorDefinedResult<T> | IteratorUndefinedResult;
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 namespace Iterable {
const _empty: Iterable<any> = Object.freeze([]);
export function empty<T>(): Iterable<T> {
return _empty;
}
export function from<T>(iterable: Iterable<T> | undefined | null): Iterable<T> {
return iterable || _empty;
}
export function first<T>(iterable: Iterable<T>): T | undefined {
return iterable[Symbol.iterator]().next().value;
}
@@ -52,291 +30,48 @@ export namespace Iterable {
export function* filter<T>(iterable: Iterable<T>, predicate: (t: T) => boolean): Iterable<T> {
for (const element of iterable) {
if (predicate(element)) {
return yield element;
yield element;
}
}
}
export function* map<T, R>(iterable: Iterable<T>, fn: (t: T) => R): Iterable<R> {
for (const element of iterable) {
return yield fn(element);
}
}
}
export module Iterator {
const _empty: Iterator<any> = {
next() {
return FIN;
}
};
export function empty<T>(): Iterator<T> {
return _empty;
}
export function single<T>(value: T): Iterator<T> {
let done = false;
return {
next(): IteratorResult<T> {
if (done) {
return FIN;
}
done = true;
return { done: false, value };
}
};
}
export function fromArray<T>(array: ReadonlyArray<T>, index = 0, length = array.length): Iterator<T> {
return {
next(): IteratorResult<T> {
if (index >= length) {
return FIN;
}
return { done: false, value: array[index++] };
}
};
}
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();
} else if (Array.isArray(elements)) {
return Iterator.fromArray(elements);
} else {
return elements;
yield fn(element);
}
}
export function map<T, R>(iterator: Iterator<T>, fn: (t: T) => R): Iterator<R> {
return {
next() {
const element = iterator.next();
if (element.done) {
return FIN;
} else {
return { done: false, value: fn(element.value) };
}
}
};
}
export function filter<T>(iterator: Iterator<T>, fn: (t: T) => boolean): Iterator<T> {
return {
next() {
while (true) {
const element = iterator.next();
if (element.done) {
return FIN;
}
if (fn(element.value)) {
return { done: false, value: element.value };
}
}
}
};
}
export function some<T>(iterator: Iterator<T> | NativeIterator<T>, fn: (t: T) => boolean): boolean {
while (true) {
const element = iterator.next();
if (element.done) {
return false;
}
if (fn(element.value)) {
return true;
export function* concat<T>(...iterables: Iterable<T>[]): Iterable<T> {
for (const iterable of iterables) {
for (const element of iterable) {
yield element;
}
}
}
export function forEach<T>(iterator: Iterator<T>, fn: (t: T) => void): void {
for (let next = iterator.next(); !next.done; next = iterator.next()) {
fn(next.value);
}
}
export function collect<T>(iterator: Iterator<T>, atMost: number = Number.POSITIVE_INFINITY): T[] {
const result: T[] = [];
/**
* Consumes `atMost` elements from iterable and returns the consumed elements,
* and an iterable for the rest of the elements.
*/
export function consume<T>(iterable: Iterable<T>, atMost: number = Number.POSITIVE_INFINITY): [T[], Iterable<T>] {
const consumed: T[] = [];
if (atMost === 0) {
return result;
return [consumed, iterable];
}
let i = 0;
const iterator = iterable[Symbol.iterator]();
for (let next = iterator.next(); !next.done; next = iterator.next()) {
result.push(next.value);
for (let i = 0; i < atMost; i++) {
const next = iterator.next();
if (++i >= atMost) {
break;
if (next.done) {
return [consumed, Iterable.empty()];
}
consumed.push(next.value);
}
return result;
}
export function concat<T>(...iterators: Iterator<T>[]): Iterator<T> {
let i = 0;
return {
next() {
if (i >= iterators.length) {
return FIN;
}
const iterator = iterators[i];
const result = iterator.next();
if (result.done) {
i++;
return this.next();
}
return result;
}
};
}
export function chain<T>(iterator: Iterator<T>): ChainableIterator<T> {
return new ChainableIterator(iterator);
return [consumed, { [Symbol.iterator]() { return iterator; } }];
}
}
export class ChainableIterator<T> implements Iterator<T> {
constructor(private it: Iterator<T>) { }
next(): IteratorResult<T> { return this.it.next(); }
map<R>(fn: (t: T) => R): ChainableIterator<R> { return new ChainableIterator(Iterator.map(this.it, fn)); }
filter(fn: (t: T) => boolean): ChainableIterator<T> { return new ChainableIterator(Iterator.filter(this.it, fn)); }
}
export type ISequence<T> = Iterator<T> | T[];
export function getSequenceIterator<T>(arg: ISequence<T> | undefined): Iterator<T> {
if (Array.isArray(arg)) {
return Iterator.fromArray(arg);
} else if (!arg) {
return Iterator.empty();
} else {
return arg;
}
}
export interface INextIterator<T> {
next(): T | null;
}
export class ArrayIterator<T> implements INextIterator<T> {
private readonly items: readonly T[];
protected start: number;
protected end: number;
protected index: number;
constructor(items: readonly T[], start: number = 0, end: number = items.length, index = start - 1) {
this.items = items;
this.start = start;
this.end = end;
this.index = index;
}
public first(): T | null {
this.index = this.start;
return this.current();
}
public next(): T | null {
this.index = Math.min(this.index + 1, this.end);
return this.current();
}
protected current(): T | null {
if (this.index === this.start - 1 || this.index === this.end) {
return null;
}
return this.items[this.index];
}
}
export class ArrayNavigator<T> extends ArrayIterator<T> implements INavigator<T> {
constructor(items: readonly T[], start: number = 0, end: number = items.length, index = start - 1) {
super(items, start, end, index);
}
public current(): T | null {
return super.current();
}
public previous(): T | null {
this.index = Math.max(this.index - 1, this.start - 1);
return this.current();
}
public first(): T | null {
this.index = this.start;
return this.current();
}
public last(): T | null {
this.index = this.end - 1;
return this.current();
}
public parent(): T | null {
return null;
}
}
export class MappedIterator<T, R> implements INextIterator<R> {
constructor(protected iterator: INextIterator<T>, protected fn: (item: T | null) => R) {
// noop
}
next() { return this.fn(this.iterator.next()); }
}
export interface INavigator<T> extends INextIterator<T> {
current(): T | null;
previous(): T | null;
parent(): T | null;
first(): T | null;
last(): T | null;
next(): T | null;
}
export class MappedNavigator<T, R> extends MappedIterator<T, R> implements INavigator<R> {
constructor(protected navigator: INavigator<T>, fn: (item: T | null) => R) {
super(navigator, fn);
}
current() { return this.fn(this.navigator.current()); }
previous() { return this.fn(this.navigator.previous()); }
parent() { return this.fn(this.navigator.parent()); }
first() { return this.fn(this.navigator.first()); }
last() { return this.fn(this.navigator.last()); }
next() { return this.fn(this.navigator.next()); }
}

View File

@@ -18,7 +18,7 @@ export interface IWorkspaceFolderProvider {
}
export interface IUserHomeProvider {
userHome: string;
userHome?: URI;
}
/**
@@ -63,8 +63,8 @@ export function getPathLabel(resource: URI | string, userHomeProvider?: IUserHom
// normalize and tildify (macOS, Linux only)
let res = normalize(resource.fsPath);
if (!isWindows && userHomeProvider) {
res = tildify(res, userHomeProvider.userHome);
if (!isWindows && userHomeProvider?.userHome) {
res = tildify(res, userHomeProvider.userHome.fsPath);
}
return res;

View File

@@ -5,7 +5,7 @@
import { URI } from 'vs/base/common/uri';
import { CharCode } from 'vs/base/common/charCode';
import { FIN } from './iterator';
import { compareIgnoreCase, compare } from 'vs/base/common/strings';
/**
* @deprecated ES6: use `[...SetOrMap.values()]`
@@ -56,8 +56,8 @@ export function setToString<K>(set: Set<K>): string {
return `Set(${set.size}) {${entries.join(', ')}}`;
}
export interface IKeyIterator {
reset(key: string): this;
export interface IKeyIterator<K> {
reset(key: K): this;
next(): this;
hasNext(): boolean;
@@ -65,7 +65,7 @@ export interface IKeyIterator {
value(): string;
}
export class StringIterator implements IKeyIterator {
export class StringIterator implements IKeyIterator<string> {
private _value: string = '';
private _pos: number = 0;
@@ -96,7 +96,7 @@ export class StringIterator implements IKeyIterator {
}
}
export class PathIterator implements IKeyIterator {
export class PathIterator implements IKeyIterator<string> {
private _value!: string;
private _from!: number;
@@ -163,33 +163,118 @@ export class PathIterator implements IKeyIterator {
}
}
class TernarySearchTreeNode<E> {
const enum UriIteratorState {
Scheme = 1, Authority = 2, Path = 3, Query = 4, Fragment = 5
}
export class UriIterator implements IKeyIterator<URI> {
private _pathIterator = new PathIterator(false);
private _value!: URI;
private _states: UriIteratorState[] = [];
private _stateIdx: number = 0;
reset(key: URI): this {
this._value = key;
this._states = [];
if (this._value.scheme) {
this._states.push(UriIteratorState.Scheme);
}
if (this._value.authority) {
this._states.push(UriIteratorState.Authority);
}
if (this._value.path) {
this._pathIterator.reset(key.path);
if (this._pathIterator.value()) {
this._states.push(UriIteratorState.Path);
}
}
if (this._value.query) {
this._states.push(UriIteratorState.Query);
}
if (this._value.fragment) {
this._states.push(UriIteratorState.Fragment);
}
this._stateIdx = 0;
return this;
}
next(): this {
if (this._states[this._stateIdx] === UriIteratorState.Path && this._pathIterator.hasNext()) {
this._pathIterator.next();
} else {
this._stateIdx += 1;
}
return this;
}
hasNext(): boolean {
return (this._states[this._stateIdx] === UriIteratorState.Path && this._pathIterator.hasNext())
|| this._stateIdx < this._states.length - 1;
}
cmp(a: string): number {
if (this._states[this._stateIdx] === UriIteratorState.Scheme) {
return compareIgnoreCase(a, this._value.scheme);
} else if (this._states[this._stateIdx] === UriIteratorState.Authority) {
return compareIgnoreCase(a, this._value.authority);
} else if (this._states[this._stateIdx] === UriIteratorState.Path) {
return this._pathIterator.cmp(a);
} else if (this._states[this._stateIdx] === UriIteratorState.Query) {
return compare(a, this._value.query);
} else if (this._states[this._stateIdx] === UriIteratorState.Fragment) {
return compare(a, this._value.fragment);
}
throw new Error();
}
value(): string {
if (this._states[this._stateIdx] === UriIteratorState.Scheme) {
return this._value.scheme;
} else if (this._states[this._stateIdx] === UriIteratorState.Authority) {
return this._value.authority;
} else if (this._states[this._stateIdx] === UriIteratorState.Path) {
return this._pathIterator.value();
} else if (this._states[this._stateIdx] === UriIteratorState.Query) {
return this._value.query;
} else if (this._states[this._stateIdx] === UriIteratorState.Fragment) {
return this._value.fragment;
}
throw new Error();
}
}
class TernarySearchTreeNode<K, V> {
segment!: string;
value: E | undefined;
key!: string;
left: TernarySearchTreeNode<E> | undefined;
mid: TernarySearchTreeNode<E> | undefined;
right: TernarySearchTreeNode<E> | undefined;
value: V | undefined;
key!: K;
left: TernarySearchTreeNode<K, V> | undefined;
mid: TernarySearchTreeNode<K, V> | undefined;
right: TernarySearchTreeNode<K, V> | undefined;
isEmpty(): boolean {
return !this.left && !this.mid && !this.right && !this.value;
}
}
export class TernarySearchTree<E> {
export class TernarySearchTree<K, V> {
static forPaths<E>(): TernarySearchTree<E> {
return new TernarySearchTree<E>(new PathIterator());
static forUris<E>(): TernarySearchTree<URI, E> {
return new TernarySearchTree<URI, E>(new UriIterator());
}
static forStrings<E>(): TernarySearchTree<E> {
return new TernarySearchTree<E>(new StringIterator());
static forPaths<E>(): TernarySearchTree<string, E> {
return new TernarySearchTree<string, E>(new PathIterator());
}
private _iter: IKeyIterator;
private _root: TernarySearchTreeNode<E> | undefined;
static forStrings<E>(): TernarySearchTree<string, E> {
return new TernarySearchTree<string, E>(new StringIterator());
}
constructor(segments: IKeyIterator) {
private _iter: IKeyIterator<K>;
private _root: TernarySearchTreeNode<K, V> | undefined;
constructor(segments: IKeyIterator<K>) {
this._iter = segments;
}
@@ -197,12 +282,12 @@ export class TernarySearchTree<E> {
this._root = undefined;
}
set(key: string, element: E): E | undefined {
set(key: K, element: V): V | undefined {
const iter = this._iter.reset(key);
let node: TernarySearchTreeNode<E>;
let node: TernarySearchTreeNode<K, V>;
if (!this._root) {
this._root = new TernarySearchTreeNode<E>();
this._root = new TernarySearchTreeNode<K, V>();
this._root.segment = iter.value();
}
@@ -212,7 +297,7 @@ export class TernarySearchTree<E> {
if (val > 0) {
// left
if (!node.left) {
node.left = new TernarySearchTreeNode<E>();
node.left = new TernarySearchTreeNode<K, V>();
node.left.segment = iter.value();
}
node = node.left;
@@ -220,7 +305,7 @@ export class TernarySearchTree<E> {
} else if (val < 0) {
// right
if (!node.right) {
node.right = new TernarySearchTreeNode<E>();
node.right = new TernarySearchTreeNode<K, V>();
node.right.segment = iter.value();
}
node = node.right;
@@ -229,7 +314,7 @@ export class TernarySearchTree<E> {
// mid
iter.next();
if (!node.mid) {
node.mid = new TernarySearchTreeNode<E>();
node.mid = new TernarySearchTreeNode<K, V>();
node.mid.segment = iter.value();
}
node = node.mid;
@@ -243,7 +328,7 @@ export class TernarySearchTree<E> {
return oldElement;
}
get(key: string): E | undefined {
get(key: K): V | undefined {
const iter = this._iter.reset(key);
let node = this._root;
while (node) {
@@ -265,10 +350,10 @@ export class TernarySearchTree<E> {
return node ? node.value : undefined;
}
delete(key: string): void {
delete(key: K): void {
const iter = this._iter.reset(key);
const stack: [-1 | 0 | 1, TernarySearchTreeNode<E>][] = [];
const stack: [-1 | 0 | 1, TernarySearchTreeNode<K, V>][] = [];
let node = this._root;
// find and unset node
@@ -306,10 +391,10 @@ export class TernarySearchTree<E> {
}
}
findSubstr(key: string): E | undefined {
findSubstr(key: K): V | undefined {
const iter = this._iter.reset(key);
let node = this._root;
let candidate: E | undefined = undefined;
let candidate: V | undefined = undefined;
while (node) {
const val = iter.cmp(node.segment);
if (val > 0) {
@@ -330,7 +415,7 @@ export class TernarySearchTree<E> {
return node && node.value || candidate;
}
findSuperstr(key: string): Iterator<E> | undefined {
findSuperstr(key: K): Iterator<V> | undefined {
const iter = this._iter.reset(key);
let node = this._root;
while (node) {
@@ -357,11 +442,11 @@ export class TernarySearchTree<E> {
return undefined;
}
private _nodeIterator(node: TernarySearchTreeNode<E>): Iterator<E> {
let res: { done: false; value: E; };
private _nodeIterator(node: TernarySearchTreeNode<K, V>): Iterator<V> {
let res: { done: false; value: V; };
let idx: number;
let data: E[];
const next = (): IteratorResult<E> => {
let data: V[];
const next = (): IteratorResult<V> => {
if (!data) {
// lazy till first invocation
data = [];
@@ -369,7 +454,7 @@ export class TernarySearchTree<E> {
this._forEach(node, value => data.push(value));
}
if (idx >= data.length) {
return FIN;
return { done: true, value: undefined };
}
if (!res) {
@@ -382,11 +467,11 @@ export class TernarySearchTree<E> {
return { next };
}
forEach(callback: (value: E, index: string) => any) {
forEach(callback: (value: V, index: K) => any) {
this._forEach(this._root, callback);
}
private _forEach(node: TernarySearchTreeNode<E> | undefined, callback: (value: E, index: string) => any) {
private _forEach(node: TernarySearchTreeNode<K, V> | undefined, callback: (value: V, index: K) => any) {
if (node) {
// left
this._forEach(node.left, callback);

View File

@@ -0,0 +1,50 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export interface INavigator<T> {
current(): T | null;
previous(): T | null;
first(): T | null;
last(): T | null;
next(): T | null;
}
export class ArrayNavigator<T> implements INavigator<T> {
constructor(
private readonly items: readonly T[],
protected start: number = 0,
protected end: number = items.length,
protected index = start - 1
) { }
current(): T | null {
if (this.index === this.start - 1 || this.index === this.end) {
return null;
}
return this.items[this.index];
}
next(): T | null {
this.index = Math.min(this.index + 1, this.end);
return this.current();
}
previous(): T | null {
this.index = Math.max(this.index - 1, this.start - 1);
return this.current();
}
first(): T | null {
this.index = this.start;
return this.current();
}
last(): T | null {
this.index = this.end - 1;
return this.current();
}
}

View File

@@ -5,7 +5,6 @@
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 { PathIterator, values } from 'vs/base/common/map';
@@ -15,7 +14,7 @@ export interface IResourceNode<T, C = void> {
readonly relativePath: string;
readonly name: string;
readonly element: T | undefined;
readonly children: Iterator<IResourceNode<T, C>>;
readonly children: Iterable<IResourceNode<T, C>>;
readonly childrenCount: number;
readonly parent: IResourceNode<T, C> | undefined;
readonly context: C;
@@ -30,8 +29,8 @@ class Node<T, C> implements IResourceNode<T, C> {
return this._children.size;
}
get children(): Iterator<Node<T, C>> {
return Iterator.fromArray(values(this._children));
get children(): Iterable<Node<T, C>> {
return [...values(this._children)];
}
@memoize
@@ -69,7 +68,9 @@ function collect<T, C>(node: IResourceNode<T, C>, result: T[]): T[] {
result.push(node.element);
}
Iterator.forEach(node.children, child => collect(child, result));
for (const child of node.children) {
collect(child, result);
}
return result;
}

View File

@@ -5,7 +5,7 @@
import * as extpath from 'vs/base/common/extpath';
import * as paths from 'vs/base/common/path';
import { URI } from 'vs/base/common/uri';
import { URI, uriToFsPath } from 'vs/base/common/uri';
import { equalsIgnoreCase } from 'vs/base/common/strings';
import { Schemas } from 'vs/base/common/network';
import { isLinux, isWindows } from 'vs/base/common/platform';
@@ -14,26 +14,7 @@ import { ParsedExpression, IExpression, parse } from 'vs/base/common/glob';
import { TernarySearchTree } from 'vs/base/common/map';
export function originalFSPath(uri: URI): string {
let value: string;
const uriPath = uri.path;
if (uri.authority && uriPath.length > 1 && uri.scheme === 'file') {
// unc path: file://shares/c$/far/boo
value = `//${uri.authority}${uriPath}`;
} else if (
isWindows
&& uriPath.charCodeAt(0) === CharCode.Slash
&& extpath.isWindowsDriveLetter(uriPath.charCodeAt(1))
&& uriPath.charCodeAt(2) === CharCode.Colon
) {
value = uriPath.substr(1);
} else {
// other path
value = uriPath;
}
if (isWindows) {
value = value.replace(/\//g, '\\');
}
return value;
return uriToFsPath(uri, true);
}
/**
@@ -336,7 +317,7 @@ export namespace DataUri {
export class ResourceGlobMatcher {
private readonly globalExpression: ParsedExpression;
private readonly expressionsByRoot: TernarySearchTree<{ root: URI, expression: ParsedExpression }> = TernarySearchTree.forPaths<{ root: URI, expression: ParsedExpression }>();
private readonly expressionsByRoot: TernarySearchTree<string, { root: URI, expression: ParsedExpression }> = TernarySearchTree.forPaths<{ root: URI, expression: ParsedExpression }>();
constructor(
globalExpression: IExpression,

View File

@@ -295,11 +295,12 @@ export function compare(a: string, b: string): number {
}
}
export function compareIgnoreCase(a: string, b: string): number {
const len = Math.min(a.length, b.length);
for (let i = 0; i < len; i++) {
let codeA = a.charCodeAt(i);
let codeB = b.charCodeAt(i);
export function compareIgnoreCase(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++) {
let codeA = a.charCodeAt(aStart);
let codeB = b.charCodeAt(bStart);
if (codeA === codeB) {
// equal
@@ -329,13 +330,16 @@ export function compareIgnoreCase(a: string, b: string): number {
}
}
if (a.length < b.length) {
const aLen = aEnd - aStart;
const bLen = bEnd - bStart;
if (aLen < bLen) {
return -1;
} else if (a.length > b.length) {
} else if (aLen > bLen) {
return 1;
} else {
return 0;
}
return 0;
}
export function isLowerAsciiLetter(code: number): boolean {

View File

@@ -205,7 +205,7 @@ export class URI implements UriComponents {
// if (this.scheme !== 'file') {
// console.warn(`[UriError] calling fsPath with scheme ${this.scheme}`);
// }
return _makeFsPath(this, false);
return uriToFsPath(this, false);
}
// ---- modify to new -------------------------
@@ -349,7 +349,7 @@ export class URI implements UriComponents {
}
let newPath: string;
if (isWindows && uri.scheme === 'file') {
newPath = URI.file(paths.win32.join(_makeFsPath(uri, true), ...pathFragment)).path;
newPath = URI.file(paths.win32.join(uriToFsPath(uri, true), ...pathFragment)).path;
} else {
newPath = paths.posix.join(uri.path, ...pathFragment);
}
@@ -421,7 +421,7 @@ class _URI extends URI {
get fsPath(): string {
if (!this._fsPath) {
this._fsPath = _makeFsPath(this, false);
this._fsPath = uriToFsPath(this, false);
}
return this._fsPath;
}
@@ -577,7 +577,7 @@ function encodeURIComponentMinimal(path: string): string {
/**
* Compute `fsPath` for the given uri
*/
function _makeFsPath(uri: URI, keepDriveLetterCasing: boolean): string {
export function uriToFsPath(uri: URI, keepDriveLetterCasing: boolean): string {
let value: string;
if (uri.authority && uri.path.length > 1 && uri.scheme === 'file') {