mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-27 12:04:04 +01:00
Merge remote-tracking branch 'origin/master' into panel-viewlet
This commit is contained in:
@@ -16,6 +16,11 @@ export interface IExpression {
|
||||
[pattern: string]: boolean | SiblingClause | any;
|
||||
}
|
||||
|
||||
export interface IRelativePattern {
|
||||
base: string;
|
||||
pattern: string;
|
||||
}
|
||||
|
||||
export function getEmptyExpression(): IExpression {
|
||||
return Object.create(null);
|
||||
}
|
||||
@@ -28,6 +33,8 @@ export interface SiblingClause {
|
||||
when: string;
|
||||
}
|
||||
|
||||
const GLOBSTAR = '**';
|
||||
const GLOB_SPLIT = '/';
|
||||
const PATH_REGEX = '[/\\\\]'; // any slash or backslash
|
||||
const NO_PATH_REGEX = '[^/\\\\]'; // any non-slash and non-backslash
|
||||
const ALL_FORWARD_SLASHES = /\//g;
|
||||
@@ -103,10 +110,10 @@ function parseRegExp(pattern: string): string {
|
||||
let regEx = '';
|
||||
|
||||
// Split up into segments for each slash found
|
||||
let segments = splitGlobAware(pattern, '/');
|
||||
let segments = splitGlobAware(pattern, GLOB_SPLIT);
|
||||
|
||||
// Special case where we only have globstars
|
||||
if (segments.every(s => s === '**')) {
|
||||
if (segments.every(s => s === GLOBSTAR)) {
|
||||
regEx = '.*';
|
||||
}
|
||||
|
||||
@@ -116,7 +123,7 @@ function parseRegExp(pattern: string): string {
|
||||
segments.forEach((segment, index) => {
|
||||
|
||||
// Globstar is special
|
||||
if (segment === '**') {
|
||||
if (segment === GLOBSTAR) {
|
||||
|
||||
// if we have more than one globstar after another, just ignore it
|
||||
if (!previousSegmentWasGlobStar) {
|
||||
@@ -207,7 +214,7 @@ function parseRegExp(pattern: string): string {
|
||||
}
|
||||
|
||||
// Tail: Add the slash we had split on if there is more to come and the next one is not a globstar
|
||||
if (index < segments.length - 1 && segments[index + 1] !== '**') {
|
||||
if (index < segments.length - 1 && segments[index + 1] !== GLOBSTAR) {
|
||||
regEx += PATH_REGEX;
|
||||
}
|
||||
|
||||
@@ -264,11 +271,39 @@ const NULL = function (): string {
|
||||
return null;
|
||||
};
|
||||
|
||||
function parsePattern(pattern: string, options: IGlobOptions): ParsedStringPattern {
|
||||
if (!pattern) {
|
||||
function toAbsolutePattern(relativePattern: IRelativePattern | string): string {
|
||||
|
||||
// Without a base URI, best we can do is add '**' to the pattern
|
||||
if (typeof relativePattern === 'string') {
|
||||
if (relativePattern.indexOf(GLOBSTAR) !== 0) {
|
||||
relativePattern = GLOBSTAR + GLOB_SPLIT + strings.ltrim(relativePattern, GLOB_SPLIT);
|
||||
}
|
||||
|
||||
return relativePattern;
|
||||
}
|
||||
|
||||
// Guard against null/undefined
|
||||
if (!relativePattern) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// With a base URI, we can append the path to the relative glob as prefix
|
||||
return relativePattern.base + GLOB_SPLIT + strings.ltrim(relativePattern.pattern, GLOB_SPLIT);
|
||||
}
|
||||
|
||||
function parsePattern(arg1: string | IRelativePattern, options: IGlobOptions): ParsedStringPattern {
|
||||
if (!arg1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Handle IRelativePattern
|
||||
let pattern: string;
|
||||
if (typeof arg1 !== 'string') {
|
||||
pattern = toAbsolutePattern(arg1.pattern);
|
||||
} else {
|
||||
pattern = arg1;
|
||||
}
|
||||
|
||||
// Whitespace trimming
|
||||
pattern = pattern.trim();
|
||||
|
||||
@@ -276,7 +311,7 @@ function parsePattern(pattern: string, options: IGlobOptions): ParsedStringPatte
|
||||
const patternKey = `${pattern}_${!!options.trimForExclusions}`;
|
||||
let parsedPattern = CACHE.get(patternKey);
|
||||
if (parsedPattern) {
|
||||
return parsedPattern;
|
||||
return wrapRelativePattern(parsedPattern, pattern);
|
||||
}
|
||||
|
||||
// Check for Trivias
|
||||
@@ -304,7 +339,21 @@ function parsePattern(pattern: string, options: IGlobOptions): ParsedStringPatte
|
||||
// Cache
|
||||
CACHE.set(patternKey, parsedPattern);
|
||||
|
||||
return parsedPattern;
|
||||
return wrapRelativePattern(parsedPattern, pattern);
|
||||
}
|
||||
|
||||
function wrapRelativePattern(parsedPattern: ParsedStringPattern, arg2: string | IRelativePattern): ParsedStringPattern {
|
||||
if (typeof arg2 === 'string') {
|
||||
return parsedPattern;
|
||||
}
|
||||
|
||||
return function (path, basename) {
|
||||
if (!paths.isEqualOrParent(path, arg2.base)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return parsedPattern(path, basename);
|
||||
};
|
||||
}
|
||||
|
||||
function trimForExclusions(pattern: string, options: IGlobOptions): string {
|
||||
@@ -395,9 +444,9 @@ function toRegExp(pattern: string): ParsedStringPattern {
|
||||
* - simple brace expansion ({js,ts} => js or ts)
|
||||
* - character ranges (using [...])
|
||||
*/
|
||||
export function match(pattern: string, path: string): boolean;
|
||||
export function match(pattern: string | IRelativePattern, path: string): boolean;
|
||||
export function match(expression: IExpression, path: string, siblingsFn?: () => string[]): string /* the matching pattern */;
|
||||
export function match(arg1: string | IExpression, path: string, siblingsFn?: () => string[]): any {
|
||||
export function match(arg1: string | IExpression | IRelativePattern, path: string, siblingsFn?: () => string[]): any {
|
||||
if (!arg1 || !path) {
|
||||
return false;
|
||||
}
|
||||
@@ -413,16 +462,16 @@ export function match(arg1: string | IExpression, path: string, siblingsFn?: ()
|
||||
* - simple brace expansion ({js,ts} => js or ts)
|
||||
* - character ranges (using [...])
|
||||
*/
|
||||
export function parse(pattern: string, options?: IGlobOptions): ParsedPattern;
|
||||
export function parse(pattern: string | IRelativePattern, options?: IGlobOptions): ParsedPattern;
|
||||
export function parse(expression: IExpression, options?: IGlobOptions): ParsedExpression;
|
||||
export function parse(arg1: string | IExpression, options: IGlobOptions = {}): any {
|
||||
export function parse(arg1: string | IExpression | IRelativePattern, options: IGlobOptions = {}): any {
|
||||
if (!arg1) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Glob with String
|
||||
if (typeof arg1 === 'string') {
|
||||
const parsedPattern = parsePattern(arg1, options);
|
||||
if (typeof arg1 === 'string' || (arg1 as IRelativePattern).base) {
|
||||
const parsedPattern = parsePattern(arg1 as string | IRelativePattern, options);
|
||||
if (parsedPattern === NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ export function isEmptyMarkdownString(oneOrMany: IMarkdownString | IMarkdownStri
|
||||
export function isMarkdownString(thing: any): thing is IMarkdownString {
|
||||
if (thing instanceof MarkdownString) {
|
||||
return true;
|
||||
} else if (typeof thing === 'object') {
|
||||
} else if (thing && typeof thing === 'object') {
|
||||
return typeof (<IMarkdownString>thing).value === 'string'
|
||||
&& (typeof (<IMarkdownString>thing).isTrusted === 'boolean' || (<IMarkdownString>thing).isTrusted === void 0);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,9 @@ export function getPathLabel(resource: URI | string, rootProvider?: IWorkspaceFo
|
||||
if (typeof resource === 'string') {
|
||||
resource = URI.file(resource);
|
||||
}
|
||||
if (resource.scheme !== 'file' && resource.scheme !== 'untitled') {
|
||||
return resource.authority + resource.path;
|
||||
}
|
||||
|
||||
// return early if we can resolve a relative path label from the root
|
||||
const baseResource = rootProvider ? rootProvider.getWorkspaceFolder(resource) : null;
|
||||
|
||||
@@ -227,22 +227,16 @@ class Node<E> {
|
||||
readonly children = new Map<string, Node<E>>();
|
||||
}
|
||||
|
||||
/**
|
||||
* A trie map that allows for fast look up when keys are substrings
|
||||
* to the actual search keys (dir/subdir-problem).
|
||||
*/
|
||||
export class TrieMap<E> {
|
||||
export class TrieMap<K, V> {
|
||||
|
||||
static PathSplitter = (s: string) => s.split(/[\\/]/).filter(s => !!s);
|
||||
private readonly _splitter: (key: K) => string[];
|
||||
private _root = new Node<V>();
|
||||
|
||||
private readonly _splitter: (s: string) => string[];
|
||||
private _root = new Node<E>();
|
||||
|
||||
constructor(splitter: (s: string) => string[] = TrieMap.PathSplitter) {
|
||||
this._splitter = s => splitter(s).filter(s => Boolean(s));
|
||||
constructor(splitter: (key: K) => string[]) {
|
||||
this._splitter = key => splitter(key).filter(part => Boolean(part));
|
||||
}
|
||||
|
||||
insert(path: string, element: E): void {
|
||||
insert(path: K, element: V): void {
|
||||
const parts = this._splitter(path);
|
||||
let i = 0;
|
||||
|
||||
@@ -258,9 +252,9 @@ export class TrieMap<E> {
|
||||
}
|
||||
|
||||
// create new nodes
|
||||
let newNode: Node<E>;
|
||||
let newNode: Node<V>;
|
||||
for (; i < parts.length; i++) {
|
||||
newNode = new Node<E>();
|
||||
newNode = new Node<V>();
|
||||
node.children.set(parts[i], newNode);
|
||||
node = newNode;
|
||||
}
|
||||
@@ -268,11 +262,11 @@ export class TrieMap<E> {
|
||||
node.element = element;
|
||||
}
|
||||
|
||||
lookUp(path: string): E {
|
||||
lookUp(path: K): V {
|
||||
const parts = this._splitter(path);
|
||||
|
||||
let { children } = this._root;
|
||||
let node: Node<E>;
|
||||
let node: Node<V>;
|
||||
for (const part of parts) {
|
||||
node = children.get(part);
|
||||
if (!node) {
|
||||
@@ -284,10 +278,10 @@ export class TrieMap<E> {
|
||||
return node.element;
|
||||
}
|
||||
|
||||
findSubstr(path: string): E {
|
||||
findSubstr(path: K): V {
|
||||
const parts = this._splitter(path);
|
||||
|
||||
let lastNode: Node<E>;
|
||||
let lastNode: Node<V>;
|
||||
let { children } = this._root;
|
||||
for (const part of parts) {
|
||||
const node = children.get(part);
|
||||
@@ -308,11 +302,11 @@ export class TrieMap<E> {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
findSuperstr(path: string): TrieMap<E> {
|
||||
findSuperstr(path: K): TrieMap<K, V> {
|
||||
const parts = this._splitter(path);
|
||||
|
||||
let { children } = this._root;
|
||||
let node: Node<E>;
|
||||
let node: Node<V>;
|
||||
for (const part of parts) {
|
||||
node = children.get(part);
|
||||
if (!node) {
|
||||
@@ -321,12 +315,26 @@ export class TrieMap<E> {
|
||||
children = node.children;
|
||||
}
|
||||
|
||||
const result = new TrieMap<E>(this._splitter);
|
||||
const result = new TrieMap<K, V>(this._splitter);
|
||||
result._root = node;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A trie map that allows for fast look up when keys are substrings
|
||||
* to the actual search keys (dir/subdir-problem).
|
||||
*/
|
||||
export class StringTrieMap<E> extends TrieMap<string, E> {
|
||||
|
||||
static PathSplitter = (s: string) => s.split(/[\\/]/).filter(s => !!s);
|
||||
|
||||
constructor(splitter = StringTrieMap.PathSplitter) {
|
||||
super(splitter);
|
||||
}
|
||||
}
|
||||
|
||||
export class ResourceMap<T> {
|
||||
|
||||
protected map: Map<string, T>;
|
||||
|
||||
26
src/vs/base/common/resources.ts
Normal file
26
src/vs/base/common/resources.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import * as paths from 'vs/base/common/paths';
|
||||
import uri from 'vs/base/common/uri';
|
||||
|
||||
export function basenameOrAuthority(resource: uri): string {
|
||||
return paths.basename(resource.fsPath) || resource.authority;
|
||||
}
|
||||
|
||||
export function isEqualOrParent(first: uri, second: uri, ignoreCase?: boolean): boolean {
|
||||
if (first.scheme === second.scheme && first.authority === second.authority) {
|
||||
return paths.isEqualOrParent(first.fsPath, second.fsPath, ignoreCase);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function dirname(resource: uri): uri {
|
||||
return resource.with({
|
||||
path: paths.dirname(resource.path)
|
||||
});
|
||||
}
|
||||
@@ -21,6 +21,42 @@ function encodeNoop(str: string): string {
|
||||
}
|
||||
|
||||
|
||||
const _schemePattern = /^\w[\w\d+.-]*$/;
|
||||
const _singleSlashStart = /^\//;
|
||||
const _doubleSlashStart = /^\/\//;
|
||||
|
||||
function _validateUri(ret: URI): void {
|
||||
// scheme, https://tools.ietf.org/html/rfc3986#section-3.1
|
||||
// ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
|
||||
if (ret.scheme && !_schemePattern.test(ret.scheme)) {
|
||||
throw new Error('[UriError]: Scheme contains illegal characters.');
|
||||
}
|
||||
|
||||
// path, http://tools.ietf.org/html/rfc3986#section-3.3
|
||||
// If a URI contains an authority component, then the path component
|
||||
// must either be empty or begin with a slash ("/") character. If a URI
|
||||
// does not contain an authority component, then the path cannot begin
|
||||
// with two slash characters ("//").
|
||||
if (ret.path) {
|
||||
if (ret.authority) {
|
||||
if (!_singleSlashStart.test(ret.path)) {
|
||||
throw new Error('[UriError]: If a URI contains an authority component, then the path component must either be empty or begin with a slash ("/") character');
|
||||
}
|
||||
} else {
|
||||
if (_doubleSlashStart.test(ret.path)) {
|
||||
throw new Error('[UriError]: If a URI does not contain an authority component, then the path cannot begin with two slash characters ("//")');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const _empty = '';
|
||||
const _slash = '/';
|
||||
const _regexp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
|
||||
const _driveLetterPath = /^\/[a-zA-Z]:/;
|
||||
const _upperCaseDrive = /^(\/)?([A-Z]:)/;
|
||||
const _driveLetter = /^[a-zA-Z]:/;
|
||||
|
||||
/**
|
||||
* Uniform Resource Identifier (URI) http://tools.ietf.org/html/rfc3986.
|
||||
* This class is a simple parser which creates the basic component paths
|
||||
@@ -53,12 +89,6 @@ export default class URI {
|
||||
&& typeof (<URI>thing).scheme === 'string';
|
||||
}
|
||||
|
||||
private static _empty = '';
|
||||
private static _slash = '/';
|
||||
private static _regexp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
|
||||
private static _driveLetterPath = /^\/[a-zA-Z]:/;
|
||||
private static _upperCaseDrive = /^(\/)?([A-Z]:)/;
|
||||
|
||||
/**
|
||||
* scheme is the 'http' part of 'http://www.msft.com/some/path?query#fragment'.
|
||||
* The part before the first colon.
|
||||
@@ -86,21 +116,18 @@ export default class URI {
|
||||
*/
|
||||
readonly fragment: string;
|
||||
|
||||
private _formatted: string = null;
|
||||
private _fsPath: string = null;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
private constructor(scheme: string, authority: string, path: string, query: string, fragment: string) {
|
||||
protected constructor(scheme: string, authority: string, path: string, query: string, fragment: string) {
|
||||
|
||||
this.scheme = scheme || URI._empty;
|
||||
this.authority = authority || URI._empty;
|
||||
this.path = path || URI._empty;
|
||||
this.query = query || URI._empty;
|
||||
this.fragment = fragment || URI._empty;
|
||||
this.scheme = scheme || _empty;
|
||||
this.authority = authority || _empty;
|
||||
this.path = path || _empty;
|
||||
this.query = query || _empty;
|
||||
this.fragment = fragment || _empty;
|
||||
|
||||
this._validate(this);
|
||||
_validateUri(this);
|
||||
}
|
||||
|
||||
// ---- filesystem path -----------------------
|
||||
@@ -112,24 +139,7 @@ export default class URI {
|
||||
* invalid characters and semantics. Will *not* look at the scheme of this URI.
|
||||
*/
|
||||
get fsPath(): string {
|
||||
if (!this._fsPath) {
|
||||
let value: string;
|
||||
if (this.authority && this.path && this.scheme === 'file') {
|
||||
// unc path: file://shares/c$/far/boo
|
||||
value = `//${this.authority}${this.path}`;
|
||||
} else if (URI._driveLetterPath.test(this.path)) {
|
||||
// windows drive letter: file:///c:/far/boo
|
||||
value = this.path[1].toLowerCase() + this.path.substr(2);
|
||||
} else {
|
||||
// other path
|
||||
value = this.path;
|
||||
}
|
||||
if (platform.isWindows) {
|
||||
value = value.replace(/\//g, '\\');
|
||||
}
|
||||
this._fsPath = value;
|
||||
}
|
||||
return this._fsPath;
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
// ---- modify to new -------------------------
|
||||
@@ -176,60 +186,66 @@ export default class URI {
|
||||
return this;
|
||||
}
|
||||
|
||||
return new URI(scheme, authority, path, query, fragment);
|
||||
return new _URI(scheme, authority, path, query, fragment);
|
||||
}
|
||||
|
||||
// ---- parse & validate ------------------------
|
||||
|
||||
public static parse(value: string): URI {
|
||||
const match = URI._regexp.exec(value);
|
||||
const match = _regexp.exec(value);
|
||||
if (!match) {
|
||||
return new URI(URI._empty, URI._empty, URI._empty, URI._empty, URI._empty);
|
||||
return new _URI(_empty, _empty, _empty, _empty, _empty);
|
||||
}
|
||||
return new URI(
|
||||
match[2] || URI._empty,
|
||||
decodeURIComponent(match[4] || URI._empty),
|
||||
decodeURIComponent(match[5] || URI._empty),
|
||||
decodeURIComponent(match[7] || URI._empty),
|
||||
decodeURIComponent(match[9] || URI._empty),
|
||||
return new _URI(
|
||||
match[2] || _empty,
|
||||
decodeURIComponent(match[4] || _empty),
|
||||
decodeURIComponent(match[5] || _empty),
|
||||
decodeURIComponent(match[7] || _empty),
|
||||
decodeURIComponent(match[9] || _empty),
|
||||
);
|
||||
}
|
||||
|
||||
public static file(path: string): URI {
|
||||
|
||||
let authority = URI._empty;
|
||||
let authority = _empty;
|
||||
|
||||
// normalize to fwd-slashes on windows,
|
||||
// on other systems bwd-slashes are valid
|
||||
// filename character, eg /f\oo/ba\r.txt
|
||||
if (platform.isWindows) {
|
||||
path = path.replace(/\\/g, URI._slash);
|
||||
path = path.replace(/\\/g, _slash);
|
||||
}
|
||||
|
||||
// check for authority as used in UNC shares
|
||||
// or use the path as given
|
||||
if (path[0] === URI._slash && path[0] === path[1]) {
|
||||
let idx = path.indexOf(URI._slash, 2);
|
||||
if (path[0] === _slash && path[1] === _slash) {
|
||||
let idx = path.indexOf(_slash, 2);
|
||||
if (idx === -1) {
|
||||
authority = path.substring(2);
|
||||
path = URI._empty;
|
||||
path = _slash;
|
||||
} else {
|
||||
authority = path.substring(2, idx);
|
||||
path = path.substring(idx);
|
||||
path = path.substring(idx) || _slash;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that path starts with a slash
|
||||
// or that it is at least a slash
|
||||
if (path[0] !== URI._slash) {
|
||||
path = URI._slash + path;
|
||||
if (_driveLetter.test(path)) {
|
||||
path = _slash + path;
|
||||
|
||||
} else if (path[0] !== _slash) {
|
||||
// tricky -> makes invalid paths
|
||||
// but otherwise we have to stop
|
||||
// allowing relative paths...
|
||||
path = _slash + path;
|
||||
}
|
||||
|
||||
return new URI('file', authority, path, URI._empty, URI._empty);
|
||||
return new _URI('file', authority, path, _empty, _empty);
|
||||
}
|
||||
|
||||
public static from(components: { scheme?: string; authority?: string; path?: string; query?: string; fragment?: string }): URI {
|
||||
return new URI(
|
||||
return new _URI(
|
||||
components.scheme,
|
||||
components.authority,
|
||||
components.path,
|
||||
@@ -238,50 +254,97 @@ export default class URI {
|
||||
);
|
||||
}
|
||||
|
||||
private static _schemePattern = /^\w[\w\d+.-]*$/;
|
||||
private static _singleSlashStart = /^\//;
|
||||
private static _doubleSlashStart = /^\/\//;
|
||||
|
||||
private _validate(ret: URI): void {
|
||||
// scheme, https://tools.ietf.org/html/rfc3986#section-3.1
|
||||
// ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
|
||||
if (ret.scheme && !URI._schemePattern.test(ret.scheme)) {
|
||||
throw new Error('[UriError]: Scheme contains illegal characters.');
|
||||
}
|
||||
|
||||
// path, http://tools.ietf.org/html/rfc3986#section-3.3
|
||||
// If a URI contains an authority component, then the path component
|
||||
// must either be empty or begin with a slash ("/") character. If a URI
|
||||
// does not contain an authority component, then the path cannot begin
|
||||
// with two slash characters ("//").
|
||||
if (ret.path) {
|
||||
if (ret.authority) {
|
||||
if (!URI._singleSlashStart.test(ret.path)) {
|
||||
throw new Error('[UriError]: If a URI contains an authority component, then the path component must either be empty or begin with a slash ("/") character');
|
||||
}
|
||||
} else {
|
||||
if (URI._doubleSlashStart.test(ret.path)) {
|
||||
throw new Error('[UriError]: If a URI does not contain an authority component, then the path cannot begin with two slash characters ("//")');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---- printing/externalize ---------------------------
|
||||
|
||||
/**
|
||||
*
|
||||
* @param skipEncoding Do not encode the result, default is `false`
|
||||
*/
|
||||
public toString(skipEncoding: boolean = false): string {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
public toJSON(): any {
|
||||
const res = <UriState>{
|
||||
$mid: 1,
|
||||
fsPath: this.fsPath,
|
||||
external: this.toString(),
|
||||
};
|
||||
|
||||
if (this.path) {
|
||||
res.path = this.path;
|
||||
}
|
||||
|
||||
if (this.scheme) {
|
||||
res.scheme = this.scheme;
|
||||
}
|
||||
|
||||
if (this.authority) {
|
||||
res.authority = this.authority;
|
||||
}
|
||||
|
||||
if (this.query) {
|
||||
res.query = this.query;
|
||||
}
|
||||
|
||||
if (this.fragment) {
|
||||
res.fragment = this.fragment;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static revive(data: any): URI {
|
||||
let result = new _URI(
|
||||
(<UriState>data).scheme,
|
||||
(<UriState>data).authority,
|
||||
(<UriState>data).path,
|
||||
(<UriState>data).query,
|
||||
(<UriState>data).fragment
|
||||
);
|
||||
result._fsPath = (<UriState>data).fsPath;
|
||||
result._formatted = (<UriState>data).external;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// tslint:disable-next-line:class-name
|
||||
class _URI extends URI {
|
||||
|
||||
_formatted: string = null;
|
||||
_fsPath: string = null;
|
||||
|
||||
get fsPath(): string {
|
||||
if (!this._fsPath) {
|
||||
let value: string;
|
||||
if (this.authority && this.path && this.scheme === 'file') {
|
||||
// unc path: file://shares/c$/far/boo
|
||||
value = `//${this.authority}${this.path}`;
|
||||
} else if (_driveLetterPath.test(this.path)) {
|
||||
// windows drive letter: file:///c:/far/boo
|
||||
value = this.path[1].toLowerCase() + this.path.substr(2);
|
||||
} else {
|
||||
// other path
|
||||
value = this.path;
|
||||
}
|
||||
if (platform.isWindows) {
|
||||
value = value.replace(/\//g, '\\');
|
||||
}
|
||||
this._fsPath = value;
|
||||
}
|
||||
return this._fsPath;
|
||||
}
|
||||
|
||||
public toString(skipEncoding: boolean = false): string {
|
||||
if (!skipEncoding) {
|
||||
if (!this._formatted) {
|
||||
this._formatted = URI._asFormatted(this, false);
|
||||
this._formatted = _URI._asFormatted(this, false);
|
||||
}
|
||||
return this._formatted;
|
||||
} else {
|
||||
// we don't cache that
|
||||
return URI._asFormatted(this, true);
|
||||
return _URI._asFormatted(this, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,7 +386,7 @@ export default class URI {
|
||||
}
|
||||
if (path) {
|
||||
// lower-case windows drive letters in /C:/fff or C:/fff
|
||||
const m = URI._upperCaseDrive.exec(path);
|
||||
const m = _upperCaseDrive.exec(path);
|
||||
if (m) {
|
||||
if (m[1]) {
|
||||
path = '/' + m[2].toLowerCase() + path.substr(3); // "/c:".length === 3
|
||||
@@ -338,12 +401,12 @@ export default class URI {
|
||||
// cannot be parsed back again
|
||||
let lastIdx = 0;
|
||||
while (true) {
|
||||
let idx = path.indexOf(URI._slash, lastIdx);
|
||||
let idx = path.indexOf(_slash, lastIdx);
|
||||
if (idx === -1) {
|
||||
parts.push(encoder(path.substring(lastIdx)));
|
||||
break;
|
||||
}
|
||||
parts.push(encoder(path.substring(lastIdx, idx)), URI._slash);
|
||||
parts.push(encoder(path.substring(lastIdx, idx)), _slash);
|
||||
lastIdx = idx + 1;
|
||||
};
|
||||
}
|
||||
@@ -354,50 +417,7 @@ export default class URI {
|
||||
parts.push('#', encoder(fragment));
|
||||
}
|
||||
|
||||
return parts.join(URI._empty);
|
||||
}
|
||||
|
||||
public toJSON(): any {
|
||||
const res = <UriState>{
|
||||
fsPath: this.fsPath,
|
||||
external: this.toString(),
|
||||
$mid: 1
|
||||
};
|
||||
|
||||
if (this.path) {
|
||||
res.path = this.path;
|
||||
}
|
||||
|
||||
if (this.scheme) {
|
||||
res.scheme = this.scheme;
|
||||
}
|
||||
|
||||
if (this.authority) {
|
||||
res.authority = this.authority;
|
||||
}
|
||||
|
||||
if (this.query) {
|
||||
res.query = this.query;
|
||||
}
|
||||
|
||||
if (this.fragment) {
|
||||
res.fragment = this.fragment;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static revive(data: any): URI {
|
||||
let result = new URI(
|
||||
(<UriState>data).scheme,
|
||||
(<UriState>data).authority,
|
||||
(<UriState>data).path,
|
||||
(<UriState>data).query,
|
||||
(<UriState>data).fragment
|
||||
);
|
||||
result._fsPath = (<UriState>data).fsPath;
|
||||
result._formatted = (<UriState>data).external;
|
||||
return result;
|
||||
return parts.join(_empty);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
125
src/vs/base/node/console.ts
Normal file
125
src/vs/base/node/console.ts
Normal file
@@ -0,0 +1,125 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import URI from 'vs/base/common/uri';
|
||||
|
||||
export interface IRemoteConsoleLog {
|
||||
type: string;
|
||||
severity: string;
|
||||
arguments: string;
|
||||
}
|
||||
|
||||
interface IStackArgument {
|
||||
__$stack: string;
|
||||
}
|
||||
|
||||
export interface IStackFrame {
|
||||
uri: URI;
|
||||
line: number;
|
||||
column: number;
|
||||
}
|
||||
|
||||
export function isRemoteConsoleLog(obj: any): obj is IRemoteConsoleLog {
|
||||
const entry = obj as IRemoteConsoleLog;
|
||||
|
||||
return entry && typeof entry.type === 'string' && typeof entry.severity === 'string';
|
||||
}
|
||||
|
||||
export function parse(entry: IRemoteConsoleLog): { args: any[], stack?: string } {
|
||||
const args: any[] = [];
|
||||
let stack: string;
|
||||
|
||||
// Parse Entry
|
||||
try {
|
||||
const parsedArguments: any[] = JSON.parse(entry.arguments);
|
||||
|
||||
// Check for special stack entry as last entry
|
||||
const stackArgument = parsedArguments[parsedArguments.length - 1] as IStackArgument;
|
||||
if (stackArgument && stackArgument.__$stack) {
|
||||
parsedArguments.pop(); // stack is handled specially
|
||||
stack = stackArgument.__$stack;
|
||||
}
|
||||
|
||||
args.push(...parsedArguments);
|
||||
} catch (error) {
|
||||
args.push('Unable to log remote console arguments', entry.arguments);
|
||||
}
|
||||
|
||||
return { args, stack };
|
||||
}
|
||||
|
||||
export function getFirstFrame(entry: IRemoteConsoleLog): IStackFrame;
|
||||
export function getFirstFrame(stack: string): IStackFrame;
|
||||
export function getFirstFrame(arg0: IRemoteConsoleLog | string): IStackFrame {
|
||||
if (typeof arg0 !== 'string') {
|
||||
return getFirstFrame(parse(arg0).stack);
|
||||
}
|
||||
|
||||
// Parse a source information out of the stack if we have one. Format:
|
||||
// at vscode.commands.registerCommand (/Users/someone/Desktop/test-ts/out/src/extension.js:18:17)
|
||||
const stack = arg0;
|
||||
if (stack) {
|
||||
const matches = /.+\((.+):(\d+):(\d+)\)/.exec(stack);
|
||||
if (matches.length === 4) {
|
||||
return {
|
||||
uri: URI.file(matches[1]),
|
||||
line: Number(matches[2]),
|
||||
column: Number(matches[3])
|
||||
} as IStackFrame;
|
||||
}
|
||||
}
|
||||
|
||||
return void 0;
|
||||
}
|
||||
|
||||
export function log(entry: IRemoteConsoleLog, label: string): void {
|
||||
const { args, stack } = parse(entry);
|
||||
|
||||
// Determine suffix based on severity of log entry if we have a stack
|
||||
let suffixColor = 'blue';
|
||||
let suffix = '';
|
||||
if (stack) {
|
||||
switch (entry.severity) {
|
||||
case 'warn':
|
||||
suffixColor = 'goldenrod';
|
||||
suffix = ' WARNING:';
|
||||
break;
|
||||
case 'error':
|
||||
suffixColor = 'darkred';
|
||||
suffix = ' ERROR:';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let consoleArgs = [];
|
||||
|
||||
// First arg is a string
|
||||
if (typeof args[0] === 'string') {
|
||||
consoleArgs = [`%c[${label}]%c${suffix} %c${args[0]}`, color('blue'), color(suffixColor), color('black'), ...args.slice(1)];
|
||||
}
|
||||
|
||||
// First arg is something else, just apply all
|
||||
else {
|
||||
consoleArgs = [`%c[${label}]%c${suffix}`, color('blue'), color(suffixColor), ...args];
|
||||
}
|
||||
|
||||
// Stack: use console group
|
||||
if (stack) {
|
||||
console.groupCollapsed.apply(console, consoleArgs);
|
||||
console.log(stack);
|
||||
console.groupEnd();
|
||||
}
|
||||
|
||||
// No stack: just log message
|
||||
else {
|
||||
console[entry.severity].apply(console, consoleArgs);
|
||||
}
|
||||
}
|
||||
|
||||
function color(color: string): string {
|
||||
return `color: ${color}; font-weight: normal;`;
|
||||
}
|
||||
@@ -9,7 +9,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import * as uuid from 'vs/base/common/uuid';
|
||||
import { networkInterfaces } from 'os';
|
||||
import { TrieMap } from 'vs/base/common/map';
|
||||
import { StringTrieMap } from 'vs/base/common/map';
|
||||
|
||||
// http://www.techrepublic.com/blog/data-center/mac-address-scorecard-for-common-virtual-machine-platforms/
|
||||
// VMware ESX 3, Server, Workstation, Player 00-50-56, 00-0C-29, 00-05-69
|
||||
@@ -23,12 +23,12 @@ import { TrieMap } from 'vs/base/common/map';
|
||||
// Sun xVM VirtualBox 08-00-27
|
||||
export const virtualMachineHint: { value(): number } = new class {
|
||||
|
||||
private _virtualMachineOUIs: TrieMap<boolean>;
|
||||
private _virtualMachineOUIs: StringTrieMap<boolean>;
|
||||
private _value: number;
|
||||
|
||||
private _isVirtualMachineMacAdress(mac: string): boolean {
|
||||
if (!this._virtualMachineOUIs) {
|
||||
this._virtualMachineOUIs = new TrieMap<boolean>(s => s.split(/[-:]/));
|
||||
this._virtualMachineOUIs = new StringTrieMap<boolean>(s => s.split(/[-:]/));
|
||||
// this._virtualMachineOUIs.insert('00-00-00', true);
|
||||
this._virtualMachineOUIs.insert('00-50-56', true);
|
||||
this._virtualMachineOUIs.insert('00-0C-29', true);
|
||||
|
||||
@@ -56,7 +56,7 @@ const ZERO_BYTE_DETECTION_BUFFER_MAX_LEN = 512; // number of bytes to look at to
|
||||
const NO_GUESS_BUFFER_MAX_LEN = 512; // when not auto guessing the encoding, small number of bytes are enough
|
||||
const AUTO_GUESS_BUFFER_MAX_LEN = 512 * 8; // with auto guessing we want a lot more content to be read for guessing
|
||||
|
||||
function maxBufferLen(arg1?: DetectMimesOption | boolean): number {
|
||||
export function maxBufferLen(arg1?: DetectMimesOption | boolean): number {
|
||||
let autoGuessEncoding: boolean;
|
||||
if (typeof arg1 === 'boolean') {
|
||||
autoGuessEncoding = arg1;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
terminateTree() {
|
||||
for cpid in $(/usr/bin/pgrep -P $1); do
|
||||
|
||||
@@ -12,6 +12,7 @@ import { Emitter } from 'vs/base/common/event';
|
||||
import { fromEventEmitter } from 'vs/base/node/event';
|
||||
import { createQueuedSender } from 'vs/base/node/processes';
|
||||
import { ChannelServer as IPCServer, ChannelClient as IPCClient, IChannelClient, IChannel } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { isRemoteConsoleLog, log } from 'vs/base/node/console';
|
||||
|
||||
export class Server extends IPCServer {
|
||||
constructor() {
|
||||
@@ -151,24 +152,15 @@ export class Client implements IChannelClient, IDisposable {
|
||||
const onRawMessage = fromEventEmitter(this.child, 'message', msg => msg);
|
||||
|
||||
onRawMessage(msg => {
|
||||
// Handle console logs specially
|
||||
if (msg && msg.type === '__$console') {
|
||||
let args = ['%c[IPC Library: ' + this.options.serverName + ']', 'color: darkgreen'];
|
||||
try {
|
||||
const parsed = JSON.parse(msg.arguments);
|
||||
args = args.concat(Object.getOwnPropertyNames(parsed).map(o => parsed[o]));
|
||||
} catch (error) {
|
||||
args.push(msg.arguments);
|
||||
}
|
||||
|
||||
console[msg.severity].apply(console, args);
|
||||
// Handle remote console logs specially
|
||||
if (isRemoteConsoleLog(msg)) {
|
||||
log(msg, `IPC Library: ${this.options.serverName}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
// Anything else goes to the outside
|
||||
else {
|
||||
onMessageEmitter.fire(msg);
|
||||
}
|
||||
onMessageEmitter.fire(msg);
|
||||
});
|
||||
|
||||
const sender = this.options.useQueue ? createQueuedSender(this.child) : this.child;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
'use strict';
|
||||
|
||||
|
||||
import { BoundedMap, TrieMap, ResourceMap } from 'vs/base/common/map';
|
||||
import { BoundedMap, StringTrieMap, ResourceMap } from 'vs/base/common/map';
|
||||
import * as assert from 'assert';
|
||||
import URI from 'vs/base/common/uri';
|
||||
|
||||
@@ -314,7 +314,7 @@ suite('Map', () => {
|
||||
|
||||
test('TrieMap - basics', function () {
|
||||
|
||||
const map = new TrieMap<number>();
|
||||
const map = new StringTrieMap<number>();
|
||||
|
||||
map.insert('/user/foo/bar', 1);
|
||||
map.insert('/user/foo', 2);
|
||||
@@ -332,7 +332,7 @@ suite('Map', () => {
|
||||
|
||||
test('TrieMap - lookup', function () {
|
||||
|
||||
const map = new TrieMap<number>();
|
||||
const map = new StringTrieMap<number>();
|
||||
map.insert('/user/foo/bar', 1);
|
||||
map.insert('/user/foo', 2);
|
||||
map.insert('/user/foo/flip/flop', 3);
|
||||
@@ -346,7 +346,7 @@ suite('Map', () => {
|
||||
|
||||
test('TrieMap - superstr', function () {
|
||||
|
||||
const map = new TrieMap<number>();
|
||||
const map = new StringTrieMap<number>();
|
||||
map.insert('/user/foo/bar', 1);
|
||||
map.insert('/user/foo', 2);
|
||||
map.insert('/user/foo/flip/flop', 3);
|
||||
|
||||
@@ -884,4 +884,35 @@ suite('Glob', () => {
|
||||
// Later expressions take precedence
|
||||
assert.deepEqual(glob.mergeExpressions({ 'a': true, 'b': false, 'c': true }, { 'a': false, 'b': true }), { 'a': false, 'b': true, 'c': true });
|
||||
});
|
||||
|
||||
test('relative pattern', function () {
|
||||
let p: glob.IRelativePattern = { base: '/DNXConsoleApp', pattern: '**/*.cs' };
|
||||
|
||||
assert(glob.match(p, '/DNXConsoleApp/Program.cs'));
|
||||
assert(glob.match(p, '/DNXConsoleApp/foo/Program.cs'));
|
||||
assert(!glob.match(p, '/DNXConsoleApp/foo/Program.ts'));
|
||||
assert(!glob.match(p, '/other/DNXConsoleApp/foo/Program.ts'));
|
||||
|
||||
p = { base: 'C:\\DNXConsoleApp', pattern: '**/*.cs' };
|
||||
assert(glob.match(p, 'C:\\DNXConsoleApp\\Program.cs'));
|
||||
assert(glob.match(p, 'C:\\DNXConsoleApp\\foo\\Program.cs'));
|
||||
assert(!glob.match(p, 'C:\\DNXConsoleApp\\foo\\Program.ts'));
|
||||
assert(!glob.match(p, 'C:\\other\\DNXConsoleApp\\foo\\Program.ts'));
|
||||
|
||||
assert(glob.match(p, 'C:/DNXConsoleApp/Program.cs'));
|
||||
assert(glob.match(p, 'C:/DNXConsoleApp/foo/Program.cs'));
|
||||
assert(!glob.match(p, 'C:/DNXConsoleApp/foo/Program.ts'));
|
||||
assert(!glob.match(p, 'C:/other/DNXConsoleApp/foo/Program.ts'));
|
||||
|
||||
p = { base: 'C:/DNXConsoleApp', pattern: '**/*.cs' };
|
||||
assert(glob.match(p, 'C:\\DNXConsoleApp\\Program.cs'));
|
||||
assert(glob.match(p, 'C:\\DNXConsoleApp\\foo\\Program.cs'));
|
||||
assert(!glob.match(p, 'C:\\DNXConsoleApp\\foo\\Program.ts'));
|
||||
assert(!glob.match(p, 'C:\\other\\DNXConsoleApp\\foo\\Program.ts'));
|
||||
|
||||
assert(glob.match(p, 'C:/DNXConsoleApp/Program.cs'));
|
||||
assert(glob.match(p, 'C:/DNXConsoleApp/foo/Program.cs'));
|
||||
assert(!glob.match(p, 'C:/DNXConsoleApp/foo/Program.ts'));
|
||||
assert(!glob.match(p, 'C:/other/DNXConsoleApp/foo/Program.ts'));
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user