Merge branch 'master' into electron-2.0.x

This commit is contained in:
Benjamin Pasero 2018-07-09 17:40:32 +02:00
commit 50f90e4275
378 changed files with 8197 additions and 3888 deletions

View file

@ -1,9 +1,9 @@
---
name: Question
about: The issue tracker is not for questions. Please ask questions on https://stackoverflow.com/questions/tagged/vscode.
about: The issue tracker is not for questions. Please ask questions on https://stackoverflow.com/questions/tagged/visual-studio-code.
---
🚨 The issue tracker is not for questions 🚨
If you have a question, please ask it on https://stackoverflow.com/questions/tagged/vscode.
If you have a question, please ask it on https://stackoverflow.com/questions/tagged/visual-studio-code.

View file

@ -1,12 +1,12 @@
[
{
"name": "ms-vscode.node-debug",
"version": "1.26.0",
"version": "1.26.1",
"repo": "https://github.com/Microsoft/vscode-node-debug"
},
{
"name": "ms-vscode.node-debug2",
"version": "1.25.5",
"version": "1.26.1",
"repo": "https://github.com/Microsoft/vscode-node-debug2"
}
]

View file

@ -15,7 +15,6 @@ const cp = require('child_process');
var root = path.dirname(__dirname);
var sha1 = util.getVersion(root);
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
var semver = require('./monaco/package.json').version;
var headerVersion = semver + '(' + sha1 + ')';
@ -230,7 +229,7 @@ gulp.task('editor-distro', ['clean-editor-distro', 'compile-editor-esm', 'minify
});
gulp.task('analyze-editor-distro', function () {
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
// @ts-ignore
var bundleInfo = require('../out-editor/bundleInfo.json');
var graph = bundleInfo.graph;
var bundles = bundleInfo.bundles;

View file

@ -15,7 +15,6 @@ const remote = require('gulp-remote-src');
const zip = require('gulp-vinyl-zip');
const assign = require('object-assign');
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const pkg = require('../package.json');
gulp.task('mixin', function () {
@ -56,7 +55,6 @@ gulp.task('mixin', function () {
.pipe(util.rebase(2))
.pipe(productJsonFilter)
.pipe(buffer())
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
.pipe(json(o => assign({}, require('../product.json'), o)))
.pipe(productJsonFilter.restore);

View file

@ -25,9 +25,7 @@ const buildfile = require('../src/buildfile');
const common = require('./lib/optimize');
const root = path.dirname(__dirname);
const commit = util.getVersion(root);
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const packageJson = require('../package.json');
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const product = require('../product.json');
const crypto = require('crypto');
const i18n = require('./lib/i18n');
@ -40,12 +38,12 @@ const productionDependencies = deps.getProductionDependencies(path.dirname(__dir
// @ts-ignore
const baseModules = Object.keys(process.binding('natives')).filter(n => !/^_|\//.test(n));
const nodeModules = ['electron', 'original-fs']
// @ts-ignore JSON checking: dependencies property is optional
.concat(Object.keys(product.dependencies || {}))
.concat(_.uniq(productionDependencies.map(d => d.name)))
.concat(baseModules);
// Build
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const builtInExtensions = require('./builtInExtensions.json');
const excludedExtensions = [
@ -120,6 +118,8 @@ gulp.task('clean-minified-vscode', util.rimraf('out-vscode-min'));
gulp.task('minify-vscode', ['clean-minified-vscode', 'optimize-index-js'], common.minifyTask('out-vscode', baseUrl));
// Package
// @ts-ignore JSON checking: darwinCredits is optional
const darwinCreditsTemplate = product.darwinCredits && _.template(fs.readFileSync(path.join(root, product.darwinCredits), 'utf8'));
const config = {
@ -148,6 +148,8 @@ const config = {
linuxExecutableName: product.applicationName,
winIcon: 'resources/win32/code.ico',
token: process.env['VSCODE_MIXIN_PASSWORD'] || process.env['GITHUB_TOKEN'] || void 0,
// @ts-ignore JSON checking: electronRepository is optional
repo: product.electronRepository || void 0
};
@ -255,6 +257,7 @@ function packageTask(platform, arch, opts) {
.pipe(filter(['**', '!**/*.js.map']));
let version = packageJson.version;
// @ts-ignore JSON checking: quality is optional
const quality = product.quality;
if (quality && quality !== 'stable') {
@ -268,10 +271,8 @@ function packageTask(platform, arch, opts) {
const date = new Date().toISOString();
const productJsonUpdate = { commit, date, checksums };
try {
if (shouldSetupSettingsSearch()) {
productJsonUpdate.settingsSearchBuildId = getSettingsSearchBuildId(packageJson);
} catch (err) {
console.warn(err);
}
const productJsonStream = gulp.src(['product.json'], { base: '.' })
@ -286,6 +287,7 @@ function packageTask(platform, arch, opts) {
const depsSrc = [
..._.flatten(productionDependencies.map(d => path.relative(root, d.path)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`])),
// @ts-ignore JSON checking: dependencies is optional
..._.flatten(Object.keys(product.dependencies || {}).map(d => [`node_modules/${d}/**`, `!node_modules/${d}/**/{test,tests}/**`]))
];
@ -470,9 +472,8 @@ gulp.task('upload-vscode-sourcemaps', ['minify-vscode'], () => {
const allConfigDetailsPath = path.join(os.tmpdir(), 'configuration.json');
gulp.task('upload-vscode-configuration', ['generate-vscode-configuration'], () => {
const branch = process.env.BUILD_SOURCEBRANCH;
if (!/\/master$/.test(branch) && branch.indexOf('/release/') < 0) {
if (!shouldSetupSettingsSearch()) {
const branch = process.env.BUILD_SOURCEBRANCH;
console.log(`Only runs on master and release branches, not ${branch}`);
return;
}
@ -495,13 +496,24 @@ gulp.task('upload-vscode-configuration', ['generate-vscode-configuration'], () =
}));
});
function getSettingsSearchBuildId(packageJson) {
const previous = util.getPreviousVersion(packageJson.version);
function shouldSetupSettingsSearch() {
const branch = process.env.BUILD_SOURCEBRANCH;
return branch && (/\/master$/.test(branch) || branch.indexOf('/release/') >= 0);
}
function getSettingsSearchBuildId(packageJson) {
try {
const out = cp.execSync(`git rev-list ${previous}..HEAD --count`);
const branch = process.env.BUILD_SOURCEBRANCH;
const branchId = branch.indexOf('/release/') >= 0 ? 0 :
/\/master$/.test(branch) ? 1 :
2; // Some unexpected branch
const out = cp.execSync(`git rev-list HEAD --count`);
const count = parseInt(out.toString());
return util.versionStringToNumber(packageJson.version) * 1e4 + count;
// <version number><commit count><branchId (avoid unlikely conflicts)>
// 1.25.1, 1,234,567 commits, master = 1250112345671
return util.versionStringToNumber(packageJson.version) * 1e8 + count * 10 + branchId;
} catch (e) {
throw new Error('Could not determine build number: ' + e.toString());
}

View file

@ -12,11 +12,8 @@ const shell = require('gulp-shell');
const es = require('event-stream');
const vfs = require('vinyl-fs');
const util = require('./lib/util');
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const packageJson = require('../package.json');
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const product = require('../product.json');
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const rpmDependencies = require('../resources/linux/rpm/dependencies.json');
const linuxPackageRevision = Math.floor(new Date().getTime() / 1000);
@ -75,7 +72,9 @@ function prepareDebPackage(arch) {
const postinst = gulp.src('resources/linux/debian/postinst.template', { base: '.' })
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@ARCHITECTURE@@', debArch))
// @ts-ignore JSON checking: quality is optional
.pipe(replace('@@QUALITY@@', product.quality || '@@QUALITY@@'))
// @ts-ignore JSON checking: updateUrl is optional
.pipe(replace('@@UPDATEURL@@', product.updateUrl || '@@UPDATEURL@@'))
.pipe(rename('DEBIAN/postinst'));
@ -133,7 +132,9 @@ function prepareRpmPackage(arch) {
.pipe(replace('@@RELEASE@@', linuxPackageRevision))
.pipe(replace('@@ARCHITECTURE@@', rpmArch))
.pipe(replace('@@LICENSE@@', product.licenseName))
// @ts-ignore JSON checking: quality is optional
.pipe(replace('@@QUALITY@@', product.quality || '@@QUALITY@@'))
// @ts-ignore JSON checking: updateUrl is optional
.pipe(replace('@@UPDATEURL@@', product.updateUrl || '@@UPDATEURL@@'))
.pipe(replace('@@DEPENDENCIES@@', rpmDependencies[rpmArch].join(', ')))
.pipe(rename('SPECS/' + product.applicationName + '.spec'));

View file

@ -12,9 +12,7 @@ const assert = require('assert');
const cp = require('child_process');
const _7z = require('7zip')['7z'];
const util = require('./lib/util');
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const pkg = require('../package.json');
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const product = require('../product.json');
const vfs = require('vinyl-fs');
const mkdirp = require('mkdirp');

View file

@ -17,7 +17,6 @@ const ext = require('./extensions');
const util = require('gulp-util');
const root = path.dirname(path.dirname(__dirname));
// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
const builtInExtensions = require('../builtInExtensions.json');
const controlFilePath = path.join(os.homedir(), '.vscode-oss-dev', 'extensions', 'control.json');

View file

@ -22,6 +22,7 @@ import * as gulpUtil from 'gulp-util';
import * as flatmap from 'gulp-flatmap';
import * as pump from 'pump';
import * as sm from 'source-map';
import { Language } from './i18n';
const REPO_ROOT_PATH = path.join(__dirname, '../..');
@ -159,6 +160,10 @@ export interface IOptimizeTaskOpts {
* (out folder name)
*/
out: string;
/**
* (out folder name)
*/
languages?: Language[];
}
export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStream {

View file

@ -1,56 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
var assert = require("assert");
var util = require("../util");
function getMockTagExists(tags) {
return function (tag) { return tags.indexOf(tag) >= 0; };
}
suite('util tests', function () {
test('getPreviousVersion - patch', function () {
assert.equal(util.getPreviousVersion('1.2.3', getMockTagExists(['1.2.2', '1.2.1', '1.2.0', '1.1.0'])), '1.2.2');
});
test('getPreviousVersion - patch invalid', function () {
try {
util.getPreviousVersion('1.2.2', getMockTagExists(['1.2.0', '1.1.0']));
}
catch (e) {
// expected
return;
}
throw new Error('Expected an exception');
});
test('getPreviousVersion - minor', function () {
assert.equal(util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.1.1', '1.1.2', '1.1.3'])), '1.1.3');
assert.equal(util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.0.0'])), '1.1.0');
});
test('getPreviousVersion - minor gap', function () {
assert.equal(util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.1.1', '1.1.3'])), '1.1.1');
});
test('getPreviousVersion - minor invalid', function () {
try {
util.getPreviousVersion('1.2.0', getMockTagExists(['1.0.0']));
}
catch (e) {
// expected
return;
}
throw new Error('Expected an exception');
});
test('getPreviousVersion - major', function () {
assert.equal(util.getPreviousVersion('2.0.0', getMockTagExists(['1.0.0', '1.1.0', '1.2.0', '1.2.1', '1.2.2'])), '1.2.2');
});
test('getPreviousVersion - major invalid', function () {
try {
util.getPreviousVersion('3.0.0', getMockTagExists(['1.0.0']));
}
catch (e) {
// expected
return;
}
throw new Error('Expected an exception');
});
});

View file

@ -1,79 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import assert = require('assert');
import util = require('../util');
function getMockTagExists(tags: string[]) {
return (tag: string) => tags.indexOf(tag) >= 0;
}
suite('util tests', () => {
test('getPreviousVersion - patch', () => {
assert.equal(
util.getPreviousVersion('1.2.3', getMockTagExists(['1.2.2', '1.2.1', '1.2.0', '1.1.0'])),
'1.2.2'
);
});
test('getPreviousVersion - patch invalid', () => {
try {
util.getPreviousVersion('1.2.2', getMockTagExists(['1.2.0', '1.1.0']));
} catch (e) {
// expected
return;
}
throw new Error('Expected an exception');
});
test('getPreviousVersion - minor', () => {
assert.equal(
util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.1.1', '1.1.2', '1.1.3'])),
'1.1.3'
);
assert.equal(
util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.0.0'])),
'1.1.0'
);
});
test('getPreviousVersion - minor gap', () => {
assert.equal(
util.getPreviousVersion('1.2.0', getMockTagExists(['1.1.0', '1.1.1', '1.1.3'])),
'1.1.1'
);
});
test('getPreviousVersion - minor invalid', () => {
try {
util.getPreviousVersion('1.2.0', getMockTagExists(['1.0.0']));
} catch (e) {
// expected
return;
}
throw new Error('Expected an exception');
});
test('getPreviousVersion - major', () => {
assert.equal(
util.getPreviousVersion('2.0.0', getMockTagExists(['1.0.0', '1.1.0', '1.2.0', '1.2.1', '1.2.2'])),
'1.2.2'
);
});
test('getPreviousVersion - major invalid', () => {
try {
util.getPreviousVersion('3.0.0', getMockTagExists(['1.0.0']));
} catch (e) {
// expected
return;
}
throw new Error('Expected an exception');
});
});

View file

@ -14,7 +14,6 @@ var fs = require("fs");
var _rimraf = require("rimraf");
var git = require("./git");
var VinylFile = require("vinyl");
var cp = require("child_process");
var NoCancellationToken = { isCancellationRequested: function () { return false; } };
function incremental(streamProvider, initial, supportsCancellation) {
var input = es.through();
@ -211,62 +210,6 @@ function filter(fn) {
return result;
}
exports.filter = filter;
function tagExists(tagName) {
try {
cp.execSync("git rev-parse " + tagName, { stdio: 'ignore' });
return true;
}
catch (e) {
return false;
}
}
/**
* Returns the version previous to the given version. Throws if a git tag for that version doesn't exist.
* Given 1.17.2, return 1.17.1
* 1.18.0 => 1.17.2. (or the highest 1.17.x)
* 2.0.0 => 1.18.0 (or the highest 1.x)
*/
function getPreviousVersion(versionStr, _tagExists) {
if (_tagExists === void 0) { _tagExists = tagExists; }
function getLatestTagFromBase(semverArr, componentToTest) {
var baseVersion = semverArr.join('.');
if (!_tagExists(baseVersion)) {
throw new Error('Failed to find git tag for base version, ' + baseVersion);
}
var goodTag;
do {
goodTag = semverArr.join('.');
semverArr[componentToTest]++;
} while (_tagExists(semverArr.join('.')));
return goodTag;
}
var semverArr = versionStringToNumberArray(versionStr);
if (semverArr[2] > 0) {
semverArr[2]--;
var previous = semverArr.join('.');
if (!_tagExists(previous)) {
throw new Error('Failed to find git tag for previous version, ' + previous);
}
return previous;
}
else if (semverArr[1] > 0) {
semverArr[1]--;
return getLatestTagFromBase(semverArr, 2);
}
else {
semverArr[0]--;
// Find 1.x.0 for latest x
var latestMinorVersion = getLatestTagFromBase(semverArr, 1);
// Find 1.x.y for latest y
return getLatestTagFromBase(versionStringToNumberArray(latestMinorVersion), 2);
}
}
exports.getPreviousVersion = getPreviousVersion;
function versionStringToNumberArray(versionStr) {
return versionStr
.split('.')
.map(function (s) { return parseInt(s); });
}
function versionStringToNumber(versionStr) {
var semverRegex = /(\d+)\.(\d+)\.(\d+)/;
var match = versionStr.match(semverRegex);

View file

@ -17,7 +17,6 @@ import * as git from './git';
import * as VinylFile from 'vinyl';
import { ThroughStream } from 'through';
import * as sm from 'source-map';
import * as cp from 'child_process';
export interface ICancellationToken {
isCancellationRequested(): boolean;
@ -271,66 +270,6 @@ export function filter(fn: (data: any) => boolean): FilterStream {
return result;
}
function tagExists(tagName: string): boolean {
try {
cp.execSync(`git rev-parse ${tagName}`, { stdio: 'ignore' });
return true;
} catch (e) {
return false;
}
}
/**
* Returns the version previous to the given version. Throws if a git tag for that version doesn't exist.
* Given 1.17.2, return 1.17.1
* 1.18.0 => 1.17.2. (or the highest 1.17.x)
* 2.0.0 => 1.18.0 (or the highest 1.x)
*/
export function getPreviousVersion(versionStr: string, _tagExists = tagExists) {
function getLatestTagFromBase(semverArr: number[], componentToTest: number): string {
const baseVersion = semverArr.join('.');
if (!_tagExists(baseVersion)) {
throw new Error('Failed to find git tag for base version, ' + baseVersion);
}
let goodTag;
do {
goodTag = semverArr.join('.');
semverArr[componentToTest]++;
} while (_tagExists(semverArr.join('.')));
return goodTag;
}
const semverArr = versionStringToNumberArray(versionStr);
if (semverArr[2] > 0) {
semverArr[2]--;
const previous = semverArr.join('.');
if (!_tagExists(previous)) {
throw new Error('Failed to find git tag for previous version, ' + previous);
}
return previous;
} else if (semverArr[1] > 0) {
semverArr[1]--;
return getLatestTagFromBase(semverArr, 2);
} else {
semverArr[0]--;
// Find 1.x.0 for latest x
const latestMinorVersion = getLatestTagFromBase(semverArr, 1);
// Find 1.x.y for latest y
return getLatestTagFromBase(versionStringToNumberArray(latestMinorVersion), 2);
}
}
function versionStringToNumberArray(versionStr: string): number[] {
return versionStr
.split('.')
.map(s => parseInt(s));
}
export function versionStringToNumber(versionStr: string) {
const semverRegex = /(\d+)\.(\d+)\.(\d+)/;
const match = versionStr.match(semverRegex);

View file

@ -6,6 +6,7 @@
"removeComments": false,
"preserveConstEnums": true,
"sourceMap": false,
"resolveJsonModule": true,
"experimentalDecorators": true,
// enable JavaScript type checking for the language service
// use the tsconfig.build.json for compiling wich disable JavaScript

View file

@ -545,33 +545,6 @@
],
"isProd": true
},
{
"name": "retep998/winapi-rs",
"version": "0.4.0",
"repositoryUrl": "https://github.com/retep998/winapi-rs",
"licenseDetail": [
"Copyright (c) 2015 The winapi-rs Developers",
"",
"Permission is hereby granted, free of charge, to any person obtaining a copy",
"of this software and associated documentation files (the \"Software\"), to deal",
"in the Software without restriction, including without limitation the rights",
"to use, copy, modify, merge, publish, distribute, sublicense, and/or sell",
"copies of the Software, and to permit persons to whom the Software is",
"furnished to do so, subject to the following conditions:",
"",
"The above copyright notice and this permission notice shall be included in all",
"copies or substantial portions of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR",
"IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",
"FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE",
"AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",
"LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,",
"OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE",
"SOFTWARE."
],
"isProd": true
},
{
"name": "retep998/winapi-rs",
"version": "0.2.8",
@ -601,7 +574,7 @@
},
{
"name": "retep998/winapi-rs",
"version": "0.2.2",
"version": "0.1.1",
"repositoryUrl": "https://github.com/retep998/winapi-rs",
"licenseDetail": [
"Copyright (c) 2015 The winapi-rs Developers",
@ -655,7 +628,34 @@
},
{
"name": "retep998/winapi-rs",
"version": "0.1.1",
"version": "0.4.0",
"repositoryUrl": "https://github.com/retep998/winapi-rs",
"licenseDetail": [
"Copyright (c) 2015 The winapi-rs Developers",
"",
"Permission is hereby granted, free of charge, to any person obtaining a copy",
"of this software and associated documentation files (the \"Software\"), to deal",
"in the Software without restriction, including without limitation the rights",
"to use, copy, modify, merge, publish, distribute, sublicense, and/or sell",
"copies of the Software, and to permit persons to whom the Software is",
"furnished to do so, subject to the following conditions:",
"",
"The above copyright notice and this permission notice shall be included in all",
"copies or substantial portions of the Software.",
"",
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR",
"IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",
"FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE",
"AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",
"LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,",
"OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE",
"SOFTWARE."
],
"isProd": true
},
{
"name": "retep998/winapi-rs",
"version": "0.2.2",
"repositoryUrl": "https://github.com/retep998/winapi-rs",
"licenseDetail": [
"Copyright (c) 2015 The winapi-rs Developers",
@ -1791,4 +1791,4 @@
],
"isProd": true
}
]
]

View file

@ -92,7 +92,7 @@ Filename: "{app}\{#ExeBasename}.exe"; Description: "{cm:LaunchProgram,{#NameLong
#if "user" == InstallTarget
#define SoftwareClassesRootKey "HKCU"
#else
#define SoftwareClassesRootKey "HKCR"
#define SoftwareClassesRootKey "HKLM"
#endif
Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\.ascx\OpenWithProgids"; ValueType: none; ValueName: "{#RegValueName}"; Flags: deletevalue uninsdeletevalue; Tasks: associatewithfiles
@ -946,7 +946,7 @@ Root: {#SoftwareClassesRootKey}; Subkey: "Software\Classes\Drive\shell\{#RegValu
#define Uninstall64RootKey "HKCU64"
#define Uninstall32RootKey "HKCU32"
#else
#define EnvironmentRootKey "HKCR"
#define EnvironmentRootKey "HKLM"
#define EnvironmentKey "System\CurrentControlSet\Control\Session Manager\Environment"
#define Uninstall64RootKey "HKLM64"
#define Uninstall32RootKey "HKLM32"

Binary file not shown.

View file

@ -18,7 +18,7 @@
},
"dependencies": {
"jsonc-parser": "^1.0.0",
"vscode-nls": "^3.2.1"
"vscode-nls": "^3.2.4"
},
"contributes": {
"languages": [

View file

@ -10,6 +10,6 @@ jsonc-parser@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-1.0.0.tgz#ddcc864ae708e60a7a6dd36daea00172fa8d9272"
vscode-nls@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.1.tgz#b1f3e04e8a94a715d5a7bcbc8339c51e6d74ca51"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"

View file

@ -709,7 +709,7 @@
"dependencies": {
"vscode-languageclient": "^4.1.4",
"vscode-languageserver-protocol-foldingprovider": "^2.0.1",
"vscode-nls": "^3.2.2"
"vscode-nls": "^3.2.4"
},
"devDependencies": {
"@types/node": "7.0.43",

View file

@ -161,9 +161,9 @@ vscode-languageserver-types@^3.7.2:
version "3.7.2"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.7.2.tgz#aad8846f8e3e27962648554de5a8417e358f34eb"
vscode-nls@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.2.tgz#3817eca5b985c2393de325197cf4e15eb2aa5350"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"
wrappy@1:
version "1.0.2"

View file

@ -449,6 +449,6 @@
"image-size": "^0.5.2",
"vscode-emmet-helper": "^1.2.10",
"vscode-languageserver-types": "^3.5.0",
"vscode-nls": "3.2.1"
"vscode-nls": "3.2.4"
}
}

View file

@ -2131,9 +2131,9 @@ vscode-languageserver-types@^3.6.0-next.1:
version "3.6.0-next.1"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.6.0-next.1.tgz#98e488d3f87b666b4ee1a3d89f0023e246d358f3"
vscode-nls@3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.1.tgz#b1f3e04e8a94a715d5a7bcbc8339c51e6d74ca51"
vscode-nls@3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"
vscode@1.0.1:
version "1.0.1"

View file

@ -21,7 +21,7 @@
"jsonc-parser": "^1.0.0",
"markdown-it": "^8.3.1",
"parse5": "^3.0.2",
"vscode-nls": "^3.2.1"
"vscode-nls": "^3.2.4"
},
"contributes": {
"jsonValidation": [

View file

@ -58,6 +58,6 @@ uc.micro@^1.0.1, uc.micro@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.3.tgz#7ed50d5e0f9a9fb0a573379259f2a77458d50192"
vscode-nls@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.1.tgz#b1f3e04e8a94a715d5a7bcbc8339c51e6d74ca51"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"

View file

@ -38,6 +38,11 @@
"dark": "resources/icons/dark/git.svg"
}
},
{
"command": "git.openRepository",
"title": "%command.openRepository%",
"category": "Git"
},
{
"command": "git.close",
"title": "%command.close%",
@ -336,6 +341,10 @@
"command": "git.init",
"when": "config.git.enabled"
},
{
"command": "git.openRepository",
"when": "config.git.enabled"
},
{
"command": "git.close",
"when": "config.git.enabled && gitOpenRepositoryCount != 0"
@ -881,7 +890,16 @@
"scope": "application"
},
"git.autoRepositoryDetection": {
"type": "boolean",
"type": [
"boolean",
"string"
],
"enum": [
true,
false,
"subFolders",
"openEditors"
],
"description": "%config.autoRepositoryDetection%",
"default": true
},
@ -943,11 +961,13 @@
},
"git.enableSmartCommit": {
"type": "boolean",
"scope": "resource",
"description": "%config.enableSmartCommit%",
"default": false
},
"git.enableCommitSigning": {
"type": "boolean",
"scope": "resource",
"description": "%config.enableCommitSigning%",
"default": false
},
@ -958,6 +978,7 @@
},
"git.promptToSaveFilesBeforeCommit": {
"type": "boolean",
"scope": "resource",
"default": false,
"description": "%config.promptToSaveFilesBeforeCommit%"
},
@ -966,6 +987,11 @@
"default": true,
"description": "%config.showInlineOpenFileAction%"
},
"git.showPushSuccessNotification": {
"type": "boolean",
"description": "%config.showPushSuccessNotification%",
"default": false
},
"git.inputValidation": {
"type": "string",
"enum": [
@ -987,6 +1013,18 @@
"scope": "resource",
"default": 10,
"description": "%config.detectSubmodulesLimit%"
},
"git.alwaysSignOff": {
"type": "boolean",
"scope": "resource",
"default": false,
"description": "%config.alwaysSignOff%"
},
"git.ignoredRepositories": {
"type": "array",
"default": [],
"scope": "window",
"description": "%config.ignoredRepositories%"
}
}
},
@ -1140,7 +1178,7 @@
"iconv-lite": "0.4.19",
"jschardet": "^1.6.0",
"vscode-extension-telemetry": "0.0.17",
"vscode-nls": "^3.2.1",
"vscode-nls": "^3.2.4",
"which": "^1.3.0"
},
"devDependencies": {
@ -1151,4 +1189,4 @@
"@types/which": "^1.0.28",
"mocha": "^3.2.0"
}
}
}

View file

@ -3,6 +3,7 @@
"description": "Git SCM Integration",
"command.clone": "Clone",
"command.init": "Initialize Repository",
"command.openRepository": "Open Repository",
"command.close": "Close Repository",
"command.refresh": "Refresh",
"command.openChange": "Open Changes",
@ -51,7 +52,7 @@
"command.stashPopLatest": "Pop Latest Stash",
"config.enabled": "Whether git is enabled",
"config.path": "Path to the git executable",
"config.autoRepositoryDetection": "Whether repositories should be automatically detected",
"config.autoRepositoryDetection": "Configures when repositories should be automatically detected.",
"config.autorefresh": "Whether auto refreshing is enabled",
"config.autofetch": "Whether auto fetching is enabled",
"config.enableLongCommitWarning": "Whether long commit messages should be warned about",
@ -68,10 +69,13 @@
"config.decorations.enabled": "Controls if Git contributes colors and badges to the explorer and the open editors view.",
"config.promptToSaveFilesBeforeCommit": "Controls whether Git should check for unsaved files before committing.",
"config.showInlineOpenFileAction": "Controls whether to show an inline Open File action in the Git changes view.",
"config.showPushSuccessNotification": "Controls whether to show a notification when a push is successful.",
"config.inputValidation": "Controls when to show commit message input validation.",
"config.detectSubmodules": "Controls whether to automatically detect git submodules.",
"colors.added": "Color for added resources.",
"config.detectSubmodulesLimit": "Controls the limit of git submodules detected.",
"config.alwaysSignOff": "Controls the signoff flag for all commits",
"config.ignoredRepositories": "List of git repositories to ignore",
"colors.modified": "Color for modified resources.",
"colors.deleted": "Color for deleted resources.",
"colors.untracked": "Color for untracked resources.",

View file

@ -137,6 +137,22 @@ const ImageMimetypes = [
'image/bmp'
];
async function categorizeResourceByResolution(resources: Resource[]): Promise<{ merge: Resource[], resolved: Resource[], unresolved: Resource[] }> {
const selection = resources.filter(s => s instanceof Resource) as Resource[];
const merge = selection.filter(s => s.resourceGroupType === ResourceGroupType.Merge);
const isBothAddedOrModified = (s: Resource) => s.type === Status.BOTH_MODIFIED || s.type === Status.BOTH_ADDED;
const possibleUnresolved = merge.filter(isBothAddedOrModified);
const promises = possibleUnresolved.map(s => grep(s.resourceUri.fsPath, /^<{7}|^={7}|^>{7}/));
const unresolvedBothModified = await Promise.all<boolean>(promises);
const resolved = possibleUnresolved.filter((s, i) => !unresolvedBothModified[i]);
const unresolved = [
...merge.filter(s => !isBothAddedOrModified(s)),
...possibleUnresolved.filter((s, i) => unresolvedBothModified[i])
];
return { merge, resolved, unresolved };
}
export class CommandCenter {
private disposables: Disposable[];
@ -236,7 +252,7 @@ export class CommandCenter {
gitRef = indexStatus ? '' : 'HEAD';
}
const { size, object } = await repository.lstree(gitRef, uri.fsPath);
const { size, object } = await repository.getObjectDetails(gitRef, uri.fsPath);
const { mimetype } = await repository.detectObjectType(object);
if (mimetype === 'text/plain') {
@ -485,7 +501,28 @@ export class CommandCenter {
}
await this.git.init(path);
await this.model.tryOpenRepository(path);
await this.model.openRepository(path);
}
@command('git.openRepository', { repository: false })
async openRepository(path?: string): Promise<void> {
if (!path) {
const result = await window.showOpenDialog({
canSelectFiles: false,
canSelectFolders: true,
canSelectMany: false,
defaultUri: Uri.file(os.homedir()),
openLabel: localize('open repo', "Open Repository")
});
if (!result || result.length === 0) {
return;
}
path = result[0].fsPath;
}
await this.model.openRepository(path);
}
@command('git.close', { repository: true })
@ -629,20 +666,12 @@ export class CommandCenter {
}
const selection = resourceStates.filter(s => s instanceof Resource) as Resource[];
const merge = selection.filter(s => s.resourceGroupType === ResourceGroupType.Merge);
const bothModified = merge.filter(s => s.type === Status.BOTH_MODIFIED);
const promises = bothModified.map(s => grep(s.resourceUri.fsPath, /^<{7}|^={7}|^>{7}/));
const unresolvedBothModified = await Promise.all<boolean>(promises);
const resolvedConflicts = bothModified.filter((s, i) => !unresolvedBothModified[i]);
const unresolvedConflicts = [
...merge.filter(s => s.type !== Status.BOTH_MODIFIED),
...bothModified.filter((s, i) => unresolvedBothModified[i])
];
const { resolved, unresolved } = await categorizeResourceByResolution(selection);
if (unresolvedConflicts.length > 0) {
const message = unresolvedConflicts.length > 1
? localize('confirm stage files with merge conflicts', "Are you sure you want to stage {0} files with merge conflicts?", unresolvedConflicts.length)
: localize('confirm stage file with merge conflicts', "Are you sure you want to stage {0} with merge conflicts?", path.basename(unresolvedConflicts[0].resourceUri.fsPath));
if (unresolved.length > 0) {
const message = unresolved.length > 1
? localize('confirm stage files with merge conflicts', "Are you sure you want to stage {0} files with merge conflicts?", unresolved.length)
: localize('confirm stage file with merge conflicts', "Are you sure you want to stage {0} with merge conflicts?", path.basename(unresolved[0].resourceUri.fsPath));
const yes = localize('yes', "Yes");
const pick = await window.showWarningMessage(message, { modal: true }, yes);
@ -653,7 +682,7 @@ export class CommandCenter {
}
const workingTree = selection.filter(s => s.resourceGroupType === ResourceGroupType.WorkingTree);
const scmResources = [...workingTree, ...resolvedConflicts, ...unresolvedConflicts];
const scmResources = [...workingTree, ...resolved, ...unresolved];
this.outputChannel.appendLine(`git.stage.scmResources ${scmResources.length}`);
if (!scmResources.length) {
@ -667,12 +696,12 @@ export class CommandCenter {
@command('git.stageAll', { repository: true })
async stageAll(repository: Repository): Promise<void> {
const resources = repository.mergeGroup.resourceStates.filter(s => s instanceof Resource) as Resource[];
const mergeConflicts = resources.filter(s => s.resourceGroupType === ResourceGroupType.Merge);
const { merge, unresolved } = await categorizeResourceByResolution(resources);
if (mergeConflicts.length > 0) {
const message = mergeConflicts.length > 1
? localize('confirm stage files with merge conflicts', "Are you sure you want to stage {0} files with merge conflicts?", mergeConflicts.length)
: localize('confirm stage file with merge conflicts', "Are you sure you want to stage {0} with merge conflicts?", path.basename(mergeConflicts[0].resourceUri.fsPath));
if (unresolved.length > 0) {
const message = unresolved.length > 1
? localize('confirm stage files with merge conflicts', "Are you sure you want to stage {0} files with merge conflicts?", merge.length)
: localize('confirm stage file with merge conflicts', "Are you sure you want to stage {0} with merge conflicts?", path.basename(merge[0].resourceUri.fsPath));
const yes = localize('yes', "Yes");
const pick = await window.showWarningMessage(message, { modal: true }, yes);
@ -775,11 +804,18 @@ export class CommandCenter {
const originalUri = toGitUri(modifiedUri, '~');
const originalDocument = await workspace.openTextDocument(originalUri);
const selectionsBeforeRevert = textEditor.selections;
const visibleRangesBeforeRevert = textEditor.visibleRanges;
const result = applyLineChanges(originalDocument, modifiedDocument, changes);
const edit = new WorkspaceEdit();
edit.replace(modifiedUri, new Range(new Position(0, 0), modifiedDocument.lineAt(modifiedDocument.lineCount - 1).range.end), result);
workspace.applyEdit(edit);
await modifiedDocument.save();
textEditor.selections = selectionsBeforeRevert;
textEditor.revealRange(visibleRangesBeforeRevert[0]);
}
@command('git.unstage')
@ -976,7 +1012,7 @@ export class CommandCenter {
getCommitMessage: () => Promise<string | undefined>,
opts?: CommitOptions
): Promise<boolean> {
const config = workspace.getConfiguration('git');
const config = workspace.getConfiguration('git', Uri.file(repository.root));
const promptToSaveFilesBeforeCommit = config.get<boolean>('promptToSaveFilesBeforeCommit') === true;
if (promptToSaveFilesBeforeCommit) {
@ -1030,6 +1066,10 @@ export class CommandCenter {
// enable signing of commits if configurated
opts.signCommit = enableCommitSigning;
if (config.get<boolean>('alwaysSignOff')) {
opts.signoff = true;
}
if (
// no changes
(noStagedChanges && noUnstagedChanges)
@ -1132,11 +1172,19 @@ export class CommandCenter {
const HEAD = repository.HEAD;
if (!HEAD || !HEAD.commit) {
window.showWarningMessage(localize('no more', "Can't undo because HEAD doesn't point to any commit."));
return;
}
const commit = await repository.getCommit('HEAD');
await repository.reset('HEAD~');
if (commit.parents.length > 0) {
await repository.reset('HEAD~');
} else {
await repository.deleteRef('HEAD');
await this.unstageAll(repository);
}
repository.inputBox.value = commit.message;
}
@ -1273,16 +1321,7 @@ export class CommandCenter {
return;
}
try {
await choice.run(repository);
} catch (err) {
if (err.gitErrorCode !== GitErrorCodes.Conflict) {
throw err;
}
const message = localize('merge conflicts', "There are merge conflicts. Resolve them before committing.");
await window.showWarningMessage(message);
}
await choice.run(repository);
}
@command('git.createTag', { repository: true })
@ -1655,10 +1694,11 @@ export class CommandCenter {
return result.catch(async err => {
const options: MessageOptions = {
modal: err.gitErrorCode === GitErrorCodes.DirtyWorkTree
modal: true
};
let message: string;
let type: 'error' | 'warning' = 'error';
switch (err.gitErrorCode) {
case GitErrorCodes.DirtyWorkTree:
@ -1667,6 +1707,11 @@ export class CommandCenter {
case GitErrorCodes.PushRejected:
message = localize('cant push', "Can't push refs to remote. Try running 'Pull' first to integrate your changes.");
break;
case GitErrorCodes.Conflict:
message = localize('merge conflicts', "There are merge conflicts. Resolve them before committing.");
type = 'warning';
options.modal = false;
break;
default:
const hint = (err.stderr || err.message || String(err))
.replace(/^error: /mi, '')
@ -1687,11 +1732,11 @@ export class CommandCenter {
return;
}
options.modal = true;
const outputChannel = this.outputChannel as OutputChannel;
const openOutputChannelChoice = localize('open git log', "Open Git Log");
const choice = await window.showErrorMessage(message, options, openOutputChannelChoice);
const choice = type === 'error'
? await window.showErrorMessage(message, options, openOutputChannelChoice)
: await window.showWarningMessage(message, options, openOutputChannelChoice);
if (choice === openOutputChannelChoice) {
outputChannel.show();

View file

@ -336,7 +336,8 @@ export const GitErrorCodes = {
NoStashFound: 'NoStashFound',
LocalChangesOverwritten: 'LocalChangesOverwritten',
NoUpstreamBranch: 'NoUpstreamBranch',
IsInSubmodule: 'IsInSubmodule'
IsInSubmodule: 'IsInSubmodule',
WrongCase: 'WrongCase',
};
function getGitErrorCode(stderr: string): string | undefined {
@ -501,6 +502,7 @@ export class Git {
export interface Commit {
hash: string;
message: string;
parents: string[];
}
export class GitStatusParser {
@ -631,6 +633,47 @@ export function parseGitmodules(raw: string): Submodule[] {
return result;
}
export function parseGitCommit(raw: string): Commit | null {
const match = /^([0-9a-f]{40})\n(.*)\n([^]*)$/m.exec(raw.trim());
if (!match) {
return null;
}
const parents = match[2] ? match[2].split(' ') : [];
return { hash: match[1], message: match[3], parents };
}
interface LsTreeElement {
mode: string;
type: string;
object: string;
size: string;
file: string;
}
export function parseLsTree(raw: string): LsTreeElement[] {
return raw.split('\n')
.filter(l => !!l)
.map(line => /^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/.exec(line)!)
.filter(m => !!m)
.map(([, mode, type, object, size, file]) => ({ mode, type, object, size, file }));
}
interface LsFilesElement {
mode: string;
object: string;
stage: string;
file: string;
}
export function parseLsFiles(raw: string): LsFilesElement[] {
return raw.split('\n')
.filter(l => !!l)
.map(line => /^(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/.exec(line)!)
.filter(m => !!m)
.map(([, mode, object, stage, file]) => ({ mode, object, stage, file }));
}
export interface DiffOptions {
cached?: boolean;
}
@ -699,47 +742,72 @@ export class Repository {
return Promise.reject<Buffer>('Can\'t open file from git');
}
const { exitCode, stdout } = await exec(child);
const { exitCode, stdout, stderr } = await exec(child);
if (exitCode) {
return Promise.reject<Buffer>(new GitError({
const err = new GitError({
message: 'Could not show object.',
exitCode
}));
});
if (/exists on disk, but not in/.test(stderr)) {
err.gitErrorCode = GitErrorCodes.WrongCase;
}
return Promise.reject<Buffer>(err);
}
return stdout;
}
async lstree(treeish: string, path: string): Promise<{ mode: string, object: string, size: number }> {
async getObjectDetails(treeish: string, path: string): Promise<{ mode: string, object: string, size: number }> {
if (!treeish) { // index
const { stdout } = await this.run(['ls-files', '--stage', '--', path]);
const elements = await this.lsfiles(path);
const match = /^(\d+)\s+([0-9a-f]{40})\s+(\d+)/.exec(stdout);
if (!match) {
if (elements.length === 0) {
throw new GitError({ message: 'Error running ls-files' });
}
const [, mode, object] = match;
const { mode, object } = elements[0];
const catFile = await this.run(['cat-file', '-s', object]);
const size = parseInt(catFile.stdout);
return { mode, object, size };
}
const { stdout } = await this.run(['ls-tree', '-l', treeish, '--', path]);
const elements = await this.lstree(treeish, path);
const match = /^(\d+)\s+(\w+)\s+([0-9a-f]{40})\s+(\d+)/.exec(stdout);
if (!match) {
throw new GitError({ message: 'Error running ls-tree' });
if (elements.length === 0) {
throw new GitError({ message: 'Error running ls-files' });
}
const [, mode, , object, size] = match;
const { mode, object, size } = elements[0];
return { mode, object, size: parseInt(size) };
}
async lstree(treeish: string, path: string): Promise<LsTreeElement[]> {
const { stdout } = await this.run(['ls-tree', '-l', treeish, '--', path]);
return parseLsTree(stdout);
}
async lsfiles(path: string): Promise<LsFilesElement[]> {
const { stdout } = await this.run(['ls-files', '--stage', '--', path]);
return parseLsFiles(stdout);
}
async getGitRelativePath(ref: string, relativePath: string): Promise<string> {
const relativePathLowercase = relativePath.toLowerCase();
const dirname = path.posix.dirname(relativePath) + '/';
const elements: { file: string; }[] = ref ? await this.lstree(ref, dirname) : await this.lsfiles(dirname);
const element = elements.filter(file => file.file.toLowerCase() === relativePathLowercase)[0];
if (!element) {
throw new GitError({ message: 'Git relative path not found.' });
}
return element.file;
}
async detectObjectType(object: string): Promise<{ mimetype: string, encoding?: string }> {
const child = await this.stream(['show', object]);
const buffer = await readBytes(child.stdout, 4100);
@ -822,7 +890,7 @@ export class Repository {
let mode: string;
try {
const details = await this.lstree('HEAD', path);
const details = await this.getObjectDetails('HEAD', path);
mode = details.mode;
} catch (err) {
mode = '100644';
@ -876,27 +944,41 @@ export class Repository {
try {
await this.run(args, { input: message || '' });
} catch (commitErr) {
if (/not possible because you have unmerged files/.test(commitErr.stderr || '')) {
commitErr.gitErrorCode = GitErrorCodes.UnmergedChanges;
throw commitErr;
}
await this.handleCommitError(commitErr);
}
}
try {
await this.run(['config', '--get-all', 'user.name']);
} catch (err) {
err.gitErrorCode = GitErrorCodes.NoUserNameConfigured;
throw err;
}
async rebaseContinue(): Promise<void> {
const args = ['rebase', '--continue'];
try {
await this.run(['config', '--get-all', 'user.email']);
} catch (err) {
err.gitErrorCode = GitErrorCodes.NoUserEmailConfigured;
throw err;
}
try {
await this.run(args);
} catch (commitErr) {
await this.handleCommitError(commitErr);
}
}
private async handleCommitError(commitErr: any): Promise<void> {
if (/not possible because you have unmerged files/.test(commitErr.stderr || '')) {
commitErr.gitErrorCode = GitErrorCodes.UnmergedChanges;
throw commitErr;
}
try {
await this.run(['config', '--get-all', 'user.name']);
} catch (err) {
err.gitErrorCode = GitErrorCodes.NoUserNameConfigured;
throw err;
}
try {
await this.run(['config', '--get-all', 'user.email']);
} catch (err) {
err.gitErrorCode = GitErrorCodes.NoUserEmailConfigured;
throw err;
}
throw commitErr;
}
async branch(name: string, checkout: boolean): Promise<void> {
@ -914,6 +996,11 @@ export class Repository {
await this.run(args);
}
async deleteRef(ref: string): Promise<void> {
const args = ['update-ref', '-d', ref];
await this.run(args);
}
async merge(ref: string): Promise<void> {
const args = ['merge', ref];
@ -1328,14 +1415,8 @@ export class Repository {
}
async getCommit(ref: string): Promise<Commit> {
const result = await this.run(['show', '-s', '--format=%H\n%B', ref]);
const match = /^([0-9a-f]{40})\n([^]*)$/m.exec(result.stdout.trim());
if (!match) {
return Promise.reject<Commit>('bad commit format');
}
return { hash: match[1], message: match[2] };
const result = await this.run(['show', '-s', '--format=%H\n%P\n%B', ref]);
return parseGitCommit(result.stdout) || Promise.reject<Commit>('bad commit format');
}
async updateSubmodules(paths: string[]): Promise<void> {

View file

@ -91,6 +91,13 @@ export class Model {
* for git repositories.
*/
private async scanWorkspaceFolders(): Promise<void> {
const config = workspace.getConfiguration('git');
const autoRepositoryDetection = config.get<boolean | 'subFolders' | 'openEditors'>('autoRepositoryDetection');
if (autoRepositoryDetection !== true && autoRepositoryDetection !== 'subFolders') {
return;
}
for (const folder of workspace.workspaceFolders || []) {
const root = folder.uri.fsPath;
@ -99,7 +106,7 @@ export class Model {
children
.filter(child => child !== '.git')
.forEach(child => this.tryOpenRepository(path.join(root, child)));
.forEach(child => this.openRepository(path.join(root, child)));
} catch (err) {
// noop
}
@ -118,7 +125,7 @@ export class Model {
@debounce(500)
private eventuallyScanPossibleGitRepositories(): void {
for (const path of this.possibleGitRepositoryPaths) {
this.tryOpenRepository(path);
this.openRepository(path);
}
this.possibleGitRepositoryPaths.clear();
@ -139,7 +146,7 @@ export class Model {
.filter(r => !activeRepositories.has(r!.repository))
.filter(r => !(workspace.workspaceFolders || []).some(f => isDescendant(f.uri.fsPath, r!.repository.root))) as OpenRepository[];
possibleRepositoryFolders.forEach(p => this.tryOpenRepository(p.uri.fsPath));
possibleRepositoryFolders.forEach(p => this.openRepository(p.uri.fsPath));
openRepositoriesToDispose.forEach(r => r.dispose());
}
@ -153,15 +160,15 @@ export class Model {
.filter(({ root }) => workspace.getConfiguration('git', root).get<boolean>('enabled') !== true)
.map(({ repository }) => repository);
possibleRepositoryFolders.forEach(p => this.tryOpenRepository(p.uri.fsPath));
possibleRepositoryFolders.forEach(p => this.openRepository(p.uri.fsPath));
openRepositoriesToDispose.forEach(r => r.dispose());
}
private onDidChangeVisibleTextEditors(editors: TextEditor[]): void {
const config = workspace.getConfiguration('git');
const enabled = config.get<boolean>('autoRepositoryDetection') === true;
const autoRepositoryDetection = config.get<boolean | 'subFolders' | 'openEditors'>('autoRepositoryDetection');
if (!enabled) {
if (autoRepositoryDetection !== true && autoRepositoryDetection !== 'openEditors') {
return;
}
@ -178,12 +185,12 @@ export class Model {
return;
}
this.tryOpenRepository(path.dirname(uri.fsPath));
this.openRepository(path.dirname(uri.fsPath));
});
}
@sequentialize
async tryOpenRepository(path: string): Promise<void> {
async openRepository(path: string): Promise<void> {
if (this.getRepository(path)) {
return;
}
@ -207,6 +214,13 @@ export class Model {
return;
}
const config = workspace.getConfiguration('git');
const ignoredRepos = new Set(config.get<Array<string>>('ignoredRepositories'));
if (ignoredRepos.has(rawRoot)) {
return;
}
const repository = new Repository(this.git.open(repositoryRoot), this.globalState);
this.open(repository);

View file

@ -5,16 +5,16 @@
'use strict';
import { ProtocolHandler, Uri, window, Disposable, commands } from 'vscode';
import { UriHandler, Uri, window, Disposable, commands } from 'vscode';
import { dispose } from './util';
import * as querystring from 'querystring';
export class GitProtocolHandler implements ProtocolHandler {
export class GitProtocolHandler implements UriHandler {
private disposables: Disposable[] = [];
constructor() {
this.disposables.push(window.registerProtocolHandler(this));
this.disposables.push(window.registerUriHandler(this));
}
handleUri(uri: Uri): void {

View file

@ -293,13 +293,15 @@ export enum Operation {
GetCommitTemplate = 'GetCommitTemplate',
DeleteBranch = 'DeleteBranch',
RenameBranch = 'RenameBranch',
DeleteRef = 'DeleteRef',
Merge = 'Merge',
Ignore = 'Ignore',
Tag = 'Tag',
Stash = 'Stash',
CheckIgnore = 'CheckIgnore',
LSTree = 'LSTree',
SubmoduleUpdate = 'SubmoduleUpdate'
GetObjectDetails = 'GetObjectDetails',
SubmoduleUpdate = 'SubmoduleUpdate',
RebaseContinue = 'RebaseContinue',
}
function isReadOnly(operation: Operation): boolean {
@ -307,7 +309,7 @@ function isReadOnly(operation: Operation): boolean {
case Operation.Show:
case Operation.GetCommitTemplate:
case Operation.CheckIgnore:
case Operation.LSTree:
case Operation.GetObjectDetails:
return true;
default:
return false;
@ -318,7 +320,7 @@ function shouldShowProgress(operation: Operation): boolean {
switch (operation) {
case Operation.Fetch:
case Operation.CheckIgnore:
case Operation.LSTree:
case Operation.GetObjectDetails:
case Operation.Show:
return false;
default:
@ -479,6 +481,22 @@ export class Repository implements Disposable {
return this._submodules;
}
private _rebaseCommit: Commit | undefined = undefined;
set rebaseCommit(rebaseCommit: Commit | undefined) {
if (this._rebaseCommit && !rebaseCommit) {
this.inputBox.value = '';
} else if (rebaseCommit && (!this._rebaseCommit || this._rebaseCommit.hash !== rebaseCommit.hash)) {
this.inputBox.value = rebaseCommit.message;
}
this._rebaseCommit = rebaseCommit;
}
get rebaseCommit(): Commit | undefined {
return this._rebaseCommit;
}
private _operations = new OperationsImpl();
get operations(): Operations { return this._operations; }
@ -540,6 +558,16 @@ export class Repository implements Disposable {
this.disposables.push(new AutoFetcher(this, globalState));
// https://github.com/Microsoft/vscode/issues/39039
const onSuccessfulPush = filterEvent(this.onDidRunOperation, e => e.operation === Operation.Push && !e.error);
onSuccessfulPush(() => {
const gitConfig = workspace.getConfiguration('git');
if (gitConfig.get<boolean>('showPushSuccessNotification')) {
window.showInformationMessage(localize('push success', "Successfully pushed."));
}
}, null, this.disposables);
const statusBar = new StatusBarCommands(this);
this.disposables.push(statusBar);
statusBar.onDidChange(() => this._sourceControl.statusBarCommands = statusBar.commands, null, this.disposables);
@ -553,6 +581,15 @@ export class Repository implements Disposable {
}
validateInput(text: string, position: number): SourceControlInputBoxValidation | undefined {
if (this.rebaseCommit) {
if (this.rebaseCommit.message !== text) {
return {
message: localize('commit in rebase', "It's not possible to change the commit message in the middle of a rebase. Please complete the rebase operation and use interactive rebase instead."),
type: SourceControlInputBoxValidationType.Warning
};
}
}
const config = workspace.getConfiguration('git');
const setting = config.get<'always' | 'warn' | 'off'>('inputValidation');
@ -636,13 +673,23 @@ export class Repository implements Disposable {
}
async commit(message: string, opts: CommitOptions = Object.create(null)): Promise<void> {
await this.run(Operation.Commit, async () => {
if (opts.all) {
await this.repository.add([]);
}
if (this.rebaseCommit) {
await this.run(Operation.RebaseContinue, async () => {
if (opts.all) {
await this.repository.add([]);
}
await this.repository.commit(message, opts);
});
await this.repository.rebaseContinue();
});
} else {
await this.run(Operation.Commit, async () => {
if (opts.all) {
await this.repository.add([]);
}
await this.repository.commit(message, opts);
});
}
}
async clean(resources: Uri[]): Promise<void> {
@ -730,6 +777,10 @@ export class Repository implements Disposable {
await this.run(Operation.Reset, () => this.repository.reset(treeish, hard));
}
async deleteRef(ref: string): Promise<void> {
await this.run(Operation.DeleteRef, () => this.repository.deleteRef(ref));
}
@throttle
async fetch(): Promise<void> {
await this.run(Operation.Fetch, () => this.repository.fetch());
@ -825,13 +876,22 @@ export class Repository implements Disposable {
}
async show(ref: string, filePath: string): Promise<string> {
return this.run(Operation.Show, () => {
return await this.run(Operation.Show, async () => {
const relativePath = path.relative(this.repository.root, filePath).replace(/\\/g, '/');
const configFiles = workspace.getConfiguration('files', Uri.file(filePath));
const defaultEncoding = configFiles.get<string>('encoding');
const autoGuessEncoding = configFiles.get<boolean>('autoGuessEncoding');
return this.repository.bufferString(`${ref}:${relativePath}`, defaultEncoding, autoGuessEncoding);
try {
return await this.repository.bufferString(`${ref}:${relativePath}`, defaultEncoding, autoGuessEncoding);
} catch (err) {
if (err.gitErrorCode === GitErrorCodes.WrongCase) {
const gitRelativePath = await this.repository.getGitRelativePath(ref, relativePath);
return await this.repository.bufferString(`${ref}:${gitRelativePath}`, defaultEncoding, autoGuessEncoding);
}
throw err;
}
});
}
@ -842,8 +902,8 @@ export class Repository implements Disposable {
});
}
lstree(ref: string, filePath: string): Promise<{ mode: string, object: string, size: number }> {
return this.run(Operation.LSTree, () => this.repository.lstree(ref, filePath));
getObjectDetails(ref: string, filePath: string): Promise<{ mode: string, object: string, size: number }> {
return this.run(Operation.GetObjectDetails, () => this.repository.getObjectDetails(ref, filePath));
}
detectObjectType(object: string): Promise<{ mimetype: string, encoding?: string }> {
@ -1025,12 +1085,13 @@ export class Repository implements Disposable {
// noop
}
const [refs, remotes, submodules] = await Promise.all([this.repository.getRefs(), this.repository.getRemotes(), this.repository.getSubmodules()]);
const [refs, remotes, submodules, rebaseCommit] = await Promise.all([this.repository.getRefs(), this.repository.getRemotes(), this.repository.getSubmodules(), this.getRebaseCommit()]);
this._HEAD = HEAD;
this._refs = refs;
this._remotes = remotes;
this._submodules = submodules;
this.rebaseCommit = rebaseCommit;
const index: Resource[] = [];
const workingTree: Resource[] = [];
@ -1089,6 +1150,17 @@ export class Repository implements Disposable {
this._onDidChangeStatus.fire();
}
private async getRebaseCommit(): Promise<Commit | undefined> {
const rebaseHeadPath = path.join(this.repository.root, '.git', 'REBASE_HEAD');
try {
const rebaseHead = await new Promise<string>((c, e) => fs.readFile(rebaseHeadPath, 'utf8', (err, result) => err ? e(err) : c(result)));
return await this.getCommit(rebaseHead.trim());
} catch (err) {
return undefined;
}
}
private onFSChange(uri: Uri): void {
const config = workspace.getConfiguration('git');
const autorefresh = config.get<boolean>('autorefresh');

View file

@ -24,7 +24,8 @@ class CheckoutStatusBar {
}
get command(): Command | undefined {
const title = `$(git-branch) ${this.repository.headLabel}`;
const rebasing = !!this.repository.rebaseCommit;
const title = `$(git-branch) ${this.repository.headLabel}${rebasing ? ` (${localize('rebasing', 'Rebasing')})` : ''}`;
return {
command: 'git.checkout',

View file

@ -6,7 +6,7 @@
'use strict';
import 'mocha';
import { GitStatusParser, parseGitmodules } from '../git';
import { GitStatusParser, parseGitCommit, parseGitmodules, parseLsTree, parseLsFiles } from '../git';
import * as assert from 'assert';
suite('git', () => {
@ -175,4 +175,106 @@ suite('git', () => {
]);
});
});
suite('parseGitCommit', () => {
test('single parent commit', function () {
const GIT_OUTPUT_SINGLE_PARENT = `52c293a05038d865604c2284aa8698bd087915a1
8e5a374372b8393906c7e380dbb09349c5385554
This is a commit message.`;
assert.deepEqual(parseGitCommit(GIT_OUTPUT_SINGLE_PARENT), {
hash: '52c293a05038d865604c2284aa8698bd087915a1',
message: 'This is a commit message.',
parents: ['8e5a374372b8393906c7e380dbb09349c5385554']
});
});
test('multiple parent commits', function () {
const GIT_OUTPUT_MULTIPLE_PARENTS = `52c293a05038d865604c2284aa8698bd087915a1
8e5a374372b8393906c7e380dbb09349c5385554 df27d8c75b129ab9b178b386077da2822101b217
This is a commit message.`;
assert.deepEqual(parseGitCommit(GIT_OUTPUT_MULTIPLE_PARENTS), {
hash: '52c293a05038d865604c2284aa8698bd087915a1',
message: 'This is a commit message.',
parents: ['8e5a374372b8393906c7e380dbb09349c5385554', 'df27d8c75b129ab9b178b386077da2822101b217']
});
});
test('no parent commits', function () {
const GIT_OUTPUT_NO_PARENTS = `52c293a05038d865604c2284aa8698bd087915a1
This is a commit message.`;
assert.deepEqual(parseGitCommit(GIT_OUTPUT_NO_PARENTS), {
hash: '52c293a05038d865604c2284aa8698bd087915a1',
message: 'This is a commit message.',
parents: []
});
});
});
suite('parseLsTree', function () {
test('sample', function () {
const input = `040000 tree 0274a81f8ee9ca3669295dc40f510bd2021d0043 - .vscode
100644 blob 1d487c1817262e4f20efbfa1d04c18f51b0046f6 491570 Screen Shot 2018-06-01 at 14.48.05.png
100644 blob 686c16e4f019b734655a2576ce8b98749a9ffdb9 764420 Screen Shot 2018-06-07 at 20.04.59.png
100644 blob 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 4 boom.txt
100644 blob 86dc360dd25f13fa50ffdc8259e9653921f4f2b7 11 boomcaboom.txt
100644 blob a68b14060589b16d7ac75f67b905c918c03c06eb 24 file.js
100644 blob f7bcfb05af46850d780f88c069edcd57481d822d 201 file.md
100644 blob ab8b86114a051f6490f1ec5e3141b9a632fb46b5 8 hello.js
100644 blob 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 4 what.js
100644 blob be859e3f412fa86513cd8bebe8189d1ea1a3e46d 24 what.txt
100644 blob 56ec42c9dc6fcf4534788f0fe34b36e09f37d085 261186 what.txt2`;
const output = parseLsTree(input);
assert.deepEqual(output, [
{ mode: '040000', type: 'tree', object: '0274a81f8ee9ca3669295dc40f510bd2021d0043', size: '-', file: '.vscode' },
{ mode: '100644', type: 'blob', object: '1d487c1817262e4f20efbfa1d04c18f51b0046f6', size: '491570', file: 'Screen Shot 2018-06-01 at 14.48.05.png' },
{ mode: '100644', type: 'blob', object: '686c16e4f019b734655a2576ce8b98749a9ffdb9', size: '764420', file: 'Screen Shot 2018-06-07 at 20.04.59.png' },
{ mode: '100644', type: 'blob', object: '257cc5642cb1a054f08cc83f2d943e56fd3ebe99', size: '4', file: 'boom.txt' },
{ mode: '100644', type: 'blob', object: '86dc360dd25f13fa50ffdc8259e9653921f4f2b7', size: '11', file: 'boomcaboom.txt' },
{ mode: '100644', type: 'blob', object: 'a68b14060589b16d7ac75f67b905c918c03c06eb', size: '24', file: 'file.js' },
{ mode: '100644', type: 'blob', object: 'f7bcfb05af46850d780f88c069edcd57481d822d', size: '201', file: 'file.md' },
{ mode: '100644', type: 'blob', object: 'ab8b86114a051f6490f1ec5e3141b9a632fb46b5', size: '8', file: 'hello.js' },
{ mode: '100644', type: 'blob', object: '257cc5642cb1a054f08cc83f2d943e56fd3ebe99', size: '4', file: 'what.js' },
{ mode: '100644', type: 'blob', object: 'be859e3f412fa86513cd8bebe8189d1ea1a3e46d', size: '24', file: 'what.txt' },
{ mode: '100644', type: 'blob', object: '56ec42c9dc6fcf4534788f0fe34b36e09f37d085', size: '261186', file: 'what.txt2' }
]);
});
});
suite('parseLsFiles', function () {
test('sample', function () {
const input = `100644 7a73a41bfdf76d6f793007240d80983a52f15f97 0 .vscode/settings.json
100644 1d487c1817262e4f20efbfa1d04c18f51b0046f6 0 Screen Shot 2018-06-01 at 14.48.05.png
100644 686c16e4f019b734655a2576ce8b98749a9ffdb9 0 Screen Shot 2018-06-07 at 20.04.59.png
100644 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 0 boom.txt
100644 86dc360dd25f13fa50ffdc8259e9653921f4f2b7 0 boomcaboom.txt
100644 a68b14060589b16d7ac75f67b905c918c03c06eb 0 file.js
100644 f7bcfb05af46850d780f88c069edcd57481d822d 0 file.md
100644 ab8b86114a051f6490f1ec5e3141b9a632fb46b5 0 hello.js
100644 257cc5642cb1a054f08cc83f2d943e56fd3ebe99 0 what.js
100644 be859e3f412fa86513cd8bebe8189d1ea1a3e46d 0 what.txt
100644 56ec42c9dc6fcf4534788f0fe34b36e09f37d085 0 what.txt2`;
const output = parseLsFiles(input);
assert.deepEqual(output, [
{ mode: '100644', object: '7a73a41bfdf76d6f793007240d80983a52f15f97', stage: '0', file: '.vscode/settings.json' },
{ mode: '100644', object: '1d487c1817262e4f20efbfa1d04c18f51b0046f6', stage: '0', file: 'Screen Shot 2018-06-01 at 14.48.05.png' },
{ mode: '100644', object: '686c16e4f019b734655a2576ce8b98749a9ffdb9', stage: '0', file: 'Screen Shot 2018-06-07 at 20.04.59.png' },
{ mode: '100644', object: '257cc5642cb1a054f08cc83f2d943e56fd3ebe99', stage: '0', file: 'boom.txt' },
{ mode: '100644', object: '86dc360dd25f13fa50ffdc8259e9653921f4f2b7', stage: '0', file: 'boomcaboom.txt' },
{ mode: '100644', object: 'a68b14060589b16d7ac75f67b905c918c03c06eb', stage: '0', file: 'file.js' },
{ mode: '100644', object: 'f7bcfb05af46850d780f88c069edcd57481d822d', stage: '0', file: 'file.md' },
{ mode: '100644', object: 'ab8b86114a051f6490f1ec5e3141b9a632fb46b5', stage: '0', file: 'hello.js' },
{ mode: '100644', object: '257cc5642cb1a054f08cc83f2d943e56fd3ebe99', stage: '0', file: 'what.js' },
{ mode: '100644', object: 'be859e3f412fa86513cd8bebe8189d1ea1a3e46d', stage: '0', file: 'what.txt' },
{ mode: '100644', object: '56ec42c9dc6fcf4534788f0fe34b36e09f37d085', stage: '0', file: 'what.txt2' },
]);
});
});
});

View file

@ -263,9 +263,9 @@ vscode-extension-telemetry@0.0.17:
dependencies:
applicationinsights "1.0.1"
vscode-nls@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.1.tgz#b1f3e04e8a94a715d5a7bcbc8339c51e6d74ca51"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"
which@^1.3.0:
version "1.3.0"

View file

@ -16,7 +16,7 @@
"watch": "gulp watch-extension:grunt"
},
"dependencies": {
"vscode-nls": "^3.2.1"
"vscode-nls": "^3.2.4"
},
"devDependencies": {
"@types/node": "7.0.43"

View file

@ -6,6 +6,6 @@
version "7.0.43"
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c"
vscode-nls@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.1.tgz#b1f3e04e8a94a715d5a7bcbc8339c51e6d74ca51"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"

View file

@ -16,7 +16,7 @@
"watch": "gulp watch-extension:gulp"
},
"dependencies": {
"vscode-nls": "^3.2.1"
"vscode-nls": "^3.2.4"
},
"devDependencies": {
"@types/node": "7.0.43"

View file

@ -6,6 +6,6 @@
version "7.0.43"
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c"
vscode-nls@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.1.tgz#b1f3e04e8a94a715d5a7bcbc8339c51e6d74ca51"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"

View file

@ -176,7 +176,7 @@
"vscode-extension-telemetry": "0.0.17",
"vscode-languageclient": "^4.1.4",
"vscode-languageserver-protocol-foldingprovider": "^2.0.1",
"vscode-nls": "^3.2.2"
"vscode-nls": "^3.2.4"
},
"devDependencies": {
"@types/node": "7.0.43"

View file

@ -13,7 +13,7 @@
"vscode-languageserver": "^4.1.3",
"vscode-languageserver-protocol-foldingprovider": "^2.0.1",
"vscode-languageserver-types": "^3.7.2",
"vscode-nls": "^3.2.2",
"vscode-nls": "^3.2.4",
"vscode-uri": "^1.0.3"
},
"devDependencies": {

View file

@ -242,6 +242,10 @@ vscode-nls@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.2.tgz#3817eca5b985c2393de325197cf4e15eb2aa5350"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"
vscode-uri@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.1.tgz#11a86befeac3c4aa3ec08623651a3c81a6d0bbc8"

View file

@ -62,9 +62,9 @@ vscode-languageserver-types@^3.7.2:
version "3.7.2"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.7.2.tgz#aad8846f8e3e27962648554de5a8417e358f34eb"
vscode-nls@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.2.tgz#3817eca5b985c2393de325197cf4e15eb2aa5350"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"
zone.js@0.7.6:
version "0.7.6"

View file

@ -16,7 +16,7 @@
"watch": "gulp watch-extension:jake"
},
"dependencies": {
"vscode-nls": "^3.2.1"
"vscode-nls": "^3.2.4"
},
"devDependencies": {
"@types/node": "7.0.43"

View file

@ -6,6 +6,6 @@
version "7.0.43"
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c"
vscode-nls@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.1.tgz#b1f3e04e8a94a715d5a7bcbc8339c51e6d74ca51"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"

View file

@ -4,7 +4,7 @@
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request."
],
"version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/7bf8960f7042474b10b519f39339fc527907ce16",
"version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/88217b1c7d36ed5d35adc3099ba7978aabe2531b",
"name": "JavaScript (with React support)",
"scopeName": "source.js",
"patterns": [
@ -4115,7 +4115,7 @@
},
"directives": {
"name": "comment.line.triple-slash.directive.js",
"begin": "^(///)\\s*(?=<(reference|amd-dependency|amd-module)(\\s+(path|types|no-default-lib|name)\\s*=\\s*((\\'([^\\'\\\\]|\\\\\\'|\\\\)*\\')|(\\\"([^\\\"\\\\]|\\\\\\\"|\\\\)*\\\")))+\\s*/>\\s*$)",
"begin": "^(///)\\s*(?=<(reference|amd-dependency|amd-module)(\\s+(path|types|no-default-lib|lib|name)\\s*=\\s*((\\'([^\\'\\\\]|\\\\\\'|\\\\)*\\')|(\\\"([^\\\"\\\\]|\\\\\\\"|\\\\)*\\\")))+\\s*/>\\s*$)",
"beginCaptures": {
"1": {
"name": "punctuation.definition.comment.js"
@ -4143,7 +4143,7 @@
"patterns": [
{
"name": "entity.other.attribute-name.directive.js",
"match": "path|types|no-default-lib|name"
"match": "path|types|no-default-lib|lib|name"
},
{
"name": "keyword.operator.assignment.js",
@ -4664,8 +4664,8 @@
]
},
"jsx-tag-in-expression": {
"begin": "(?x)\n (?<!\\+\\+|--)(?<=[({\\[,?=>:*]|&&|\\|\\||\\?|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)|(\\s+))(?!\\?)|\\/?>))",
"end": "(?!(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)|(\\s+))(?!\\?)|\\/?>))",
"begin": "(?x)\n (?<!\\+\\+|--)(?<=[({\\[,?=>:*]|&&|\\|\\||\\?|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*)|(\\s+))(?!\\?)|\\/?>))",
"end": "(?!(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*)|(\\s+))(?!\\?)|\\/?>))",
"patterns": [
{
"include": "#jsx-tag"
@ -4674,7 +4674,7 @@
},
"jsx-tag": {
"name": "meta.tag.js",
"begin": "(?=(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)|(\\s+))(?!\\?)|\\/?>))",
"begin": "(?=(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*)|(\\s+))(?!\\?)|\\/?>))",
"end": "(/>)|(?:(</)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))?\\s*(>))",
"endCaptures": {
"1": {
@ -4701,7 +4701,7 @@
},
"patterns": [
{
"begin": "(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)|(\\s+))(?!\\?)|\\/?>)",
"begin": "(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*)|(\\s+))(?!\\?)|\\/?>)",
"beginCaptures": {
"1": {
"name": "punctuation.definition.tag.begin.js"

View file

@ -4,7 +4,7 @@
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request."
],
"version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/7bf8960f7042474b10b519f39339fc527907ce16",
"version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/88217b1c7d36ed5d35adc3099ba7978aabe2531b",
"name": "JavaScript (with React support)",
"scopeName": "source.js.jsx",
"patterns": [
@ -4115,7 +4115,7 @@
},
"directives": {
"name": "comment.line.triple-slash.directive.js.jsx",
"begin": "^(///)\\s*(?=<(reference|amd-dependency|amd-module)(\\s+(path|types|no-default-lib|name)\\s*=\\s*((\\'([^\\'\\\\]|\\\\\\'|\\\\)*\\')|(\\\"([^\\\"\\\\]|\\\\\\\"|\\\\)*\\\")))+\\s*/>\\s*$)",
"begin": "^(///)\\s*(?=<(reference|amd-dependency|amd-module)(\\s+(path|types|no-default-lib|lib|name)\\s*=\\s*((\\'([^\\'\\\\]|\\\\\\'|\\\\)*\\')|(\\\"([^\\\"\\\\]|\\\\\\\"|\\\\)*\\\")))+\\s*/>\\s*$)",
"beginCaptures": {
"1": {
"name": "punctuation.definition.comment.js.jsx"
@ -4143,7 +4143,7 @@
"patterns": [
{
"name": "entity.other.attribute-name.directive.js.jsx",
"match": "path|types|no-default-lib|name"
"match": "path|types|no-default-lib|lib|name"
},
{
"name": "keyword.operator.assignment.js.jsx",
@ -4664,8 +4664,8 @@
]
},
"jsx-tag-in-expression": {
"begin": "(?x)\n (?<!\\+\\+|--)(?<=[({\\[,?=>:*]|&&|\\|\\||\\?|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)|(\\s+))(?!\\?)|\\/?>))",
"end": "(?!(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)|(\\s+))(?!\\?)|\\/?>))",
"begin": "(?x)\n (?<!\\+\\+|--)(?<=[({\\[,?=>:*]|&&|\\|\\||\\?|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*)|(\\s+))(?!\\?)|\\/?>))",
"end": "(?!(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*)|(\\s+))(?!\\?)|\\/?>))",
"patterns": [
{
"include": "#jsx-tag"
@ -4674,7 +4674,7 @@
},
"jsx-tag": {
"name": "meta.tag.js.jsx",
"begin": "(?=(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)|(\\s+))(?!\\?)|\\/?>))",
"begin": "(?=(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*)|(\\s+))(?!\\?)|\\/?>))",
"end": "(/>)|(?:(</)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))?\\s*(>))",
"endCaptures": {
"1": {
@ -4701,7 +4701,7 @@
},
"patterns": [
{
"begin": "(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)|(\\s+))(?!\\?)|\\/?>)",
"begin": "(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*)|(\\s+))(?!\\?)|\\/?>)",
"beginCaptures": {
"1": {
"name": "punctuation.definition.tag.begin.js.jsx"

View file

@ -103,7 +103,7 @@
"vscode-extension-telemetry": "0.0.17",
"vscode-languageclient": "^4.1.4",
"vscode-languageserver-protocol-foldingprovider": "^2.0.1",
"vscode-nls": "^3.2.2"
"vscode-nls": "^3.2.4"
},
"devDependencies": {
"@types/node": "7.0.43"

View file

@ -16,7 +16,7 @@
"vscode-json-languageservice": "^3.1.2",
"vscode-languageserver": "^4.1.3",
"vscode-languageserver-protocol-foldingprovider": "^2.0.1",
"vscode-nls": "^3.2.2",
"vscode-nls": "^3.2.4",
"vscode-uri": "^1.0.3"
},
"devDependencies": {

View file

@ -118,6 +118,10 @@ vscode-nls@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.2.tgz#3817eca5b985c2393de325197cf4e15eb2aa5350"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"
vscode-uri@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.1.tgz#11a86befeac3c4aa3ec08623651a3c81a6d0bbc8"

View file

@ -62,9 +62,9 @@ vscode-languageserver-types@^3.7.2:
version "3.7.2"
resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.7.2.tgz#aad8846f8e3e27962648554de5a8417e358f34eb"
vscode-nls@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.2.tgz#3817eca5b985c2393de325197cf4e15eb2aa5350"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"
zone.js@0.7.6:
version "0.7.6"

View file

@ -296,7 +296,7 @@
"markdown-it": "^8.4.1",
"markdown-it-named-headers": "0.0.4",
"vscode-extension-telemetry": "0.0.17",
"vscode-nls": "^3.2.1"
"vscode-nls": "^3.2.4"
},
"devDependencies": {
"@types/highlight.js": "9.1.10",

View file

@ -5462,9 +5462,9 @@ vscode-extension-telemetry@0.0.17:
dependencies:
applicationinsights "1.0.1"
vscode-nls@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.1.tgz#b1f3e04e8a94a715d5a7bcbc8339c51e6d74ca51"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"
vscode@^1.1.10:
version "1.1.10"

View file

@ -100,7 +100,7 @@
}
},
"dependencies": {
"vscode-nls": "^3.2.1"
"vscode-nls": "^3.2.4"
},
"devDependencies": {
"@types/node": "8.0.33"

View file

@ -6,6 +6,6 @@
version "8.0.33"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.33.tgz#1126e94374014e54478092830704f6ea89df04cd"
vscode-nls@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.1.tgz#b1f3e04e8a94a715d5a7bcbc8339c51e6d74ca51"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"

View file

@ -20,7 +20,7 @@
"jsonc-parser": "^1.0.0",
"minimatch": "^3.0.4",
"request-light": "^0.2.2",
"vscode-nls": "^3.2.1"
"vscode-nls": "^3.2.4"
},
"devDependencies": {
"@types/minimatch": "^3.0.3",

View file

@ -164,10 +164,14 @@ export class NpmScriptsTreeDataProvider implements TreeDataProvider<TreeItem> {
private extractDebugArg(scripts: any, task: Task): [string, number] | undefined {
let script: string = scripts[task.name];
let match = script.match(/--(inspect|debug)(-brk)?(=(\d*))?/);
// matches --debug, --debug=1234, --debug-brk, debug-brk=1234, --inspect,
// --inspect=1234, --inspect-brk, --inspect-brk=1234,
// --inspect=localhost:1245, --inspect=127.0.0.1:1234, --inspect=[aa:1:0:0:0]:1234, --inspect=:1234
let match = script.match(/--(inspect|debug)(-brk)?(=((\[[0-9a-fA-F:]*\]|[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+|[a-zA-Z0-9\.]*):)?(\d+))?/);
if (match) {
if (match[4]) {
return [match[1], parseInt(match[4])];
if (match[6]) {
return [match[1], parseInt(match[6])];
}
if (match[1] === 'inspect') {
return [match[1], 9229];

View file

@ -93,6 +93,6 @@ vscode-nls@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da"
vscode-nls@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.1.tgz#b1f3e04e8a94a715d5a7bcbc8339c51e6d74ca51"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"

View file

@ -77,7 +77,7 @@
"watch": "gulp watch-extension:php"
},
"dependencies": {
"vscode-nls": "^3.2.1"
"vscode-nls": "^3.2.4"
},
"devDependencies": {
"@types/node": "7.0.43"

View file

@ -6,6 +6,6 @@
version "7.0.43"
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c"
vscode-nls@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.1.tgz#b1f3e04e8a94a715d5a7bcbc8339c51e6d74ca51"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"

View file

@ -4,7 +4,7 @@
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request."
],
"version": "https://github.com/PowerShell/EditorSyntax/commit/6f5438611c54922ea94c81532a2dcfee72190039",
"version": "https://github.com/PowerShell/EditorSyntax/commit/146e421358945dbfbd24a9dcf56d759bdb0693db",
"name": "PowerShell",
"scopeName": "source.powershell",
"patterns": [
@ -71,7 +71,17 @@
},
{
"begin": "(?<!')'",
"beginCaptures": {
"0": {
"name": "punctuation.definition.string.begin.powershell"
}
},
"end": "'(?!')",
"endCaptures": {
"0": {
"name": "punctuation.definition.string.end.powershell"
}
},
"name": "string.quoted.single.powershell",
"patterns": [
{
@ -137,7 +147,7 @@
"begin": "(\\$)(\\()",
"beginCaptures": {
"1": {
"name": "keyword.other.variable.definition.powershell"
"name": "punctuation.definition.variable.powershell"
},
"2": {
"name": "punctuation.section.group.begin.powershell"
@ -170,8 +180,20 @@
"name": "keyword.control.powershell"
},
{
"match": "(?<!\\w)(--%)(?!\\w)",
"name": "keyword.control.powershell"
"begin": "(?<!\\w)(--%)(?!\\w)",
"beginCaptures": {
"1": {
"name": "keyword.control.powershell"
}
},
"end": "$",
"patterns": [
{
"match": ".+",
"name": "string.unquoted.powershell"
}
],
"comment": "This should be moved to the repository at some point."
},
{
"comment": "This should only be relevant inside a class but will require a rework of how classes are matched. This is a temp fix.",
@ -220,7 +242,7 @@
},
{
"match": "\\|{2}|&{2}|;",
"name": "keyword.other.statement-separator.powershell"
"name": "punctuation.terminator.statement.powershell"
},
{
"match": "&|(?<!\\w)\\.(?= )|`|,|\\|",
@ -326,7 +348,17 @@
},
{
"begin": "(?<!')'",
"beginCaptures": {
"0": {
"name": "punctuation.definition.string.begin.powershell"
}
},
"end": "'(?!')",
"endCaptures": {
"0": {
"name": "punctuation.definition.string.end.powershell"
}
},
"name": "string.quoted.single.powershell",
"patterns": [
{
@ -379,7 +411,7 @@
"name": "keyword.operator.documentation.powershell"
}
},
"match": "(?i:\\s*(\\.)(COMPONENT|DESCRIPTION|EXAMPLE|EXTERNALHELP|FORWARDHELPCATEGORY|FORWARDHELPTARGETNAME|FUNCTIONALITY|INPUTS|LINK|NOTES|OUTPUTS|REMOTEHELPRUNSPACE|ROLE|SYNOPSIS))",
"match": "^(?i:(?:\\s*|#)+(\\.)(COMPONENT|DESCRIPTION|EXAMPLE|EXTERNALHELP|FORWARDHELPCATEGORY|FORWARDHELPTARGETNAME|FUNCTIONALITY|INPUTS|LINK|NOTES|OUTPUTS|REMOTEHELPRUNSPACE|ROLE|SYNOPSIS))",
"name": "comment.documentation.embedded.powershell"
},
{
@ -464,7 +496,7 @@
"begin": "(\\$)(\\()",
"beginCaptures": {
"1": {
"name": "keyword.other.variable.definition.powershell"
"name": "punctuation.definition.variable.powershell"
},
"2": {
"name": "punctuation.section.group.begin.powershell"
@ -617,11 +649,11 @@
"patterns": [
{
"captures": {
"1": {
"name": "keyword.other.variable.definition.powershell"
},
"2": {
"0": {
"name": "constant.language.powershell"
},
"1": {
"name": "punctuation.definition.variable.powershell"
}
},
"comment": "These are special constants.",
@ -629,14 +661,14 @@
},
{
"captures": {
"1": {
"name": "keyword.other.variable.definition.powershell"
},
"2": {
"0": {
"name": "support.constant.variable.powershell"
},
"1": {
"name": "punctuation.definition.variable.powershell"
},
"3": {
"name": "entity.name.function.invocation.powershell"
"name": "variable.other.member.powershell"
}
},
"comment": "These are the other built-in constants.",
@ -644,14 +676,14 @@
},
{
"captures": {
"1": {
"name": "keyword.other.variable.definition.powershell"
},
"2": {
"0": {
"name": "support.constant.automatic.powershell"
},
"1": {
"name": "punctuation.definition.variable.powershell"
},
"3": {
"name": "entity.name.function.invocation.powershell"
"name": "variable.other.member.powershell"
}
},
"comment": "Automatic variables are not constants, but they are read-only. In monokai (default) color schema support.variable doesn't have color, so we use constant.",
@ -659,14 +691,14 @@
},
{
"captures": {
"1": {
"name": "keyword.other.variable.definition.powershell"
},
"2": {
"0": {
"name": "variable.language.powershell"
},
"1": {
"name": "punctuation.definition.variable.powershell"
},
"3": {
"name": "entity.name.function.invocation.powershell"
"name": "variable.other.member.powershell"
}
},
"comment": "Style preference variables as language variables so that they stand out.",
@ -674,25 +706,28 @@
},
{
"captures": {
"0": {
"name": "variable.other.readwrite.powershell"
},
"1": {
"name": "keyword.other.variable.definition.powershell"
"name": "punctuation.definition.variable.powershell"
},
"2": {
"name": "storage.modifier.scope.powershell"
},
"3": {
"name": "variable.other.readwrite.powershell"
},
"4": {
"name": "entity.name.function.invocation.powershell"
"name": "variable.other.member.powershell"
}
},
"match": "(?i:(\\$|@)(global|local|private|script|using|workflow):((?:\\p{L}|\\d|_)+))((?:\\.(?:\\p{L}|\\d|_)+)*\\b)?"
},
{
"captures": {
"0": {
"name": "variable.other.readwrite.powershell"
},
"1": {
"name": "keyword.other.variable.definition.powershell"
"name": "punctuation.definition.variable.powershell"
},
"2": {
"name": "punctuation.section.braces.begin.powershell"
@ -700,39 +735,39 @@
"3": {
"name": "storage.modifier.scope.powershell"
},
"4": {
"name": "variable.other.readwrite.powershell"
},
"5": {
"name": "punctuation.section.braces.end.powershell"
},
"6": {
"name": "entity.name.function.invocation.powershell"
"name": "variable.other.member.powershell"
}
},
"match": "(?i:(\\$)(\\{)(global|local|private|script|using|workflow):([^}]*[^}`])(\\}))((?:\\.(?:\\p{L}|\\d|_)+)*\\b)?"
},
{
"captures": {
"0": {
"name": "variable.other.readwrite.powershell"
},
"1": {
"name": "keyword.other.variable.definition.powershell"
"name": "punctuation.definition.variable.powershell"
},
"2": {
"name": "support.variable.drive.powershell"
},
"3": {
"name": "variable.other.readwrite.powershell"
},
"4": {
"name": "entity.name.function.invocation.powershell"
"name": "variable.other.member.powershell"
}
},
"match": "(?i:(\\$|@)((?:\\p{L}|\\d|_)+:)?((?:\\p{L}|\\d|_)+))((?:\\.(?:\\p{L}|\\d|_)+)*\\b)?"
},
{
"captures": {
"0": {
"name": "variable.other.readwrite.powershell"
},
"1": {
"name": "keyword.other.variable.definition.powershell"
"name": "punctuation.definition.variable.powershell"
},
"2": {
"name": "punctuation.section.braces.begin.powershell"
@ -740,14 +775,11 @@
"3": {
"name": "support.variable.drive.powershell"
},
"4": {
"name": "variable.other.readwrite.powershell"
},
"5": {
"name": "punctuation.section.braces.end.powershell"
},
"6": {
"name": "entity.name.function.invocation.powershell"
"name": "variable.other.member.powershell"
}
},
"match": "(?i:(\\$)(\\{)((?:\\p{L}|\\d|_)+:)?([^}]*[^}`])(\\}))((?:\\.(?:\\p{L}|\\d|_)+)*\\b)?"
@ -795,11 +827,11 @@
"patterns": [
{
"captures": {
"1": {
"name": "keyword.other.variable.definition.powershell"
},
"2": {
"0": {
"name": "constant.language.powershell"
},
"1": {
"name": "punctuation.definition.variable.powershell"
}
},
"comment": "These are special constants.",
@ -807,14 +839,14 @@
},
{
"captures": {
"1": {
"name": "keyword.other.variable.definition.powershell"
},
"2": {
"0": {
"name": "support.constant.variable.powershell"
},
"1": {
"name": "punctuation.definition.variable.powershell"
},
"3": {
"name": "entity.name.function.invocation.powershell"
"name": "variable.other.member.powershell"
}
},
"comment": "These are the other built-in constants.",
@ -822,14 +854,14 @@
},
{
"captures": {
"1": {
"name": "keyword.other.variable.definition.powershell"
},
"2": {
"0": {
"name": "support.variable.automatic.powershell"
},
"1": {
"name": "punctuation.definition.variable.powershell"
},
"3": {
"name": "entity.name.function.invocation.powershell"
"name": "variable.other.member.powershell"
}
},
"comment": "Automatic variables are not constants, but they are read-only...",
@ -837,14 +869,14 @@
},
{
"captures": {
"1": {
"name": "keyword.other.variable.definition.powershell"
},
"2": {
"0": {
"name": "variable.language.powershell"
},
"1": {
"name": "punctuation.definition.variable.powershell"
},
"3": {
"name": "entity.name.function.invocation.powershell"
"name": "variable.other.member.powershell"
}
},
"comment": "Style preference variables as language variables so that they stand out.",
@ -852,62 +884,65 @@
},
{
"captures": {
"0": {
"name": "variable.other.readwrite.powershell"
},
"1": {
"name": "keyword.other.variable.definition.powershell"
"name": "punctuation.definition.variable.powershell"
},
"2": {
"name": "storage.modifier.scope.powershell"
},
"3": {
"name": "variable.other.readwrite.powershell"
},
"4": {
"name": "entity.name.function.invocation.powershell"
"name": "variable.other.member.powershell"
}
},
"match": "(?i:(\\$|@)(global|local|private|script|using|workflow):((?:\\p{L}|\\d|_)+))"
},
{
"captures": {
"0": {
"name": "variable.other.readwrite.powershell"
},
"1": {
"name": "keyword.other.variable.definition.powershell"
"name": "punctuation.definition.variable.powershell"
},
"2": {
"name": "storage.modifier.scope.powershell"
},
"3": {
"name": "variable.other.readwrite.powershell"
},
"4": {
"name": "keyword.other.powershell"
},
"5": {
"name": "entity.name.function.invocation.powershell"
"name": "variable.other.member.powershell"
}
},
"match": "(?i:(\\$)(\\{)(global|local|private|script|using|workflow):([^}]*[^}`])(\\}))"
},
{
"captures": {
"0": {
"name": "variable.other.readwrite.powershell"
},
"1": {
"name": "keyword.other.variable.definition.powershell"
"name": "punctuation.definition.variable.powershell"
},
"2": {
"name": "support.variable.drive.powershell"
},
"3": {
"name": "variable.other.readwrite.powershell"
},
"4": {
"name": "entity.name.function.invocation.powershell"
"name": "variable.other.member.powershell"
}
},
"match": "(?i:(\\$)((?:\\p{L}|\\d|_)+:)?((?:\\p{L}|\\d|_)+))"
},
{
"captures": {
"0": {
"name": "variable.other.readwrite.powershell"
},
"1": {
"name": "keyword.other.variable.definition.powershell"
"name": "punctuation.definition.variable.powershell"
},
"2": {
"name": "punctuation.section.braces.begin"
@ -915,9 +950,6 @@
"3": {
"name": "support.variable.drive.powershell"
},
"4": {
"name": "variable.other.readwrite.powershell"
},
"5": {
"name": "punctuation.section.braces.end"
}
@ -972,7 +1004,17 @@
},
"doubleQuotedString": {
"begin": "(?<!(?<!`)\")\"",
"beginCaptures": {
"0": {
"name": "punctuation.definition.string.begin.powershell"
}
},
"end": "\"(?!\")",
"endCaptures": {
"0": {
"name": "punctuation.definition.string.end.powershell"
}
},
"name": "string.quoted.double.powershell",
"patterns": [
{

View file

@ -155,13 +155,13 @@
},
{
"c": "$",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell variable.other.readwrite.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
@ -287,13 +287,13 @@
},
{
"c": "$",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell variable.other.readwrite.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
@ -386,13 +386,13 @@
},
{
"c": "$",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell variable.other.readwrite.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
@ -441,13 +441,13 @@
},
{
"c": "$",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell variable.other.readwrite.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
@ -463,13 +463,13 @@
},
{
"c": ".IsInRole",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell entity.name.function.invocation.powershell",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell variable.other.readwrite.powershell variable.other.member.powershell",
"r": {
"dark_plus": "entity.name.function: #DCDCAA",
"light_plus": "entity.name.function: #795E26",
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "entity.name.function: #DCDCAA"
"hc_black": "variable: #9CDCFE"
}
},
{
@ -649,7 +649,18 @@
}
},
{
"c": "\"Failed to determine if the current user has elevated privileges. The error was: '{0}'.\"",
"c": "\"",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell string.quoted.double.powershell punctuation.definition.string.begin.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": "Failed to determine if the current user has elevated privileges. The error was: '{0}'.",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell string.quoted.double.powershell",
"r": {
"dark_plus": "string: #CE9178",
@ -659,6 +670,17 @@
"hc_black": "string: #CE9178"
}
},
{
"c": "\"",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell string.quoted.double.powershell punctuation.definition.string.end.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": " ",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell",
@ -694,13 +716,13 @@
},
{
"c": "$",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell support.constant.automatic.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
@ -991,13 +1013,13 @@
},
{
"c": "$",
"t": "source.powershell meta.scriptblock.powershell interpolated.simple.source.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell meta.scriptblock.powershell interpolated.simple.source.powershell variable.other.readwrite.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
@ -1068,13 +1090,13 @@
},
{
"c": "$",
"t": "source.powershell meta.scriptblock.powershell interpolated.simple.source.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.constant.automatic.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
@ -1145,7 +1167,7 @@
},
{
"c": "\"",
"t": "source.powershell meta.scriptblock.powershell interpolated.simple.source.powershell string.quoted.double.powershell",
"t": "source.powershell meta.scriptblock.powershell interpolated.simple.source.powershell string.quoted.double.powershell punctuation.definition.string.begin.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
@ -1156,13 +1178,13 @@
},
{
"c": "$",
"t": "source.powershell meta.scriptblock.powershell interpolated.simple.source.powershell string.quoted.double.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell meta.scriptblock.powershell interpolated.simple.source.powershell string.quoted.double.powershell variable.other.readwrite.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "variable: #9CDCFE"
}
},
{
@ -1177,7 +1199,7 @@
}
},
{
"c": " 2>&1 & set\"",
"c": " 2>&1 & set",
"t": "source.powershell meta.scriptblock.powershell interpolated.simple.source.powershell string.quoted.double.powershell",
"r": {
"dark_plus": "string: #CE9178",
@ -1187,6 +1209,17 @@
"hc_black": "string: #CE9178"
}
},
{
"c": "\"",
"t": "source.powershell meta.scriptblock.powershell interpolated.simple.source.powershell string.quoted.double.powershell punctuation.definition.string.end.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": ")",
"t": "source.powershell meta.scriptblock.powershell punctuation.section.group.end.powershell",
@ -1266,13 +1299,13 @@
},
{
"c": "$",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.constant.automatic.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
@ -1320,7 +1353,18 @@
}
},
{
"c": "'^([^=]+)=(.*)'",
"c": "'",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell string.quoted.single.powershell punctuation.definition.string.begin.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": "^([^=]+)=(.*)",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell string.quoted.single.powershell",
"r": {
"dark_plus": "string: #CE9178",
@ -1330,6 +1374,17 @@
"hc_black": "string: #CE9178"
}
},
{
"c": "'",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell string.quoted.single.powershell punctuation.definition.string.end.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": ")",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell punctuation.section.group.end.powershell",
@ -1431,13 +1486,13 @@
},
{
"c": "$",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.constant.automatic.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
@ -1508,13 +1563,13 @@
},
{
"c": "$",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell meta.scriptblock.powershell meta.scriptblock.powershell meta.scriptblock.powershell interpolated.simple.source.powershell support.constant.automatic.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
@ -1672,7 +1727,18 @@
}
},
{
"c": "'Initializing Azure PowerShell environment...'",
"c": "'",
"t": "source.powershell string.quoted.single.powershell punctuation.definition.string.begin.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": "Initializing Azure PowerShell environment...",
"t": "source.powershell string.quoted.single.powershell",
"r": {
"dark_plus": "string: #CE9178",
@ -1683,14 +1749,25 @@
}
},
{
"c": ";",
"t": "source.powershell keyword.other.statement-separator.powershell",
"c": "'",
"t": "source.powershell string.quoted.single.powershell punctuation.definition.string.end.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": ";",
"t": "source.powershell punctuation.terminator.statement.powershell",
"r": {
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
@ -1870,7 +1947,18 @@
}
},
{
"c": "'Please launch command under administrator account. It is needed for environment setting up and unit test.'",
"c": "'",
"t": "source.powershell meta.scriptblock.powershell string.quoted.single.powershell punctuation.definition.string.begin.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": "Please launch command under administrator account. It is needed for environment setting up and unit test.",
"t": "source.powershell meta.scriptblock.powershell string.quoted.single.powershell",
"r": {
"dark_plus": "string: #CE9178",
@ -1880,6 +1968,17 @@
"hc_black": "string: #CE9178"
}
},
{
"c": "'",
"t": "source.powershell meta.scriptblock.powershell string.quoted.single.powershell punctuation.definition.string.end.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": " ",
"t": "source.powershell meta.scriptblock.powershell",
@ -1915,13 +2014,13 @@
},
{
"c": ";",
"t": "source.powershell meta.scriptblock.powershell keyword.other.statement-separator.powershell",
"t": "source.powershell meta.scriptblock.powershell punctuation.terminator.statement.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
@ -1937,18 +2036,18 @@
},
{
"c": "$",
"t": "source.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell variable.other.readwrite.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
"c": "env:",
"t": "source.powershell support.variable.drive.powershell",
"t": "source.powershell variable.other.readwrite.powershell support.variable.drive.powershell",
"r": {
"dark_plus": "support.variable: #9CDCFE",
"light_plus": "support.variable: #001080",
@ -2069,18 +2168,18 @@
},
{
"c": "$",
"t": "source.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell variable.other.readwrite.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
"c": "env:",
"t": "source.powershell support.variable.drive.powershell",
"t": "source.powershell variable.other.readwrite.powershell support.variable.drive.powershell",
"r": {
"dark_plus": "support.variable: #9CDCFE",
"light_plus": "support.variable: #001080",
@ -2102,13 +2201,13 @@
},
{
"c": ";",
"t": "source.powershell keyword.other.statement-separator.powershell",
"t": "source.powershell punctuation.terminator.statement.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
@ -2190,7 +2289,7 @@
},
{
"c": "\"",
"t": "source.powershell interpolated.simple.source.powershell string.quoted.double.powershell",
"t": "source.powershell interpolated.simple.source.powershell string.quoted.double.powershell punctuation.definition.string.begin.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
@ -2201,18 +2300,18 @@
},
{
"c": "$",
"t": "source.powershell interpolated.simple.source.powershell string.quoted.double.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell interpolated.simple.source.powershell string.quoted.double.powershell variable.other.readwrite.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "variable: #9CDCFE"
}
},
{
"c": "env:",
"t": "source.powershell interpolated.simple.source.powershell string.quoted.double.powershell support.variable.drive.powershell",
"t": "source.powershell interpolated.simple.source.powershell string.quoted.double.powershell variable.other.readwrite.powershell support.variable.drive.powershell",
"r": {
"dark_plus": "support.variable: #9CDCFE",
"light_plus": "support.variable: #001080",
@ -2233,7 +2332,7 @@
}
},
{
"c": "\\Microsoft Visual Studio 12.0\"",
"c": "\\Microsoft Visual Studio 12.0",
"t": "source.powershell interpolated.simple.source.powershell string.quoted.double.powershell",
"r": {
"dark_plus": "string: #CE9178",
@ -2243,6 +2342,17 @@
"hc_black": "string: #CE9178"
}
},
{
"c": "\"",
"t": "source.powershell interpolated.simple.source.powershell string.quoted.double.powershell punctuation.definition.string.end.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": ")",
"t": "source.powershell punctuation.section.group.end.powershell",
@ -2289,13 +2399,13 @@
},
{
"c": "$",
"t": "source.powershell meta.scriptblock.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell meta.scriptblock.powershell variable.other.readwrite.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
@ -2321,7 +2431,18 @@
}
},
{
"c": "\"12.0\"",
"c": "\"",
"t": "source.powershell meta.scriptblock.powershell string.quoted.double.powershell punctuation.definition.string.begin.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": "12.0",
"t": "source.powershell meta.scriptblock.powershell string.quoted.double.powershell",
"r": {
"dark_plus": "string: #CE9178",
@ -2331,6 +2452,17 @@
"hc_black": "string: #CE9178"
}
},
{
"c": "\"",
"t": "source.powershell meta.scriptblock.powershell string.quoted.double.powershell punctuation.definition.string.end.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": "}",
"t": "source.powershell meta.scriptblock.powershell punctuation.section.braces.end.powershell",
@ -2399,13 +2531,13 @@
},
{
"c": "$",
"t": "source.powershell meta.scriptblock.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell meta.scriptblock.powershell variable.other.readwrite.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
@ -2431,7 +2563,18 @@
}
},
{
"c": "\"11.0\"",
"c": "\"",
"t": "source.powershell meta.scriptblock.powershell string.quoted.double.powershell punctuation.definition.string.begin.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": "11.0",
"t": "source.powershell meta.scriptblock.powershell string.quoted.double.powershell",
"r": {
"dark_plus": "string: #CE9178",
@ -2441,6 +2584,17 @@
"hc_black": "string: #CE9178"
}
},
{
"c": "\"",
"t": "source.powershell meta.scriptblock.powershell string.quoted.double.powershell punctuation.definition.string.end.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": "}",
"t": "source.powershell meta.scriptblock.powershell punctuation.section.braces.end.powershell",
@ -2454,13 +2608,13 @@
},
{
"c": "$",
"t": "source.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell variable.other.readwrite.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
@ -2508,7 +2662,18 @@
}
},
{
"c": "'\"{0}\\Microsoft Visual Studio {1}\\VC\\vcvarsall.bat\" x64'",
"c": "'",
"t": "source.powershell string.quoted.single.powershell punctuation.definition.string.begin.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": "\"{0}\\Microsoft Visual Studio {1}\\VC\\vcvarsall.bat\" x64",
"t": "source.powershell string.quoted.single.powershell",
"r": {
"dark_plus": "string: #CE9178",
@ -2518,6 +2683,17 @@
"hc_black": "string: #CE9178"
}
},
{
"c": "'",
"t": "source.powershell string.quoted.single.powershell punctuation.definition.string.end.powershell",
"r": {
"dark_plus": "string: #CE9178",
"light_plus": "string: #A31515",
"dark_vs": "string: #CE9178",
"light_vs": "string: #A31515",
"hc_black": "string: #CE9178"
}
},
{
"c": " ",
"t": "source.powershell",
@ -2553,18 +2729,18 @@
},
{
"c": "$",
"t": "source.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell variable.other.readwrite.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
"c": "env:",
"t": "source.powershell support.variable.drive.powershell",
"t": "source.powershell variable.other.readwrite.powershell support.variable.drive.powershell",
"r": {
"dark_plus": "support.variable: #9CDCFE",
"light_plus": "support.variable: #001080",
@ -2608,13 +2784,13 @@
},
{
"c": "$",
"t": "source.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell variable.other.readwrite.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
@ -2630,13 +2806,13 @@
},
{
"c": ";",
"t": "source.powershell keyword.other.statement-separator.powershell",
"t": "source.powershell punctuation.terminator.statement.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
},
{
@ -2685,13 +2861,13 @@
},
{
"c": "$",
"t": "source.powershell keyword.other.variable.definition.powershell",
"t": "source.powershell variable.other.readwrite.powershell punctuation.definition.variable.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "variable: #9CDCFE",
"light_plus": "variable: #001080",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "variable: #9CDCFE"
}
},
{
@ -2707,13 +2883,13 @@
},
{
"c": ";",
"t": "source.powershell keyword.other.statement-separator.powershell",
"t": "source.powershell punctuation.terminator.statement.powershell",
"r": {
"dark_plus": "keyword: #569CD6",
"light_plus": "keyword: #0000FF",
"dark_vs": "keyword: #569CD6",
"light_vs": "keyword: #0000FF",
"hc_black": "keyword: #569CD6"
"dark_plus": "default: #D4D4D4",
"light_plus": "default: #000000",
"dark_vs": "default: #D4D4D4",
"light_vs": "default: #000000",
"hc_black": "default: #FFFFFF"
}
}
]

View file

@ -14,7 +14,7 @@
"categories": [],
"dependencies": {
"vscode-extension-telemetry": "0.0.15",
"vscode-nls": "^3.2.1",
"vscode-nls": "^3.2.4",
"vscode-ripgrep": "^1.0.1"
},
"devDependencies": {

View file

@ -0,0 +1,229 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as path from 'path';
import * as vscode from 'vscode';
import * as arrays from './common/arrays';
import { compareItemsByScore, IItemAccessor, prepareQuery, ScorerCache } from './common/fileSearchScorer';
import * as strings from './common/strings';
import { joinPath } from './utils';
interface IProviderArgs {
query: vscode.FileSearchQuery;
options: vscode.FileSearchOptions;
progress: vscode.Progress<vscode.Uri>;
token: vscode.CancellationToken;
}
export interface IInternalFileSearchProvider {
provideFileSearchResults(options: vscode.FileSearchOptions, progress: vscode.Progress<string>, token: vscode.CancellationToken): Thenable<void>;
}
export class CachedSearchProvider {
private static readonly BATCH_SIZE = 512;
private caches: { [cacheKey: string]: Cache; } = Object.create(null);
provideFileSearchResults(provider: IInternalFileSearchProvider, query: vscode.FileSearchQuery, options: vscode.FileSearchOptions, progress: vscode.Progress<vscode.Uri>, token: vscode.CancellationToken): Thenable<void> {
const onResult = (result: IInternalFileMatch) => {
progress.report(joinPath(options.folder, result.relativePath));
};
const providerArgs: IProviderArgs = {
query, options, progress, token
};
let sortedSearch = this.trySortedSearchFromCache(providerArgs, onResult);
if (!sortedSearch) {
const engineOpts = options.maxResults ?
{
...options,
...{ maxResults: 1e9 }
} :
options;
providerArgs.options = engineOpts;
sortedSearch = this.doSortedSearch(providerArgs, provider);
}
return sortedSearch.then(rawMatches => {
rawMatches.forEach(onResult);
});
}
private doSortedSearch(args: IProviderArgs, provider: IInternalFileSearchProvider): Promise<IInternalFileMatch[]> {
const allResultsPromise = new Promise<IInternalFileMatch[]>((c, e) => {
const results: IInternalFileMatch[] = [];
const onResult = (progress: IInternalFileMatch[]) => results.push(...progress);
// TODO@roblou set maxResult = null
this.doSearch(args, provider, onResult, CachedSearchProvider.BATCH_SIZE)
.then(() => c(results), e);
});
let cache: Cache;
if (args.query.cacheKey) {
cache = this.getOrCreateCache(args.query.cacheKey); // TODO include folder in cache key
cache.resultsToSearchCache[args.query.pattern] = { finished: allResultsPromise };
allResultsPromise.then(null, err => {
delete cache.resultsToSearchCache[args.query.pattern];
});
}
return allResultsPromise.then(results => {
const scorerCache: ScorerCache = cache ? cache.scorerCache : Object.create(null);
return this.sortResults(args, results, scorerCache);
});
}
private getOrCreateCache(cacheKey: string): Cache {
const existing = this.caches[cacheKey];
if (existing) {
return existing;
}
return this.caches[cacheKey] = new Cache();
}
private trySortedSearchFromCache(args: IProviderArgs, onResult: (result: IInternalFileMatch) => void): Promise<IInternalFileMatch[]> {
const cache = args.query.cacheKey && this.caches[args.query.cacheKey];
if (!cache) {
return undefined;
}
const cached = this.getResultsFromCache(cache, args.query.pattern, onResult);
if (cached) {
return cached.then((results) => this.sortResults(args, results, cache.scorerCache));
}
return undefined;
}
private sortResults(args: IProviderArgs, results: IInternalFileMatch[], scorerCache: ScorerCache): Promise<IInternalFileMatch[]> {
// we use the same compare function that is used later when showing the results using fuzzy scoring
// this is very important because we are also limiting the number of results by config.maxResults
// and as such we want the top items to be included in this result set if the number of items
// exceeds config.maxResults.
const preparedQuery = prepareQuery(args.query.pattern);
const compare = (matchA: IInternalFileMatch, matchB: IInternalFileMatch) => compareItemsByScore(matchA, matchB, preparedQuery, true, FileMatchItemAccessor, scorerCache);
return arrays.topAsync(results, compare, args.options.maxResults || 0, 10000);
}
private getResultsFromCache(cache: Cache, searchValue: string, onResult: (results: IInternalFileMatch) => void): Promise<IInternalFileMatch[]> {
// Find cache entries by prefix of search value
const hasPathSep = searchValue.indexOf(path.sep) >= 0;
let cached: CacheEntry<IInternalFileMatch>;
let wasResolved: boolean;
for (let previousSearch in cache.resultsToSearchCache) {
// If we narrow down, we might be able to reuse the cached results
if (searchValue.startsWith(previousSearch)) {
if (hasPathSep && previousSearch.indexOf(path.sep) < 0) {
continue; // since a path character widens the search for potential more matches, require it in previous search too
}
const c = cache.resultsToSearchCache[previousSearch];
c.finished.then(() => { wasResolved = false; });
cached = c;
wasResolved = true;
break;
}
}
if (!cached) {
return null;
}
return new Promise((c, e) => {
cached.finished.then(cachedEntries => {
const cacheFilterStartTime = Date.now();
// Pattern match on results
let results: IInternalFileMatch[] = [];
const normalizedSearchValueLowercase = strings.stripWildcards(searchValue).toLowerCase();
for (let i = 0; i < cachedEntries.length; i++) {
let entry = cachedEntries[i];
// Check if this entry is a match for the search value
if (!strings.fuzzyContains(entry.relativePath, normalizedSearchValueLowercase)) {
continue;
}
results.push(entry);
}
c(results);
}, e);
});
}
private doSearch(args: IProviderArgs, provider: IInternalFileSearchProvider, onResult: (result: IInternalFileMatch[]) => void, batchSize: number): Promise<void> {
return new Promise<void>((c, e) => {
let batch: IInternalFileMatch[] = [];
const onProviderResult = (match: string) => {
if (match) {
const internalMatch: IInternalFileMatch = {
relativePath: match,
basename: path.basename(match)
};
batch.push(internalMatch);
if (batchSize > 0 && batch.length >= batchSize) {
onResult(batch);
batch = [];
}
}
};
provider.provideFileSearchResults(args.options, { report: onProviderResult }, args.token).then(() => {
if (batch.length) {
onResult(batch);
}
c();
}, error => {
if (batch.length) {
onResult(batch);
}
e(error);
});
});
}
public clearCache(cacheKey: string): Promise<void> {
delete this.caches[cacheKey];
return Promise.resolve(undefined);
}
}
interface IInternalFileMatch {
relativePath?: string; // Not present for extraFiles or absolute path matches
basename: string;
}
interface CacheEntry<T> {
finished: Promise<T[]>;
}
class Cache {
public resultsToSearchCache: { [searchValue: string]: CacheEntry<IInternalFileMatch> } = Object.create(null);
public scorerCache: ScorerCache = Object.create(null);
}
const FileMatchItemAccessor = new class implements IItemAccessor<IInternalFileMatch> {
public getItemLabel(match: IInternalFileMatch): string {
return match.basename; // e.g. myFile.txt
}
public getItemDescription(match: IInternalFileMatch): string {
return match.relativePath.substr(0, match.relativePath.length - match.basename.length - 1); // e.g. some/path/to/file
}
public getItemPath(match: IInternalFileMatch): string {
return match.relativePath; // e.g. some/path/to/file/myFile.txt
}
};

View file

@ -0,0 +1,75 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/**
* Asynchronous variant of `top()` allowing for splitting up work in batches between which the event loop can run.
*
* Returns the top N elements from the array.
*
* Faster than sorting the entire array when the array is a lot larger than N.
*
* @param array The unsorted array.
* @param compare A sort function for the elements.
* @param n The number of elements to return.
* @param batch The number of elements to examine before yielding to the event loop.
* @return The first n elemnts from array when sorted with compare.
*/
export function topAsync<T>(array: T[], compare: (a: T, b: T) => number, n: number, batch: number): Promise<T[]> {
// TODO@roblou cancellation
if (n === 0) {
return Promise.resolve([]);
}
let canceled = false;
return new Promise((resolve, reject) => {
(async () => {
const o = array.length;
const result = array.slice(0, n).sort(compare);
for (let i = n, m = Math.min(n + batch, o); i < o; i = m, m = Math.min(m + batch, o)) {
if (i > n) {
await new Promise(resolve => setTimeout(resolve, 0)); // nextTick() would starve I/O.
}
if (canceled) {
throw new Error('canceled');
}
topStep(array, compare, result, i, m);
}
return result;
})()
.then(resolve, reject);
});
}
function topStep<T>(array: T[], compare: (a: T, b: T) => number, result: T[], i: number, m: number): void {
for (const n = result.length; i < m; i++) {
const element = array[i];
if (compare(element, result[n - 1]) < 0) {
result.pop();
const j = findFirstInSorted(result, e => compare(element, e) < 0);
result.splice(j, 0, element);
}
}
}
/**
* Takes a sorted array and a function p. The array is sorted in such a way that all elements where p(x) is false
* are located before all elements where p(x) is true.
* @returns the least x for which p(x) is true or array.length if no element fullfills the given function.
*/
export function findFirstInSorted<T>(array: T[], p: (x: T) => boolean): number {
let low = 0, high = array.length;
if (high === 0) {
return 0; // no children
}
while (low < high) {
let mid = Math.floor((low + high) / 2);
if (p(array[mid])) {
high = mid;
} else {
low = mid + 1;
}
}
return low;
}

View file

@ -0,0 +1,422 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
// Names from https://blog.codinghorror.com/ascii-pronunciation-rules-for-programmers/
/**
* An inlined enum containing useful character codes (to be used with String.charCodeAt).
* Please leave the const keyword such that it gets inlined when compiled to JavaScript!
*/
export const enum CharCode {
Null = 0,
/**
* The `\t` character.
*/
Tab = 9,
/**
* The `\n` character.
*/
LineFeed = 10,
/**
* The `\r` character.
*/
CarriageReturn = 13,
Space = 32,
/**
* The `!` character.
*/
ExclamationMark = 33,
/**
* The `"` character.
*/
DoubleQuote = 34,
/**
* The `#` character.
*/
Hash = 35,
/**
* The `$` character.
*/
DollarSign = 36,
/**
* The `%` character.
*/
PercentSign = 37,
/**
* The `&` character.
*/
Ampersand = 38,
/**
* The `'` character.
*/
SingleQuote = 39,
/**
* The `(` character.
*/
OpenParen = 40,
/**
* The `)` character.
*/
CloseParen = 41,
/**
* The `*` character.
*/
Asterisk = 42,
/**
* The `+` character.
*/
Plus = 43,
/**
* The `,` character.
*/
Comma = 44,
/**
* The `-` character.
*/
Dash = 45,
/**
* The `.` character.
*/
Period = 46,
/**
* The `/` character.
*/
Slash = 47,
Digit0 = 48,
Digit1 = 49,
Digit2 = 50,
Digit3 = 51,
Digit4 = 52,
Digit5 = 53,
Digit6 = 54,
Digit7 = 55,
Digit8 = 56,
Digit9 = 57,
/**
* The `:` character.
*/
Colon = 58,
/**
* The `;` character.
*/
Semicolon = 59,
/**
* The `<` character.
*/
LessThan = 60,
/**
* The `=` character.
*/
Equals = 61,
/**
* The `>` character.
*/
GreaterThan = 62,
/**
* The `?` character.
*/
QuestionMark = 63,
/**
* The `@` character.
*/
AtSign = 64,
A = 65,
B = 66,
C = 67,
D = 68,
E = 69,
F = 70,
G = 71,
H = 72,
I = 73,
J = 74,
K = 75,
L = 76,
M = 77,
N = 78,
O = 79,
P = 80,
Q = 81,
R = 82,
S = 83,
T = 84,
U = 85,
V = 86,
W = 87,
X = 88,
Y = 89,
Z = 90,
/**
* The `[` character.
*/
OpenSquareBracket = 91,
/**
* The `\` character.
*/
Backslash = 92,
/**
* The `]` character.
*/
CloseSquareBracket = 93,
/**
* The `^` character.
*/
Caret = 94,
/**
* The `_` character.
*/
Underline = 95,
/**
* The ``(`)`` character.
*/
BackTick = 96,
a = 97,
b = 98,
c = 99,
d = 100,
e = 101,
f = 102,
g = 103,
h = 104,
i = 105,
j = 106,
k = 107,
l = 108,
m = 109,
n = 110,
o = 111,
p = 112,
q = 113,
r = 114,
s = 115,
t = 116,
u = 117,
v = 118,
w = 119,
x = 120,
y = 121,
z = 122,
/**
* The `{` character.
*/
OpenCurlyBrace = 123,
/**
* The `|` character.
*/
Pipe = 124,
/**
* The `}` character.
*/
CloseCurlyBrace = 125,
/**
* The `~` character.
*/
Tilde = 126,
U_Combining_Grave_Accent = 0x0300, // U+0300 Combining Grave Accent
U_Combining_Acute_Accent = 0x0301, // U+0301 Combining Acute Accent
U_Combining_Circumflex_Accent = 0x0302, // U+0302 Combining Circumflex Accent
U_Combining_Tilde = 0x0303, // U+0303 Combining Tilde
U_Combining_Macron = 0x0304, // U+0304 Combining Macron
U_Combining_Overline = 0x0305, // U+0305 Combining Overline
U_Combining_Breve = 0x0306, // U+0306 Combining Breve
U_Combining_Dot_Above = 0x0307, // U+0307 Combining Dot Above
U_Combining_Diaeresis = 0x0308, // U+0308 Combining Diaeresis
U_Combining_Hook_Above = 0x0309, // U+0309 Combining Hook Above
U_Combining_Ring_Above = 0x030A, // U+030A Combining Ring Above
U_Combining_Double_Acute_Accent = 0x030B, // U+030B Combining Double Acute Accent
U_Combining_Caron = 0x030C, // U+030C Combining Caron
U_Combining_Vertical_Line_Above = 0x030D, // U+030D Combining Vertical Line Above
U_Combining_Double_Vertical_Line_Above = 0x030E, // U+030E Combining Double Vertical Line Above
U_Combining_Double_Grave_Accent = 0x030F, // U+030F Combining Double Grave Accent
U_Combining_Candrabindu = 0x0310, // U+0310 Combining Candrabindu
U_Combining_Inverted_Breve = 0x0311, // U+0311 Combining Inverted Breve
U_Combining_Turned_Comma_Above = 0x0312, // U+0312 Combining Turned Comma Above
U_Combining_Comma_Above = 0x0313, // U+0313 Combining Comma Above
U_Combining_Reversed_Comma_Above = 0x0314, // U+0314 Combining Reversed Comma Above
U_Combining_Comma_Above_Right = 0x0315, // U+0315 Combining Comma Above Right
U_Combining_Grave_Accent_Below = 0x0316, // U+0316 Combining Grave Accent Below
U_Combining_Acute_Accent_Below = 0x0317, // U+0317 Combining Acute Accent Below
U_Combining_Left_Tack_Below = 0x0318, // U+0318 Combining Left Tack Below
U_Combining_Right_Tack_Below = 0x0319, // U+0319 Combining Right Tack Below
U_Combining_Left_Angle_Above = 0x031A, // U+031A Combining Left Angle Above
U_Combining_Horn = 0x031B, // U+031B Combining Horn
U_Combining_Left_Half_Ring_Below = 0x031C, // U+031C Combining Left Half Ring Below
U_Combining_Up_Tack_Below = 0x031D, // U+031D Combining Up Tack Below
U_Combining_Down_Tack_Below = 0x031E, // U+031E Combining Down Tack Below
U_Combining_Plus_Sign_Below = 0x031F, // U+031F Combining Plus Sign Below
U_Combining_Minus_Sign_Below = 0x0320, // U+0320 Combining Minus Sign Below
U_Combining_Palatalized_Hook_Below = 0x0321, // U+0321 Combining Palatalized Hook Below
U_Combining_Retroflex_Hook_Below = 0x0322, // U+0322 Combining Retroflex Hook Below
U_Combining_Dot_Below = 0x0323, // U+0323 Combining Dot Below
U_Combining_Diaeresis_Below = 0x0324, // U+0324 Combining Diaeresis Below
U_Combining_Ring_Below = 0x0325, // U+0325 Combining Ring Below
U_Combining_Comma_Below = 0x0326, // U+0326 Combining Comma Below
U_Combining_Cedilla = 0x0327, // U+0327 Combining Cedilla
U_Combining_Ogonek = 0x0328, // U+0328 Combining Ogonek
U_Combining_Vertical_Line_Below = 0x0329, // U+0329 Combining Vertical Line Below
U_Combining_Bridge_Below = 0x032A, // U+032A Combining Bridge Below
U_Combining_Inverted_Double_Arch_Below = 0x032B, // U+032B Combining Inverted Double Arch Below
U_Combining_Caron_Below = 0x032C, // U+032C Combining Caron Below
U_Combining_Circumflex_Accent_Below = 0x032D, // U+032D Combining Circumflex Accent Below
U_Combining_Breve_Below = 0x032E, // U+032E Combining Breve Below
U_Combining_Inverted_Breve_Below = 0x032F, // U+032F Combining Inverted Breve Below
U_Combining_Tilde_Below = 0x0330, // U+0330 Combining Tilde Below
U_Combining_Macron_Below = 0x0331, // U+0331 Combining Macron Below
U_Combining_Low_Line = 0x0332, // U+0332 Combining Low Line
U_Combining_Double_Low_Line = 0x0333, // U+0333 Combining Double Low Line
U_Combining_Tilde_Overlay = 0x0334, // U+0334 Combining Tilde Overlay
U_Combining_Short_Stroke_Overlay = 0x0335, // U+0335 Combining Short Stroke Overlay
U_Combining_Long_Stroke_Overlay = 0x0336, // U+0336 Combining Long Stroke Overlay
U_Combining_Short_Solidus_Overlay = 0x0337, // U+0337 Combining Short Solidus Overlay
U_Combining_Long_Solidus_Overlay = 0x0338, // U+0338 Combining Long Solidus Overlay
U_Combining_Right_Half_Ring_Below = 0x0339, // U+0339 Combining Right Half Ring Below
U_Combining_Inverted_Bridge_Below = 0x033A, // U+033A Combining Inverted Bridge Below
U_Combining_Square_Below = 0x033B, // U+033B Combining Square Below
U_Combining_Seagull_Below = 0x033C, // U+033C Combining Seagull Below
U_Combining_X_Above = 0x033D, // U+033D Combining X Above
U_Combining_Vertical_Tilde = 0x033E, // U+033E Combining Vertical Tilde
U_Combining_Double_Overline = 0x033F, // U+033F Combining Double Overline
U_Combining_Grave_Tone_Mark = 0x0340, // U+0340 Combining Grave Tone Mark
U_Combining_Acute_Tone_Mark = 0x0341, // U+0341 Combining Acute Tone Mark
U_Combining_Greek_Perispomeni = 0x0342, // U+0342 Combining Greek Perispomeni
U_Combining_Greek_Koronis = 0x0343, // U+0343 Combining Greek Koronis
U_Combining_Greek_Dialytika_Tonos = 0x0344, // U+0344 Combining Greek Dialytika Tonos
U_Combining_Greek_Ypogegrammeni = 0x0345, // U+0345 Combining Greek Ypogegrammeni
U_Combining_Bridge_Above = 0x0346, // U+0346 Combining Bridge Above
U_Combining_Equals_Sign_Below = 0x0347, // U+0347 Combining Equals Sign Below
U_Combining_Double_Vertical_Line_Below = 0x0348, // U+0348 Combining Double Vertical Line Below
U_Combining_Left_Angle_Below = 0x0349, // U+0349 Combining Left Angle Below
U_Combining_Not_Tilde_Above = 0x034A, // U+034A Combining Not Tilde Above
U_Combining_Homothetic_Above = 0x034B, // U+034B Combining Homothetic Above
U_Combining_Almost_Equal_To_Above = 0x034C, // U+034C Combining Almost Equal To Above
U_Combining_Left_Right_Arrow_Below = 0x034D, // U+034D Combining Left Right Arrow Below
U_Combining_Upwards_Arrow_Below = 0x034E, // U+034E Combining Upwards Arrow Below
U_Combining_Grapheme_Joiner = 0x034F, // U+034F Combining Grapheme Joiner
U_Combining_Right_Arrowhead_Above = 0x0350, // U+0350 Combining Right Arrowhead Above
U_Combining_Left_Half_Ring_Above = 0x0351, // U+0351 Combining Left Half Ring Above
U_Combining_Fermata = 0x0352, // U+0352 Combining Fermata
U_Combining_X_Below = 0x0353, // U+0353 Combining X Below
U_Combining_Left_Arrowhead_Below = 0x0354, // U+0354 Combining Left Arrowhead Below
U_Combining_Right_Arrowhead_Below = 0x0355, // U+0355 Combining Right Arrowhead Below
U_Combining_Right_Arrowhead_And_Up_Arrowhead_Below = 0x0356, // U+0356 Combining Right Arrowhead And Up Arrowhead Below
U_Combining_Right_Half_Ring_Above = 0x0357, // U+0357 Combining Right Half Ring Above
U_Combining_Dot_Above_Right = 0x0358, // U+0358 Combining Dot Above Right
U_Combining_Asterisk_Below = 0x0359, // U+0359 Combining Asterisk Below
U_Combining_Double_Ring_Below = 0x035A, // U+035A Combining Double Ring Below
U_Combining_Zigzag_Above = 0x035B, // U+035B Combining Zigzag Above
U_Combining_Double_Breve_Below = 0x035C, // U+035C Combining Double Breve Below
U_Combining_Double_Breve = 0x035D, // U+035D Combining Double Breve
U_Combining_Double_Macron = 0x035E, // U+035E Combining Double Macron
U_Combining_Double_Macron_Below = 0x035F, // U+035F Combining Double Macron Below
U_Combining_Double_Tilde = 0x0360, // U+0360 Combining Double Tilde
U_Combining_Double_Inverted_Breve = 0x0361, // U+0361 Combining Double Inverted Breve
U_Combining_Double_Rightwards_Arrow_Below = 0x0362, // U+0362 Combining Double Rightwards Arrow Below
U_Combining_Latin_Small_Letter_A = 0x0363, // U+0363 Combining Latin Small Letter A
U_Combining_Latin_Small_Letter_E = 0x0364, // U+0364 Combining Latin Small Letter E
U_Combining_Latin_Small_Letter_I = 0x0365, // U+0365 Combining Latin Small Letter I
U_Combining_Latin_Small_Letter_O = 0x0366, // U+0366 Combining Latin Small Letter O
U_Combining_Latin_Small_Letter_U = 0x0367, // U+0367 Combining Latin Small Letter U
U_Combining_Latin_Small_Letter_C = 0x0368, // U+0368 Combining Latin Small Letter C
U_Combining_Latin_Small_Letter_D = 0x0369, // U+0369 Combining Latin Small Letter D
U_Combining_Latin_Small_Letter_H = 0x036A, // U+036A Combining Latin Small Letter H
U_Combining_Latin_Small_Letter_M = 0x036B, // U+036B Combining Latin Small Letter M
U_Combining_Latin_Small_Letter_R = 0x036C, // U+036C Combining Latin Small Letter R
U_Combining_Latin_Small_Letter_T = 0x036D, // U+036D Combining Latin Small Letter T
U_Combining_Latin_Small_Letter_V = 0x036E, // U+036E Combining Latin Small Letter V
U_Combining_Latin_Small_Letter_X = 0x036F, // U+036F Combining Latin Small Letter X
/**
* Unicode Character 'LINE SEPARATOR' (U+2028)
* http://www.fileformat.info/info/unicode/char/2028/index.htm
*/
LINE_SEPARATOR_2028 = 8232,
// http://www.fileformat.info/info/unicode/category/Sk/list.htm
U_CIRCUMFLEX = 0x005E, // U+005E CIRCUMFLEX
U_GRAVE_ACCENT = 0x0060, // U+0060 GRAVE ACCENT
U_DIAERESIS = 0x00A8, // U+00A8 DIAERESIS
U_MACRON = 0x00AF, // U+00AF MACRON
U_ACUTE_ACCENT = 0x00B4, // U+00B4 ACUTE ACCENT
U_CEDILLA = 0x00B8, // U+00B8 CEDILLA
U_MODIFIER_LETTER_LEFT_ARROWHEAD = 0x02C2, // U+02C2 MODIFIER LETTER LEFT ARROWHEAD
U_MODIFIER_LETTER_RIGHT_ARROWHEAD = 0x02C3, // U+02C3 MODIFIER LETTER RIGHT ARROWHEAD
U_MODIFIER_LETTER_UP_ARROWHEAD = 0x02C4, // U+02C4 MODIFIER LETTER UP ARROWHEAD
U_MODIFIER_LETTER_DOWN_ARROWHEAD = 0x02C5, // U+02C5 MODIFIER LETTER DOWN ARROWHEAD
U_MODIFIER_LETTER_CENTRED_RIGHT_HALF_RING = 0x02D2, // U+02D2 MODIFIER LETTER CENTRED RIGHT HALF RING
U_MODIFIER_LETTER_CENTRED_LEFT_HALF_RING = 0x02D3, // U+02D3 MODIFIER LETTER CENTRED LEFT HALF RING
U_MODIFIER_LETTER_UP_TACK = 0x02D4, // U+02D4 MODIFIER LETTER UP TACK
U_MODIFIER_LETTER_DOWN_TACK = 0x02D5, // U+02D5 MODIFIER LETTER DOWN TACK
U_MODIFIER_LETTER_PLUS_SIGN = 0x02D6, // U+02D6 MODIFIER LETTER PLUS SIGN
U_MODIFIER_LETTER_MINUS_SIGN = 0x02D7, // U+02D7 MODIFIER LETTER MINUS SIGN
U_BREVE = 0x02D8, // U+02D8 BREVE
U_DOT_ABOVE = 0x02D9, // U+02D9 DOT ABOVE
U_RING_ABOVE = 0x02DA, // U+02DA RING ABOVE
U_OGONEK = 0x02DB, // U+02DB OGONEK
U_SMALL_TILDE = 0x02DC, // U+02DC SMALL TILDE
U_DOUBLE_ACUTE_ACCENT = 0x02DD, // U+02DD DOUBLE ACUTE ACCENT
U_MODIFIER_LETTER_RHOTIC_HOOK = 0x02DE, // U+02DE MODIFIER LETTER RHOTIC HOOK
U_MODIFIER_LETTER_CROSS_ACCENT = 0x02DF, // U+02DF MODIFIER LETTER CROSS ACCENT
U_MODIFIER_LETTER_EXTRA_HIGH_TONE_BAR = 0x02E5, // U+02E5 MODIFIER LETTER EXTRA-HIGH TONE BAR
U_MODIFIER_LETTER_HIGH_TONE_BAR = 0x02E6, // U+02E6 MODIFIER LETTER HIGH TONE BAR
U_MODIFIER_LETTER_MID_TONE_BAR = 0x02E7, // U+02E7 MODIFIER LETTER MID TONE BAR
U_MODIFIER_LETTER_LOW_TONE_BAR = 0x02E8, // U+02E8 MODIFIER LETTER LOW TONE BAR
U_MODIFIER_LETTER_EXTRA_LOW_TONE_BAR = 0x02E9, // U+02E9 MODIFIER LETTER EXTRA-LOW TONE BAR
U_MODIFIER_LETTER_YIN_DEPARTING_TONE_MARK = 0x02EA, // U+02EA MODIFIER LETTER YIN DEPARTING TONE MARK
U_MODIFIER_LETTER_YANG_DEPARTING_TONE_MARK = 0x02EB, // U+02EB MODIFIER LETTER YANG DEPARTING TONE MARK
U_MODIFIER_LETTER_UNASPIRATED = 0x02ED, // U+02ED MODIFIER LETTER UNASPIRATED
U_MODIFIER_LETTER_LOW_DOWN_ARROWHEAD = 0x02EF, // U+02EF MODIFIER LETTER LOW DOWN ARROWHEAD
U_MODIFIER_LETTER_LOW_UP_ARROWHEAD = 0x02F0, // U+02F0 MODIFIER LETTER LOW UP ARROWHEAD
U_MODIFIER_LETTER_LOW_LEFT_ARROWHEAD = 0x02F1, // U+02F1 MODIFIER LETTER LOW LEFT ARROWHEAD
U_MODIFIER_LETTER_LOW_RIGHT_ARROWHEAD = 0x02F2, // U+02F2 MODIFIER LETTER LOW RIGHT ARROWHEAD
U_MODIFIER_LETTER_LOW_RING = 0x02F3, // U+02F3 MODIFIER LETTER LOW RING
U_MODIFIER_LETTER_MIDDLE_GRAVE_ACCENT = 0x02F4, // U+02F4 MODIFIER LETTER MIDDLE GRAVE ACCENT
U_MODIFIER_LETTER_MIDDLE_DOUBLE_GRAVE_ACCENT = 0x02F5, // U+02F5 MODIFIER LETTER MIDDLE DOUBLE GRAVE ACCENT
U_MODIFIER_LETTER_MIDDLE_DOUBLE_ACUTE_ACCENT = 0x02F6, // U+02F6 MODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT
U_MODIFIER_LETTER_LOW_TILDE = 0x02F7, // U+02F7 MODIFIER LETTER LOW TILDE
U_MODIFIER_LETTER_RAISED_COLON = 0x02F8, // U+02F8 MODIFIER LETTER RAISED COLON
U_MODIFIER_LETTER_BEGIN_HIGH_TONE = 0x02F9, // U+02F9 MODIFIER LETTER BEGIN HIGH TONE
U_MODIFIER_LETTER_END_HIGH_TONE = 0x02FA, // U+02FA MODIFIER LETTER END HIGH TONE
U_MODIFIER_LETTER_BEGIN_LOW_TONE = 0x02FB, // U+02FB MODIFIER LETTER BEGIN LOW TONE
U_MODIFIER_LETTER_END_LOW_TONE = 0x02FC, // U+02FC MODIFIER LETTER END LOW TONE
U_MODIFIER_LETTER_SHELF = 0x02FD, // U+02FD MODIFIER LETTER SHELF
U_MODIFIER_LETTER_OPEN_SHELF = 0x02FE, // U+02FE MODIFIER LETTER OPEN SHELF
U_MODIFIER_LETTER_LOW_LEFT_ARROW = 0x02FF, // U+02FF MODIFIER LETTER LOW LEFT ARROW
U_GREEK_LOWER_NUMERAL_SIGN = 0x0375, // U+0375 GREEK LOWER NUMERAL SIGN
U_GREEK_TONOS = 0x0384, // U+0384 GREEK TONOS
U_GREEK_DIALYTIKA_TONOS = 0x0385, // U+0385 GREEK DIALYTIKA TONOS
U_GREEK_KORONIS = 0x1FBD, // U+1FBD GREEK KORONIS
U_GREEK_PSILI = 0x1FBF, // U+1FBF GREEK PSILI
U_GREEK_PERISPOMENI = 0x1FC0, // U+1FC0 GREEK PERISPOMENI
U_GREEK_DIALYTIKA_AND_PERISPOMENI = 0x1FC1, // U+1FC1 GREEK DIALYTIKA AND PERISPOMENI
U_GREEK_PSILI_AND_VARIA = 0x1FCD, // U+1FCD GREEK PSILI AND VARIA
U_GREEK_PSILI_AND_OXIA = 0x1FCE, // U+1FCE GREEK PSILI AND OXIA
U_GREEK_PSILI_AND_PERISPOMENI = 0x1FCF, // U+1FCF GREEK PSILI AND PERISPOMENI
U_GREEK_DASIA_AND_VARIA = 0x1FDD, // U+1FDD GREEK DASIA AND VARIA
U_GREEK_DASIA_AND_OXIA = 0x1FDE, // U+1FDE GREEK DASIA AND OXIA
U_GREEK_DASIA_AND_PERISPOMENI = 0x1FDF, // U+1FDF GREEK DASIA AND PERISPOMENI
U_GREEK_DIALYTIKA_AND_VARIA = 0x1FED, // U+1FED GREEK DIALYTIKA AND VARIA
U_GREEK_DIALYTIKA_AND_OXIA = 0x1FEE, // U+1FEE GREEK DIALYTIKA AND OXIA
U_GREEK_VARIA = 0x1FEF, // U+1FEF GREEK VARIA
U_GREEK_OXIA = 0x1FFD, // U+1FFD GREEK OXIA
U_GREEK_DASIA = 0x1FFE, // U+1FFE GREEK DASIA
U_OVERLINE = 0x203E, // Unicode Character 'OVERLINE'
/**
* UTF-8 BOM
* Unicode Character 'ZERO WIDTH NO-BREAK SPACE' (U+FEFF)
* http://www.fileformat.info/info/unicode/char/feff/index.htm
*/
UTF8_BOM = 65279
}

View file

@ -0,0 +1,115 @@
/*---------------------------------------------------------------------------------------------
* 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 strings from './strings';
let intlFileNameCollator: Intl.Collator;
let intlFileNameCollatorIsNumeric: boolean;
setFileNameComparer(new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }));
export function setFileNameComparer(collator: Intl.Collator): void {
intlFileNameCollator = collator;
intlFileNameCollatorIsNumeric = collator.resolvedOptions().numeric;
}
export function compareFileNames(one: string, other: string, caseSensitive = false): number {
if (intlFileNameCollator) {
const a = one || '';
const b = other || '';
const result = intlFileNameCollator.compare(a, b);
// Using the numeric option in the collator will
// make compare(`foo1`, `foo01`) === 0. We must disambiguate.
if (intlFileNameCollatorIsNumeric && result === 0 && a !== b) {
return a < b ? -1 : 1;
}
return result;
}
return noIntlCompareFileNames(one, other, caseSensitive);
}
const FileNameMatch = /^(.*?)(\.([^.]*))?$/;
export function noIntlCompareFileNames(one: string, other: string, caseSensitive = false): number {
if (!caseSensitive) {
one = one && one.toLowerCase();
other = other && other.toLowerCase();
}
const [oneName, oneExtension] = extractNameAndExtension(one);
const [otherName, otherExtension] = extractNameAndExtension(other);
if (oneName !== otherName) {
return oneName < otherName ? -1 : 1;
}
if (oneExtension === otherExtension) {
return 0;
}
return oneExtension < otherExtension ? -1 : 1;
}
function extractNameAndExtension(str?: string): [string, string] {
const match = str ? FileNameMatch.exec(str) : [] as RegExpExecArray;
return [(match && match[1]) || '', (match && match[3]) || ''];
}
export function compareAnything(one: string, other: string, lookFor: string): number {
let elementAName = one.toLowerCase();
let elementBName = other.toLowerCase();
// Sort prefix matches over non prefix matches
const prefixCompare = compareByPrefix(one, other, lookFor);
if (prefixCompare) {
return prefixCompare;
}
// Sort suffix matches over non suffix matches
let elementASuffixMatch = strings.endsWith(elementAName, lookFor);
let elementBSuffixMatch = strings.endsWith(elementBName, lookFor);
if (elementASuffixMatch !== elementBSuffixMatch) {
return elementASuffixMatch ? -1 : 1;
}
// Understand file names
let r = compareFileNames(elementAName, elementBName);
if (r !== 0) {
return r;
}
// Compare by name
return elementAName.localeCompare(elementBName);
}
export function compareByPrefix(one: string, other: string, lookFor: string): number {
let elementAName = one.toLowerCase();
let elementBName = other.toLowerCase();
// Sort prefix matches over non prefix matches
let elementAPrefixMatch = strings.startsWith(elementAName, lookFor);
let elementBPrefixMatch = strings.startsWith(elementBName, lookFor);
if (elementAPrefixMatch !== elementBPrefixMatch) {
return elementAPrefixMatch ? -1 : 1;
}
// Same prefix: Sort shorter matches to the top to have those on top that match more precisely
else if (elementAPrefixMatch && elementBPrefixMatch) {
if (elementAName.length < elementBName.length) {
return -1;
}
if (elementAName.length > elementBName.length) {
return 1;
}
}
return 0;
}

View file

@ -0,0 +1,619 @@
/*---------------------------------------------------------------------------------------------
* 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 { stripWildcards, equalsIgnoreCase } from './strings';
import { matchesPrefix, matchesCamelCase, createMatches, IMatch, isUpper } from './filters';
import { compareAnything } from './comparers';
import { CharCode } from './charCode';
const isWindows = process.platform === 'win32';
const isMacintosh = (process.platform === 'darwin');
const isLinux = (process.platform === 'linux');
const nativeSep = isWindows ? '\\' : '/';
export type Score = [number /* score */, number[] /* match positions */];
export type ScorerCache = { [key: string]: IItemScore };
const NO_MATCH = 0;
const NO_SCORE: Score = [NO_MATCH, []];
// const DEBUG = false;
// const DEBUG_MATRIX = false;
export function score(target: string, query: string, queryLower: string, fuzzy: boolean): Score {
if (!target || !query) {
return NO_SCORE; // return early if target or query are undefined
}
const targetLength = target.length;
const queryLength = query.length;
if (targetLength < queryLength) {
return NO_SCORE; // impossible for query to be contained in target
}
// if (DEBUG) {
// console.group(`Target: ${target}, Query: ${query}`);
// }
const targetLower = target.toLowerCase();
// When not searching fuzzy, we require the query to be contained fully
// in the target string contiguously.
if (!fuzzy) {
const indexOfQueryInTarget = targetLower.indexOf(queryLower);
if (indexOfQueryInTarget === -1) {
// if (DEBUG) {
// console.log(`Characters not matching consecutively ${queryLower} within ${targetLower}`);
// }
return NO_SCORE;
}
}
const res = doScore(query, queryLower, queryLength, target, targetLower, targetLength);
// if (DEBUG) {
// console.log(`%cFinal Score: ${res[0]}`, 'font-weight: bold');
// console.groupEnd();
// }
return res;
}
function doScore(query: string, queryLower: string, queryLength: number, target: string, targetLower: string, targetLength: number): [number, number[]] {
const scores = [];
const matches = [];
//
// Build Scorer Matrix:
//
// The matrix is composed of query q and target t. For each index we score
// q[i] with t[i] and compare that with the previous score. If the score is
// equal or larger, we keep the match. In addition to the score, we also keep
// the length of the consecutive matches to use as boost for the score.
//
// t a r g e t
// q
// u
// e
// r
// y
//
for (let queryIndex = 0; queryIndex < queryLength; queryIndex++) {
for (let targetIndex = 0; targetIndex < targetLength; targetIndex++) {
const currentIndex = queryIndex * targetLength + targetIndex;
const leftIndex = currentIndex - 1;
const diagIndex = (queryIndex - 1) * targetLength + targetIndex - 1;
const leftScore: number = targetIndex > 0 ? scores[leftIndex] : 0;
const diagScore: number = queryIndex > 0 && targetIndex > 0 ? scores[diagIndex] : 0;
const matchesSequenceLength: number = queryIndex > 0 && targetIndex > 0 ? matches[diagIndex] : 0;
// If we are not matching on the first query character any more, we only produce a
// score if we had a score previously for the last query index (by looking at the diagScore).
// This makes sure that the query always matches in sequence on the target. For example
// given a target of "ede" and a query of "de", we would otherwise produce a wrong high score
// for query[1] ("e") matching on target[0] ("e") because of the "beginning of word" boost.
let score: number;
if (!diagScore && queryIndex > 0) {
score = 0;
} else {
score = computeCharScore(query, queryLower, queryIndex, target, targetLower, targetIndex, matchesSequenceLength);
}
// We have a score and its equal or larger than the left score
// Match: sequence continues growing from previous diag value
// Score: increases by diag score value
if (score && diagScore + score >= leftScore) {
matches[currentIndex] = matchesSequenceLength + 1;
scores[currentIndex] = diagScore + score;
}
// We either have no score or the score is lower than the left score
// Match: reset to 0
// Score: pick up from left hand side
else {
matches[currentIndex] = NO_MATCH;
scores[currentIndex] = leftScore;
}
}
}
// Restore Positions (starting from bottom right of matrix)
const positions = [];
let queryIndex = queryLength - 1;
let targetIndex = targetLength - 1;
while (queryIndex >= 0 && targetIndex >= 0) {
const currentIndex = queryIndex * targetLength + targetIndex;
const match = matches[currentIndex];
if (match === NO_MATCH) {
targetIndex--; // go left
} else {
positions.push(targetIndex);
// go up and left
queryIndex--;
targetIndex--;
}
}
// Print matrix
// if (DEBUG_MATRIX) {
// printMatrix(query, target, matches, scores);
// }
return [scores[queryLength * targetLength - 1], positions.reverse()];
}
function computeCharScore(query: string, queryLower: string, queryIndex: number, target: string, targetLower: string, targetIndex: number, matchesSequenceLength: number): number {
let score = 0;
if (queryLower[queryIndex] !== targetLower[targetIndex]) {
return score; // no match of characters
}
// Character match bonus
score += 1;
// if (DEBUG) {
// console.groupCollapsed(`%cCharacter match bonus: +1 (char: ${queryLower[queryIndex]} at index ${targetIndex}, total score: ${score})`, 'font-weight: normal');
// }
// Consecutive match bonus
if (matchesSequenceLength > 0) {
score += (matchesSequenceLength * 5);
// if (DEBUG) {
// console.log('Consecutive match bonus: ' + (matchesSequenceLength * 5));
// }
}
// Same case bonus
if (query[queryIndex] === target[targetIndex]) {
score += 1;
// if (DEBUG) {
// console.log('Same case bonus: +1');
// }
}
// Start of word bonus
if (targetIndex === 0) {
score += 8;
// if (DEBUG) {
// console.log('Start of word bonus: +8');
// }
}
else {
// After separator bonus
const separatorBonus = scoreSeparatorAtPos(target.charCodeAt(targetIndex - 1));
if (separatorBonus) {
score += separatorBonus;
// if (DEBUG) {
// console.log('After separtor bonus: +4');
// }
}
// Inside word upper case bonus (camel case)
else if (isUpper(target.charCodeAt(targetIndex))) {
score += 1;
// if (DEBUG) {
// console.log('Inside word upper case bonus: +1');
// }
}
}
// if (DEBUG) {
// console.groupEnd();
// }
return score;
}
function scoreSeparatorAtPos(charCode: number): number {
switch (charCode) {
case CharCode.Slash:
case CharCode.Backslash:
return 5; // prefer path separators...
case CharCode.Underline:
case CharCode.Dash:
case CharCode.Period:
case CharCode.Space:
case CharCode.SingleQuote:
case CharCode.DoubleQuote:
case CharCode.Colon:
return 4; // ...over other separators
default:
return 0;
}
}
// function printMatrix(query: string, target: string, matches: number[], scores: number[]): void {
// console.log('\t' + target.split('').join('\t'));
// for (let queryIndex = 0; queryIndex < query.length; queryIndex++) {
// let line = query[queryIndex] + '\t';
// for (let targetIndex = 0; targetIndex < target.length; targetIndex++) {
// const currentIndex = queryIndex * target.length + targetIndex;
// line = line + 'M' + matches[currentIndex] + '/' + 'S' + scores[currentIndex] + '\t';
// }
// console.log(line);
// }
// }
/**
* Scoring on structural items that have a label and optional description.
*/
export interface IItemScore {
/**
* Overall score.
*/
score: number;
/**
* Matches within the label.
*/
labelMatch?: IMatch[];
/**
* Matches within the description.
*/
descriptionMatch?: IMatch[];
}
const NO_ITEM_SCORE: IItemScore = Object.freeze({ score: 0 });
export interface IItemAccessor<T> {
/**
* Just the label of the item to score on.
*/
getItemLabel(item: T): string;
/**
* The optional description of the item to score on. Can be null.
*/
getItemDescription(item: T): string;
/**
* If the item is a file, the path of the file to score on. Can be null.
*/
getItemPath(file: T): string;
}
const PATH_IDENTITY_SCORE = 1 << 18;
const LABEL_PREFIX_SCORE = 1 << 17;
const LABEL_CAMELCASE_SCORE = 1 << 16;
const LABEL_SCORE_THRESHOLD = 1 << 15;
export interface IPreparedQuery {
original: string;
value: string;
lowercase: string;
containsPathSeparator: boolean;
}
/**
* Helper function to prepare a search value for scoring in quick open by removing unwanted characters.
*/
export function prepareQuery(original: string): IPreparedQuery {
let lowercase: string;
let containsPathSeparator: boolean;
let value: string;
if (original) {
value = stripWildcards(original).replace(/\s/g, ''); // get rid of all wildcards and whitespace
if (isWindows) {
value = value.replace(/\//g, nativeSep); // Help Windows users to search for paths when using slash
}
lowercase = value.toLowerCase();
containsPathSeparator = value.indexOf(nativeSep) >= 0;
}
return { original, value, lowercase, containsPathSeparator };
}
export function scoreItem<T>(item: T, query: IPreparedQuery, fuzzy: boolean, accessor: IItemAccessor<T>, cache: ScorerCache): IItemScore {
if (!item || !query.value) {
return NO_ITEM_SCORE; // we need an item and query to score on at least
}
const label = accessor.getItemLabel(item);
if (!label) {
return NO_ITEM_SCORE; // we need a label at least
}
const description = accessor.getItemDescription(item);
let cacheHash: string;
if (description) {
cacheHash = `${label}${description}${query.value}${fuzzy}`;
} else {
cacheHash = `${label}${query.value}${fuzzy}`;
}
const cached = cache[cacheHash];
if (cached) {
return cached;
}
const itemScore = doScoreItem(label, description, accessor.getItemPath(item), query, fuzzy);
cache[cacheHash] = itemScore;
return itemScore;
}
function doScoreItem(label: string, description: string, path: string, query: IPreparedQuery, fuzzy: boolean): IItemScore {
// 1.) treat identity matches on full path highest
if (path && isLinux ? query.original === path : equalsIgnoreCase(query.original, path)) {
return { score: PATH_IDENTITY_SCORE, labelMatch: [{ start: 0, end: label.length }], descriptionMatch: description ? [{ start: 0, end: description.length }] : void 0 };
}
// We only consider label matches if the query is not including file path separators
const preferLabelMatches = !path || !query.containsPathSeparator;
if (preferLabelMatches) {
// 2.) treat prefix matches on the label second highest
const prefixLabelMatch = matchesPrefix(query.value, 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);
if (camelcaseLabelMatch) {
return { score: LABEL_CAMELCASE_SCORE, labelMatch: camelcaseLabelMatch };
}
// 4.) prefer scores on the label if any
const [labelScore, labelPositions] = score(label, query.value, query.lowercase, fuzzy);
if (labelScore) {
return { score: labelScore + LABEL_SCORE_THRESHOLD, labelMatch: createMatches(labelPositions) };
}
}
// 5.) finally compute description + label scores if we have a description
if (description) {
let descriptionPrefix = description;
if (!!path) {
descriptionPrefix = `${description}${nativeSep}`; // assume this is a file path
}
const descriptionPrefixLength = descriptionPrefix.length;
const descriptionAndLabel = `${descriptionPrefix}${label}`;
const [labelDescriptionScore, labelDescriptionPositions] = score(descriptionAndLabel, query.value, query.lowercase, fuzzy);
if (labelDescriptionScore) {
const labelDescriptionMatches = createMatches(labelDescriptionPositions);
const labelMatch: IMatch[] = [];
const descriptionMatch: IMatch[] = [];
// We have to split the matches back onto the label and description portions
labelDescriptionMatches.forEach(h => {
// Match overlaps label and description part, we need to split it up
if (h.start < descriptionPrefixLength && h.end > descriptionPrefixLength) {
labelMatch.push({ start: 0, end: h.end - descriptionPrefixLength });
descriptionMatch.push({ start: h.start, end: descriptionPrefixLength });
}
// Match on label part
else if (h.start >= descriptionPrefixLength) {
labelMatch.push({ start: h.start - descriptionPrefixLength, end: h.end - descriptionPrefixLength });
}
// Match on description part
else {
descriptionMatch.push(h);
}
});
return { score: labelDescriptionScore, labelMatch, descriptionMatch };
}
}
return NO_ITEM_SCORE;
}
export function compareItemsByScore<T>(itemA: T, itemB: T, query: IPreparedQuery, fuzzy: boolean, accessor: IItemAccessor<T>, cache: ScorerCache, fallbackComparer = fallbackCompare): number {
const itemScoreA = scoreItem(itemA, query, fuzzy, accessor, cache);
const itemScoreB = scoreItem(itemB, query, fuzzy, accessor, cache);
const scoreA = itemScoreA.score;
const scoreB = itemScoreB.score;
// 1.) prefer identity matches
if (scoreA === PATH_IDENTITY_SCORE || scoreB === PATH_IDENTITY_SCORE) {
if (scoreA !== scoreB) {
return scoreA === PATH_IDENTITY_SCORE ? -1 : 1;
}
}
// 2.) prefer label prefix matches
if (scoreA === LABEL_PREFIX_SCORE || scoreB === LABEL_PREFIX_SCORE) {
if (scoreA !== scoreB) {
return scoreA === LABEL_PREFIX_SCORE ? -1 : 1;
}
const labelA = accessor.getItemLabel(itemA);
const labelB = accessor.getItemLabel(itemB);
// prefer shorter names when both match on label prefix
if (labelA.length !== labelB.length) {
return labelA.length - labelB.length;
}
}
// 3.) prefer camelcase matches
if (scoreA === LABEL_CAMELCASE_SCORE || scoreB === LABEL_CAMELCASE_SCORE) {
if (scoreA !== scoreB) {
return scoreA === LABEL_CAMELCASE_SCORE ? -1 : 1;
}
const labelA = accessor.getItemLabel(itemA);
const labelB = accessor.getItemLabel(itemB);
// prefer more compact camel case matches over longer
const comparedByMatchLength = compareByMatchLength(itemScoreA.labelMatch, itemScoreB.labelMatch);
if (comparedByMatchLength !== 0) {
return comparedByMatchLength;
}
// prefer shorter names when both match on label camelcase
if (labelA.length !== labelB.length) {
return labelA.length - labelB.length;
}
}
// 4.) prefer label scores
if (scoreA > LABEL_SCORE_THRESHOLD || scoreB > LABEL_SCORE_THRESHOLD) {
if (scoreB < LABEL_SCORE_THRESHOLD) {
return -1;
}
if (scoreA < LABEL_SCORE_THRESHOLD) {
return 1;
}
}
// 5.) compare by score
if (scoreA !== scoreB) {
return scoreA > scoreB ? -1 : 1;
}
// 6.) scores are identical, prefer more compact matches (label and description)
const itemAMatchDistance = computeLabelAndDescriptionMatchDistance(itemA, itemScoreA, accessor);
const itemBMatchDistance = computeLabelAndDescriptionMatchDistance(itemB, itemScoreB, accessor);
if (itemAMatchDistance && itemBMatchDistance && itemAMatchDistance !== itemBMatchDistance) {
return itemBMatchDistance > itemAMatchDistance ? -1 : 1;
}
// 7.) at this point, scores are identical and match compactness as well
// for both items so we start to use the fallback compare
return fallbackComparer(itemA, itemB, query, accessor);
}
function computeLabelAndDescriptionMatchDistance<T>(item: T, score: IItemScore, accessor: IItemAccessor<T>): number {
const hasLabelMatches = (score.labelMatch && score.labelMatch.length);
const hasDescriptionMatches = (score.descriptionMatch && score.descriptionMatch.length);
let matchStart: number = -1;
let matchEnd: number = -1;
// If we have description matches, the start is first of description match
if (hasDescriptionMatches) {
matchStart = score.descriptionMatch[0].start;
}
// Otherwise, the start is the first label match
else if (hasLabelMatches) {
matchStart = score.labelMatch[0].start;
}
// If we have label match, the end is the last label match
// If we had a description match, we add the length of the description
// as offset to the end to indicate this.
if (hasLabelMatches) {
matchEnd = score.labelMatch[score.labelMatch.length - 1].end;
if (hasDescriptionMatches) {
const itemDescription = accessor.getItemDescription(item);
if (itemDescription) {
matchEnd += itemDescription.length;
}
}
}
// If we have just a description match, the end is the last description match
else if (hasDescriptionMatches) {
matchEnd = score.descriptionMatch[score.descriptionMatch.length - 1].end;
}
return matchEnd - matchStart;
}
function compareByMatchLength(matchesA?: IMatch[], matchesB?: IMatch[]): number {
if ((!matchesA && !matchesB) || (!matchesA.length && !matchesB.length)) {
return 0; // make sure to not cause bad comparing when matches are not provided
}
if (!matchesB || !matchesB.length) {
return -1;
}
if (!matchesA || !matchesA.length) {
return 1;
}
// Compute match length of A (first to last match)
const matchStartA = matchesA[0].start;
const matchEndA = matchesA[matchesA.length - 1].end;
const matchLengthA = matchEndA - matchStartA;
// Compute match length of B (first to last match)
const matchStartB = matchesB[0].start;
const matchEndB = matchesB[matchesB.length - 1].end;
const matchLengthB = matchEndB - matchStartB;
// Prefer shorter match length
return matchLengthA === matchLengthB ? 0 : matchLengthB < matchLengthA ? 1 : -1;
}
export function fallbackCompare<T>(itemA: T, itemB: T, query: IPreparedQuery, accessor: IItemAccessor<T>): number {
// check for label + description length and prefer shorter
const labelA = accessor.getItemLabel(itemA);
const labelB = accessor.getItemLabel(itemB);
const descriptionA = accessor.getItemDescription(itemA);
const descriptionB = accessor.getItemDescription(itemB);
const labelDescriptionALength = labelA.length + (descriptionA ? descriptionA.length : 0);
const labelDescriptionBLength = labelB.length + (descriptionB ? descriptionB.length : 0);
if (labelDescriptionALength !== labelDescriptionBLength) {
return labelDescriptionALength - labelDescriptionBLength;
}
// check for path length and prefer shorter
const pathA = accessor.getItemPath(itemA);
const pathB = accessor.getItemPath(itemB);
if (pathA && pathB && pathA.length !== pathB.length) {
return pathA.length - pathB.length;
}
// 7.) finally we have equal scores and equal length, we fallback to comparer
// compare by label
if (labelA !== labelB) {
return compareAnything(labelA, labelB, query.value);
}
// compare by description
if (descriptionA && descriptionB && descriptionA !== descriptionB) {
return compareAnything(descriptionA, descriptionB, query.value);
}
// compare by path
if (pathA && pathB && pathA !== pathB) {
return compareAnything(pathA, pathB, query.value);
}
// equal
return 0;
}

View file

@ -0,0 +1,224 @@
/*---------------------------------------------------------------------------------------------
* 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 strings from './strings';
import { CharCode } from './charCode';
export interface IFilter {
// Returns null if word doesn't match.
(word: string, wordToMatchAgainst: string): IMatch[];
}
export interface IMatch {
start: number;
end: number;
}
// Prefix
export const matchesPrefix: IFilter = _matchesPrefix.bind(undefined, true);
function _matchesPrefix(ignoreCase: boolean, word: string, wordToMatchAgainst: string): IMatch[] {
if (!wordToMatchAgainst || wordToMatchAgainst.length < word.length) {
return null;
}
let matches: boolean;
if (ignoreCase) {
matches = strings.startsWithIgnoreCase(wordToMatchAgainst, word);
} else {
matches = wordToMatchAgainst.indexOf(word) === 0;
}
if (!matches) {
return null;
}
return word.length > 0 ? [{ start: 0, end: word.length }] : [];
}
// CamelCase
function isLower(code: number): boolean {
return CharCode.a <= code && code <= CharCode.z;
}
export function isUpper(code: number): boolean {
return CharCode.A <= code && code <= CharCode.Z;
}
function isNumber(code: number): boolean {
return CharCode.Digit0 <= code && code <= CharCode.Digit9;
}
function isWhitespace(code: number): boolean {
return (
code === CharCode.Space
|| code === CharCode.Tab
|| code === CharCode.LineFeed
|| code === CharCode.CarriageReturn
);
}
function isAlphanumeric(code: number): boolean {
return isLower(code) || isUpper(code) || isNumber(code);
}
function join(head: IMatch, tail: IMatch[]): IMatch[] {
if (tail.length === 0) {
tail = [head];
} else if (head.end === tail[0].start) {
tail[0].start = head.start;
} else {
tail.unshift(head);
}
return tail;
}
function nextAnchor(camelCaseWord: string, start: number): number {
for (let i = start; i < camelCaseWord.length; i++) {
let c = camelCaseWord.charCodeAt(i);
if (isUpper(c) || isNumber(c) || (i > 0 && !isAlphanumeric(camelCaseWord.charCodeAt(i - 1)))) {
return i;
}
}
return camelCaseWord.length;
}
function _matchesCamelCase(word: string, camelCaseWord: string, i: number, j: number): IMatch[] {
if (i === word.length) {
return [];
} else if (j === camelCaseWord.length) {
return null;
} else if (word[i] !== camelCaseWord[j].toLowerCase()) {
return null;
} else {
let result: IMatch[] = null;
let nextUpperIndex = j + 1;
result = _matchesCamelCase(word, camelCaseWord, i + 1, j + 1);
while (!result && (nextUpperIndex = nextAnchor(camelCaseWord, nextUpperIndex)) < camelCaseWord.length) {
result = _matchesCamelCase(word, camelCaseWord, i + 1, nextUpperIndex);
nextUpperIndex++;
}
return result === null ? null : join({ start: j, end: j + 1 }, result);
}
}
interface ICamelCaseAnalysis {
upperPercent: number;
lowerPercent: number;
alphaPercent: number;
numericPercent: number;
}
// Heuristic to avoid computing camel case matcher for words that don't
// look like camelCaseWords.
function analyzeCamelCaseWord(word: string): ICamelCaseAnalysis {
let upper = 0, lower = 0, alpha = 0, numeric = 0, code = 0;
for (let i = 0; i < word.length; i++) {
code = word.charCodeAt(i);
if (isUpper(code)) { upper++; }
if (isLower(code)) { lower++; }
if (isAlphanumeric(code)) { alpha++; }
if (isNumber(code)) { numeric++; }
}
let upperPercent = upper / word.length;
let lowerPercent = lower / word.length;
let alphaPercent = alpha / word.length;
let numericPercent = numeric / word.length;
return { upperPercent, lowerPercent, alphaPercent, numericPercent };
}
function isUpperCaseWord(analysis: ICamelCaseAnalysis): boolean {
const { upperPercent, lowerPercent } = analysis;
return lowerPercent === 0 && upperPercent > 0.6;
}
function isCamelCaseWord(analysis: ICamelCaseAnalysis): boolean {
const { upperPercent, lowerPercent, alphaPercent, numericPercent } = analysis;
return lowerPercent > 0.2 && upperPercent < 0.8 && alphaPercent > 0.6 && numericPercent < 0.2;
}
// Heuristic to avoid computing camel case matcher for words that don't
// look like camel case patterns.
function isCamelCasePattern(word: string): boolean {
let upper = 0, lower = 0, code = 0, whitespace = 0;
for (let i = 0; i < word.length; i++) {
code = word.charCodeAt(i);
if (isUpper(code)) { upper++; }
if (isLower(code)) { lower++; }
if (isWhitespace(code)) { whitespace++; }
}
if ((upper === 0 || lower === 0) && whitespace === 0) {
return word.length <= 30;
} else {
return upper <= 5;
}
}
export function matchesCamelCase(word: string, camelCaseWord: string): IMatch[] {
if (!camelCaseWord) {
return null;
}
camelCaseWord = camelCaseWord.trim();
if (camelCaseWord.length === 0) {
return null;
}
if (!isCamelCasePattern(word)) {
return null;
}
if (camelCaseWord.length > 60) {
return null;
}
const analysis = analyzeCamelCaseWord(camelCaseWord);
if (!isCamelCaseWord(analysis)) {
if (!isUpperCaseWord(analysis)) {
return null;
}
camelCaseWord = camelCaseWord.toLowerCase();
}
let result: IMatch[] = null;
let i = 0;
word = word.toLowerCase();
while (i < camelCaseWord.length && (result = _matchesCamelCase(word, camelCaseWord, 0, i)) === null) {
i = nextAnchor(camelCaseWord, i + 1);
}
return result;
}
export function createMatches(position: number[]): IMatch[] {
let ret: IMatch[] = [];
if (!position) {
return ret;
}
let last: IMatch;
for (const pos of position) {
if (last && last.end === pos) {
last.end += 1;
} else {
last = { start: pos, end: pos + 1 };
ret.push(last);
}
}
return ret;
}

View file

@ -0,0 +1,143 @@
/*---------------------------------------------------------------------------------------------
* 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 { CharCode } from './charCode';
export function stripWildcards(pattern: string): string {
return pattern.replace(/\*/g, '');
}
/**
* Determines if haystack starts with needle.
*/
export function startsWith(haystack: string, needle: string): boolean {
if (haystack.length < needle.length) {
return false;
}
if (haystack === needle) {
return true;
}
for (let i = 0; i < needle.length; i++) {
if (haystack[i] !== needle[i]) {
return false;
}
}
return true;
}
export function startsWithIgnoreCase(str: string, candidate: string): boolean {
const candidateLength = candidate.length;
if (candidate.length > str.length) {
return false;
}
return doEqualsIgnoreCase(str, candidate, candidateLength);
}
/**
* Determines if haystack ends with needle.
*/
export function endsWith(haystack: string, needle: string): boolean {
let diff = haystack.length - needle.length;
if (diff > 0) {
return haystack.indexOf(needle, diff) === diff;
} else if (diff === 0) {
return haystack === needle;
} else {
return false;
}
}
function isLowerAsciiLetter(code: number): boolean {
return code >= CharCode.a && code <= CharCode.z;
}
function isUpperAsciiLetter(code: number): boolean {
return code >= CharCode.A && code <= CharCode.Z;
}
function isAsciiLetter(code: number): boolean {
return isLowerAsciiLetter(code) || isUpperAsciiLetter(code);
}
export function equalsIgnoreCase(a: string, b: string): boolean {
const len1 = a ? a.length : 0;
const len2 = b ? b.length : 0;
if (len1 !== len2) {
return false;
}
return doEqualsIgnoreCase(a, b);
}
function doEqualsIgnoreCase(a: string, b: string, stopAt = a.length): boolean {
if (typeof a !== 'string' || typeof b !== 'string') {
return false;
}
for (let i = 0; i < stopAt; i++) {
const codeA = a.charCodeAt(i);
const codeB = b.charCodeAt(i);
if (codeA === codeB) {
continue;
}
// a-z A-Z
if (isAsciiLetter(codeA) && isAsciiLetter(codeB)) {
let diff = Math.abs(codeA - codeB);
if (diff !== 0 && diff !== 32) {
return false;
}
}
// Any other charcode
else {
if (String.fromCharCode(codeA).toLowerCase() !== String.fromCharCode(codeB).toLowerCase()) {
return false;
}
}
}
return true;
}
/**
* Checks if the characters of the provided query string are included in the
* target string. The characters do not have to be contiguous within the string.
*/
export function fuzzyContains(target: string, query: string): boolean {
if (!target || !query) {
return false; // return early if target or query are undefined
}
if (target.length < query.length) {
return false; // impossible for query to be contained in target
}
const queryLen = query.length;
const targetLower = target.toLowerCase();
let index = 0;
let lastIndexOf = -1;
while (index < queryLen) {
let indexOf = targetLower.indexOf(query[index], lastIndexOf + 1);
if (indexOf < 0) {
return false;
}
lastIndexOf = indexOf;
index++;
}
return true;
}

View file

@ -6,6 +6,7 @@
import * as vscode from 'vscode';
import { RipgrepTextSearchEngine } from './ripgrepTextSearch';
import { RipgrepFileSearchEngine } from './ripgrepFileSearch';
import { CachedSearchProvider } from './cachedSearchProvider';
export function activate(): void {
if (vscode.workspace.getConfiguration('searchRipgrep').get('enable')) {
@ -15,17 +16,39 @@ export function activate(): void {
}
}
type SearchEngine = RipgrepFileSearchEngine | RipgrepTextSearchEngine;
class RipgrepSearchProvider implements vscode.SearchProvider {
private cachedProvider: CachedSearchProvider;
private inProgress: Set<SearchEngine> = new Set();
constructor(private outputChannel: vscode.OutputChannel) {
this.cachedProvider = new CachedSearchProvider();
process.once('exit', () => this.dispose());
}
provideTextSearchResults(query: vscode.TextSearchQuery, options: vscode.TextSearchOptions, progress: vscode.Progress<vscode.TextSearchResult>, token: vscode.CancellationToken): Thenable<void> {
const engine = new RipgrepTextSearchEngine(this.outputChannel);
return engine.provideTextSearchResults(query, options, progress, token);
return this.withEngine(engine, () => engine.provideTextSearchResults(query, options, progress, token));
}
provideFileSearchResults(options: vscode.SearchOptions, progress: vscode.Progress<string>, token: vscode.CancellationToken): Thenable<void> {
provideFileSearchResults(query: vscode.FileSearchQuery, options: vscode.SearchOptions, progress: vscode.Progress<vscode.Uri>, token: vscode.CancellationToken): Thenable<void> {
const engine = new RipgrepFileSearchEngine(this.outputChannel);
return engine.provideFileSearchResults(options, progress, token);
return this.withEngine(engine, () => this.cachedProvider.provideFileSearchResults(engine, query, options, progress, token));
}
clearCache(cacheKey: string): void {
this.cachedProvider.clearCache(cacheKey);
}
private withEngine(engine: SearchEngine, fn: () => Thenable<void>): Thenable<void> {
this.inProgress.add(engine);
return fn().then(() => {
this.inProgress.delete(engine);
});
}
private dispose() {
this.inProgress.forEach(engine => engine.cancel());
}
}

View file

@ -7,30 +7,31 @@ import * as cp from 'child_process';
import { Readable } from 'stream';
import { NodeStringDecoder, StringDecoder } from 'string_decoder';
import * as vscode from 'vscode';
import { normalizeNFC, normalizeNFD } from './normalization';
import { normalizeNFC, normalizeNFD } from './common/normalization';
import { rgPath } from './ripgrep';
import { anchorGlob } from './ripgrepHelpers';
import { anchorGlob } from './utils';
import { rgErrorMsgForDisplay } from './ripgrepTextSearch';
import { IInternalFileSearchProvider } from './cachedSearchProvider';
const isMac = process.platform === 'darwin';
// If vscode-ripgrep is in an .asar file, then the binary is unpacked.
const rgDiskPath = rgPath.replace(/\bnode_modules\.asar\b/, 'node_modules.asar.unpacked');
export class RipgrepFileSearchEngine {
export class RipgrepFileSearchEngine implements IInternalFileSearchProvider {
private rgProc: cp.ChildProcess;
private killRgProcFn: (code?: number) => void;
private isDone: boolean;
constructor(private outputChannel: vscode.OutputChannel) {
this.killRgProcFn = () => this.rgProc && this.rgProc.kill();
process.once('exit', this.killRgProcFn);
constructor(private outputChannel: vscode.OutputChannel) { }
cancel() {
this.isDone = true;
if (this.rgProc) {
this.rgProc.kill();
}
}
private dispose() {
process.removeListener('exit', this.killRgProcFn);
}
provideFileSearchResults(options: vscode.SearchOptions, progress: vscode.Progress<string>, token: vscode.CancellationToken): Thenable<void> {
provideFileSearchResults(options: vscode.FileSearchOptions, progress: vscode.Progress<string>, token: vscode.CancellationToken): Thenable<void> {
this.outputChannel.appendLine(`provideFileSearchResults ${JSON.stringify({
...options,
...{
@ -39,12 +40,7 @@ export class RipgrepFileSearchEngine {
})}`);
return new Promise((resolve, reject) => {
let isDone = false;
const cancel = () => {
isDone = true;
this.rgProc.kill();
};
token.onCancellationRequested(cancel);
token.onCancellationRequested(() => this.cancel());
const rgArgs = getRgArgs(options);
@ -93,7 +89,7 @@ export class RipgrepFileSearchEngine {
});
if (last) {
if (isDone) {
if (this.isDone) {
resolve();
} else {
// Trigger last result
@ -106,12 +102,7 @@ export class RipgrepFileSearchEngine {
}
}
});
}).then(
() => this.dispose(),
err => {
this.dispose();
return Promise.reject(err);
});
});
}
private collectStdout(cmd: cp.ChildProcess, cb: (err: Error, stdout?: string, last?: boolean) => void): void {

View file

@ -7,10 +7,11 @@
import * as cp from 'child_process';
import { EventEmitter } from 'events';
import * as path from 'path';
import { NodeStringDecoder, StringDecoder } from 'string_decoder';
import * as vscode from 'vscode';
import { rgPath } from './ripgrep';
import { anchorGlob } from './ripgrepHelpers';
import { anchorGlob } from './utils';
// If vscode-ripgrep is in an .asar file, then the binary is unpacked.
const rgDiskPath = rgPath.replace(/\bnode_modules\.asar\b/, 'node_modules.asar.unpacked');
@ -21,12 +22,21 @@ const MAX_TEXT_RESULTS = 10000;
export class RipgrepTextSearchEngine {
private isDone = false;
private rgProc: cp.ChildProcess;
private killRgProcFn: (code?: number) => void;
private ripgrepParser: RipgrepParser;
constructor(private outputChannel: vscode.OutputChannel) {
this.killRgProcFn = () => this.rgProc && this.rgProc.kill();
constructor(private outputChannel: vscode.OutputChannel) { }
cancel() {
this.isDone = true;
if (this.rgProc) {
this.rgProc.kill();
}
if (this.ripgrepParser) {
this.ripgrepParser.cancel();
}
}
provideTextSearchResults(query: vscode.TextSearchQuery, options: vscode.TextSearchOptions, progress: vscode.Progress<vscode.TextSearchResult>, token: vscode.CancellationToken): Thenable<void> {
@ -38,12 +48,7 @@ export class RipgrepTextSearchEngine {
})}`);
return new Promise((resolve, reject) => {
const cancel = () => {
this.isDone = true;
this.ripgrepParser.cancel();
this.rgProc.kill();
};
token.onCancellationRequested(cancel);
token.onCancellationRequested(() => this.cancel());
const rgArgs = getRgArgs(query, options);
@ -55,7 +60,6 @@ export class RipgrepTextSearchEngine {
this.outputChannel.appendLine(`rg ${escapedArgs}\n - cwd: ${cwd}`);
this.rgProc = cp.spawn(rgDiskPath, rgArgs, { cwd });
process.once('exit', this.killRgProcFn);
this.rgProc.on('error', e => {
console.error(e);
this.outputChannel.append('Error: ' + (e && e.message));
@ -70,7 +74,7 @@ export class RipgrepTextSearchEngine {
});
this.ripgrepParser.on('hitLimit', () => {
cancel();
this.cancel();
});
this.rgProc.stdout.on('data', data => {
@ -91,7 +95,6 @@ export class RipgrepTextSearchEngine {
this.outputChannel.appendLine(gotData ? 'Got data from stdout' : 'No data from stdout');
this.outputChannel.appendLine(gotResult ? 'Got result from parser' : 'No result from parser');
this.outputChannel.appendLine('');
process.removeListener('exit', this.killRgProcFn);
if (this.isDone) {
resolve();
} else {
@ -291,7 +294,7 @@ export class RipgrepParser extends EventEmitter {
lineMatches
.map(range => {
return <vscode.TextSearchResult>{
path: this.currentFile,
uri: vscode.Uri.file(path.join(this.rootFolder, this.currentFile)),
range,
preview: {
text: preview,

View file

@ -5,9 +5,8 @@
'use strict';
import * as vscode from 'vscode';
import * as path from 'path';
import * as vscode from 'vscode';
export function fixDriveC(_path: string): string {
const root = path.parse(_path).root;
@ -19,3 +18,10 @@ export function fixDriveC(_path: string): string {
export function anchorGlob(glob: string): string {
return glob.startsWith('**') || glob.startsWith('/') ? glob : `/${glob}`;
}
export function joinPath(resource: vscode.Uri, pathFragment: string): vscode.Uri {
const joinedPath = path.join(resource.path || '/', pathFragment);
return resource.with({
path: joinedPath
});
}

View file

@ -1545,9 +1545,9 @@ vscode-extension-telemetry@0.0.15:
dependencies:
applicationinsights "1.0.1"
vscode-nls@^3.2.1:
version "3.2.2"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.2.tgz#3817eca5b985c2393de325197cf4e15eb2aa5350"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"
vscode-ripgrep@^1.0.1:
version "1.0.1"

View file

@ -4,7 +4,7 @@
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request."
],
"version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/7bf8960f7042474b10b519f39339fc527907ce16",
"version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/40288b872220e5c0b844b1de507f1749ed14589b",
"name": "TypeScript",
"scopeName": "source.ts",
"patterns": [
@ -4149,7 +4149,7 @@
},
"directives": {
"name": "comment.line.triple-slash.directive.ts",
"begin": "^(///)\\s*(?=<(reference|amd-dependency|amd-module)(\\s+(path|types|no-default-lib|name)\\s*=\\s*((\\'([^\\'\\\\]|\\\\\\'|\\\\)*\\')|(\\\"([^\\\"\\\\]|\\\\\\\"|\\\\)*\\\")))+\\s*/>\\s*$)",
"begin": "^(///)\\s*(?=<(reference|amd-dependency|amd-module)(\\s+(path|types|no-default-lib|lib|name)\\s*=\\s*((\\'([^\\'\\\\]|\\\\\\'|\\\\)*\\')|(\\\"([^\\\"\\\\]|\\\\\\\"|\\\\)*\\\")))+\\s*/>\\s*$)",
"beginCaptures": {
"1": {
"name": "punctuation.definition.comment.ts"
@ -4177,7 +4177,7 @@
"patterns": [
{
"name": "entity.other.attribute-name.directive.ts",
"match": "path|types|no-default-lib|name"
"match": "path|types|no-default-lib|lib|name"
},
{
"name": "keyword.operator.assignment.ts",

View file

@ -4,7 +4,7 @@
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request."
],
"version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/7bf8960f7042474b10b519f39339fc527907ce16",
"version": "https://github.com/Microsoft/TypeScript-TmLanguage/commit/88217b1c7d36ed5d35adc3099ba7978aabe2531b",
"name": "TypeScriptReact",
"scopeName": "source.tsx",
"patterns": [
@ -4115,7 +4115,7 @@
},
"directives": {
"name": "comment.line.triple-slash.directive.tsx",
"begin": "^(///)\\s*(?=<(reference|amd-dependency|amd-module)(\\s+(path|types|no-default-lib|name)\\s*=\\s*((\\'([^\\'\\\\]|\\\\\\'|\\\\)*\\')|(\\\"([^\\\"\\\\]|\\\\\\\"|\\\\)*\\\")))+\\s*/>\\s*$)",
"begin": "^(///)\\s*(?=<(reference|amd-dependency|amd-module)(\\s+(path|types|no-default-lib|lib|name)\\s*=\\s*((\\'([^\\'\\\\]|\\\\\\'|\\\\)*\\')|(\\\"([^\\\"\\\\]|\\\\\\\"|\\\\)*\\\")))+\\s*/>\\s*$)",
"beginCaptures": {
"1": {
"name": "punctuation.definition.comment.tsx"
@ -4143,7 +4143,7 @@
"patterns": [
{
"name": "entity.other.attribute-name.directive.tsx",
"match": "path|types|no-default-lib|name"
"match": "path|types|no-default-lib|lib|name"
},
{
"name": "keyword.operator.assignment.tsx",
@ -4664,8 +4664,8 @@
]
},
"jsx-tag-in-expression": {
"begin": "(?x)\n (?<!\\+\\+|--)(?<=[({\\[,?=>:*]|&&|\\|\\||\\?|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)|(\\s+))(?!\\?)|\\/?>))",
"end": "(?!(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)|(\\s+))(?!\\?)|\\/?>))",
"begin": "(?x)\n (?<!\\+\\+|--)(?<=[({\\[,?=>:*]|&&|\\|\\||\\?|^return|[^\\._$[:alnum:]]return|^default|[^\\._$[:alnum:]]default|^)\\s*\n (?!<\\s*[_$[:alpha:]][_$[:alnum:]]*((\\s+extends\\s+[^=>])|,)) # look ahead is not type parameter of arrow\n (?=(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*)|(\\s+))(?!\\?)|\\/?>))",
"end": "(?!(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*)|(\\s+))(?!\\?)|\\/?>))",
"patterns": [
{
"include": "#jsx-tag"
@ -4674,7 +4674,7 @@
},
"jsx-tag": {
"name": "meta.tag.tsx",
"begin": "(?=(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)|(\\s+))(?!\\?)|\\/?>))",
"begin": "(?=(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*)|(\\s+))(?!\\?)|\\/?>))",
"end": "(/>)|(?:(</)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))?\\s*(>))",
"endCaptures": {
"1": {
@ -4701,7 +4701,7 @@
},
"patterns": [
{
"begin": "(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>|\\<\\s*(((keyof|infer)\\s+)|(([_$[:alpha:]][_$[:alnum:]]*|(\\{([^\\{\\}]|(\\{[^\\{\\}]*\\}))*\\})|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(\\[([^\\[\\]]|(\\[[^\\[\\]]*\\]))*\\])|(\\'[^\\']*\\')|(\\\"[^\\\"]*\\\")|(\\`[^\\`]*\\`))(?=\\s*([\\<\\>\\,\\.\\[=]|&(?!&)|\\|(?!\\|)))))([^<>\\(]|(\\(([^\\(\\)]|(\\([^\\(\\)]*\\)))*\\))|(?<==)\\>)*(?!=)\\>)*(?!=)>\\s*)|(\\s+))(?!\\?)|\\/?>)",
"begin": "(<)\\s*(?:([_$a-zA-Z][-$\\w.]*)(?<!\\.|-)(:))?((?:[a-z][a-z0-9]*|([_$a-zA-Z][-$\\w.]*))(?<!\\.|-))(?=((<\\s*)|(\\s+))(?!\\?)|\\/?>)",
"beginCaptures": {
"1": {
"name": "punctuation.definition.tag.begin.tsx"

View file

@ -18,7 +18,7 @@
"dependencies": {
"semver": "4.3.6",
"vscode-extension-telemetry": "0.0.17",
"vscode-nls": "^3.2.1"
"vscode-nls": "^3.2.4"
},
"devDependencies": {
"@types/node": "8.0.33",

View file

@ -318,20 +318,9 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider
}
const enableDotCompletions = this.shouldEnableDotCompletions(document, position);
const completionItems: vscode.CompletionItem[] = [];
for (const element of msg) {
if (element.kind === PConst.Kind.warning && !completionConfiguration.nameSuggestions) {
continue;
}
if (!completionConfiguration.autoImportSuggestions && element.hasAction) {
continue;
}
const item = new MyCompletionItem(position, document, line.text, element, enableDotCompletions, completionConfiguration.useCodeSnippetsOnMethodSuggest);
completionItems.push(item);
}
return completionItems;
return msg
.filter(entry => !shouldExcludeCompletionEntry(entry, completionConfiguration))
.map(entry => new MyCompletionItem(position, document, line.text, entry, enableDotCompletions, completionConfiguration.useCodeSnippetsOnMethodSuggest));
}
public async resolveCompletionItem(
@ -595,6 +584,17 @@ class TypeScriptCompletionItemProvider implements vscode.CompletionItemProvider
}
}
function shouldExcludeCompletionEntry(
element: Proto.CompletionEntry,
completionConfiguration: CompletionConfiguration
) {
return (
(!completionConfiguration.nameSuggestions && element.kind === PConst.Kind.warning)
|| (!completionConfiguration.quickSuggestionsForPaths &&
(element.kind === PConst.Kind.directory || element.kind === PConst.Kind.script))
|| (!completionConfiguration.autoImportSuggestions && element.hasAction)
);
}
export function register(
selector: vscode.DocumentSelector,

View file

@ -0,0 +1,22 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import 'mocha';
import { tagsMarkdownPreview } from '../utils/previewer';
suite('typescript.previewer', () => {
test('Should ignore hyphens after a param tag', async () => {
assert.strictEqual(
tagsMarkdownPreview([
{
name: 'param',
text: 'a - b'
}
]),
'*@param* `a` — b');
});
});

View file

@ -27,7 +27,7 @@ function getTagBodyText(tag: Proto.JSDocTagInfo): string | undefined {
function getTagDocumentation(tag: Proto.JSDocTagInfo): string | undefined {
switch (tag.name) {
case 'param':
const body = (tag.text || '').split(/^([\w\.]+)\s*/);
const body = (tag.text || '').split(/^([\w\.]+)\s*-?\s*/);
if (body && body.length === 3) {
const param = body[1];
const doc = body[2];
@ -81,4 +81,4 @@ export function addMarkdownDocumentation(
out.appendMarkdown('\n\n' + tagsPreview);
}
return out;
}
}

View file

@ -1548,9 +1548,9 @@ vscode-extension-telemetry@0.0.17:
dependencies:
applicationinsights "1.0.1"
vscode-nls@^3.2.1:
version "3.2.1"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.1.tgz#b1f3e04e8a94a715d5a7bcbc8339c51e6d74ca51"
vscode-nls@^3.2.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-3.2.4.tgz#2166b4183c8aea884d20727f5449e62be69fd398"
vscode@^1.1.10:
version "1.1.17"

View file

@ -511,6 +511,16 @@ suite('workspace-namespace', () => {
// });
// });
test('findTextInFiles', async () => {
const results: vscode.TextSearchResult[] = [];
await vscode.workspace.findTextInFiles({ pattern: 'foo' }, { include: '*.ts' }, result => {
results.push(result);
});
assert.equal(results.length, 1);
assert.equal(vscode.workspace.asRelativePath(results[0].uri), '10linefile.ts');
});
test('applyEdit', () => {
return vscode.workspace.openTextDocument(vscode.Uri.parse('untitled:' + join(vscode.workspace.rootPath || '', './new2.txt'))).then(doc => {
@ -603,8 +613,8 @@ suite('workspace-namespace', () => {
let newDoc = await vscode.workspace.openTextDocument(newUri);
assert.equal(newDoc.getText(), 'HelloFoo');
// let doc = await vscode.workspace.openTextDocument(docUri);
// assert.equal(doc.getText(), 'Bar');
let doc = await vscode.workspace.openTextDocument(docUri);
assert.equal(doc.getText(), 'Bar');
});
test('WorkspaceEdit api - after saving a deleted file, it still shows up as deleted. #42667', async function () {
@ -679,8 +689,7 @@ suite('workspace-namespace', () => {
we = new vscode.WorkspaceEdit();
we.createFile(docUri, { overwrite: true });
assert.ok(await vscode.workspace.applyEdit(we));
// todo@ben
// assert.equal((await vscode.workspace.openTextDocument(docUri)).getText(), '');
assert.equal((await vscode.workspace.openTextDocument(docUri)).getText(), '');
});
test('WorkspaceEdit: create & ignoreIfExists', async function () {

View file

@ -49,7 +49,7 @@
"vscode-nsfw": "1.0.17",
"vscode-ripgrep": "^1.0.1",
"vscode-textmate": "^4.0.1",
"vscode-xterm": "3.5.0-beta17",
"vscode-xterm": "3.6.0-beta2",
"yauzl": "^2.9.1"
},
"devDependencies": {

13
src/bootstrap-amd.js vendored
View file

@ -29,6 +29,8 @@ function readFile(file) {
});
}
const writeFile = (file, content) => new Promise((c, e) => fs.writeFile(file, content, 'utf8', err => err ? e(err) : c()));
var rawNlsConfig = process.env['VSCODE_NLS_CONFIG'];
var nlsConfig = rawNlsConfig ? JSON.parse(rawNlsConfig) : { availableLanguages: {} };
@ -46,8 +48,15 @@ if (nlsConfig._resolvedLanguagePackCoreLocation) {
let json = JSON.parse(content);
bundles[bundle] = json;
cb(undefined, json);
})
.catch(cb);
}).catch((error) => {
try {
if (nlsConfig._corruptedFile) {
writeFile(nlsConfig._corruptedFile, 'corrupted').catch(function (error) { console.error(error); });
}
} finally {
cb(error, undefined);
}
});
};
}

View file

@ -100,6 +100,19 @@ const args = minimist(process.argv, {
]
});
function getUserDataPath() {
if (isPortable) {
return path.join(portableDataPath, 'user-data');
}
return path.resolve(args['user-data-dir'] || paths.getDefaultUserDataPath(process.platform));
}
const userDataPath = getUserDataPath();
// Set userData path before app 'ready' event and call to process.chdir
app.setPath('userData', userDataPath);
//#region NLS
function stripComments(content) {
let regexp = /("(?:[^\\\"]*(?:\\.)?)*")|('(?:[^\\\']*(?:\\.)?)*')|(\/\*(?:\r?\n|.)*?\*\/)|(\/{2,}.*?(?:(?:\r?\n)|$))/g;
@ -130,6 +143,10 @@ const exists = file => new Promise(c => fs.exists(file, c));
const readFile = file => new Promise((c, e) => fs.readFile(file, 'utf8', (err, data) => err ? e(err) : c(data)));
const writeFile = (file, content) => new Promise((c, e) => fs.writeFile(file, content, 'utf8', err => err ? e(err) : c()));
const touch = file => new Promise((c, e) => { const d = new Date(); fs.utimes(file, d, d, err => err ? e(err) : c()); });
const lstat = file => new Promise((c, e) => fs.lstat(file, (err, stats) => err ? e(err) : c(stats)));
const readdir = dir => new Promise((c, e) => fs.readdir(dir, (err, files) => err ? e(err) : c(files)));
const rmdir = dir => new Promise((c, e) => fs.rmdir(dir, err => err ? e(err) : c(undefined)));
const unlink = file => new Promise((c, e) => fs.unlink(file, err => err ? e(err) : c(undefined)));
function mkdirp(dir) {
return mkdir(dir).then(null, err => {
@ -145,6 +162,23 @@ function mkdirp(dir) {
});
}
function rimraf(location) {
return lstat(location).then(stat => {
if (stat.isDirectory() && !stat.isSymbolicLink()) {
return readdir(location)
.then(children => Promise.all(children.map(child => rimraf(path.join(location, child)))))
.then(() => rmdir(location));
} else {
return unlink(location);
}
}, (err) => {
if (err.code === 'ENOENT') {
return void 0;
}
throw err;
});
}
function resolveJSFlags(...jsFlags) {
if (args['js-flags']) {
@ -169,8 +203,7 @@ function getUserDefinedLocale() {
return Promise.resolve(locale.toLowerCase());
}
let userData = app.getPath('userData');
let localeConfig = path.join(userData, 'User', 'locale.json');
let localeConfig = path.join(userDataPath, 'User', 'locale.json');
return exists(localeConfig).then((result) => {
if (result) {
return readFile(localeConfig).then((content) => {
@ -189,8 +222,7 @@ function getUserDefinedLocale() {
}
function getLanguagePackConfigurations() {
let userData = app.getPath('userData');
let configFile = path.join(userData, 'languagepacks.json');
let configFile = path.join(userDataPath, 'languagepacks.json');
try {
return require(configFile);
} catch (err) {
@ -229,8 +261,6 @@ function getNLSConfiguration(locale) {
return Promise.resolve({ locale: locale, availableLanguages: {} });
}
let userData = app.getPath('userData');
// We have a built version so we have extracted nls file. Try to find
// the right file to use.
@ -271,65 +301,78 @@ function getNLSConfiguration(locale) {
return defaultResult(initialLocale);
}
let packId = packConfig.hash + '.' + locale;
let cacheRoot = path.join(userData, 'clp', packId);
let cacheRoot = path.join(userDataPath, 'clp', packId);
let coreLocation = path.join(cacheRoot, commit);
let translationsConfigFile = path.join(cacheRoot, 'tcf.json');
let corruptedFile = path.join(cacheRoot, 'corrupted.info');
let result = {
locale: initialLocale,
availableLanguages: { '*': locale },
_languagePackId: packId,
_translationsConfigFile: translationsConfigFile,
_cacheRoot: cacheRoot,
_resolvedLanguagePackCoreLocation: coreLocation
_resolvedLanguagePackCoreLocation: coreLocation,
_corruptedFile: corruptedFile
};
return exists(coreLocation).then((fileExists) => {
if (fileExists) {
// We don't wait for this. No big harm if we can't touch
touch(coreLocation).catch(() => { });
perf.mark('nlsGeneration:end');
return result;
return exists(corruptedFile).then((corrupted) => {
// The nls cache directory is corrupted.
let toDelete;
if (corrupted) {
toDelete = rimraf(cacheRoot);
} else {
toDelete = Promise.resolve(undefined);
}
return mkdirp(coreLocation).then(() => {
return Promise.all([readFile(path.join(__dirname, 'nls.metadata.json')), readFile(mainPack)]);
}).then((values) => {
let metadata = JSON.parse(values[0]);
let packData = JSON.parse(values[1]).contents;
let bundles = Object.keys(metadata.bundles);
let writes = [];
for (let bundle of bundles) {
let modules = metadata.bundles[bundle];
let target = Object.create(null);
for (let module of modules) {
let keys = metadata.keys[module];
let defaultMessages = metadata.messages[module];
let translations = packData[module];
let targetStrings;
if (translations) {
targetStrings = [];
for (let i = 0; i < keys.length; i++) {
let elem = keys[i];
let key = typeof elem === 'string' ? elem : elem.key;
let translatedMessage = translations[key];
if (translatedMessage === undefined) {
translatedMessage = defaultMessages[i];
}
targetStrings.push(translatedMessage);
}
} else {
targetStrings = defaultMessages;
}
target[module] = targetStrings;
return toDelete.then(() => {
return exists(coreLocation).then((fileExists) => {
if (fileExists) {
// We don't wait for this. No big harm if we can't touch
touch(coreLocation).catch(() => { });
perf.mark('nlsGeneration:end');
return result;
}
writes.push(writeFile(path.join(coreLocation, bundle.replace(/\//g, '!') + '.nls.json'), JSON.stringify(target)));
}
writes.push(writeFile(translationsConfigFile, JSON.stringify(packConfig.translations)));
return Promise.all(writes);
}).then(() => {
perf.mark('nlsGeneration:end');
return result;
}).catch((err) => {
console.error('Generating translation files failed.', err);
return defaultResult(locale);
return mkdirp(coreLocation).then(() => {
return Promise.all([readFile(path.join(__dirname, 'nls.metadata.json')), readFile(mainPack)]);
}).then((values) => {
let metadata = JSON.parse(values[0]);
let packData = JSON.parse(values[1]).contents;
let bundles = Object.keys(metadata.bundles);
let writes = [];
for (let bundle of bundles) {
let modules = metadata.bundles[bundle];
let target = Object.create(null);
for (let module of modules) {
let keys = metadata.keys[module];
let defaultMessages = metadata.messages[module];
let translations = packData[module];
let targetStrings;
if (translations) {
targetStrings = [];
for (let i = 0; i < keys.length; i++) {
let elem = keys[i];
let key = typeof elem === 'string' ? elem : elem.key;
let translatedMessage = translations[key];
if (translatedMessage === undefined) {
translatedMessage = defaultMessages[i];
}
targetStrings.push(translatedMessage);
}
} else {
targetStrings = defaultMessages;
}
target[module] = targetStrings;
}
writes.push(writeFile(path.join(coreLocation, bundle.replace(/\//g, '!') + '.nls.json'), JSON.stringify(target)));
}
writes.push(writeFile(translationsConfigFile, JSON.stringify(packConfig.translations)));
return Promise.all(writes);
}).then(() => {
perf.mark('nlsGeneration:end');
return result;
}).catch((err) => {
console.error('Generating translation files failed.', err);
return defaultResult(locale);
});
});
});
});
});
@ -368,23 +411,12 @@ const nodeCachedDataDir = new class {
if (!commit) {
return undefined;
}
return path.join(app.getPath('userData'), 'CachedData', commit);
return path.join(userDataPath, 'CachedData', commit);
}
};
//#endregion
function getUserDataPath() {
if (isPortable) {
return path.join(portableDataPath, 'user-data');
}
return path.resolve(args['user-data-dir'] || paths.getDefaultUserDataPath(process.platform));
}
// Set userData path before app 'ready' event and call to process.chdir
app.setPath('userData', getUserDataPath());
// Update cwd based on environment and platform
try {
if (process.platform === 'win32') {

View file

@ -18,5 +18,10 @@
"typeRoots": [
"typings"
]
}
},
"exclude": [
"../out",
"../out-build",
"../out-vscode"
]
}

View file

@ -124,6 +124,15 @@ declare module 'vscode-xterm' {
*/
macOptionIsMeta?: boolean;
/**
* Whether holding a modifier key will force normal selection behavior,
* regardless of whether the terminal is in mouse events mode. This will
* also prevent mouse events from being emitted by the terminal. For example,
* this allows you to use xterm.js' regular selection inside tmux with
* mouse mode enabled.
*/
macOptionClickForcesSelection?: boolean;
/**
* (EXPERIMENTAL) The type of renderer to use, this allows using the
* fallback DOM renderer when canvas is too slow for the environment. The

View file

@ -5,9 +5,8 @@
'use strict';
import 'vs/css!./builder';
import { TPromise } from 'vs/base/common/winjs.base';
import * as types from 'vs/base/common/types';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
import * as strings from 'vs/base/common/strings';
import * as assert from 'vs/base/common/assert';
import * as DOM from 'vs/base/browser/dom';
@ -907,7 +906,7 @@ export class Builder implements IDisposable {
this.attr('aria-hidden', 'false');
// Cancel any pending showDelayed() invocation
this.cancelVisibilityPromise();
this.cancelVisibilityTimeout();
return this;
}
@ -922,15 +921,15 @@ export class Builder implements IDisposable {
showDelayed(delay: number): Builder {
// Cancel any pending showDelayed() invocation
this.cancelVisibilityPromise();
this.cancelVisibilityTimeout();
let promise = TPromise.timeout(delay);
this.setProperty(VISIBILITY_BINDING_ID, promise);
promise.done(() => {
// Install new delay for showing
const handle = setTimeout(() => {
this.removeProperty(VISIBILITY_BINDING_ID);
this.show();
});
}, delay);
this.setProperty(VISIBILITY_BINDING_ID, toDisposable(() => clearTimeout(handle)));
return this;
}
@ -945,7 +944,7 @@ export class Builder implements IDisposable {
this.attr('aria-hidden', 'true');
// Cancel any pending showDelayed() invocation
this.cancelVisibilityPromise();
this.cancelVisibilityTimeout();
return this;
}
@ -957,10 +956,10 @@ export class Builder implements IDisposable {
return this.hasClass('monaco-builder-hidden') || this.currentElement.style.display === 'none';
}
private cancelVisibilityPromise(): void {
let promise: TPromise<void> = this.getProperty(VISIBILITY_BINDING_ID);
if (promise) {
promise.cancel();
private cancelVisibilityTimeout(): void {
const visibilityDisposable = this.getProperty(VISIBILITY_BINDING_ID) as IDisposable;
if (visibilityDisposable) {
visibilityDisposable.dispose();
this.removeProperty(VISIBILITY_BINDING_ID);
}
}

View file

@ -819,6 +819,7 @@ export const EventType = {
MOUSE_OVER: 'mouseover',
MOUSE_MOVE: 'mousemove',
MOUSE_OUT: 'mouseout',
MOUSE_ENTER: 'mouseenter',
MOUSE_LEAVE: 'mouseleave',
CONTEXT_MENU: 'contextmenu',
WHEEL: 'wheel',

View file

@ -0,0 +1,40 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-breadcrumbs {
user-select: none;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
}
.monaco-breadcrumbs .monaco-breadcrumb-item {
display: flex;
align-items: center;
flex: 0 1 auto;
white-space: nowrap;
cursor: default;
align-self: center;
height: 100%;
}
.monaco-breadcrumbs .monaco-breadcrumb-item:not(:last-child)::after {
background-image: url(./collapsed.svg);
width: 16px;
height: 16px;
display: inline-block;
background-size: 16px;
background-position: 50% 50%;
content: ' ';
}
.vs-dark .monaco-breadcrumbs .monaco-breadcrumb-item:not(:last-child)::after {
background-image: url(./collpased-dark.svg);
}
.monaco-breadcrumbs .monaco-breadcrumb-item.focused {
font-weight: bold;
}

View file

@ -0,0 +1,248 @@
/*---------------------------------------------------------------------------------------------
* 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 'vs/css!./breadcrumbsWidget';
import * as dom from 'vs/base/browser/dom';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IMouseEvent } from 'vs/base/browser/mouseEvent';
import { Event, Emitter } from 'vs/base/common/event';
import { Color } from 'vs/base/common/color';
import { commonPrefixLength, tail } from 'vs/base/common/arrays';
export abstract class BreadcrumbsItem {
dispose(): void { }
abstract equals(other: BreadcrumbsItem): boolean;
abstract render(container: HTMLElement): void;
}
export class SimpleBreadcrumbsItem extends BreadcrumbsItem {
constructor(
readonly text: string,
readonly title: string = text
) {
super();
}
equals(other: this) {
return other === this || other instanceof SimpleBreadcrumbsItem && other.text === this.text && other.title === this.title;
}
render(container: HTMLElement): void {
let node = document.createElement('div');
node.title = this.title;
node.innerText = this.text;
container.appendChild(node);
}
}
export interface IBreadcrumbsWidgetStyles {
breadcrumbsBackground?: Color;
breadcrumbsActiveForeground?: Color;
breadcrumbsInactiveForeground?: Color;
}
export interface IBreadcrumbsItemEvent {
item: BreadcrumbsItem;
node: HTMLElement;
}
export class BreadcrumbsWidget {
private readonly _disposables = new Array<IDisposable>();
private readonly _domNode: HTMLDivElement;
private readonly _styleElement: HTMLStyleElement;
private readonly _scrollable: DomScrollableElement;
private readonly _onDidSelectItem = new Emitter<IBreadcrumbsItemEvent>();
private readonly _onDidFocusItem = new Emitter<IBreadcrumbsItemEvent>();
private readonly _onDidChangeFocus = new Emitter<boolean>();
readonly onDidSelectItem: Event<IBreadcrumbsItemEvent> = this._onDidSelectItem.event;
readonly onDidFocusItem: Event<IBreadcrumbsItemEvent> = this._onDidFocusItem.event;
readonly onDidChangeFocus: Event<boolean> = this._onDidChangeFocus.event;
private readonly _items = new Array<BreadcrumbsItem>();
private readonly _nodes = new Array<HTMLDivElement>();
private readonly _freeNodes = new Array<HTMLDivElement>();
private _focusedItemIdx: number = -1;
private _selectedItemIdx: number = -1;
constructor(
container: HTMLElement
) {
this._domNode = document.createElement('div');
this._domNode.className = 'monaco-breadcrumbs';
this._domNode.tabIndex = -1;
this._scrollable = new DomScrollableElement(this._domNode, {
vertical: ScrollbarVisibility.Hidden,
horizontal: ScrollbarVisibility.Auto,
horizontalScrollbarSize: 3,
useShadows: false
});
this._disposables.push(this._scrollable);
this._disposables.push(dom.addStandardDisposableListener(this._domNode, 'click', e => this._onClick(e)));
container.appendChild(this._scrollable.getDomNode());
this._styleElement = dom.createStyleSheet(this._domNode);
let focusTracker = dom.trackFocus(this._domNode);
this._disposables.push(focusTracker);
this._disposables.push(focusTracker.onDidBlur(_ => this._onDidChangeFocus.fire(false)));
this._disposables.push(focusTracker.onDidFocus(_ => this._onDidChangeFocus.fire(true)));
}
dispose(): void {
dispose(this._disposables);
this._domNode.remove();
this._disposables.length = 0;
this._nodes.length = 0;
this._freeNodes.length = 0;
}
layout(dim: dom.Dimension): void {
if (!dim) {
this._scrollable.scanDomNode();
} else {
this._domNode.style.width = `${dim.width}px`;
this._domNode.style.height = `${dim.height}px`;
this._scrollable.scanDomNode();
}
}
style(style: IBreadcrumbsWidgetStyles): void {
let content = '';
if (style.breadcrumbsBackground) {
content += `.monaco-breadcrumbs { background-color: ${style.breadcrumbsBackground}}`;
}
if (style.breadcrumbsActiveForeground) {
content += `.monaco-breadcrumbs:focus .monaco-breadcrumb-item { color: ${style.breadcrumbsActiveForeground}}\n`;
}
if (style.breadcrumbsInactiveForeground) {
content += `.monaco-breadcrumbs .monaco-breadcrumb-item { color: ${style.breadcrumbsInactiveForeground}}\n`;
}
if (this._styleElement.innerHTML !== content) {
this._styleElement.innerHTML = content;
}
}
domFocus(): void {
const focused = this.getFocused() || tail(this._items);
this.setFocused(focused);
this._domNode.focus();
}
getFocused(): BreadcrumbsItem {
return this._items[this._focusedItemIdx];
}
setFocused(item: BreadcrumbsItem): void {
this._focus(this._items.indexOf(item));
}
focusPrev(): any {
this._focus((this._focusedItemIdx - 1 + this._nodes.length) % this._nodes.length);
this._domNode.focus();
}
focusNext(): any {
this._focus((this._focusedItemIdx + 1) % this._nodes.length);
this._domNode.focus();
}
private _focus(nth: number): void {
this._focusedItemIdx = -1;
for (let i = 0; i < this._nodes.length; i++) {
const node = this._nodes[i];
if (i !== nth) {
dom.removeClass(node, 'focused');
} else {
this._focusedItemIdx = i;
dom.addClass(node, 'focused');
}
}
this._onDidFocusItem.fire({ item: this._items[this._focusedItemIdx], node: this._nodes[this._focusedItemIdx] });
}
getSelected(): BreadcrumbsItem {
return this._items[this._selectedItemIdx];
}
setSelected(item: BreadcrumbsItem): void {
this._select(this._items.indexOf(item));
}
private _select(nth: number): void {
this._selectedItemIdx = -1;
for (let i = 0; i < this._nodes.length; i++) {
const node = this._nodes[i];
if (i !== nth) {
dom.removeClass(node, 'selected');
} else {
this._selectedItemIdx = i;
dom.addClass(node, 'selected');
}
}
this._onDidSelectItem.fire({ item: this._items[this._selectedItemIdx], node: this._nodes[this._selectedItemIdx] });
}
setItems(items: BreadcrumbsItem[]): void {
let prefix = commonPrefixLength(this._items, items, (a, b) => a.equals(b));
let removed = this._items.splice(prefix, this._items.length - prefix, ...items.slice(prefix));
this._render(prefix);
dispose(removed);
if (prefix >= this._focusedItemIdx) {
this._focus(-1);
}
}
private _render(start: number): void {
for (; start < this._items.length && start < this._nodes.length; start++) {
let item = this._items[start];
let node = this._nodes[start];
this._renderItem(item, node);
}
// case a: more nodes -> remove them
for (; start < this._nodes.length; start++) {
this._nodes[start].remove();
this._freeNodes.push(this._nodes[start]);
}
this._nodes.length = this._items.length;
// case b: more items -> render them
for (; start < this._items.length; start++) {
let item = this._items[start];
let node = this._freeNodes.length > 0 ? this._freeNodes.pop() : document.createElement('div');
this._renderItem(item, node);
this._domNode.appendChild(node);
this._nodes[start] = node;
}
this.layout(undefined);
}
private _renderItem(item: BreadcrumbsItem, container: HTMLDivElement): void {
dom.clearNode(container);
container.className = '';
item.render(container);
dom.append(container);
dom.addClass(container, 'monaco-breadcrumb-item');
}
private _onClick(event: IMouseEvent): void {
for (let el = event.target; el; el = el.parentElement) {
let idx = this._nodes.indexOf(el as any);
if (idx >= 0) {
this._focus(idx);
this._select(idx);
break;
}
}
}
}

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#646465" d="M6 4v8l4-4-4-4zm1 2.414L8.586 8 7 9.586V6.414z"/></svg>

After

Width:  |  Height:  |  Size: 139 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill="#E8E8E8" d="M6 4v8l4-4-4-4zm1 2.414L8.586 8 7 9.586V6.414z"/></svg>

After

Width:  |  Height:  |  Size: 139 B

View file

@ -4,10 +4,13 @@
*--------------------------------------------------------------------------------------------*/
.monaco-count-badge {
padding: 0.2em 0.5em;
padding: 0.3em 0.5em;
border-radius: 1em;
font-size: 85%;
min-width: 1.6em;
line-height: 1em;
font-weight: normal;
text-align: center;
display: inline;
display: inline-block;
box-sizing: border-box;
}

View file

@ -279,10 +279,15 @@ export class Grid<T extends IView> implements IDisposable {
getViewSize(view: T): number {
const location = this.getViewLocation(view);
const viewSize = this.gridview.getViewSize(location);
return getLocationOrientation(this.orientation, location) === Orientation.HORIZONTAL ? viewSize.width : viewSize.height;
}
// TODO@joao cleanup
getViewSize2(view: T): { width: number; height: number; } {
const location = this.getViewLocation(view);
return this.gridview.getViewSize(location);
}
maximizeViewSize(view: T): void {
const location = this.getViewLocation(view);
this.gridview.maximizeViewSize(location);

View file

@ -9,7 +9,7 @@ import 'vs/css!./gridview';
import { Event, anyEvent, Emitter, mapEvent, Relay } from 'vs/base/common/event';
import { Orientation, Sash } from 'vs/base/browser/ui/sash/sash';
import { SplitView, IView as ISplitView, Sizing, ISplitViewStyles } from 'vs/base/browser/ui/splitview/splitview';
import { empty as EmptyDisposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { $ } from 'vs/base/browser/dom';
import { tail2 as tail } from 'vs/base/common/arrays';
import { Color } from 'vs/base/common/color';
@ -122,12 +122,12 @@ class BranchNode implements ISplitView, IDisposable {
private _onDidChange = new Emitter<number | undefined>();
readonly onDidChange: Event<number | undefined> = this._onDidChange.event;
private childrenChangeDisposable: IDisposable = EmptyDisposable;
private childrenChangeDisposable: IDisposable = Disposable.None;
private _onDidSashReset = new Emitter<number[]>();
readonly onDidSashReset: Event<number[]> = this._onDidSashReset.event;
private splitviewSashResetDisposable: IDisposable = EmptyDisposable;
private childrenSashResetDisposable: IDisposable = EmptyDisposable;
private splitviewSashResetDisposable: IDisposable = Disposable.None;
private childrenSashResetDisposable: IDisposable = Disposable.None;
get orthogonalStartSash(): Sash | undefined { return this.splitview.orthogonalStartSash; }
set orthogonalStartSash(sash: Sash | undefined) { this.splitview.orthogonalStartSash = sash; }
@ -280,22 +280,22 @@ class BranchNode implements ISplitView, IDisposable {
trySet2x2(other: BranchNode): IDisposable {
if (this.children.length !== 2 || other.children.length !== 2) {
return EmptyDisposable;
return Disposable.None;
}
if (this.getChildSize(0) !== other.getChildSize(0)) {
return EmptyDisposable;
return Disposable.None;
}
const [firstChild, secondChild] = this.children;
const [otherFirstChild, otherSecondChild] = other.children;
if (!(firstChild instanceof LeafNode) || !(secondChild instanceof LeafNode)) {
return EmptyDisposable;
return Disposable.None;
}
if (!(otherFirstChild instanceof LeafNode) || !(otherSecondChild instanceof LeafNode)) {
return EmptyDisposable;
return Disposable.None;
}
if (this.orientation === Orientation.VERTICAL) {
@ -485,7 +485,7 @@ export class GridView implements IDisposable {
private onDidSashResetRelay = new Relay<number[]>();
readonly onDidSashReset: Event<number[]> = this.onDidSashResetRelay.event;
private disposable2x2: IDisposable = EmptyDisposable;
private disposable2x2: IDisposable = Disposable.None;
private get root(): BranchNode {
return this._root;
@ -550,7 +550,7 @@ export class GridView implements IDisposable {
addView(view: IView, size: number | Sizing, location: number[]): void {
this.disposable2x2.dispose();
this.disposable2x2 = EmptyDisposable;
this.disposable2x2 = Disposable.None;
const [rest, index] = tail(location);
const [pathToParent, parent] = this.getNode(rest);
@ -582,7 +582,7 @@ export class GridView implements IDisposable {
removeView(location: number[], sizing?: Sizing): IView {
this.disposable2x2.dispose();
this.disposable2x2 = EmptyDisposable;
this.disposable2x2 = Disposable.None;
const [rest, index] = tail(location);
const [pathToParent, parent] = this.getNode(rest);
@ -783,7 +783,7 @@ export class GridView implements IDisposable {
trySet2x2(): void {
this.disposable2x2.dispose();
this.disposable2x2 = EmptyDisposable;
this.disposable2x2 = Disposable.None;
if (this.root.children.length !== 2) {
return;

View file

@ -282,6 +282,11 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
private insertItemInDOM(index: number, beforeElement: HTMLElement | null): void {
const item = this.items[index];
if (!item) {
console.log(this.items);
throw new Error(`Got index ${index} and there are ${this.items.length} items. File issue to joao!`);
}
if (!item.row) {
item.row = this.cache.alloc(item.templateId);
}
@ -311,6 +316,12 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
private removeItemFromDOM(index: number): void {
const item = this.items[index];
if (!item) {
console.log(this.items);
throw new Error(`Got index ${index} and there are ${this.items.length} items. File issue to joao!`);
}
this.cache.release(item.row);
item.row = null;
}
@ -371,7 +382,12 @@ export class ListView<T> implements ISpliceable<T>, IDisposable {
}
private onScroll(e: ScrollEvent): void {
this.render(e.scrollTop, e.height);
try {
this.render(e.scrollTop, e.height);
} catch (err) {
console.log('Got bad scroll event:', e);
throw err;
}
}
private onTouchChange(event: GestureEvent): void {

View file

@ -13,7 +13,7 @@ import { ResolvedKeybinding, KeyCode } from 'vs/base/common/keyCodes';
import { Event } from 'vs/base/common/event';
import { addClass, EventType, EventHelper, EventLike } from 'vs/base/browser/dom';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
import { $ } from 'vs/base/browser/builder';
import { $, Builder } from 'vs/base/browser/builder';
export interface IMenuOptions {
context?: any;
@ -152,6 +152,7 @@ class MenuActionItem extends ActionItem {
class SubmenuActionItem extends MenuActionItem {
private mysubmenu: Menu;
private submenuContainer: Builder;
private mouseOver: boolean;
constructor(
@ -224,18 +225,23 @@ class SubmenuActionItem extends MenuActionItem {
if (this.parentData.submenu && (force || (this.parentData.submenu !== this.mysubmenu))) {
this.parentData.submenu.dispose();
this.parentData.submenu = null;
if (this.submenuContainer) {
this.submenuContainer.dispose();
this.submenuContainer = null;
}
}
}
private createSubmenu() {
if (!this.parentData.submenu) {
const submenuContainer = $(this.builder).div({ class: 'monaco-submenu menubar-menu-items-holder context-view' });
this.submenuContainer = $(this.builder).div({ class: 'monaco-submenu menubar-menu-items-holder context-view' });
$(submenuContainer).style({
$(this.submenuContainer).style({
'left': `${$(this.builder).getClientArea().width}px`
});
$(submenuContainer).on(EventType.KEY_UP, (e) => {
$(this.submenuContainer).on(EventType.KEY_UP, (e) => {
let event = new StandardKeyboardEvent(e as KeyboardEvent);
if (event.equals(KeyCode.LeftArrow)) {
EventHelper.stop(e, true);
@ -243,10 +249,13 @@ class SubmenuActionItem extends MenuActionItem {
this.parentData.parent.focus();
this.parentData.submenu.dispose();
this.parentData.submenu = null;
this.submenuContainer.dispose();
this.submenuContainer = null;
}
});
$(submenuContainer).on(EventType.KEY_DOWN, (e) => {
$(this.submenuContainer).on(EventType.KEY_DOWN, (e) => {
let event = new StandardKeyboardEvent(e as KeyboardEvent);
if (event.equals(KeyCode.LeftArrow)) {
EventHelper.stop(e, true);
@ -254,10 +263,24 @@ class SubmenuActionItem extends MenuActionItem {
});
this.parentData.submenu = new Menu(submenuContainer.getHTMLElement(), this.submenuActions, this.submenuOptions);
this.parentData.submenu = new Menu(this.submenuContainer.getHTMLElement(), this.submenuActions, this.submenuOptions);
this.parentData.submenu.focus();
this.mysubmenu = this.parentData.submenu;
}
}
public dispose() {
super.dispose();
if (this.mysubmenu) {
this.mysubmenu.dispose();
this.mysubmenu = null;
}
if (this.submenuContainer) {
this.submenuContainer.dispose();
this.submenuContainer = null;
}
}
}

Some files were not shown because too many files have changed in this diff Show more