diff --git a/.travis.yml b/.travis.yml
index 4eb8148574..693cdcbb4d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,8 +12,8 @@ cache:
notifications:
email: false
webhooks:
- - http://vscode-probot.westus.cloudapp.azure.com:3450/travis/notifications
- - http://vscode-test-probot.westus.cloudapp.azure.com:3450/travis/notifications
+ - https://vscode-probot.westus.cloudapp.azure.com:7890/travis/notifications
+ - https://vscode-test-probot.westus.cloudapp.azure.com:7890/travis/notifications
addons:
apt:
@@ -31,6 +31,7 @@ addons:
- libsecret-1-dev
before_install:
+ - export GITHUB_TOKEN=$PUBLIC_GITHUB_TOKEN
- git submodule update --init --recursive
- git clone --depth 1 https://github.com/creationix/nvm.git ./.nvm
- source ./.nvm/nvm.sh
@@ -52,9 +53,17 @@ install:
script:
- node_modules/.bin/gulp electron --silent
+ - node_modules/.bin/tsc -p ./src/tsconfig.monaco.json --noEmit
- node_modules/.bin/gulp compile --silent --max_old_space_size=4096
- - node_modules/.bin/gulp optimize-vscode --silent --max_old_space_size=4096
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then ./scripts/test.sh --coverage --reporter dot; else ./scripts/test.sh --reporter dot; fi
+ - ./scripts/test-integration.sh
after_success:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then node_modules/.bin/coveralls < .build/coverage/lcov.info; fi
+
+matrix:
+ include:
+ - os: linux
+ env: label=hygiene
+ script: node_modules/.bin/gulp hygiene
+ after_success: skip
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 2d103c98a8..6da9da2976 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -1,7 +1,6 @@
{
"version": "0.1.0",
"configurations": [
-
{
"type": "node",
"request": "launch",
@@ -9,7 +8,7 @@
"program": "${workspaceFolder}/node_modules/gulp/bin/gulp.js",
"stopOnEntry": true,
"args": [
- "watch-extension:json-client"
+ "hygiene"
],
"cwd": "${workspaceFolder}"
},
@@ -87,6 +86,9 @@
"runtimeArgs": [
"--inspect=5875"
],
+ "skipFiles": [
+ "**/winjs*.js"
+ ],
"webRoot": "${workspaceFolder}"
},
{
diff --git a/.vscode/settings.json b/.vscode/settings.json
index b58e165fc0..67174474c1 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -10,6 +10,9 @@
"when": "$(basename).ts"
}
},
+ "files.associations": {
+ "OSSREADME.json": "jsonc"
+ },
"search.exclude": {
"**/node_modules": true,
"**/bower_components": true,
@@ -35,6 +38,5 @@
}
}
],
- "typescript.tsdk": "node_modules/typescript/lib",
- "git.ignoreLimitWarning": true
-}
\ No newline at end of file
+ "typescript.tsdk": "node_modules/typescript/lib"
+}
diff --git a/appveyor.yml b/appveyor.yml
index d9471f2a8f..3ece36f7a3 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -11,6 +11,7 @@ install:
build_script:
- yarn
- .\node_modules\.bin\gulp electron
+ - .\node_modules\.bin\tsc -p .\src\tsconfig.monaco.json --noEmit
- npm run compile
test_script:
diff --git a/build/builtInExtensions.json b/build/builtInExtensions.json
new file mode 100644
index 0000000000..edf3e072a5
--- /dev/null
+++ b/build/builtInExtensions.json
@@ -0,0 +1,12 @@
+[
+ {
+ "name": "ms-vscode.node-debug",
+ "version": "1.21.8",
+ "repo": "https://github.com/Microsoft/vscode-node-debug"
+ },
+ {
+ "name": "ms-vscode.node-debug2",
+ "version": "1.21.2",
+ "repo": "https://github.com/Microsoft/vscode-node-debug2"
+ }
+]
\ No newline at end of file
diff --git a/build/builtin/.eslintrc b/build/builtin/.eslintrc
new file mode 100644
index 0000000000..84e384941f
--- /dev/null
+++ b/build/builtin/.eslintrc
@@ -0,0 +1,20 @@
+{
+ "env": {
+ "node": true,
+ "es6": true,
+ "browser": true
+ },
+ "rules": {
+ "no-console": 0,
+ "no-cond-assign": 0,
+ "no-unused-vars": 1,
+ "no-extra-semi": "warn",
+ "semi": "warn"
+ },
+ "extends": "eslint:recommended",
+ "parserOptions": {
+ "ecmaFeatures": {
+ "experimentalObjectRestSpread": true
+ }
+ }
+}
\ No newline at end of file
diff --git a/build/builtin/browser-main.js b/build/builtin/browser-main.js
new file mode 100644
index 0000000000..b7726c71cb
--- /dev/null
+++ b/build/builtin/browser-main.js
@@ -0,0 +1,126 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+const fs = require('fs');
+const path = require('path');
+const os = require('os');
+// @ts-ignore review
+const { remote } = require('electron');
+const dialog = remote.dialog;
+
+const builtInExtensionsPath = path.join(__dirname, '..', 'builtInExtensions.json');
+const controlFilePath = path.join(os.homedir(), '.vscode-oss-dev', 'extensions', 'control.json');
+
+function readJson(filePath) {
+ return JSON.parse(fs.readFileSync(filePath, { encoding: 'utf8' }));
+}
+
+function writeJson(filePath, obj) {
+ fs.writeFileSync(filePath, JSON.stringify(obj, null, 2));
+}
+
+function renderOption(form, id, title, value, checked) {
+ const input = document.createElement('input');
+ input.type = 'radio';
+ input.id = id;
+ input.name = 'choice';
+ input.value = value;
+ input.checked = !!checked;
+ form.appendChild(input);
+
+ const label = document.createElement('label');
+ label.setAttribute('for', id);
+ label.textContent = title;
+ form.appendChild(label);
+
+ return input;
+}
+
+function render(el, state) {
+ function setState(state) {
+ try {
+ writeJson(controlFilePath, state.control);
+ } catch (err) {
+ console.error(err);
+ }
+
+ el.innerHTML = '';
+ render(el, state);
+ }
+
+ const ul = document.createElement('ul');
+ const { builtin, control } = state;
+
+ for (const ext of builtin) {
+ const controlState = control[ext.name] || 'marketplace';
+
+ const li = document.createElement('li');
+ ul.appendChild(li);
+
+ const name = document.createElement('code');
+ name.textContent = ext.name;
+ li.appendChild(name);
+
+ const form = document.createElement('form');
+ li.appendChild(form);
+
+ const marketplaceInput = renderOption(form, `marketplace-${ext.name}`, 'Marketplace', 'marketplace', controlState === 'marketplace');
+ marketplaceInput.onchange = function () {
+ control[ext.name] = 'marketplace';
+ setState({ builtin, control });
+ };
+
+ const disabledInput = renderOption(form, `disabled-${ext.name}`, 'Disabled', 'disabled', controlState === 'disabled');
+ disabledInput.onchange = function () {
+ control[ext.name] = 'disabled';
+ setState({ builtin, control });
+ };
+
+ let local = undefined;
+
+ if (controlState !== 'marketplace' && controlState !== 'disabled') {
+ local = controlState;
+ }
+
+ const localInput = renderOption(form, `local-${ext.name}`, 'Local', 'local', !!local);
+ localInput.onchange = function () {
+ const result = dialog.showOpenDialog(remote.getCurrentWindow(), {
+ title: 'Choose Folder',
+ properties: ['openDirectory']
+ });
+
+ if (result && result.length >= 1) {
+ control[ext.name] = result[0];
+ }
+
+ setState({ builtin, control });
+ };
+
+ if (local) {
+ const localSpan = document.createElement('code');
+ localSpan.className = 'local';
+ localSpan.textContent = local;
+ form.appendChild(localSpan);
+ }
+ }
+
+ el.appendChild(ul);
+}
+
+function main() {
+ const el = document.getElementById('extensions');
+ const builtin = readJson(builtInExtensionsPath);
+ let control;
+
+ try {
+ control = readJson(controlFilePath);
+ } catch (err) {
+ control = {};
+ }
+
+ render(el, { builtin, control });
+}
+
+window.onload = main;
\ No newline at end of file
diff --git a/build/builtin/index.html b/build/builtin/index.html
new file mode 100644
index 0000000000..13c84e0375
--- /dev/null
+++ b/build/builtin/index.html
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+ Manage Built-in Extensions
+
+
+
+
+
+
+ Built-in Extensions
+
+
+
+
\ No newline at end of file
diff --git a/build/builtin/main.js b/build/builtin/main.js
new file mode 100644
index 0000000000..52223b3310
--- /dev/null
+++ b/build/builtin/main.js
@@ -0,0 +1,20 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+const { app, BrowserWindow } = require('electron');
+const url = require('url');
+const path = require('path');
+
+let window = null;
+
+app.once('ready', () => {
+ window = new BrowserWindow({ width: 800, height: 600 });
+ window.setMenuBarVisibility(false);
+ window.loadURL(url.format({ pathname: path.join(__dirname, 'index.html'), protocol: 'file:', slashes: true }));
+ // window.webContents.openDevTools();
+ window.once('closed', () => window = null);
+});
+
+app.on('window-all-closed', () => app.quit());
\ No newline at end of file
diff --git a/build/builtin/package.json b/build/builtin/package.json
new file mode 100644
index 0000000000..6843791a5d
--- /dev/null
+++ b/build/builtin/package.json
@@ -0,0 +1,5 @@
+{
+ "name": "builtin",
+ "version": "0.1.0",
+ "main": "main.js"
+}
\ No newline at end of file
diff --git a/build/gulpfile.editor.js b/build/gulpfile.editor.js
index eb6bbf3c13..59e5638d62 100644
--- a/build/gulpfile.editor.js
+++ b/build/gulpfile.editor.js
@@ -12,6 +12,7 @@ var File = require('vinyl');
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 + ')';
@@ -21,14 +22,14 @@ var editorEntryPoints = [
{
name: 'vs/editor/editor.main',
include: [],
- exclude: [ 'vs/css', 'vs/nls' ],
- prepend: [ 'out-build/vs/css.js', 'out-build/vs/nls.js' ],
+ exclude: ['vs/css', 'vs/nls'],
+ prepend: ['out-build/vs/css.js', 'out-build/vs/nls.js'],
},
{
name: 'vs/base/common/worker/simpleWorker',
- include: [ 'vs/editor/common/services/editorSimpleWorker' ],
- prepend: [ 'vs/loader.js' ],
- append: [ 'vs/base/worker/workerMain' ],
+ include: ['vs/editor/common/services/editorSimpleWorker'],
+ prepend: ['vs/loader.js'],
+ append: ['vs/base/worker/workerMain'],
dest: 'vs/base/worker/workerMain.js'
}
];
@@ -79,14 +80,15 @@ gulp.task('optimize-editor', ['clean-optimized-editor', 'compile-client-build'],
bundleLoader: false,
header: BUNDLED_FILE_HEADER,
bundleInfo: true,
- out: 'out-editor'
+ out: 'out-editor',
+ languages: undefined
}));
gulp.task('clean-minified-editor', util.rimraf('out-editor-min'));
gulp.task('minify-editor', ['clean-minified-editor', 'optimize-editor'], common.minifyTask('out-editor'));
gulp.task('clean-editor-distro', util.rimraf('out-monaco-editor-core'));
-gulp.task('editor-distro', ['clean-editor-distro', 'minify-editor', 'optimize-editor'], function() {
+gulp.task('editor-distro', ['clean-editor-distro', 'minify-editor', 'optimize-editor'], function () {
return es.merge(
// other assets
es.merge(
@@ -97,17 +99,17 @@ gulp.task('editor-distro', ['clean-editor-distro', 'minify-editor', 'optimize-ed
// package.json
gulp.src('build/monaco/package.json')
- .pipe(es.through(function(data) {
+ .pipe(es.through(function (data) {
var json = JSON.parse(data.contents.toString());
json.private = false;
- data.contents = new Buffer(JSON.stringify(json, null, ' '));
+ data.contents = Buffer.from(JSON.stringify(json, null, ' '));
this.emit('data', data);
}))
.pipe(gulp.dest('out-monaco-editor-core')),
// README.md
gulp.src('build/monaco/README-npm.md')
- .pipe(es.through(function(data) {
+ .pipe(es.through(function (data) {
this.emit('data', new File({
path: data.path.replace(/README-npm\.md/, 'README.md'),
base: data.base,
@@ -124,10 +126,10 @@ gulp.task('editor-distro', ['clean-editor-distro', 'minify-editor', 'optimize-ed
// min folder
es.merge(
gulp.src('out-editor-min/**/*')
- ).pipe(filterStream(function(path) {
+ ).pipe(filterStream(function (path) {
// no map files
return !/(\.js\.map$)|(nls\.metadata\.json$)|(bundleInfo\.json$)/.test(path);
- })).pipe(es.through(function(data) {
+ })).pipe(es.through(function (data) {
// tweak the sourceMappingURL
if (!/\.js$/.test(data.path)) {
this.emit('data', data);
@@ -140,49 +142,50 @@ gulp.task('editor-distro', ['clean-editor-distro', 'minify-editor', 'optimize-ed
var newStr = '//# sourceMappingURL=' + relativePathToMap.replace(/\\/g, '/');
strContents = strContents.replace(/\/\/\# sourceMappingURL=[^ ]+$/, newStr);
- data.contents = new Buffer(strContents);
+ data.contents = Buffer.from(strContents);
this.emit('data', data);
})).pipe(gulp.dest('out-monaco-editor-core/min')),
// min-maps folder
es.merge(
gulp.src('out-editor-min/**/*')
- ).pipe(filterStream(function(path) {
+ ).pipe(filterStream(function (path) {
// no map files
return /\.js\.map$/.test(path);
})).pipe(gulp.dest('out-monaco-editor-core/min-maps'))
);
});
-gulp.task('analyze-editor-distro', function() {
+gulp.task('analyze-editor-distro', function () {
+ // @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
var bundleInfo = require('../out-editor/bundleInfo.json');
var graph = bundleInfo.graph;
var bundles = bundleInfo.bundles;
var inverseGraph = {};
- Object.keys(graph).forEach(function(module) {
+ Object.keys(graph).forEach(function (module) {
var dependencies = graph[module];
- dependencies.forEach(function(dep) {
+ dependencies.forEach(function (dep) {
inverseGraph[dep] = inverseGraph[dep] || [];
inverseGraph[dep].push(module);
});
});
var detailed = {};
- Object.keys(bundles).forEach(function(entryPoint) {
+ Object.keys(bundles).forEach(function (entryPoint) {
var included = bundles[entryPoint];
var includedMap = {};
- included.forEach(function(included) {
+ included.forEach(function (included) {
includedMap[included] = true;
});
var explanation = [];
- included.map(function(included) {
+ included.map(function (included) {
if (included.indexOf('!') >= 0) {
return;
}
- var reason = (inverseGraph[included]||[]).filter(function(mod) {
+ var reason = (inverseGraph[included] || []).filter(function (mod) {
return !!includedMap[mod];
});
explanation.push({
@@ -198,7 +201,7 @@ gulp.task('analyze-editor-distro', function() {
});
function filterStream(testFunc) {
- return es.through(function(data) {
+ return es.through(function (data) {
if (!testFunc(data.relative)) {
return;
}
diff --git a/build/gulpfile.extensions.js b/build/gulpfile.extensions.js
index 16b5982894..c8ba60b608 100644
--- a/build/gulpfile.extensions.js
+++ b/build/gulpfile.extensions.js
@@ -20,6 +20,7 @@ const sourcemaps = require('gulp-sourcemaps');
const nlsDev = require('vscode-nls-dev');
const root = path.dirname(__dirname);
const commit = util.getVersion(root);
+const i18n = require('./lib/i18n');
const extensionsPath = path.join(path.dirname(__dirname), 'extensions');
@@ -29,7 +30,8 @@ const compilations = glob.sync('**/tsconfig.json', {
});
const getBaseUrl = out => `https://ticino.blob.core.windows.net/sourcemaps/${commit}/${out}`;
-const languages = ['chs', 'cht', 'jpn', 'kor', 'deu', 'fra', 'esn', 'rus', 'ita'];
+
+const languages = i18n.defaultLanguages.concat(process.env.VSCODE_QUALITY !== 'stable' ? i18n.extraLanguages : []);
const tasks = compilations.map(function (tsconfigFile) {
const absolutePath = path.join(extensionsPath, tsconfigFile);
@@ -55,9 +57,19 @@ const tasks = compilations.map(function (tsconfigFile) {
const srcBase = path.join(root, 'src');
const src = path.join(srcBase, '**');
const out = path.join(root, 'out');
- const i18n = path.join(__dirname, '..', 'i18n');
+ const i18nPath = path.join(__dirname, '..', 'i18n');
const baseUrl = getBaseUrl(out);
+ let headerId, headerOut;
+ let index = relativeDirname.indexOf('/');
+ if (index < 0) {
+ headerId = 'vscode.' + relativeDirname;
+ headerOut = 'out';
+ } else {
+ headerId = 'vscode.' + relativeDirname.substr(0, index);
+ headerOut = relativeDirname.substr(index + 1) + '/out';
+ }
+
function createPipeline(build, emitError) {
const reporter = createReporter();
@@ -82,7 +94,9 @@ const tasks = compilations.map(function (tsconfigFile) {
sourceRoot: '../src'
}))
.pipe(tsFilter.restore)
- .pipe(build ? nlsDev.createAdditionalLanguageFiles(languages, i18n, out) : es.through())
+ .pipe(build ? nlsDev.createAdditionalLanguageFiles(languages, i18nPath, out) : es.through())
+ .pipe(build ? nlsDev.bundleMetaDataFiles(headerId, headerOut) : es.through())
+ .pipe(build ? nlsDev.bundleLanguageFiles() : es.through())
.pipe(reporter.end(emitError));
return es.duplex(input, output);
@@ -129,7 +143,7 @@ const tasks = compilations.map(function (tsconfigFile) {
const watchInput = watcher(src, srcOpts);
return watchInput
- .pipe(util.incremental(() => pipeline(true), input))
+ .pipe(util.incremental(() => pipeline(), input))
.pipe(gulp.dest(out));
});
diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js
index a6a2cdd5e9..5b9fab8643 100644
--- a/build/gulpfile.hygiene.js
+++ b/build/gulpfile.hygiene.js
@@ -12,7 +12,11 @@ const gulptslint = require('gulp-tslint');
const gulpeslint = require('gulp-eslint');
const tsfmt = require('typescript-formatter');
const tslint = require('tslint');
+const VinylFile = require('vinyl');
const vfs = require('vinyl-fs');
+const path = require('path');
+const fs = require('fs');
+const pall = require('p-all');
/**
* Hygiene works by creating cascading subsets of all our files and
@@ -29,55 +33,56 @@ const all = [
'extensions/**/*',
'scripts/**/*',
'src/**/*',
- 'test/**/*'
-];
-
-const eolFilter = [
- '**',
- '!ThirdPartyNotices.txt',
- '!LICENSE.txt',
- '!extensions/**/out/**',
- '!test/smoke/out/**',
- '!**/node_modules/**',
- '!**/fixtures/**',
- '!**/*.{svg,exe,png,bmp,scpt,bat,cmd,cur,ttf,woff,eot}',
- '!build/{lib,tslintRules}/**/*.js',
- '!build/monaco/**',
- '!build/win32/**',
- '!build/**/*.sh',
- '!build/tfs/**/*.js',
- '!**/Dockerfile'
+ 'test/**/*',
+ '!**/node_modules/**'
];
const indentationFilter = [
'**',
+
+ // except specific files
'!ThirdPartyNotices.txt',
- '!**/*.md',
- '!**/*.ps1',
- '!**/*.template',
- '!**/*.yaml',
- '!**/*.yml',
- '!**/yarn.lock',
- '!**/lib/**',
- '!extensions/**/*.d.ts',
- '!src/typings/**/*.d.ts',
- '!src/vs/*/**/*.d.ts',
- '!**/*.d.ts.recipe',
+ '!LICENSE.txt',
+ '!src/vs/nls.js',
+ '!src/vs/css.js',
+ '!src/vs/loader.js',
+ '!src/vs/base/common/marked/raw.marked.js',
+ '!src/vs/base/common/winjs.base.raw.js',
+ '!src/vs/base/node/terminateProcess.sh',
+ '!src/vs/base/node/ps-win.ps1',
'!test/assert.js',
+
+ // except specific folders
+ '!test/smoke/out/**',
+ '!extensions/vscode-api-tests/testWorkspace/**',
+ '!extensions/vscode-api-tests/testWorkspace2/**',
+ '!build/monaco/**',
+ '!build/win32/**',
+
+ // except multiple specific files
'!**/package.json',
+ '!**/yarn.lock',
+
+ // except multiple specific folders
'!**/octicons/**',
- '!**/vs/base/common/marked/raw.marked.js',
- '!**/vs/base/common/winjs.base.raw.js',
- '!**/vs/base/node/terminateProcess.sh',
- '!**/vs/base/node/ps-win.ps1',
- '!**/vs/nls.js',
- '!**/vs/css.js',
- '!**/vs/loader.js',
+ '!**/fixtures/**',
+ '!**/lib/**',
+ '!extensions/**/out/**',
'!extensions/**/snippets/**',
'!extensions/**/syntaxes/**',
'!extensions/**/themes/**',
'!extensions/**/colorize-fixtures/**',
- '!extensions/vscode-api-tests/testWorkspace/**'
+
+ // except specific file types
+ '!src/vs/*/**/*.d.ts',
+ '!src/typings/**/*.d.ts',
+ '!extensions/**/*.d.ts',
+ '!**/*.{svg,exe,png,bmp,scpt,bat,cmd,cur,ttf,woff,eot,md,ps1,template,yaml,yml,d.ts.recipe}',
+ '!build/{lib,tslintRules}/**/*.js',
+ '!build/**/*.sh',
+ '!build/tfs/**/*.js',
+ '!**/Dockerfile',
+ '!extensions/markdown/media/*.js'
];
const copyrightFilter = [
@@ -95,6 +100,7 @@ const copyrightFilter = [
'!**/*.xpm',
'!**/*.opts',
'!**/*.disabled',
+ '!**/*.code-workspace',
'!build/**/*.init',
'!resources/linux/snap/snapcraft.yaml',
'!resources/win32/bin/code.js',
@@ -124,6 +130,7 @@ const tslintFilter = [
'!**/node_modules/**',
'!extensions/typescript/test/colorize-fixtures/**',
'!extensions/vscode-api-tests/testWorkspace/**',
+ '!extensions/vscode-api-tests/testWorkspace2/**',
'!extensions/**/*.test.ts',
'!extensions/html/server/lib/jquery.d.ts'
];
@@ -144,31 +151,23 @@ gulp.task('eslint', () => {
});
gulp.task('tslint', () => {
+ // {{SQL CARBON EDIT}}
const options = { emitError: false };
return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
.pipe(filter(tslintFilter))
- .pipe(gulptslint({ rulesDirectory: 'build/lib/tslint' }))
- .pipe(gulptslint.report(options));
+ .pipe(gulptslint.default({ rulesDirectory: 'build/lib/tslint' }))
+ .pipe(gulptslint.default.report(options));
});
-const hygiene = exports.hygiene = (some, options) => {
- options = options || {};
+function hygiene(some) {
let errorCount = 0;
- const eol = es.through(function (file) {
- if (/\r\n?/g.test(file.contents.toString('utf8'))) {
- console.error(file.relative + ': Bad EOL found');
- errorCount++;
- }
-
- this.emit('data', file);
- });
-
const indentation = es.through(function (file) {
- file.contents
- .toString('utf8')
- .split(/\r\n|\r|\n/)
+ const lines = file.contents.toString('utf8').split(/\r\n|\r|\n/);
+ file.__lines = lines;
+
+ lines
.forEach((line, i) => {
if (/^\s*$/.test(line)) {
// empty or whitespace lines are OK
@@ -186,9 +185,14 @@ const hygiene = exports.hygiene = (some, options) => {
});
const copyrights = es.through(function (file) {
- if (file.contents.toString('utf8').indexOf(copyrightHeader) !== 0) {
- console.error(file.relative + ': Missing or bad copyright statement');
- errorCount++;
+ const lines = file.__lines;
+
+ for (let i = 0; i < copyrightHeaderLines.length; i++) {
+ if (lines[i] !== copyrightHeaderLines[i]) {
+ console.error(file.relative + ': Missing or bad copyright statement');
+ errorCount++;
+ break;
+ }
}
this.emit('data', file);
@@ -196,12 +200,20 @@ const hygiene = exports.hygiene = (some, options) => {
const formatting = es.map(function (file, cb) {
tsfmt.processString(file.path, file.contents.toString('utf8'), {
- verify: true,
+ verify: false,
tsfmt: true,
// verbose: true
+ // keep checkJS happy
+ editorconfig: undefined,
+ replace: undefined,
+ tsconfig: undefined,
+ tslint: undefined
}).then(result => {
- if (result.error) {
- console.error(result.message);
+ let original = result.src.replace(/\r\n/gm, '\n');
+ let formatted = result.dest.replace(/\r\n/gm, '\n');
+
+ if (original !== formatted) {
+ console.error('File not formatted:', file.relative);
errorCount++;
}
cb(null, file);
@@ -211,43 +223,31 @@ const hygiene = exports.hygiene = (some, options) => {
});
});
- function reportFailures(failures) {
- failures.forEach(failure => {
- const name = failure.name || failure.fileName;
- const position = failure.startPosition;
- const line = position.lineAndCharacter ? position.lineAndCharacter.line : position.line;
- const character = position.lineAndCharacter ? position.lineAndCharacter.character : position.character;
-
- // console.error(`${name}:${line + 1}:${character + 1}:${failure.failure}`);
- });
- }
+ const tslintConfiguration = tslint.Configuration.findConfiguration('tslint.json', '.');
+ const tslintOptions = { fix: false, formatter: 'json' };
+ const tsLinter = new tslint.Linter(tslintOptions);
const tsl = es.through(function (file) {
- const configuration = tslint.Configuration.findConfiguration(null, '.');
- const options = { formatter: 'json', rulesDirectory: 'build/lib/tslint' };
const contents = file.contents.toString('utf8');
- const linter = new tslint.Linter(options);
- linter.lint(file.relative, contents, configuration.results);
- const result = linter.getResult();
-
- if (result.failures.length > 0) {
- reportFailures(result.failures);
- errorCount += result.failures.length;
- }
-
+ tsLinter.lint(file.relative, contents, tslintConfiguration.results);
this.emit('data', file);
});
- const result = vfs.src(some || all, { base: '.', follow: true, allowEmpty: true })
+ let input;
+
+ if (Array.isArray(some) || typeof some === 'string' || !some) {
+ input = vfs.src(some || all, { base: '.', follow: true, allowEmpty: true });
+ } else {
+ input = some;
+ }
+
+ const result = input
.pipe(filter(f => !f.stat.isDirectory()))
- .pipe(filter(eolFilter))
- // {{SQL CARBON EDIT}}
- //.pipe(options.skipEOL ? es.through() : eol)
.pipe(filter(indentationFilter))
.pipe(indentation)
- .pipe(filter(copyrightFilter))
+ .pipe(filter(copyrightFilter));
// {{SQL CARBON EDIT}}
- //.pipe(copyrights);
+ // .pipe(copyrights);
const typescript = result
.pipe(filter(tslintFilter))
@@ -257,23 +257,52 @@ const hygiene = exports.hygiene = (some, options) => {
const javascript = result
.pipe(filter(eslintFilter))
.pipe(gulpeslint('src/.eslintrc'))
- .pipe(gulpeslint.formatEach('compact'))
- // {{SQL CARBON EDIT}}
+ .pipe(gulpeslint.formatEach('compact'));
+ // {{SQL CARBON EDIT}}
// .pipe(gulpeslint.failAfterError());
- return es.merge(typescript, javascript)
- .pipe(es.through(null, function () {
- // {{SQL CARBON EDIT}}
- // if (errorCount > 0) {
- // this.emit('error', 'Hygiene failed with ' + errorCount + ' errors. Check \'build/gulpfile.hygiene.js\'.');
- // } else {
- // this.emit('end');
- // }
- this.emit('end');
- }));
-};
+ let count = 0;
+ return es.merge(typescript, javascript)
+ .pipe(es.through(function (data) {
+ // {{SQL CARBON EDIT}}
+ this.emit('end');
+ }));
+}
-gulp.task('hygiene', () => hygiene(''));
+function createGitIndexVinyls(paths) {
+ const cp = require('child_process');
+ const repositoryPath = process.cwd();
+
+ const fns = paths.map(relativePath => () => new Promise((c, e) => {
+ const fullPath = path.join(repositoryPath, relativePath);
+
+ fs.stat(fullPath, (err, stat) => {
+ if (err && err.code === 'ENOENT') { // ignore deletions
+ return c(null);
+ } else if (err) {
+ return e(err);
+ }
+
+ cp.exec(`git show :${relativePath}`, { maxBuffer: 2000 * 1024, encoding: 'buffer' }, (err, out) => {
+ if (err) {
+ return e(err);
+ }
+
+ c(new VinylFile({
+ path: fullPath,
+ base: repositoryPath,
+ contents: out,
+ stat
+ }));
+ });
+ });
+ }));
+
+ return pall(fns, { concurrency: 4 })
+ .then(r => r.filter(p => !!p));
+}
+
+gulp.task('hygiene', () => hygiene());
// this allows us to run hygiene as a git pre-commit hook
if (require.main === module) {
@@ -284,22 +313,19 @@ if (require.main === module) {
process.exit(1);
});
- cp.exec('git config core.autocrlf', (err, out) => {
- const skipEOL = out.trim() === 'true';
-
- if (process.argv.length > 2) {
- return hygiene(process.argv.slice(2), { skipEOL: skipEOL }).on('error', err => {
- console.error();
- console.error(err);
- process.exit(1);
- });
- }
-
+ if (process.argv.length > 2) {
+ hygiene(process.argv.slice(2)).on('error', err => {
+ console.error();
+ console.error(err);
+ process.exit(1);
+ });
+ } else {
cp.exec('git diff --cached --name-only', { maxBuffer: 2000 * 1024 }, (err, out) => {
if (err) {
console.error();
console.error(err);
process.exit(1);
+ return;
}
const some = out
@@ -307,12 +333,18 @@ if (require.main === module) {
.filter(l => !!l);
if (some.length > 0) {
- hygiene(some, { skipEOL: skipEOL }).on('error', err => {
- console.error();
- console.error(err);
- process.exit(1);
- });
+ console.log('Reading git index versions...');
+
+ createGitIndexVinyls(some)
+ .then(vinyls => new Promise((c, e) => hygiene(es.readArray(vinyls))
+ .on('end', () => c())
+ .on('error', e)))
+ .catch(err => {
+ console.error();
+ console.error(err);
+ process.exit(1);
+ });
}
});
- });
+ }
}
diff --git a/build/gulpfile.mixin.js b/build/gulpfile.mixin.js
index 50efeee515..bffd6d3517 100644
--- a/build/gulpfile.mixin.js
+++ b/build/gulpfile.mixin.js
@@ -6,9 +6,21 @@
'use strict';
const gulp = require('gulp');
+const json = require('gulp-json-editor');
+const buffer = require('gulp-buffer');
+const filter = require('gulp-filter');
+const es = require('event-stream');
+const util = require('./lib/util');
+const remote = require('gulp-remote-src');
+const zip = require('gulp-vinyl-zip');
+const assign = require('object-assign');
+
// {{SQL CARBON EDIT}}
const jeditor = require('gulp-json-editor');
+// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
+const pkg = require('../package.json');
+
gulp.task('mixin', function () {
// {{SQL CARBON EDIT}}
const updateUrl = process.env['SQLOPS_UPDATEURL'];
diff --git a/build/gulpfile.vscode.js b/build/gulpfile.vscode.js
index 86d5c699d9..1fcb2bf739 100644
--- a/build/gulpfile.vscode.js
+++ b/build/gulpfile.vscode.js
@@ -27,18 +27,22 @@ const common = require('./lib/optimize');
const nlsDev = require('vscode-nls-dev');
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');
+// {{SQL CARBON EDIT}}
const serviceDownloader = require('service-downloader').ServiceDownloadProvider;
const platformInfo = require('service-downloader/out/platform').PlatformInformation;
const glob = require('glob');
const deps = require('./dependencies');
const getElectronVersion = require('./lib/electron').getElectronVersion;
+const createAsar = require('./lib/asar').createAsar;
const productionDependencies = deps.getProductionDependencies(path.dirname(__dirname));
-
+// @ts-ignore
// {{SQL CARBON EDIT}}
var del = require('del');
const extensionsRoot = path.join(root, 'extensions');
@@ -56,16 +60,16 @@ const nodeModules = [
.concat(_.uniq(productionDependencies.map(d => d.name)))
.concat(baseModules);
-// Build
-const builtInExtensions = [
- { name: 'ms-vscode.node-debug', version: '1.19.8' },
- { name: 'ms-vscode.node-debug2', version: '1.19.4' }
-];
+// Build
+// @ts-ignore Microsoft/TypeScript#21262 complains about a require of a JSON file
+const builtInExtensions = require('./builtInExtensions.json');
const excludedExtensions = [
'vscode-api-tests',
- 'vscode-colorize-tests'
+ 'vscode-colorize-tests',
+ 'ms-vscode.node-debug',
+ 'ms-vscode.node-debug2',
];
// {{SQL CARBON EDIT}}
@@ -104,7 +108,8 @@ const vscodeResources = [
'out-build/vs/workbench/parts/welcome/walkThrough/**/*.md',
'out-build/vs/workbench/services/files/**/*.exe',
'out-build/vs/workbench/services/files/**/*.md',
- 'out-build/vs/code/electron-browser/sharedProcess.js',
+ 'out-build/vs/code/electron-browser/sharedProcess/sharedProcess.js',
+ 'out-build/vs/code/electron-browser/issue/issueReporter.js',
// {{SQL CARBON EDIT}}
'out-build/sql/workbench/electron-browser/splashscreen/*',
'out-build/sql/**/*.{svg,png,cur,html}',
@@ -134,10 +139,7 @@ const BUNDLED_FILE_HEADER = [
' *--------------------------------------------------------*/'
].join('\n');
-var languages = ['chs', 'cht', 'jpn', 'kor', 'deu', 'fra', 'esn', 'rus', 'ita'];
-if (process.env.VSCODE_QUALITY !== 'stable') {
- languages = languages.concat(['ptb', 'hun', 'trk']); // Add languages requested by the community to non-stable builds
-}
+const languages = i18n.defaultLanguages.concat([]); // i18n.defaultLanguages.concat(process.env.VSCODE_QUALITY !== 'stable' ? i18n.extraLanguages : []);
gulp.task('clean-optimized-vscode', util.rimraf('out-vscode'));
gulp.task('optimize-vscode', ['clean-optimized-vscode', 'compile-build', 'compile-extensions-build'], common.optimizeTask({
@@ -147,7 +149,8 @@ gulp.task('optimize-vscode', ['clean-optimized-vscode', 'compile-build', 'compil
loaderConfig: common.loaderConfig(nodeModules),
header: BUNDLED_FILE_HEADER,
out: 'out-vscode',
- languages: languages
+ languages: languages,
+ bundleInfo: undefined
}));
@@ -169,7 +172,7 @@ const config = {
version: getElectronVersion(),
productAppName: product.nameLong,
companyName: 'Microsoft Corporation',
- copyright: 'Copyright (C) 2017 Microsoft. All rights reserved',
+ copyright: 'Copyright (C) 2018 Microsoft. All rights reserved',
darwinIcon: 'resources/darwin/code.icns',
darwinBundleIdentifier: product.darwinBundleIdentifier,
darwinApplicationCategoryType: 'public.app-category.developer-tools',
@@ -188,7 +191,7 @@ const config = {
name: product.nameLong,
urlSchemes: [product.urlProtocol]
}],
- darwinCredits: darwinCreditsTemplate ? new Buffer(darwinCreditsTemplate({ commit: commit, date: new Date().toISOString() })) : void 0,
+ darwinCredits: darwinCreditsTemplate ? Buffer.from(darwinCreditsTemplate({ commit: commit, date: new Date().toISOString() })) : void 0,
linuxExecutableName: product.applicationName,
winIcon: 'resources/win32/code.ico',
token: process.env['VSCODE_MIXIN_PASSWORD'] || process.env['GITHUB_TOKEN'] || void 0,
@@ -328,12 +331,10 @@ function packageTask(platform, arch, opts) {
.pipe(util.cleanNodeModule('account-provider-azure', ['node_modules/date-utils/doc/**', 'node_modules/adal_node/node_modules/**'], undefined))
.pipe(util.cleanNodeModule('typescript', ['**/**'], undefined));
+
const sources = es.merge(src, localExtensions, localExtensionDependencies)
.pipe(util.setExecutableBit(['**/*.sh']))
- .pipe(filter(['**',
- '!**/*.js.map',
- '!extensions/**/node_modules/**/{test, tests}/**',
- '!extensions/**/node_modules/**/test.js']));
+ .pipe(filter(['**', '!**/*.js.map']));
let version = packageJson.version;
const quality = product.quality;
@@ -357,7 +358,7 @@ function packageTask(platform, arch, opts) {
// TODO the API should be copied to `out` during compile, not here
const api = gulp.src('src/vs/vscode.d.ts').pipe(rename('out/vs/vscode.d.ts'));
- // {{SQL CARBON EDIT}}
+ // {{SQL CARBON EDIT}}
const dataApi = gulp.src('src/vs/data.d.ts').pipe(rename('out/sql/data.d.ts'));
const depsSrc = [
@@ -371,6 +372,7 @@ function packageTask(platform, arch, opts) {
.pipe(util.cleanNodeModule('oniguruma', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node', 'src/*.js']))
.pipe(util.cleanNodeModule('windows-mutex', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('native-keymap', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node']))
+ .pipe(util.cleanNodeModule('native-is-elevated', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('native-watchdog', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('spdlog', ['binding.gyp', 'build/**', 'deps/**', 'src/**', 'test/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('jschardet', ['dist/**']))
@@ -378,18 +380,27 @@ function packageTask(platform, arch, opts) {
.pipe(util.cleanNodeModule('windows-process-tree', ['binding.gyp', 'build/**', 'src/**'], ['**/*.node']))
.pipe(util.cleanNodeModule('gc-signals', ['binding.gyp', 'build/**', 'src/**', 'deps/**'], ['**/*.node', 'src/index.js']))
.pipe(util.cleanNodeModule('keytar', ['binding.gyp', 'build/**', 'src/**', 'script/**', 'node_modules/**'], ['**/*.node']))
-
+ .pipe(util.cleanNodeModule('node-pty', ['binding.gyp', 'build/**', 'src/**', 'tools/**'], ['build/Release/*.exe', 'build/Release/*.dll', 'build/Release/*.node']))
// {{SQL CARBON EDIT}}
- .pipe(util.cleanNodeModule('node-pty', ['binding.gyp', 'build/**', 'src/**', 'tools/**'], ['build/Release/*.node', 'build/Release/*.dll', 'build/Release/*.exe']))
.pipe(util.cleanNodeModule('chart.js', ['node_modules/**'], undefined))
.pipe(util.cleanNodeModule('emmet', ['node_modules/**'], undefined))
.pipe(util.cleanNodeModule('pty.js', ['build/**'], ['build/Release/**']))
.pipe(util.cleanNodeModule('jquery-ui', ['external/**', 'demos/**'], undefined))
.pipe(util.cleanNodeModule('core-js', ['**/**'], undefined))
.pipe(util.cleanNodeModule('slickgrid', ['node_modules/**', 'examples/**'], undefined))
-
.pipe(util.cleanNodeModule('nsfw', ['binding.gyp', 'build/**', 'src/**', 'openpa/**', 'includes/**'], ['**/*.node', '**/*.a']))
- .pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node']));
+ .pipe(util.cleanNodeModule('vsda', ['binding.gyp', 'README.md', 'build/**', '*.bat', '*.sh', '*.cpp', '*.h'], ['build/Release/vsda.node']))
+ .pipe(createAsar(path.join(process.cwd(), 'node_modules'), ['**/*.node', '**/vscode-ripgrep/bin/*', '**/node-pty/build/Release/*'], 'app/node_modules.asar'));
+
+ // {{SQL CARBON EDIT}}
+ let copiedModules = gulp.src([
+ 'node_modules/jquery/**/*.*',
+ 'node_modules/reflect-metadata/**/*.*',
+ 'node_modules/slickgrid/**/*.*',
+ 'node_modules/underscore/**/*.*',
+ 'node_modules/zone.js/**/*.*',
+ 'node_modules/chart.js/**/*.*'
+ ], { base: '.', dot: true });
let all = es.merge(
packageJsonStream,
@@ -397,7 +408,8 @@ function packageTask(platform, arch, opts) {
license,
watermark,
api,
- // {{SQL CARBON EDIT}}
+ // {{SQL CARBON EDIT}}
+ copiedModules,
dataApi,
sources,
deps
@@ -468,25 +480,21 @@ gulp.task('vscode-linux-x64-min', ['minify-vscode', 'clean-vscode-linux-x64'], p
gulp.task('vscode-linux-arm-min', ['minify-vscode', 'clean-vscode-linux-arm'], packageTask('linux', 'arm', { minified: true }));
// Transifex Localizations
-const vscodeLanguages = [
- 'zh-hans',
- 'zh-hant',
- 'ja',
- 'ko',
- 'de',
- 'fr',
- 'es',
- 'ru',
- 'it',
- 'pt-br',
- 'hu',
- 'tr'
-];
-const setupDefaultLanguages = [
- 'zh-hans',
- 'zh-hant',
- 'ko'
-];
+
+const innoSetupConfig = {
+ 'zh-cn': { codePage: 'CP936', defaultInfo: { name: 'Simplified Chinese', id: '$0804', } },
+ 'zh-tw': { codePage: 'CP950', defaultInfo: { name: 'Traditional Chinese', id: '$0404' } },
+ 'ko': { codePage: 'CP949', defaultInfo: { name: 'Korean', id: '$0412' } },
+ 'ja': { codePage: 'CP932' },
+ 'de': { codePage: 'CP1252' },
+ 'fr': { codePage: 'CP1252' },
+ 'es': { codePage: 'CP1252' },
+ 'ru': { codePage: 'CP1251' },
+ 'it': { codePage: 'CP1252' },
+ 'pt-br': { codePage: 'CP1252' },
+ 'hu': { codePage: 'CP1250' },
+ 'tr': { codePage: 'CP1254' }
+};
const apiHostname = process.env.TRANSIFEX_API_URL;
const apiName = process.env.TRANSIFEX_API_NAME;
@@ -494,27 +502,48 @@ const apiToken = process.env.TRANSIFEX_API_TOKEN;
gulp.task('vscode-translations-push', ['optimize-vscode'], function () {
const pathToMetadata = './out-vscode/nls.metadata.json';
- const pathToExtensions = './extensions/**/*.nls.json';
+ const pathToExtensions = './extensions/*';
const pathToSetup = 'build/win32/**/{Default.isl,messages.en.isl}';
return es.merge(
- gulp.src(pathToMetadata).pipe(i18n.prepareXlfFiles()),
- gulp.src(pathToSetup).pipe(i18n.prepareXlfFiles()),
- gulp.src(pathToExtensions).pipe(i18n.prepareXlfFiles('vscode-extensions'))
+ gulp.src(pathToMetadata).pipe(i18n.createXlfFilesForCoreBundle()),
+ gulp.src(pathToSetup).pipe(i18n.createXlfFilesForIsl()),
+ gulp.src(pathToExtensions).pipe(i18n.createXlfFilesForExtensions())
+ ).pipe(i18n.findObsoleteResources(apiHostname, apiName, apiToken)
).pipe(i18n.pushXlfFiles(apiHostname, apiName, apiToken));
});
-gulp.task('vscode-translations-pull', function () {
+gulp.task('vscode-translations-push-test', ['optimize-vscode'], function () {
+ const pathToMetadata = './out-vscode/nls.metadata.json';
+ const pathToExtensions = './extensions/*';
+ const pathToSetup = 'build/win32/**/{Default.isl,messages.en.isl}';
+
return es.merge(
- i18n.pullXlfFiles('vscode-editor', apiHostname, apiName, apiToken, vscodeLanguages),
- i18n.pullXlfFiles('vscode-workbench', apiHostname, apiName, apiToken, vscodeLanguages),
- i18n.pullXlfFiles('vscode-extensions', apiHostname, apiName, apiToken, vscodeLanguages),
- i18n.pullXlfFiles('vscode-setup', apiHostname, apiName, apiToken, setupDefaultLanguages)
- ).pipe(vfs.dest('../vscode-localization'));
+ gulp.src(pathToMetadata).pipe(i18n.createXlfFilesForCoreBundle()),
+ gulp.src(pathToSetup).pipe(i18n.createXlfFilesForIsl()),
+ gulp.src(pathToExtensions).pipe(i18n.createXlfFilesForExtensions())
+ ).pipe(i18n.findObsoleteResources(apiHostname, apiName, apiToken)
+ ).pipe(vfs.dest('../vscode-transifex-input'));
+});
+
+gulp.task('vscode-translations-pull', function () {
+ [...i18n.defaultLanguages, ...i18n.extraLanguages].forEach(language => {
+ i18n.pullCoreAndExtensionsXlfFiles(apiHostname, apiName, apiToken, language).pipe(vfs.dest(`../vscode-localization/${language.id}/build`));
+
+ let includeDefault = !!innoSetupConfig[language.id].defaultInfo;
+ i18n.pullSetupXlfFiles(apiHostname, apiName, apiToken, language, includeDefault).pipe(vfs.dest(`../vscode-localization/${language.id}/setup`));
+ });
});
gulp.task('vscode-translations-import', function () {
- return gulp.src('../vscode-localization/**/*.xlf').pipe(i18n.prepareJsonFiles()).pipe(vfs.dest('./i18n'));
+ [...i18n.defaultLanguages, ...i18n.extraLanguages].forEach(language => {
+ gulp.src(`../vscode-localization/${language.id}/build/*/*.xlf`)
+ .pipe(i18n.prepareI18nFiles())
+ .pipe(vfs.dest(`./i18n/${language.folderName}`));
+ gulp.src(`../vscode-localization/${language.id}/setup/*/*.xlf`)
+ .pipe(i18n.prepareIslFiles(language, innoSetupConfig[language.id]))
+ .pipe(vfs.dest(`./build/win32/i18n`));
+ });
});
// Sourcemaps
@@ -540,7 +569,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 (!branch.endsWith('/master') && branch.indexOf('/release/') < 0) {
+
+ if (!/\/master$/.test(branch) && branch.indexOf('/release/') < 0) {
console.log(`Only runs on master and release branches, not ${branch}`);
return;
}
@@ -635,6 +665,7 @@ function versionStringToNumber(versionStr) {
return parseInt(match[1], 10) * 1e4 + parseInt(match[2], 10) * 1e2 + parseInt(match[3], 10);
}
+// This task is only run for the MacOS build
gulp.task('generate-vscode-configuration', () => {
return new Promise((resolve, reject) => {
const buildDir = process.env['AGENT_BUILDDIRECTORY'];
@@ -644,7 +675,8 @@ gulp.task('generate-vscode-configuration', () => {
const userDataDir = path.join(os.tmpdir(), 'tmpuserdata');
const extensionsDir = path.join(os.tmpdir(), 'tmpextdir');
- const appPath = path.join(buildDir, 'VSCode-darwin/Visual\\ Studio\\ Code\\ -\\ Insiders.app/Contents/Resources/app/bin/code');
+ const appName = process.env.VSCODE_QUALITY === 'insider' ? 'Visual\\ Studio\\ Code\\ -\\ Insiders.app' : 'Visual\\ Studio\\ Code.app';
+ const appPath = path.join(buildDir, `VSCode-darwin/${appName}/Contents/Resources/app/bin/code`);
const codeProc = cp.exec(`${appPath} --export-default-configuration='${allConfigDetailsPath}' --wait --user-data-dir='${userDataDir}' --extensions-dir='${extensionsDir}'`);
const timer = setTimeout(() => {
@@ -694,3 +726,4 @@ function installService() {
gulp.task('install-sqltoolsservice', () => {
return installService();
});
+
diff --git a/build/gulpfile.vscode.linux.js b/build/gulpfile.vscode.linux.js
index 581bc198c9..2c06afb10d 100644
--- a/build/gulpfile.vscode.linux.js
+++ b/build/gulpfile.vscode.linux.js
@@ -12,9 +12,12 @@ 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');
-const rpmDependencies = require('../resources/linux/rpm/dependencies');
+// @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);
@@ -111,8 +114,7 @@ function buildDebPackage(arch) {
return shell.task([
'chmod 755 ' + product.applicationName + '-' + debArch + '/DEBIAN/postinst ' + product.applicationName + '-' + debArch + '/DEBIAN/prerm ' + product.applicationName + '-' + debArch + '/DEBIAN/postrm',
'mkdir -p deb',
- 'fakeroot dpkg-deb -b ' + product.applicationName + '-' + debArch + ' deb',
- 'dpkg-scanpackages deb /dev/null > Packages'
+ 'fakeroot dpkg-deb -b ' + product.applicationName + '-' + debArch + ' deb'
], { cwd: '.build/linux/deb/' + debArch });
}
@@ -220,10 +222,10 @@ function prepareSnapPackage(arch) {
function buildSnapPackage(arch) {
const snapBuildPath = getSnapBuildPath(arch);
-
+ const snapFilename = `${product.applicationName}-${packageJson.version}-${linuxPackageRevision}-${arch}.snap`;
return shell.task([
`chmod +x ${snapBuildPath}/electron-launch`,
- `cd ${snapBuildPath} && snapcraft snap`
+ `cd ${snapBuildPath} && snapcraft snap --output ../${snapFilename}`
]);
}
diff --git a/build/gulpfile.vscode.win32.js b/build/gulpfile.vscode.win32.js
index 74a88c368a..69b83c5069 100644
--- a/build/gulpfile.vscode.win32.js
+++ b/build/gulpfile.vscode.win32.js
@@ -11,8 +11,11 @@ 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 repoPath = path.dirname(__dirname);
// {{SQL CARBON EDIT}}
@@ -91,3 +94,13 @@ gulp.task('vscode-win32-ia32-archive', ['clean-vscode-win32-ia32-archive'], arch
gulp.task('clean-vscode-win32-x64-archive', util.rimraf(zipDir('x64')));
gulp.task('vscode-win32-x64-archive', ['clean-vscode-win32-x64-archive'], archiveWin32Setup('x64'));
+
+function copyInnoUpdater(arch) {
+ return () => {
+ return gulp.src('build/win32/{inno_updater.exe,vcruntime140.dll}', { base: 'build/win32' })
+ .pipe(vfs.dest(path.join(buildPath(arch), 'tools')));
+ };
+}
+
+gulp.task('vscode-win32-ia32-copy-inno-updater', copyInnoUpdater('ia32'));
+gulp.task('vscode-win32-x64-copy-inno-updater', copyInnoUpdater('x64'));
\ No newline at end of file
diff --git a/build/lib/asar.js b/build/lib/asar.js
new file mode 100644
index 0000000000..66618cc828
--- /dev/null
+++ b/build/lib/asar.js
@@ -0,0 +1,118 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+'use strict';
+Object.defineProperty(exports, "__esModule", { value: true });
+var path = require("path");
+var es = require("event-stream");
+var pickle = require("chromium-pickle-js");
+var Filesystem = require("asar/lib/filesystem");
+var VinylFile = require("vinyl");
+var minimatch = require("minimatch");
+function createAsar(folderPath, unpackGlobs, destFilename) {
+ var shouldUnpackFile = function (file) {
+ for (var i = 0; i < unpackGlobs.length; i++) {
+ if (minimatch(file.relative, unpackGlobs[i])) {
+ return true;
+ }
+ }
+ return false;
+ };
+ var filesystem = new Filesystem(folderPath);
+ var out = [];
+ // Keep track of pending inserts
+ var pendingInserts = 0;
+ var onFileInserted = function () { pendingInserts--; };
+ // Do not insert twice the same directory
+ var seenDir = {};
+ var insertDirectoryRecursive = function (dir) {
+ if (seenDir[dir]) {
+ return;
+ }
+ var lastSlash = dir.lastIndexOf('/');
+ if (lastSlash === -1) {
+ lastSlash = dir.lastIndexOf('\\');
+ }
+ if (lastSlash !== -1) {
+ insertDirectoryRecursive(dir.substring(0, lastSlash));
+ }
+ seenDir[dir] = true;
+ filesystem.insertDirectory(dir);
+ };
+ var insertDirectoryForFile = function (file) {
+ var lastSlash = file.lastIndexOf('/');
+ if (lastSlash === -1) {
+ lastSlash = file.lastIndexOf('\\');
+ }
+ if (lastSlash !== -1) {
+ insertDirectoryRecursive(file.substring(0, lastSlash));
+ }
+ };
+ var insertFile = function (relativePath, stat, shouldUnpack) {
+ insertDirectoryForFile(relativePath);
+ pendingInserts++;
+ filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}, onFileInserted);
+ };
+ return es.through(function (file) {
+ if (file.stat.isDirectory()) {
+ return;
+ }
+ if (!file.stat.isFile()) {
+ throw new Error("unknown item in stream!");
+ }
+ var shouldUnpack = shouldUnpackFile(file);
+ insertFile(file.relative, { size: file.contents.length, mode: file.stat.mode }, shouldUnpack);
+ if (shouldUnpack) {
+ // The file goes outside of xx.asar, in a folder xx.asar.unpacked
+ var relative = path.relative(folderPath, file.path);
+ this.queue(new VinylFile({
+ cwd: folderPath,
+ base: folderPath,
+ path: path.join(destFilename + '.unpacked', relative),
+ stat: file.stat,
+ contents: file.contents
+ }));
+ }
+ else {
+ // The file goes inside of xx.asar
+ out.push(file.contents);
+ }
+ }, function () {
+ var _this = this;
+ var finish = function () {
+ {
+ var headerPickle = pickle.createEmpty();
+ headerPickle.writeString(JSON.stringify(filesystem.header));
+ var headerBuf = headerPickle.toBuffer();
+ var sizePickle = pickle.createEmpty();
+ sizePickle.writeUInt32(headerBuf.length);
+ var sizeBuf = sizePickle.toBuffer();
+ out.unshift(headerBuf);
+ out.unshift(sizeBuf);
+ }
+ var contents = Buffer.concat(out);
+ out.length = 0;
+ _this.queue(new VinylFile({
+ cwd: folderPath,
+ base: folderPath,
+ path: destFilename,
+ contents: contents
+ }));
+ _this.queue(null);
+ };
+ // Call finish() only when all file inserts have finished...
+ if (pendingInserts === 0) {
+ finish();
+ }
+ else {
+ onFileInserted = function () {
+ pendingInserts--;
+ if (pendingInserts === 0) {
+ finish();
+ }
+ };
+ }
+ });
+}
+exports.createAsar = createAsar;
diff --git a/build/lib/asar.ts b/build/lib/asar.ts
new file mode 100644
index 0000000000..c3ae9a5761
--- /dev/null
+++ b/build/lib/asar.ts
@@ -0,0 +1,131 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+'use strict';
+
+import * as path from 'path';
+import * as es from 'event-stream';
+import * as pickle from 'chromium-pickle-js';
+import * as Filesystem from 'asar/lib/filesystem';
+import * as VinylFile from 'vinyl';
+import * as minimatch from 'minimatch';
+
+export function createAsar(folderPath: string, unpackGlobs: string[], destFilename: string): NodeJS.ReadWriteStream {
+
+ const shouldUnpackFile = (file: VinylFile): boolean => {
+ for (let i = 0; i < unpackGlobs.length; i++) {
+ if (minimatch(file.relative, unpackGlobs[i])) {
+ return true;
+ }
+ }
+ return false;
+ };
+
+ const filesystem = new Filesystem(folderPath);
+ const out: Buffer[] = [];
+
+ // Keep track of pending inserts
+ let pendingInserts = 0;
+ let onFileInserted = () => { pendingInserts--; };
+
+ // Do not insert twice the same directory
+ const seenDir: { [key: string]: boolean; } = {};
+ const insertDirectoryRecursive = (dir: string) => {
+ if (seenDir[dir]) {
+ return;
+ }
+
+ let lastSlash = dir.lastIndexOf('/');
+ if (lastSlash === -1) {
+ lastSlash = dir.lastIndexOf('\\');
+ }
+ if (lastSlash !== -1) {
+ insertDirectoryRecursive(dir.substring(0, lastSlash));
+ }
+ seenDir[dir] = true;
+ filesystem.insertDirectory(dir);
+ };
+
+ const insertDirectoryForFile = (file: string) => {
+ let lastSlash = file.lastIndexOf('/');
+ if (lastSlash === -1) {
+ lastSlash = file.lastIndexOf('\\');
+ }
+ if (lastSlash !== -1) {
+ insertDirectoryRecursive(file.substring(0, lastSlash));
+ }
+ };
+
+ const insertFile = (relativePath: string, stat: { size: number; mode: number; }, shouldUnpack: boolean) => {
+ insertDirectoryForFile(relativePath);
+ pendingInserts++;
+ filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}, onFileInserted);
+ };
+
+ return es.through(function (file) {
+ if (file.stat.isDirectory()) {
+ return;
+ }
+ if (!file.stat.isFile()) {
+ throw new Error(`unknown item in stream!`);
+ }
+ const shouldUnpack = shouldUnpackFile(file);
+ insertFile(file.relative, { size: file.contents.length, mode: file.stat.mode }, shouldUnpack);
+
+ if (shouldUnpack) {
+ // The file goes outside of xx.asar, in a folder xx.asar.unpacked
+ const relative = path.relative(folderPath, file.path);
+ this.queue(new VinylFile({
+ cwd: folderPath,
+ base: folderPath,
+ path: path.join(destFilename + '.unpacked', relative),
+ stat: file.stat,
+ contents: file.contents
+ }));
+ } else {
+ // The file goes inside of xx.asar
+ out.push(file.contents);
+ }
+ }, function () {
+
+ let finish = () => {
+ {
+ const headerPickle = pickle.createEmpty();
+ headerPickle.writeString(JSON.stringify(filesystem.header));
+ const headerBuf = headerPickle.toBuffer();
+
+ const sizePickle = pickle.createEmpty();
+ sizePickle.writeUInt32(headerBuf.length);
+ const sizeBuf = sizePickle.toBuffer();
+
+ out.unshift(headerBuf);
+ out.unshift(sizeBuf);
+ }
+
+ const contents = Buffer.concat(out);
+ out.length = 0;
+
+ this.queue(new VinylFile({
+ cwd: folderPath,
+ base: folderPath,
+ path: destFilename,
+ contents: contents
+ }));
+ this.queue(null);
+ };
+
+ // Call finish() only when all file inserts have finished...
+ if (pendingInserts === 0) {
+ finish();
+ } else {
+ onFileInserted = () => {
+ pendingInserts--;
+ if (pendingInserts === 0) {
+ finish();
+ }
+ };
+ }
+ });
+}
diff --git a/build/lib/builtInExtensions.js b/build/lib/builtInExtensions.js
new file mode 100644
index 0000000000..1cdf72b468
--- /dev/null
+++ b/build/lib/builtInExtensions.js
@@ -0,0 +1,122 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+'use strict';
+
+const fs = require('fs');
+const path = require('path');
+const os = require('os');
+const mkdirp = require('mkdirp');
+const rimraf = require('rimraf');
+const es = require('event-stream');
+const rename = require('gulp-rename');
+const vfs = require('vinyl-fs');
+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');
+
+function getExtensionPath(extension) {
+ return path.join(root, '.build', 'builtInExtensions', extension.name);
+}
+
+function isUpToDate(extension) {
+ const packagePath = path.join(getExtensionPath(extension), 'package.json');
+
+ if (!fs.existsSync(packagePath)) {
+ return false;
+ }
+
+ const packageContents = fs.readFileSync(packagePath, { encoding: 'utf8' });
+
+ try {
+ const diskVersion = JSON.parse(packageContents).version;
+ return (diskVersion === extension.version);
+ } catch (err) {
+ return false;
+ }
+}
+
+function syncMarketplaceExtension(extension) {
+ if (isUpToDate(extension)) {
+ util.log(util.colors.blue('[marketplace]'), `${extension.name}@${extension.version}`, util.colors.green('✔︎'));
+ return es.readArray([]);
+ }
+
+ rimraf.sync(getExtensionPath(extension));
+
+ return ext.fromMarketplace(extension.name, extension.version)
+ .pipe(rename(p => p.dirname = `${extension.name}/${p.dirname}`))
+ .pipe(vfs.dest('.build/builtInExtensions'))
+ .on('end', () => util.log(util.colors.blue('[marketplace]'), extension.name, util.colors.green('✔︎')));
+}
+
+function syncExtension(extension, controlState) {
+ switch (controlState) {
+ case 'disabled':
+ util.log(util.colors.blue('[disabled]'), util.colors.gray(extension.name));
+ return es.readArray([]);
+
+ case 'marketplace':
+ return syncMarketplaceExtension(extension);
+
+ default:
+ if (!fs.existsSync(controlState)) {
+ util.log(util.colors.red(`Error: Built-in extension '${extension.name}' is configured to run from '${controlState}' but that path does not exist.`));
+ return es.readArray([]);
+
+ } else if (!fs.existsSync(path.join(controlState, 'package.json'))) {
+ util.log(util.colors.red(`Error: Built-in extension '${extension.name}' is configured to run from '${controlState}' but there is no 'package.json' file in that directory.`));
+ return es.readArray([]);
+ }
+
+ util.log(util.colors.blue('[local]'), `${extension.name}: ${util.colors.cyan(controlState)}`, util.colors.green('✔︎'));
+ return es.readArray([]);
+ }
+}
+
+function readControlFile() {
+ try {
+ return JSON.parse(fs.readFileSync(controlFilePath, 'utf8'));
+ } catch (err) {
+ return {};
+ }
+}
+
+function writeControlFile(control) {
+ mkdirp.sync(path.dirname(controlFilePath));
+ fs.writeFileSync(controlFilePath, JSON.stringify(control, null, 2));
+}
+
+function main() {
+ util.log('Syncronizing built-in extensions...');
+ util.log(`You can manage built-in extensions with the ${util.colors.cyan('--builtin')} flag`);
+
+ const control = readControlFile();
+ const streams = [];
+
+ for (const extension of builtInExtensions) {
+ let controlState = control[extension.name] || 'marketplace';
+ control[extension.name] = controlState;
+
+ streams.push(syncExtension(extension, controlState));
+ }
+
+ writeControlFile(control);
+
+ es.merge(streams)
+ .on('error', err => {
+ console.error(err);
+ process.exit(1);
+ })
+ .on('end', () => {
+ process.exit(0);
+ });
+}
+
+main();
diff --git a/build/lib/bundle.js b/build/lib/bundle.js
index 2c95f4c3b2..f21491635e 100644
--- a/build/lib/bundle.js
+++ b/build/lib/bundle.js
@@ -217,6 +217,7 @@ function removeDuplicateTSBoilerplate(destFiles) {
{ start: /^var __metadata/, end: /^};$/ },
{ start: /^var __param/, end: /^};$/ },
{ start: /^var __awaiter/, end: /^};$/ },
+ { start: /^var __generator/, end: /^};$/ },
];
destFiles.forEach(function (destFile) {
var SEEN_BOILERPLATE = [];
diff --git a/build/lib/bundle.ts b/build/lib/bundle.ts
index 96c961e229..b7ef43c4dd 100644
--- a/build/lib/bundle.ts
+++ b/build/lib/bundle.ts
@@ -44,11 +44,11 @@ interface ILoaderPluginReqFunc {
export interface IEntryPoint {
name: string;
- include: string[];
- exclude: string[];
+ include?: string[];
+ exclude?: string[];
prepend: string[];
- append: string[];
- dest: string;
+ append?: string[];
+ dest?: string;
}
interface IEntryPointMap {
@@ -339,6 +339,7 @@ function removeDuplicateTSBoilerplate(destFiles: IConcatFile[]): IConcatFile[] {
{ start: /^var __metadata/, end: /^};$/ },
{ start: /^var __param/, end: /^};$/ },
{ start: /^var __awaiter/, end: /^};$/ },
+ { start: /^var __generator/, end: /^};$/ },
];
destFiles.forEach((destFile) => {
diff --git a/build/lib/compilation.js b/build/lib/compilation.js
index dfb4de1540..7ce9c33d34 100644
--- a/build/lib/compilation.js
+++ b/build/lib/compilation.js
@@ -22,6 +22,9 @@ var rootDir = path.join(__dirname, '../../src');
var options = require('../../src/tsconfig.json').compilerOptions;
options.verbose = false;
options.sourceMap = true;
+if (process.env['VSCODE_NO_SOURCEMAP']) {
+ options.sourceMap = false;
+}
options.rootDir = rootDir;
options.sourceRoot = util.toFileUri(rootDir);
function createCompile(build, emitError) {
@@ -58,9 +61,13 @@ function compileTask(out, build) {
return function () {
var compile = createCompile(build, true);
var src = es.merge(gulp.src('src/**', { base: 'src' }), gulp.src('node_modules/typescript/lib/lib.d.ts'));
+ // Do not write .d.ts files to disk, as they are not needed there.
+ var dtsFilter = util.filter(function (data) { return !/\.d\.ts$/.test(data.path); });
return src
.pipe(compile())
+ .pipe(dtsFilter)
.pipe(gulp.dest(out))
+ .pipe(dtsFilter.restore)
.pipe(monacodtsTask(out, false));
};
}
@@ -70,54 +77,19 @@ function watchTask(out, build) {
var compile = createCompile(build);
var src = es.merge(gulp.src('src/**', { base: 'src' }), gulp.src('node_modules/typescript/lib/lib.d.ts'));
var watchSrc = watch('src/**', { base: 'src' });
+ // Do not write .d.ts files to disk, as they are not needed there.
+ var dtsFilter = util.filter(function (data) { return !/\.d\.ts$/.test(data.path); });
return watchSrc
.pipe(util.incremental(compile, src, true))
+ .pipe(dtsFilter)
.pipe(gulp.dest(out))
+ .pipe(dtsFilter.restore)
.pipe(monacodtsTask(out, true));
};
}
exports.watchTask = watchTask;
-function reloadTypeScriptNodeModule() {
- var util = require('gulp-util');
- function log(message) {
- var rest = [];
- for (var _i = 1; _i < arguments.length; _i++) {
- rest[_i - 1] = arguments[_i];
- }
- util.log.apply(util, [util.colors.cyan('[memory watch dog]'), message].concat(rest));
- }
- function heapUsed() {
- return (process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2) + ' MB';
- }
- return es.through(function (data) {
- this.emit('data', data);
- }, function () {
- log('memory usage after compilation finished: ' + heapUsed());
- // It appears we are running into some variant of
- // https://bugs.chromium.org/p/v8/issues/detail?id=2073
- //
- // Even though all references are dropped, some
- // optimized methods in the TS compiler end up holding references
- // to the entire TypeScript language host (>600MB)
- //
- // The idea is to force v8 to drop references to these
- // optimized methods, by "reloading" the typescript node module
- log('Reloading typescript node module...');
- var resolvedName = require.resolve('typescript');
- var originalModule = require.cache[resolvedName];
- delete require.cache[resolvedName];
- var newExports = require('typescript');
- require.cache[resolvedName] = originalModule;
- for (var prop in newExports) {
- if (newExports.hasOwnProperty(prop)) {
- originalModule.exports[prop] = newExports[prop];
- }
- }
- log('typescript node module reloaded.');
- this.emit('end');
- });
-}
function monacodtsTask(out, isWatch) {
+ var basePath = path.resolve(process.cwd(), out);
var neededFiles = {};
monacodts.getFilesToWatch(out).forEach(function (filePath) {
filePath = path.normalize(filePath);
@@ -160,7 +132,7 @@ function monacodtsTask(out, isWatch) {
}));
}
resultStream = es.through(function (data) {
- var filePath = path.normalize(data.path);
+ var filePath = path.normalize(path.resolve(basePath, data.relative));
if (neededFiles[filePath]) {
setInputFile(filePath, data.contents.toString());
}
diff --git a/build/lib/compilation.ts b/build/lib/compilation.ts
index 4080677623..f7f25001db 100644
--- a/build/lib/compilation.ts
+++ b/build/lib/compilation.ts
@@ -25,6 +25,9 @@ const rootDir = path.join(__dirname, '../../src');
const options = require('../../src/tsconfig.json').compilerOptions;
options.verbose = false;
options.sourceMap = true;
+if (process.env['VSCODE_NO_SOURCEMAP']) { // To be used by developers in a hurry
+ options.sourceMap = false;
+}
options.rootDir = rootDir;
options.sourceRoot = util.toFileUri(rootDir);
@@ -49,7 +52,6 @@ function createCompile(build: boolean, emitError?: boolean): (token?: util.ICanc
.pipe(tsFilter)
.pipe(util.loadSourcemaps())
.pipe(ts(token))
- // .pipe(build ? reloadTypeScriptNodeModule() : es.through())
.pipe(noDeclarationsFilter)
.pipe(build ? nls() : es.through())
.pipe(noDeclarationsFilter.restore)
@@ -75,9 +77,14 @@ export function compileTask(out: string, build: boolean): () => NodeJS.ReadWrite
gulp.src('node_modules/typescript/lib/lib.d.ts'),
);
+ // Do not write .d.ts files to disk, as they are not needed there.
+ const dtsFilter = util.filter(data => !/\.d\.ts$/.test(data.path));
+
return src
.pipe(compile())
+ .pipe(dtsFilter)
.pipe(gulp.dest(out))
+ .pipe(dtsFilter.restore)
.pipe(monacodtsTask(out, false));
};
}
@@ -93,62 +100,22 @@ export function watchTask(out: string, build: boolean): () => NodeJS.ReadWriteSt
);
const watchSrc = watch('src/**', { base: 'src' });
+ // Do not write .d.ts files to disk, as they are not needed there.
+ const dtsFilter = util.filter(data => !/\.d\.ts$/.test(data.path));
+
return watchSrc
.pipe(util.incremental(compile, src, true))
+ .pipe(dtsFilter)
.pipe(gulp.dest(out))
+ .pipe(dtsFilter.restore)
.pipe(monacodtsTask(out, true));
};
}
-function reloadTypeScriptNodeModule(): NodeJS.ReadWriteStream {
- var util = require('gulp-util');
- function log(message: any, ...rest: any[]): void {
- util.log(util.colors.cyan('[memory watch dog]'), message, ...rest);
- }
-
- function heapUsed(): string {
- return (process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2) + ' MB';
- }
-
- return es.through(function (data) {
- this.emit('data', data);
- }, function () {
-
- log('memory usage after compilation finished: ' + heapUsed());
-
- // It appears we are running into some variant of
- // https://bugs.chromium.org/p/v8/issues/detail?id=2073
- //
- // Even though all references are dropped, some
- // optimized methods in the TS compiler end up holding references
- // to the entire TypeScript language host (>600MB)
- //
- // The idea is to force v8 to drop references to these
- // optimized methods, by "reloading" the typescript node module
-
- log('Reloading typescript node module...');
-
- var resolvedName = require.resolve('typescript');
-
- var originalModule = require.cache[resolvedName];
- delete require.cache[resolvedName];
- var newExports = require('typescript');
- require.cache[resolvedName] = originalModule;
-
- for (var prop in newExports) {
- if (newExports.hasOwnProperty(prop)) {
- originalModule.exports[prop] = newExports[prop];
- }
- }
-
- log('typescript node module reloaded.');
-
- this.emit('end');
- });
-}
-
function monacodtsTask(out: string, isWatch: boolean): NodeJS.ReadWriteStream {
+ const basePath = path.resolve(process.cwd(), out);
+
const neededFiles: { [file: string]: boolean; } = {};
monacodts.getFilesToWatch(out).forEach(function (filePath) {
filePath = path.normalize(filePath);
@@ -196,7 +163,7 @@ function monacodtsTask(out: string, isWatch: boolean): NodeJS.ReadWriteStream {
}
resultStream = es.through(function (data) {
- const filePath = path.normalize(data.path);
+ const filePath = path.normalize(path.resolve(basePath, data.relative));
if (neededFiles[filePath]) {
setInputFile(filePath, data.contents.toString());
}
diff --git a/build/lib/i18n.js b/build/lib/i18n.js
index c88619e000..10cafc2703 100644
--- a/build/lib/i18n.js
+++ b/build/lib/i18n.js
@@ -12,8 +12,10 @@ var Is = require("is");
var xml2js = require("xml2js");
var glob = require("glob");
var https = require("https");
+var gulp = require("gulp");
var util = require('gulp-util');
var iconv = require('iconv-lite');
+var NUMBER_OF_CONCURRENT_DOWNLOADS = 4;
function log(message) {
var rest = [];
for (var _i = 1; _i < arguments.length; _i++) {
@@ -21,6 +23,29 @@ function log(message) {
}
util.log.apply(util, [util.colors.green('[i18n]'), message].concat(rest));
}
+exports.defaultLanguages = [
+ { id: 'zh-tw', folderName: 'cht', transifexId: 'zh-hant' },
+ { id: 'zh-cn', folderName: 'chs', transifexId: 'zh-hans' },
+ { id: 'ja', folderName: 'jpn' },
+ { id: 'ko', folderName: 'kor' },
+ { id: 'de', folderName: 'deu' },
+ { id: 'fr', folderName: 'fra' },
+ { id: 'es', folderName: 'esn' },
+ { id: 'ru', folderName: 'rus' },
+ { id: 'it', folderName: 'ita' }
+];
+// languages requested by the community to non-stable builds
+exports.extraLanguages = [
+ { id: 'pt-br', folderName: 'ptb' },
+ { id: 'hu', folderName: 'hun' },
+ { id: 'tr', folderName: 'trk' }
+];
+// non built-in extensions also that are transifex and need to be part of the language packs
+var externalExtensionsWithTranslations = {
+ 'vscode-chrome-debug': 'msjsdiag.debugger-for-chrome',
+ 'vscode-node-debug': 'ms-vscode.node-debug',
+ 'vscode-node-debug2': 'ms-vscode.node-debug2'
+};
var LocalizeInfo;
(function (LocalizeInfo) {
function is(value) {
@@ -101,6 +126,7 @@ var XLF = /** @class */ (function () {
this.project = project;
this.buffer = [];
this.files = Object.create(null);
+ this.numberOfMessages = 0;
}
XLF.prototype.toString = function () {
this.appendHeader();
@@ -116,27 +142,36 @@ var XLF = /** @class */ (function () {
return this.buffer.join('\r\n');
};
XLF.prototype.addFile = function (original, keys, messages) {
+ if (keys.length === 0) {
+ console.log('No keys in ' + original);
+ return;
+ }
+ if (keys.length !== messages.length) {
+ throw new Error("Unmatching keys(" + keys.length + ") and messages(" + messages.length + ").");
+ }
+ this.numberOfMessages += keys.length;
this.files[original] = [];
- var existingKeys = [];
- for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
- var key = keys_1[_i];
- // Ignore duplicate keys because Transifex does not populate those with translated values.
- if (existingKeys.indexOf(key) !== -1) {
+ var existingKeys = new Set();
+ for (var i = 0; i < keys.length; i++) {
+ var key = keys[i];
+ var realKey = void 0;
+ var comment = void 0;
+ if (Is.string(key)) {
+ realKey = key;
+ comment = undefined;
+ }
+ else if (LocalizeInfo.is(key)) {
+ realKey = key.key;
+ if (key.comment && key.comment.length > 0) {
+ comment = key.comment.map(function (comment) { return encodeEntities(comment); }).join('\r\n');
+ }
+ }
+ if (!realKey || existingKeys.has(realKey)) {
continue;
}
- existingKeys.push(key);
- var message = encodeEntities(messages[keys.indexOf(key)]);
- var comment = undefined;
- // Check if the message contains description (if so, it becomes an object type in JSON)
- if (Is.string(key)) {
- this.files[original].push({ id: key, message: message, comment: comment });
- }
- else {
- if (key['comment'] && key['comment'].length > 0) {
- comment = key['comment'].map(function (comment) { return encodeEntities(comment); }).join('\r\n');
- }
- this.files[original].push({ id: key['key'], message: message, comment: comment });
- }
+ existingKeys.add(realKey);
+ var message = encodeEntities(messages[i]);
+ this.files[original].push({ id: realKey, message: message, comment: comment });
}
};
XLF.prototype.addStringItem = function (item) {
@@ -162,43 +197,70 @@ var XLF = /** @class */ (function () {
line.append(content);
this.buffer.push(line.toString());
};
+ XLF.parsePseudo = function (xlfString) {
+ return new Promise(function (resolve, reject) {
+ var parser = new xml2js.Parser();
+ var files = [];
+ parser.parseString(xlfString, function (err, result) {
+ var fileNodes = result['xliff']['file'];
+ fileNodes.forEach(function (file) {
+ var originalFilePath = file.$.original;
+ var messages = {};
+ var transUnits = file.body[0]['trans-unit'];
+ if (transUnits) {
+ transUnits.forEach(function (unit) {
+ var key = unit.$.id;
+ var val = pseudify(unit.source[0]['_'].toString());
+ if (key && val) {
+ messages[key] = decodeEntities(val);
+ }
+ });
+ files.push({ messages: messages, originalFilePath: originalFilePath, language: 'ps' });
+ }
+ });
+ resolve(files);
+ });
+ });
+ };
XLF.parse = function (xlfString) {
return new Promise(function (resolve, reject) {
var parser = new xml2js.Parser();
var files = [];
parser.parseString(xlfString, function (err, result) {
if (err) {
- reject("Failed to parse XLIFF string. " + err);
+ reject(new Error("XLF parsing error: Failed to parse XLIFF string. " + err));
}
var fileNodes = result['xliff']['file'];
if (!fileNodes) {
- reject('XLIFF file does not contain "xliff" or "file" node(s) required for parsing.');
+ reject(new Error("XLF parsing error: XLIFF file does not contain \"xliff\" or \"file\" node(s) required for parsing."));
}
fileNodes.forEach(function (file) {
var originalFilePath = file.$.original;
if (!originalFilePath) {
- reject('XLIFF file node does not contain original attribute to determine the original location of the resource file.');
+ reject(new Error("XLF parsing error: XLIFF file node does not contain original attribute to determine the original location of the resource file."));
}
- var language = file.$['target-language'].toLowerCase();
+ var language = file.$['target-language'];
if (!language) {
- reject('XLIFF file node does not contain target-language attribute to determine translated language.');
+ reject(new Error("XLF parsing error: XLIFF file node does not contain target-language attribute to determine translated language."));
}
var messages = {};
var transUnits = file.body[0]['trans-unit'];
- transUnits.forEach(function (unit) {
- var key = unit.$.id;
- if (!unit.target) {
- return; // No translation available
- }
- var val = unit.target.toString();
- if (key && val) {
- messages[key] = decodeEntities(val);
- }
- else {
- reject('XLIFF file does not contain full localization data. ID or target translation for one of the trans-unit nodes is not present.');
- }
- });
- files.push({ messages: messages, originalFilePath: originalFilePath, language: language });
+ if (transUnits) {
+ transUnits.forEach(function (unit) {
+ var key = unit.$.id;
+ if (!unit.target) {
+ return; // No translation available
+ }
+ var val = unit.target.toString();
+ if (key && val) {
+ messages[key] = decodeEntities(val);
+ }
+ else {
+ reject(new Error("XLF parsing error: XLIFF file does not contain full localization data. ID or target translation for one of the trans-unit nodes is not present."));
+ }
+ });
+ files.push({ messages: messages, originalFilePath: originalFilePath, language: language.toLowerCase() });
+ }
});
resolve(files);
});
@@ -207,67 +269,39 @@ var XLF = /** @class */ (function () {
return XLF;
}());
exports.XLF = XLF;
-var iso639_3_to_2 = {
- 'chs': 'zh-cn',
- 'cht': 'zh-tw',
- 'csy': 'cs-cz',
- 'deu': 'de',
- 'enu': 'en',
- 'esn': 'es',
- 'fra': 'fr',
- 'hun': 'hu',
- 'ita': 'it',
- 'jpn': 'ja',
- 'kor': 'ko',
- 'nld': 'nl',
- 'plk': 'pl',
- 'ptb': 'pt-br',
- 'ptg': 'pt',
- 'rus': 'ru',
- 'sve': 'sv-se',
- 'trk': 'tr'
-};
-/**
- * Used to map Transifex to VS Code language code representation.
- */
-var iso639_2_to_3 = {
- 'zh-hans': 'chs',
- 'zh-hant': 'cht',
- 'cs-cz': 'csy',
- 'de': 'deu',
- 'en': 'enu',
- 'es': 'esn',
- 'fr': 'fra',
- 'hu': 'hun',
- 'it': 'ita',
- 'ja': 'jpn',
- 'ko': 'kor',
- 'nl': 'nld',
- 'pl': 'plk',
- 'pt-br': 'ptb',
- 'pt': 'ptg',
- 'ru': 'rus',
- 'sv-se': 'sve',
- 'tr': 'trk'
-};
-function sortLanguages(directoryNames) {
- return directoryNames.map(function (dirName) {
- var lower = dirName.toLowerCase();
- return {
- name: lower,
- iso639_2: iso639_3_to_2[lower]
- };
- }).sort(function (a, b) {
- if (!a.iso639_2 && !b.iso639_2) {
- return 0;
+var Limiter = /** @class */ (function () {
+ function Limiter(maxDegreeOfParalellism) {
+ this.maxDegreeOfParalellism = maxDegreeOfParalellism;
+ this.outstandingPromises = [];
+ this.runningPromises = 0;
+ }
+ Limiter.prototype.queue = function (factory) {
+ var _this = this;
+ return new Promise(function (c, e) {
+ _this.outstandingPromises.push({ factory: factory, c: c, e: e });
+ _this.consume();
+ });
+ };
+ Limiter.prototype.consume = function () {
+ var _this = this;
+ while (this.outstandingPromises.length && this.runningPromises < this.maxDegreeOfParalellism) {
+ var iLimitedTask = this.outstandingPromises.shift();
+ this.runningPromises++;
+ var promise = iLimitedTask.factory();
+ promise.then(iLimitedTask.c).catch(iLimitedTask.e);
+ promise.then(function () { return _this.consumed(); }).catch(function () { return _this.consumed(); });
}
- if (!a.iso639_2) {
- return -1;
- }
- if (!b.iso639_2) {
- return 1;
- }
- return a.iso639_2 < b.iso639_2 ? -1 : (a.iso639_2 > b.iso639_2 ? 1 : 0);
+ };
+ Limiter.prototype.consumed = function () {
+ this.runningPromises--;
+ this.consume();
+ };
+ return Limiter;
+}());
+exports.Limiter = Limiter;
+function sortLanguages(languages) {
+ return languages.sort(function (a, b) {
+ return a.id < b.id ? -1 : (a.id > b.id ? 1 : 0);
});
}
function stripComments(content) {
@@ -355,7 +389,7 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) {
defaultMessages[module] = messageMap;
keys.map(function (key, i) {
total++;
- if (Is.string(key)) {
+ if (typeof key === 'string') {
messageMap[key] = messages[i];
}
else {
@@ -364,23 +398,15 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) {
});
});
var languageDirectory = path.join(__dirname, '..', '..', 'i18n');
- var languageDirs;
- if (languages) {
- languageDirs = sortLanguages(languages);
- }
- else {
- languageDirs = sortLanguages(fs.readdirSync(languageDirectory).filter(function (item) { return fs.statSync(path.join(languageDirectory, item)).isDirectory(); }));
- }
- languageDirs.forEach(function (language) {
- if (!language.iso639_2) {
- return;
- }
+ var sortedLanguages = sortLanguages(languages);
+ sortedLanguages.forEach(function (language) {
if (process.env['VSCODE_BUILD_VERBOSE']) {
- log("Generating nls bundles for: " + language.iso639_2);
+ log("Generating nls bundles for: " + language.id);
}
- statistics[language.iso639_2] = 0;
+ statistics[language.id] = 0;
var localizedModules = Object.create(null);
- var cwd = path.join(languageDirectory, language.name, 'src');
+ var languageFolderName = language.folderName || language.id;
+ var cwd = path.join(languageDirectory, languageFolderName, 'src');
modules.forEach(function (module) {
var order = keysSection[module];
var i18nFile = path.join(cwd, module) + '.i18n.json';
@@ -394,12 +420,12 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) {
log("No localized messages found for module " + module + ". Using default messages.");
}
messages = defaultMessages[module];
- statistics[language.iso639_2] = statistics[language.iso639_2] + Object.keys(messages).length;
+ statistics[language.id] = statistics[language.id] + Object.keys(messages).length;
}
var localizedMessages = [];
order.forEach(function (keyInfo) {
var key = null;
- if (Is.string(keyInfo)) {
+ if (typeof keyInfo === 'string') {
key = keyInfo;
}
else {
@@ -411,7 +437,7 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) {
log("No localized message found for key " + key + " in module " + module + ". Using default message.");
}
message = defaultMessages[module][key];
- statistics[language.iso639_2] = statistics[language.iso639_2] + 1;
+ statistics[language.id] = statistics[language.id] + 1;
}
localizedMessages.push(message);
});
@@ -421,7 +447,7 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) {
var modules = bundleSection[bundle];
var contents = [
fileHeader,
- "define(\"" + bundle + ".nls." + language.iso639_2 + "\", {"
+ "define(\"" + bundle + ".nls." + language.id + "\", {"
];
modules.forEach(function (module, index) {
contents.push("\t\"" + module + "\": [");
@@ -436,24 +462,17 @@ function processCoreBundleFormat(fileHeader, languages, json, emitter) {
contents.push(index < modules.length - 1 ? '\t],' : '\t]');
});
contents.push('});');
- emitter.emit('data', new File({ path: bundle + '.nls.' + language.iso639_2 + '.js', contents: new Buffer(contents.join('\n'), 'utf-8') }));
+ emitter.queue(new File({ path: bundle + '.nls.' + language.id + '.js', contents: Buffer.from(contents.join('\n'), 'utf-8') }));
});
});
Object.keys(statistics).forEach(function (key) {
var value = statistics[key];
log(key + " has " + value + " untranslated strings.");
});
- languageDirs.forEach(function (dir) {
- var language = dir.name;
- var iso639_2 = iso639_3_to_2[language];
- if (!iso639_2) {
- log("\tCouldn't find iso639 2 mapping for language " + language + ". Using default language instead.");
- }
- else {
- var stats = statistics[iso639_2];
- if (Is.undef(stats)) {
- log("\tNo translations found for language " + language + ". Using default language instead.");
- }
+ sortedLanguages.forEach(function (language) {
+ var stats = statistics[language.id];
+ if (Is.undef(stats)) {
+ log("\tNo translations found for language " + language.id + ". Using default language instead.");
}
});
}
@@ -467,39 +486,16 @@ function processNlsFiles(opts) {
}
else {
this.emit('error', "Failed to read component file: " + file.relative);
+ return;
}
if (BundledFormat.is(json)) {
processCoreBundleFormat(opts.fileHeader, opts.languages, json, this);
}
}
- this.emit('data', file);
+ this.queue(file);
});
}
exports.processNlsFiles = processNlsFiles;
-function prepareXlfFiles(projectName, extensionName) {
- return event_stream_1.through(function (file) {
- if (!file.isBuffer()) {
- throw new Error("Failed to read component file: " + file.relative);
- }
- var extension = path.extname(file.path);
- if (extension === '.json') {
- var json = JSON.parse(file.contents.toString('utf8'));
- if (BundledFormat.is(json)) {
- importBundleJson(file, json, this);
- }
- else if (PackageJsonFormat.is(json) || ModuleJsonFormat.is(json)) {
- importModuleOrPackageJson(file, json, projectName, this, extensionName);
- }
- else {
- throw new Error("JSON format cannot be deduced for " + file.relative + ".");
- }
- }
- else if (extension === '.isl') {
- importIsl(file, this);
- }
- });
-}
-exports.prepareXlfFiles = prepareXlfFiles;
var editorProject = 'vscode-editor', workbenchProject = 'vscode-workbench', extensionsProject = 'vscode-extensions', setupProject = 'vscode-setup';
// {{SQL CARBON EDIT}}
var sqlopsProject = 'sqlops-core';
@@ -537,113 +533,186 @@ function getResource(sourceFile) {
throw new Error("Could not identify the XLF bundle for " + sourceFile);
}
exports.getResource = getResource;
-function importBundleJson(file, json, stream) {
- var bundleXlfs = Object.create(null);
- for (var source in json.keys) {
- var projectResource = getResource(source);
- var resource = projectResource.name;
- var project = projectResource.project;
- var keys = json.keys[source];
- var messages = json.messages[source];
- if (keys.length !== messages.length) {
- throw new Error("There is a mismatch between keys and messages in " + file.relative);
- }
- var xlf = bundleXlfs[resource] ? bundleXlfs[resource] : bundleXlfs[resource] = new XLF(project);
- xlf.addFile('src/' + source, keys, messages);
- }
- for (var resource in bundleXlfs) {
- var newFilePath = bundleXlfs[resource].project + "/" + resource.replace(/\//g, '_') + ".xlf";
- var xlfFile = new File({ path: newFilePath, contents: new Buffer(bundleXlfs[resource].toString(), 'utf-8') });
- stream.emit('data', xlfFile);
- }
-}
-// Keeps existing XLF instances and a state of how many files were already processed for faster file emission
-var extensions = Object.create(null);
-function importModuleOrPackageJson(file, json, projectName, stream, extensionName) {
- if (ModuleJsonFormat.is(json) && json['keys'].length !== json['messages'].length) {
- throw new Error("There is a mismatch between keys and messages in " + file.relative);
- }
- // Prepare the source path for attribute in XLF & extract messages from JSON
- var formattedSourcePath = file.relative.replace(/\\/g, '/');
- var messages = Object.keys(json).map(function (key) { return json[key].toString(); });
- // Stores the amount of localization files to be transformed to XLF before the emission
- var localizationFilesCount, originalFilePath;
- // If preparing XLF for external extension, then use different glob pattern and source path
- if (extensionName) {
- localizationFilesCount = glob.sync('**/*.nls.json').length;
- originalFilePath = "" + formattedSourcePath.substr(0, formattedSourcePath.length - '.nls.json'.length);
- }
- else {
- // Used for vscode/extensions folder
- extensionName = formattedSourcePath.split('/')[0];
- localizationFilesCount = glob.sync("./extensions/" + extensionName + "/**/*.nls.json").length;
- originalFilePath = "extensions/" + formattedSourcePath.substr(0, formattedSourcePath.length - '.nls.json'.length);
- }
- var extension = extensions[extensionName] ?
- extensions[extensionName] : extensions[extensionName] = { xlf: new XLF(projectName), processed: 0 };
- // .nls.json can come with empty array of keys and messages, check for it
- if (ModuleJsonFormat.is(json) && json.keys.length !== 0) {
- extension.xlf.addFile(originalFilePath, json.keys, json.messages);
- }
- else if (PackageJsonFormat.is(json) && Object.keys(json).length !== 0) {
- extension.xlf.addFile(originalFilePath, Object.keys(json), messages);
- }
- // Check if XLF is populated with file nodes to emit it
- if (++extensions[extensionName].processed === localizationFilesCount) {
- var newFilePath = path.join(projectName, extensionName + '.xlf');
- var xlfFile = new File({ path: newFilePath, contents: new Buffer(extension.xlf.toString(), 'utf-8') });
- stream.emit('data', xlfFile);
- }
-}
-function importIsl(file, stream) {
- var projectName, resourceFile;
- if (path.basename(file.path) === 'Default.isl') {
- projectName = setupProject;
- resourceFile = 'setup_default.xlf';
- }
- else {
- projectName = workbenchProject;
- resourceFile = 'setup_messages.xlf';
- }
- var xlf = new XLF(projectName), keys = [], messages = [];
- var model = new TextModel(file.contents.toString());
- var inMessageSection = false;
- model.lines.forEach(function (line) {
- if (line.length === 0) {
- return;
- }
- var firstChar = line.charAt(0);
- switch (firstChar) {
- case ';':
- // Comment line;
+function createXlfFilesForCoreBundle() {
+ return event_stream_1.through(function (file) {
+ var basename = path.basename(file.path);
+ if (basename === 'nls.metadata.json') {
+ if (file.isBuffer()) {
+ var xlfs = Object.create(null);
+ var json = JSON.parse(file.contents.toString('utf8'));
+ for (var coreModule in json.keys) {
+ var projectResource = getResource(coreModule);
+ var resource = projectResource.name;
+ var project = projectResource.project;
+ var keys = json.keys[coreModule];
+ var messages = json.messages[coreModule];
+ if (keys.length !== messages.length) {
+ this.emit('error', "There is a mismatch between keys and messages in " + file.relative + " for module " + coreModule);
+ return;
+ }
+ else {
+ var xlf = xlfs[resource];
+ if (!xlf) {
+ xlf = new XLF(project);
+ xlfs[resource] = xlf;
+ }
+ xlf.addFile("src/" + coreModule, keys, messages);
+ }
+ }
+ for (var resource in xlfs) {
+ var xlf = xlfs[resource];
+ var filePath = xlf.project + "/" + resource.replace(/\//g, '_') + ".xlf";
+ var xlfFile = new File({
+ path: filePath,
+ contents: Buffer.from(xlf.toString(), 'utf8')
+ });
+ this.queue(xlfFile);
+ }
+ }
+ else {
+ this.emit('error', new Error("File " + file.relative + " is not using a buffer content"));
return;
- case '[':
- inMessageSection = '[Messages]' === line || '[CustomMessages]' === line;
- return;
- }
- if (!inMessageSection) {
- return;
- }
- var sections = line.split('=');
- if (sections.length !== 2) {
- throw new Error("Badly formatted message found: " + line);
- }
- else {
- var key = sections[0];
- var value = sections[1];
- if (key.length > 0 && value.length > 0) {
- keys.push(key);
- messages.push(value);
}
}
+ else {
+ this.emit('error', new Error("File " + file.relative + " is not a core meta data file."));
+ return;
+ }
});
- var originalPath = file.path.substring(file.cwd.length + 1, file.path.split('.')[0].length).replace(/\\/g, '/');
- xlf.addFile(originalPath, keys, messages);
- // Emit only upon all ISL files combined into single XLF instance
- var newFilePath = path.join(projectName, resourceFile);
- var xlfFile = new File({ path: newFilePath, contents: new Buffer(xlf.toString(), 'utf-8') });
- stream.emit('data', xlfFile);
}
+exports.createXlfFilesForCoreBundle = createXlfFilesForCoreBundle;
+function createXlfFilesForExtensions() {
+ var counter = 0;
+ var folderStreamEnded = false;
+ var folderStreamEndEmitted = false;
+ return event_stream_1.through(function (extensionFolder) {
+ var folderStream = this;
+ var stat = fs.statSync(extensionFolder.path);
+ if (!stat.isDirectory()) {
+ return;
+ }
+ var extensionName = path.basename(extensionFolder.path);
+ if (extensionName === 'node_modules') {
+ return;
+ }
+ counter++;
+ var _xlf;
+ function getXlf() {
+ if (!_xlf) {
+ _xlf = new XLF(extensionsProject);
+ }
+ return _xlf;
+ }
+ gulp.src(["./extensions/" + extensionName + "/package.nls.json", "./extensions/" + extensionName + "/**/nls.metadata.json"]).pipe(event_stream_1.through(function (file) {
+ if (file.isBuffer()) {
+ var buffer = file.contents;
+ var basename = path.basename(file.path);
+ if (basename === 'package.nls.json') {
+ var json_1 = JSON.parse(buffer.toString('utf8'));
+ var keys = Object.keys(json_1);
+ var messages = keys.map(function (key) {
+ var value = json_1[key];
+ if (Is.string(value)) {
+ return value;
+ }
+ else if (value) {
+ return value.message;
+ }
+ else {
+ return "Unknown message for key: " + key;
+ }
+ });
+ getXlf().addFile("extensions/" + extensionName + "/package", keys, messages);
+ }
+ else if (basename === 'nls.metadata.json') {
+ var json = JSON.parse(buffer.toString('utf8'));
+ var relPath = path.relative("./extensions/" + extensionName, path.dirname(file.path));
+ for (var file_1 in json) {
+ var fileContent = json[file_1];
+ getXlf().addFile("extensions/" + extensionName + "/" + relPath + "/" + file_1, fileContent.keys, fileContent.messages);
+ }
+ }
+ else {
+ this.emit('error', new Error(file.path + " is not a valid extension nls file"));
+ return;
+ }
+ }
+ }, function () {
+ if (_xlf) {
+ var xlfFile = new File({
+ path: path.join(extensionsProject, extensionName + '.xlf'),
+ contents: Buffer.from(_xlf.toString(), 'utf8')
+ });
+ folderStream.queue(xlfFile);
+ }
+ this.queue(null);
+ counter--;
+ if (counter === 0 && folderStreamEnded && !folderStreamEndEmitted) {
+ folderStreamEndEmitted = true;
+ folderStream.queue(null);
+ }
+ }));
+ }, function () {
+ folderStreamEnded = true;
+ if (counter === 0) {
+ folderStreamEndEmitted = true;
+ this.queue(null);
+ }
+ });
+}
+exports.createXlfFilesForExtensions = createXlfFilesForExtensions;
+function createXlfFilesForIsl() {
+ return event_stream_1.through(function (file) {
+ var projectName, resourceFile;
+ if (path.basename(file.path) === 'Default.isl') {
+ projectName = setupProject;
+ resourceFile = 'setup_default.xlf';
+ }
+ else {
+ projectName = workbenchProject;
+ resourceFile = 'setup_messages.xlf';
+ }
+ var xlf = new XLF(projectName), keys = [], messages = [];
+ var model = new TextModel(file.contents.toString());
+ var inMessageSection = false;
+ model.lines.forEach(function (line) {
+ if (line.length === 0) {
+ return;
+ }
+ var firstChar = line.charAt(0);
+ switch (firstChar) {
+ case ';':
+ // Comment line;
+ return;
+ case '[':
+ inMessageSection = '[Messages]' === line || '[CustomMessages]' === line;
+ return;
+ }
+ if (!inMessageSection) {
+ return;
+ }
+ var sections = line.split('=');
+ if (sections.length !== 2) {
+ throw new Error("Badly formatted message found: " + line);
+ }
+ else {
+ var key = sections[0];
+ var value = sections[1];
+ if (key.length > 0 && value.length > 0) {
+ keys.push(key);
+ messages.push(value);
+ }
+ }
+ });
+ var originalPath = file.path.substring(file.cwd.length + 1, file.path.split('.')[0].length).replace(/\\/g, '/');
+ xlf.addFile(originalPath, keys, messages);
+ // Emit only upon all ISL files combined into single XLF instance
+ var newFilePath = path.join(projectName, resourceFile);
+ var xlfFile = new File({ path: newFilePath, contents: Buffer.from(xlf.toString(), 'utf-8') });
+ this.queue(xlfFile);
+ });
+}
+exports.createXlfFilesForIsl = createXlfFilesForIsl;
function pushXlfFiles(apiHostname, username, password) {
var tryGetPromises = [];
var updateCreatePromises = [];
@@ -669,12 +738,94 @@ function pushXlfFiles(apiHostname, username, password) {
// End the pipe only after all the communication with Transifex API happened
Promise.all(tryGetPromises).then(function () {
Promise.all(updateCreatePromises).then(function () {
- _this.emit('end');
+ _this.queue(null);
}).catch(function (reason) { throw new Error(reason); });
}).catch(function (reason) { throw new Error(reason); });
});
}
exports.pushXlfFiles = pushXlfFiles;
+function getAllResources(project, apiHostname, username, password) {
+ return new Promise(function (resolve, reject) {
+ var credentials = username + ":" + password;
+ var options = {
+ hostname: apiHostname,
+ path: "/api/2/project/" + project + "/resources",
+ auth: credentials,
+ method: 'GET'
+ };
+ var request = https.request(options, function (res) {
+ var buffer = [];
+ res.on('data', function (chunk) { return buffer.push(chunk); });
+ res.on('end', function () {
+ if (res.statusCode === 200) {
+ var json = JSON.parse(Buffer.concat(buffer).toString());
+ if (Array.isArray(json)) {
+ resolve(json.map(function (o) { return o.slug; }));
+ return;
+ }
+ reject("Unexpected data format. Response code: " + res.statusCode + ".");
+ }
+ else {
+ reject("No resources in " + project + " returned no data. Response code: " + res.statusCode + ".");
+ }
+ });
+ });
+ request.on('error', function (err) {
+ reject("Failed to query resources in " + project + " with the following error: " + err + ". " + options.path);
+ });
+ request.end();
+ });
+}
+function findObsoleteResources(apiHostname, username, password) {
+ var resourcesByProject = Object.create(null);
+ resourcesByProject[extensionsProject] = [].concat(externalExtensionsWithTranslations); // clone
+ return event_stream_1.through(function (file) {
+ var project = path.dirname(file.relative);
+ var fileName = path.basename(file.path);
+ var slug = fileName.substr(0, fileName.length - '.xlf'.length);
+ var slugs = resourcesByProject[project];
+ if (!slugs) {
+ resourcesByProject[project] = slugs = [];
+ }
+ slugs.push(slug);
+ this.push(file);
+ }, function () {
+ var _this = this;
+ var json = JSON.parse(fs.readFileSync('./build/lib/i18n.resources.json', 'utf8'));
+ var i18Resources = json.editor.concat(json.workbench).map(function (r) { return r.project + '/' + r.name.replace(/\//g, '_'); });
+ var extractedResources = [];
+ for (var _i = 0, _a = [workbenchProject, editorProject]; _i < _a.length; _i++) {
+ var project = _a[_i];
+ for (var _b = 0, _c = resourcesByProject[project]; _b < _c.length; _b++) {
+ var resource = _c[_b];
+ if (resource !== 'setup_messages') {
+ extractedResources.push(project + '/' + resource);
+ }
+ }
+ }
+ if (i18Resources.length !== extractedResources.length) {
+ console.log("[i18n] Obsolete resources in file 'build/lib/i18n.resources.json': JSON.stringify(" + i18Resources.filter(function (p) { return extractedResources.indexOf(p) === -1; }) + ")");
+ console.log("[i18n] Missing resources in file 'build/lib/i18n.resources.json': JSON.stringify(" + extractedResources.filter(function (p) { return i18Resources.indexOf(p) === -1; }) + ")");
+ }
+ var promises = [];
+ var _loop_1 = function (project) {
+ promises.push(getAllResources(project, apiHostname, username, password).then(function (resources) {
+ var expectedResources = resourcesByProject[project];
+ var unusedResources = resources.filter(function (resource) { return resource && expectedResources.indexOf(resource) === -1; });
+ if (unusedResources.length) {
+ console.log("[transifex] Obsolete resources in project '" + project + "': " + unusedResources.join(', '));
+ }
+ }));
+ };
+ for (var project in resourcesByProject) {
+ _loop_1(project);
+ }
+ return Promise.all(promises).then(function (_) {
+ _this.push(null);
+ }).catch(function (reason) { throw new Error(reason); });
+ });
+}
+exports.findObsoleteResources = findObsoleteResources;
function tryGetResource(project, slug, apiHostname, credentials) {
return new Promise(function (resolve, reject) {
var options = {
@@ -774,40 +925,42 @@ function updateResource(project, slug, xlfFile, apiHostname, credentials) {
request.end();
});
}
-function obtainProjectResources(projectName) {
- var resources = [];
- if (projectName === editorProject) {
- var json = fs.readFileSync('./build/lib/i18n.resources.json', 'utf8');
- resources = JSON.parse(json).editor;
- }
- else if (projectName === workbenchProject) {
- var json = fs.readFileSync('./build/lib/i18n.resources.json', 'utf8');
- resources = JSON.parse(json).workbench;
- }
- else if (projectName === extensionsProject) {
- var extensionsToLocalize = glob.sync('./extensions/**/*.nls.json').map(function (extension) { return extension.split('/')[2]; });
- var resourcesToPull_1 = [];
- extensionsToLocalize.forEach(function (extension) {
- if (resourcesToPull_1.indexOf(extension) === -1) {
- resourcesToPull_1.push(extension);
- resources.push({ name: extension, project: projectName });
- }
+// cache resources
+var _coreAndExtensionResources;
+function pullCoreAndExtensionsXlfFiles(apiHostname, username, password, language, externalExtensions) {
+ if (!_coreAndExtensionResources) {
+ _coreAndExtensionResources = [];
+ // editor and workbench
+ var json = JSON.parse(fs.readFileSync('./build/lib/i18n.resources.json', 'utf8'));
+ _coreAndExtensionResources.push.apply(_coreAndExtensionResources, json.editor);
+ _coreAndExtensionResources.push.apply(_coreAndExtensionResources, json.workbench);
+ // extensions
+ var extensionsToLocalize_1 = Object.create(null);
+ glob.sync('./extensions/**/*.nls.json').forEach(function (extension) { return extensionsToLocalize_1[extension.split('/')[2]] = true; });
+ glob.sync('./extensions/*/node_modules/vscode-nls').forEach(function (extension) { return extensionsToLocalize_1[extension.split('/')[2]] = true; });
+ Object.keys(extensionsToLocalize_1).forEach(function (extension) {
+ _coreAndExtensionResources.push({ name: extension, project: extensionsProject });
});
+ if (externalExtensions) {
+ for (var resourceName in externalExtensions) {
+ _coreAndExtensionResources.push({ name: resourceName, project: extensionsProject });
+ }
+ }
}
- else if (projectName === setupProject) {
- resources.push({ name: 'setup_default', project: setupProject });
- }
- return resources;
+ return pullXlfFiles(apiHostname, username, password, language, _coreAndExtensionResources);
}
-function pullXlfFiles(projectName, apiHostname, username, password, languages, resources) {
- if (!resources) {
- resources = obtainProjectResources(projectName);
- }
- if (!resources) {
- throw new Error('Transifex projects and resources must be defined to be able to pull translations from Transifex.');
+exports.pullCoreAndExtensionsXlfFiles = pullCoreAndExtensionsXlfFiles;
+function pullSetupXlfFiles(apiHostname, username, password, language, includeDefault) {
+ var setupResources = [{ name: 'setup_messages', project: workbenchProject }];
+ if (includeDefault) {
+ setupResources.push({ name: 'setup_default', project: setupProject });
}
+ return pullXlfFiles(apiHostname, username, password, language, setupResources);
+}
+exports.pullSetupXlfFiles = pullSetupXlfFiles;
+function pullXlfFiles(apiHostname, username, password, language, resources) {
var credentials = username + ":" + password;
- var expectedTranslationsCount = languages.length * resources.length;
+ var expectedTranslationsCount = resources.length;
var translationsRetrieved = 0, called = false;
return event_stream_1.readable(function (count, callback) {
// Mark end of stream when all resources were retrieved
@@ -817,48 +970,55 @@ function pullXlfFiles(projectName, apiHostname, username, password, languages, r
if (!called) {
called = true;
var stream_1 = this;
- // Retrieve XLF files from main projects
- languages.map(function (language) {
- resources.map(function (resource) {
- retrieveResource(language, resource, apiHostname, credentials).then(function (file) {
+ resources.map(function (resource) {
+ retrieveResource(language, resource, apiHostname, credentials).then(function (file) {
+ if (file) {
stream_1.emit('data', file);
- translationsRetrieved++;
- }).catch(function (error) { throw new Error(error); });
- });
+ }
+ translationsRetrieved++;
+ }).catch(function (error) { throw new Error(error); });
});
}
callback();
});
}
-exports.pullXlfFiles = pullXlfFiles;
+var limiter = new Limiter(NUMBER_OF_CONCURRENT_DOWNLOADS);
function retrieveResource(language, resource, apiHostname, credentials) {
- return new Promise(function (resolve, reject) {
+ return limiter.queue(function () { return new Promise(function (resolve, reject) {
var slug = resource.name.replace(/\//g, '_');
var project = resource.project;
- var iso639 = language.toLowerCase();
+ var transifexLanguageId = language.id === 'ps' ? 'en' : language.transifexId || language.id;
var options = {
hostname: apiHostname,
- path: "/api/2/project/" + project + "/resource/" + slug + "/translation/" + iso639 + "?file&mode=onlyreviewed",
+ path: "/api/2/project/" + project + "/resource/" + slug + "/translation/" + transifexLanguageId + "?file&mode=onlyreviewed",
auth: credentials,
+ port: 443,
method: 'GET'
};
+ console.log('[transifex] Fetching ' + options.path);
var request = https.request(options, function (res) {
var xlfBuffer = [];
res.on('data', function (chunk) { return xlfBuffer.push(chunk); });
res.on('end', function () {
if (res.statusCode === 200) {
- resolve(new File({ contents: Buffer.concat(xlfBuffer), path: project + "/" + iso639_2_to_3[language] + "/" + slug + ".xlf" }));
+ resolve(new File({ contents: Buffer.concat(xlfBuffer), path: project + "/" + slug + ".xlf" }));
+ }
+ else if (res.statusCode === 404) {
+ console.log("[transifex] " + slug + " in " + project + " returned no data.");
+ resolve(null);
+ }
+ else {
+ reject(slug + " in " + project + " returned no data. Response code: " + res.statusCode + ".");
}
- reject(slug + " in " + project + " returned no data. Response code: " + res.statusCode + ".");
});
});
request.on('error', function (err) {
- reject("Failed to query resource " + slug + " with the following error: " + err);
+ reject("Failed to query resource " + slug + " with the following error: " + err + ". " + options.path);
});
request.end();
- });
+ }); });
}
-function prepareJsonFiles() {
+function prepareI18nFiles() {
var parsePromises = [];
return event_stream_1.through(function (xlf) {
var stream = this;
@@ -866,69 +1026,126 @@ function prepareJsonFiles() {
parsePromises.push(parsePromise);
parsePromise.then(function (resolvedFiles) {
resolvedFiles.forEach(function (file) {
- var messages = file.messages, translatedFile;
- // ISL file path always starts with 'build/'
- if (/^build\//.test(file.originalFilePath)) {
- var defaultLanguages = { 'zh-hans': true, 'zh-hant': true, 'ko': true };
- if (path.basename(file.originalFilePath) === 'Default' && !defaultLanguages[file.language]) {
- return;
- }
- translatedFile = createIslFile('..', file.originalFilePath, messages, iso639_2_to_3[file.language]);
- }
- else {
- translatedFile = createI18nFile(iso639_2_to_3[file.language], file.originalFilePath, messages);
- }
- stream.emit('data', translatedFile);
+ var translatedFile = createI18nFile(file.originalFilePath, file.messages);
+ stream.queue(translatedFile);
});
- }, function (rejectReason) {
- throw new Error("XLF parsing error: " + rejectReason);
});
}, function () {
var _this = this;
Promise.all(parsePromises)
- .then(function () { _this.emit('end'); })
+ .then(function () { _this.queue(null); })
.catch(function (reason) { throw new Error(reason); });
});
}
-exports.prepareJsonFiles = prepareJsonFiles;
-function createI18nFile(base, originalFilePath, messages) {
- var content = [
- '/*---------------------------------------------------------------------------------------------',
- ' * Copyright (c) Microsoft Corporation. All rights reserved.',
- ' * Licensed under the Source EULA. See License.txt in the project root for license information.',
- ' *--------------------------------------------------------------------------------------------*/',
- '// Do not edit this file. It is machine generated.'
- ].join('\n') + '\n' + JSON.stringify(messages, null, '\t').replace(/\r\n/g, '\n');
+exports.prepareI18nFiles = prepareI18nFiles;
+function createI18nFile(originalFilePath, messages) {
+ var result = Object.create(null);
+ result[''] = [
+ '--------------------------------------------------------------------------------------------',
+ 'Copyright (c) Microsoft Corporation. All rights reserved.',
+ 'Licensed under the Source EULA. See License.txt in the project root for license information.',
+ '--------------------------------------------------------------------------------------------',
+ 'Do not edit this file. It is machine generated.'
+ ];
+ for (var _i = 0, _a = Object.keys(messages); _i < _a.length; _i++) {
+ var key = _a[_i];
+ result[key] = messages[key];
+ }
+ var content = JSON.stringify(result, null, '\t').replace(/\r\n/g, '\n');
return new File({
- path: path.join(base, originalFilePath + '.i18n.json'),
- contents: new Buffer(content, 'utf8')
+ path: path.join(originalFilePath + '.i18n.json'),
+ contents: Buffer.from(content, 'utf8')
});
}
-var languageNames = {
- 'chs': 'Simplified Chinese',
- 'cht': 'Traditional Chinese',
- 'kor': 'Korean'
-};
-var languageIds = {
- 'chs': '$0804',
- 'cht': '$0404',
- 'kor': '$0412'
-};
-var encodings = {
- 'chs': 'CP936',
- 'cht': 'CP950',
- 'jpn': 'CP932',
- 'kor': 'CP949',
- 'deu': 'CP1252',
- 'fra': 'CP1252',
- 'esn': 'CP1252',
- 'rus': 'CP1251',
- 'ita': 'CP1252',
- 'ptb': 'CP1252',
- 'hun': 'CP1250',
- 'trk': 'CP1254'
-};
-function createIslFile(base, originalFilePath, messages, language) {
+var i18nPackVersion = "1.0.0";
+function pullI18nPackFiles(apiHostname, username, password, language, resultingTranslationPaths) {
+ return pullCoreAndExtensionsXlfFiles(apiHostname, username, password, language, externalExtensionsWithTranslations)
+ .pipe(prepareI18nPackFiles(externalExtensionsWithTranslations, resultingTranslationPaths, language.id === 'ps'));
+}
+exports.pullI18nPackFiles = pullI18nPackFiles;
+function prepareI18nPackFiles(externalExtensions, resultingTranslationPaths, pseudo) {
+ if (pseudo === void 0) { pseudo = false; }
+ var parsePromises = [];
+ var mainPack = { version: i18nPackVersion, contents: {} };
+ var extensionsPacks = {};
+ return event_stream_1.through(function (xlf) {
+ var stream = this;
+ var project = path.dirname(xlf.path);
+ var resource = path.basename(xlf.path, '.xlf');
+ var contents = xlf.contents.toString();
+ var parsePromise = pseudo ? XLF.parsePseudo(contents) : XLF.parse(contents);
+ parsePromises.push(parsePromise);
+ parsePromise.then(function (resolvedFiles) {
+ resolvedFiles.forEach(function (file) {
+ var path = file.originalFilePath;
+ var firstSlash = path.indexOf('/');
+ if (project === extensionsProject) {
+ var extPack = extensionsPacks[resource];
+ if (!extPack) {
+ extPack = extensionsPacks[resource] = { version: i18nPackVersion, contents: {} };
+ }
+ var externalId = externalExtensions[resource];
+ if (!externalId) {
+ var secondSlash = path.indexOf('/', firstSlash + 1);
+ extPack.contents[path.substr(secondSlash + 1)] = file.messages;
+ }
+ else {
+ extPack.contents[path] = file.messages;
+ }
+ }
+ else {
+ mainPack.contents[path.substr(firstSlash + 1)] = file.messages;
+ }
+ });
+ });
+ }, function () {
+ var _this = this;
+ Promise.all(parsePromises)
+ .then(function () {
+ var translatedMainFile = createI18nFile('./main', mainPack);
+ resultingTranslationPaths.push({ id: 'vscode', resourceName: 'main.i18n.json' });
+ _this.queue(translatedMainFile);
+ for (var extension in extensionsPacks) {
+ var translatedExtFile = createI18nFile("./extensions/" + extension, extensionsPacks[extension]);
+ _this.queue(translatedExtFile);
+ var externalExtensionId = externalExtensions[extension];
+ if (externalExtensionId) {
+ resultingTranslationPaths.push({ id: externalExtensionId, resourceName: "extensions/" + extension + ".i18n.json" });
+ }
+ else {
+ resultingTranslationPaths.push({ id: "vscode." + extension, resourceName: "extensions/" + extension + ".i18n.json" });
+ }
+ }
+ _this.queue(null);
+ })
+ .catch(function (reason) { throw new Error(reason); });
+ });
+}
+exports.prepareI18nPackFiles = prepareI18nPackFiles;
+function prepareIslFiles(language, innoSetupConfig) {
+ var parsePromises = [];
+ return event_stream_1.through(function (xlf) {
+ var stream = this;
+ var parsePromise = XLF.parse(xlf.contents.toString());
+ parsePromises.push(parsePromise);
+ parsePromise.then(function (resolvedFiles) {
+ resolvedFiles.forEach(function (file) {
+ if (path.basename(file.originalFilePath) === 'Default' && !innoSetupConfig.defaultInfo) {
+ return;
+ }
+ var translatedFile = createIslFile(file.originalFilePath, file.messages, language, innoSetupConfig);
+ stream.queue(translatedFile);
+ });
+ });
+ }, function () {
+ var _this = this;
+ Promise.all(parsePromises)
+ .then(function () { _this.queue(null); })
+ .catch(function (reason) { throw new Error(reason); });
+ });
+}
+exports.prepareIslFiles = prepareIslFiles;
+function createIslFile(originalFilePath, messages, language, innoSetup) {
var content = [];
var originalContent;
if (path.basename(originalFilePath) === 'Default') {
@@ -942,7 +1159,7 @@ function createIslFile(base, originalFilePath, messages, language) {
var firstChar = line.charAt(0);
if (firstChar === '[' || firstChar === ';') {
if (line === '; *** Inno Setup version 5.5.3+ English messages ***') {
- content.push("; *** Inno Setup version 5.5.3+ " + languageNames[language] + " messages ***");
+ content.push("; *** Inno Setup version 5.5.3+ " + innoSetup.defaultInfo.name + " messages ***");
}
else {
content.push(line);
@@ -954,13 +1171,13 @@ function createIslFile(base, originalFilePath, messages, language) {
var translated = line;
if (key) {
if (key === 'LanguageName') {
- translated = key + "=" + languageNames[language];
+ translated = key + "=" + innoSetup.defaultInfo.name;
}
else if (key === 'LanguageID') {
- translated = key + "=" + languageIds[language];
+ translated = key + "=" + innoSetup.defaultInfo.id;
}
else if (key === 'LanguageCodePage') {
- translated = key + "=" + encodings[language].substr(2);
+ translated = key + "=" + innoSetup.codePage.substr(2);
}
else {
var translatedMessage = messages[key];
@@ -973,12 +1190,11 @@ function createIslFile(base, originalFilePath, messages, language) {
}
}
});
- var tag = iso639_3_to_2[language];
var basename = path.basename(originalFilePath);
- var filePath = path.join(base, path.dirname(originalFilePath), basename) + "." + tag + ".isl";
+ var filePath = basename + "." + language.id + ".isl";
return new File({
path: filePath,
- contents: iconv.encode(new Buffer(content.join('\r\n'), 'utf8'), encodings[language])
+ contents: iconv.encode(Buffer.from(content.join('\r\n'), 'utf8'), innoSetup.codePage)
});
}
function encodeEntities(value) {
@@ -1004,3 +1220,6 @@ function encodeEntities(value) {
function decodeEntities(value) {
return value.replace(/</g, '<').replace(/>/g, '>').replace(/&/g, '&');
}
+function pseudify(message) {
+ return '\uFF3B' + message.replace(/[aouei]/g, '$&$&') + '\uFF3D';
+}
diff --git a/build/lib/i18n.resources.json b/build/lib/i18n.resources.json
index 0e4c15c740..56fab72bd5 100644
--- a/build/lib/i18n.resources.json
+++ b/build/lib/i18n.resources.json
@@ -46,10 +46,6 @@
"name": "vs/workbench/parts/execution",
"project": "vscode-workbench"
},
- {
- "name": "vs/workbench/parts/explorers",
- "project": "vscode-workbench"
- },
{
"name": "vs/workbench/parts/extensions",
"project": "vscode-workbench"
@@ -71,7 +67,11 @@
"project": "vscode-workbench"
},
{
- "name": "vs/workbench/parts/nps",
+ "name": "vs/workbench/parts/localizations",
+ "project": "vscode-workbench"
+ },
+ {
+ "name": "vs/workbench/parts/logs",
"project": "vscode-workbench"
},
{
@@ -138,6 +138,10 @@
"name": "vs/workbench/parts/welcome",
"project": "vscode-workbench"
},
+ {
+ "name": "vs/workbench/services/actions",
+ "project": "vscode-workbench"
+ },
{
"name": "vs/workbench/services/configuration",
"project": "vscode-workbench"
@@ -146,6 +150,10 @@
"name": "vs/workbench/services/crashReporter",
"project": "vscode-workbench"
},
+ {
+ "name": "vs/workbench/services/dialogs",
+ "project": "vscode-workbench"
+ },
{
"name": "vs/workbench/services/editor",
"project": "vscode-workbench"
@@ -154,6 +162,10 @@
"name": "vs/workbench/services/extensions",
"project": "vscode-workbench"
},
+ {
+ "name": "vs/workbench/services/jsonschemas",
+ "project": "vscode-workbench"
+ },
{
"name": "vs/workbench/services/files",
"project": "vscode-workbench"
@@ -162,10 +174,6 @@
"name": "vs/workbench/services/keybinding",
"project": "vscode-workbench"
},
- {
- "name": "vs/workbench/services/message",
- "project": "vscode-workbench"
- },
{
"name": "vs/workbench/services/mode",
"project": "vscode-workbench"
@@ -193,10 +201,6 @@
{
"name": "vs/workbench/services/decorations",
"project": "vscode-workbench"
- },
- {
- "name": "setup_messages",
- "project": "vscode-workbench"
}
]
-}
+}
\ No newline at end of file
diff --git a/build/lib/i18n.ts b/build/lib/i18n.ts
index d0780c5fbb..e9a62ecfe9 100644
--- a/build/lib/i18n.ts
+++ b/build/lib/i18n.ts
@@ -6,21 +6,64 @@
import * as path from 'path';
import * as fs from 'fs';
-import { through, readable } from 'event-stream';
-import { ThroughStream } from 'through';
+import { through, readable, ThroughStream } from 'event-stream';
import File = require('vinyl');
import * as Is from 'is';
import * as xml2js from 'xml2js';
import * as glob from 'glob';
import * as https from 'https';
+import * as gulp from 'gulp';
var util = require('gulp-util');
var iconv = require('iconv-lite');
+const NUMBER_OF_CONCURRENT_DOWNLOADS = 4;
+
function log(message: any, ...rest: any[]): void {
util.log(util.colors.green('[i18n]'), message, ...rest);
}
+export interface Language {
+ id: string; // laguage id, e.g. zh-tw, de
+ transifexId?: string; // language id used in transifex, e.g zh-hant, de (optional, if not set, the id is used)
+ folderName?: string; // language specific folder name, e.g. cht, deu (optional, if not set, the id is used)
+}
+
+export interface InnoSetup {
+ codePage: string; //code page for encoding (http://www.jrsoftware.org/ishelp/index.php?topic=langoptionssection)
+ defaultInfo?: {
+ name: string; // inno setup language name
+ id: string; // locale identifier (https://msdn.microsoft.com/en-us/library/dd318693.aspx)
+ };
+}
+
+export const defaultLanguages: Language[] = [
+ { id: 'zh-tw', folderName: 'cht', transifexId: 'zh-hant' },
+ { id: 'zh-cn', folderName: 'chs', transifexId: 'zh-hans' },
+ { id: 'ja', folderName: 'jpn' },
+ { id: 'ko', folderName: 'kor' },
+ { id: 'de', folderName: 'deu' },
+ { id: 'fr', folderName: 'fra' },
+ { id: 'es', folderName: 'esn' },
+ { id: 'ru', folderName: 'rus' },
+ { id: 'it', folderName: 'ita' }
+];
+
+// languages requested by the community to non-stable builds
+export const extraLanguages: Language[] = [
+ { id: 'pt-br', folderName: 'ptb' },
+ { id: 'hu', folderName: 'hun' },
+ { id: 'tr', folderName: 'trk' }
+];
+
+// non built-in extensions also that are transifex and need to be part of the language packs
+const externalExtensionsWithTranslations = {
+ 'vscode-chrome-debug': 'msjsdiag.debugger-for-chrome',
+ 'vscode-node-debug': 'ms-vscode.node-debug',
+ 'vscode-node-debug2': 'ms-vscode.node-debug2'
+};
+
+
interface Map {
[key: string]: V;
}
@@ -108,6 +151,20 @@ module ModuleJsonFormat {
}
}
+interface BundledExtensionHeaderFormat {
+ id: string;
+ type: string;
+ hash: string;
+ outDir: string;
+}
+
+interface BundledExtensionFormat {
+ [key: string]: {
+ messages: string[];
+ keys: (string | LocalizeInfo)[];
+ };
+}
+
export class Line {
private buffer: string[] = [];
@@ -142,10 +199,12 @@ class TextModel {
export class XLF {
private buffer: string[];
private files: Map- ;
+ public numberOfMessages: number;
constructor(public project: string) {
this.buffer = [];
this.files = Object.create(null);
+ this.numberOfMessages = 0;
}
public toString(): string {
@@ -163,30 +222,36 @@ export class XLF {
return this.buffer.join('\r\n');
}
- public addFile(original: string, keys: any[], messages: string[]) {
+ public addFile(original: string, keys: (string | LocalizeInfo)[], messages: string[]) {
+ if (keys.length === 0) {
+ console.log('No keys in ' + original);
+ return;
+ }
+ if (keys.length !== messages.length) {
+ throw new Error(`Unmatching keys(${keys.length}) and messages(${messages.length}).`);
+ }
+ this.numberOfMessages += keys.length;
this.files[original] = [];
- let existingKeys = [];
-
- for (let key of keys) {
- // Ignore duplicate keys because Transifex does not populate those with translated values.
- if (existingKeys.indexOf(key) !== -1) {
+ let existingKeys = new Set();
+ for (let i = 0; i < keys.length; i++) {
+ let key = keys[i];
+ let realKey: string;
+ let comment: string;
+ if (Is.string(key)) {
+ realKey = key;
+ comment = undefined;
+ } else if (LocalizeInfo.is(key)) {
+ realKey = key.key;
+ if (key.comment && key.comment.length > 0) {
+ comment = key.comment.map(comment => encodeEntities(comment)).join('\r\n');
+ }
+ }
+ if (!realKey || existingKeys.has(realKey)) {
continue;
}
- existingKeys.push(key);
-
- let message: string = encodeEntities(messages[keys.indexOf(key)]);
- let comment: string = undefined;
-
- // Check if the message contains description (if so, it becomes an object type in JSON)
- if (Is.string(key)) {
- this.files[original].push({ id: key, message: message, comment: comment });
- } else {
- if (key['comment'] && key['comment'].length > 0) {
- comment = key['comment'].map(comment => encodeEntities(comment)).join('\r\n');
- }
-
- this.files[original].push({ id: key['key'], message: message, comment: comment });
- }
+ existingKeys.add(realKey);
+ let message: string = encodeEntities(messages[i]);
+ this.files[original].push({ id: realKey, message: message, comment: comment });
}
}
@@ -220,6 +285,32 @@ export class XLF {
this.buffer.push(line.toString());
}
+ static parsePseudo = function (xlfString: string): Promise {
+ return new Promise((resolve, reject) => {
+ let parser = new xml2js.Parser();
+ let files: { messages: Map, originalFilePath: string, language: string }[] = [];
+ parser.parseString(xlfString, function (err, result) {
+ const fileNodes: any[] = result['xliff']['file'];
+ fileNodes.forEach(file => {
+ const originalFilePath = file.$.original;
+ const messages: Map = {};
+ const transUnits = file.body[0]['trans-unit'];
+ if (transUnits) {
+ transUnits.forEach(unit => {
+ const key = unit.$.id;
+ const val = pseudify(unit.source[0]['_'].toString());
+ if (key && val) {
+ messages[key] = decodeEntities(val);
+ }
+ });
+ files.push({ messages: messages, originalFilePath: originalFilePath, language: 'ps' });
+ }
+ });
+ resolve(files);
+ });
+ });
+ };
+
static parse = function (xlfString: string): Promise {
return new Promise((resolve, reject) => {
let parser = new xml2js.Parser();
@@ -228,42 +319,42 @@ export class XLF {
parser.parseString(xlfString, function (err, result) {
if (err) {
- reject(`Failed to parse XLIFF string. ${err}`);
+ reject(new Error(`XLF parsing error: Failed to parse XLIFF string. ${err}`));
}
const fileNodes: any[] = result['xliff']['file'];
if (!fileNodes) {
- reject('XLIFF file does not contain "xliff" or "file" node(s) required for parsing.');
+ reject(new Error(`XLF parsing error: XLIFF file does not contain "xliff" or "file" node(s) required for parsing.`));
}
fileNodes.forEach((file) => {
const originalFilePath = file.$.original;
if (!originalFilePath) {
- reject('XLIFF file node does not contain original attribute to determine the original location of the resource file.');
+ reject(new Error(`XLF parsing error: XLIFF file node does not contain original attribute to determine the original location of the resource file.`));
}
- const language = file.$['target-language'].toLowerCase();
+ let language = file.$['target-language'];
if (!language) {
- reject('XLIFF file node does not contain target-language attribute to determine translated language.');
+ reject(new Error(`XLF parsing error: XLIFF file node does not contain target-language attribute to determine translated language.`));
}
+ const messages: Map = {};
- let messages: Map = {};
const transUnits = file.body[0]['trans-unit'];
+ if (transUnits) {
+ transUnits.forEach(unit => {
+ const key = unit.$.id;
+ if (!unit.target) {
+ return; // No translation available
+ }
- transUnits.forEach(unit => {
- const key = unit.$.id;
- if (!unit.target) {
- return; // No translation available
- }
-
- const val = unit.target.toString();
- if (key && val) {
- messages[key] = decodeEntities(val);
- } else {
- reject('XLIFF file does not contain full localization data. ID or target translation for one of the trans-unit nodes is not present.');
- }
- });
-
- files.push({ messages: messages, originalFilePath: originalFilePath, language: language });
+ const val = unit.target.toString();
+ if (key && val) {
+ messages[key] = decodeEntities(val);
+ } else {
+ reject(new Error(`XLF parsing error: XLIFF file does not contain full localization data. ID or target translation for one of the trans-unit nodes is not present.`));
+ }
+ });
+ files.push({ messages: messages, originalFilePath: originalFilePath, language: language.toLowerCase() });
+ }
});
resolve(files);
@@ -272,74 +363,52 @@ export class XLF {
};
}
-const iso639_3_to_2: Map = {
- 'chs': 'zh-cn',
- 'cht': 'zh-tw',
- 'csy': 'cs-cz',
- 'deu': 'de',
- 'enu': 'en',
- 'esn': 'es',
- 'fra': 'fr',
- 'hun': 'hu',
- 'ita': 'it',
- 'jpn': 'ja',
- 'kor': 'ko',
- 'nld': 'nl',
- 'plk': 'pl',
- 'ptb': 'pt-br',
- 'ptg': 'pt',
- 'rus': 'ru',
- 'sve': 'sv-se',
- 'trk': 'tr'
-};
-
-/**
- * Used to map Transifex to VS Code language code representation.
- */
-const iso639_2_to_3: Map = {
- 'zh-hans': 'chs',
- 'zh-hant': 'cht',
- 'cs-cz': 'csy',
- 'de': 'deu',
- 'en': 'enu',
- 'es': 'esn',
- 'fr': 'fra',
- 'hu': 'hun',
- 'it': 'ita',
- 'ja': 'jpn',
- 'ko': 'kor',
- 'nl': 'nld',
- 'pl': 'plk',
- 'pt-br': 'ptb',
- 'pt': 'ptg',
- 'ru': 'rus',
- 'sv-se': 'sve',
- 'tr': 'trk'
-};
-
-interface IDirectoryInfo {
- name: string;
- iso639_2: string;
+export interface ITask {
+ (): T;
}
-function sortLanguages(directoryNames: string[]): IDirectoryInfo[] {
- return directoryNames.map((dirName) => {
- var lower = dirName.toLowerCase();
- return {
- name: lower,
- iso639_2: iso639_3_to_2[lower]
- };
- }).sort((a: IDirectoryInfo, b: IDirectoryInfo): number => {
- if (!a.iso639_2 && !b.iso639_2) {
- return 0;
+interface ILimitedTaskFactory {
+ factory: ITask>;
+ c: (value?: T | Thenable) => void;
+ e: (error?: any) => void;
+}
+
+export class Limiter {
+ private runningPromises: number;
+ private outstandingPromises: ILimitedTaskFactory[];
+
+ constructor(private maxDegreeOfParalellism: number) {
+ this.outstandingPromises = [];
+ this.runningPromises = 0;
+ }
+
+ queue(factory: ITask>): Promise {
+ return new Promise((c, e) => {
+ this.outstandingPromises.push({ factory, c, e });
+ this.consume();
+ });
+ }
+
+ private consume(): void {
+ while (this.outstandingPromises.length && this.runningPromises < this.maxDegreeOfParalellism) {
+ const iLimitedTask = this.outstandingPromises.shift();
+ this.runningPromises++;
+
+ const promise = iLimitedTask.factory();
+ promise.then(iLimitedTask.c).catch(iLimitedTask.e);
+ promise.then(() => this.consumed()).catch(() => this.consumed());
}
- if (!a.iso639_2) {
- return -1;
- }
- if (!b.iso639_2) {
- return 1;
- }
- return a.iso639_2 < b.iso639_2 ? -1 : (a.iso639_2 > b.iso639_2 ? 1 : 0);
+ }
+
+ private consumed(): void {
+ this.runningPromises--;
+ this.consume();
+ }
+}
+
+function sortLanguages(languages: Language[]): Language[] {
+ return languages.sort((a: Language, b: Language): number => {
+ return a.id < b.id ? -1 : (a.id > b.id ? 1 : 0);
});
}
@@ -408,7 +477,7 @@ function escapeCharacters(value: string): string {
return result.join('');
}
-function processCoreBundleFormat(fileHeader: string, languages: string[], json: BundledFormat, emitter: any) {
+function processCoreBundleFormat(fileHeader: string, languages: Language[], json: BundledFormat, emitter: ThroughStream) {
let keysSection = json.keys;
let messageSection = json.messages;
let bundleSection = json.bundles;
@@ -429,7 +498,7 @@ function processCoreBundleFormat(fileHeader: string, languages: string[], json:
defaultMessages[module] = messageMap;
keys.map((key, i) => {
total++;
- if (Is.string(key)) {
+ if (typeof key === 'string') {
messageMap[key] = messages[i];
} else {
messageMap[key.key] = messages[i];
@@ -438,24 +507,16 @@ function processCoreBundleFormat(fileHeader: string, languages: string[], json:
});
let languageDirectory = path.join(__dirname, '..', '..', 'i18n');
- let languageDirs;
- if (languages) {
- languageDirs = sortLanguages(languages);
- } else {
- languageDirs = sortLanguages(fs.readdirSync(languageDirectory).filter((item) => fs.statSync(path.join(languageDirectory, item)).isDirectory()));
- }
- languageDirs.forEach((language) => {
- if (!language.iso639_2) {
- return;
- }
-
+ let sortedLanguages = sortLanguages(languages);
+ sortedLanguages.forEach((language) => {
if (process.env['VSCODE_BUILD_VERBOSE']) {
- log(`Generating nls bundles for: ${language.iso639_2}`);
+ log(`Generating nls bundles for: ${language.id}`);
}
- statistics[language.iso639_2] = 0;
+ statistics[language.id] = 0;
let localizedModules: Map = Object.create(null);
- let cwd = path.join(languageDirectory, language.name, 'src');
+ let languageFolderName = language.folderName || language.id;
+ let cwd = path.join(languageDirectory, languageFolderName, 'src');
modules.forEach((module) => {
let order = keysSection[module];
let i18nFile = path.join(cwd, module) + '.i18n.json';
@@ -468,12 +529,12 @@ function processCoreBundleFormat(fileHeader: string, languages: string[], json:
log(`No localized messages found for module ${module}. Using default messages.`);
}
messages = defaultMessages[module];
- statistics[language.iso639_2] = statistics[language.iso639_2] + Object.keys(messages).length;
+ statistics[language.id] = statistics[language.id] + Object.keys(messages).length;
}
let localizedMessages: string[] = [];
order.forEach((keyInfo) => {
let key: string = null;
- if (Is.string(keyInfo)) {
+ if (typeof keyInfo === 'string') {
key = keyInfo;
} else {
key = keyInfo.key;
@@ -484,7 +545,7 @@ function processCoreBundleFormat(fileHeader: string, languages: string[], json:
log(`No localized message found for key ${key} in module ${module}. Using default message.`);
}
message = defaultMessages[module][key];
- statistics[language.iso639_2] = statistics[language.iso639_2] + 1;
+ statistics[language.id] = statistics[language.id] + 1;
}
localizedMessages.push(message);
});
@@ -494,7 +555,7 @@ function processCoreBundleFormat(fileHeader: string, languages: string[], json:
let modules = bundleSection[bundle];
let contents: string[] = [
fileHeader,
- `define("${bundle}.nls.${language.iso639_2}", {`
+ `define("${bundle}.nls.${language.id}", {`
];
modules.forEach((module, index) => {
contents.push(`\t"${module}": [`);
@@ -509,29 +570,23 @@ function processCoreBundleFormat(fileHeader: string, languages: string[], json:
contents.push(index < modules.length - 1 ? '\t],' : '\t]');
});
contents.push('});');
- emitter.emit('data', new File({ path: bundle + '.nls.' + language.iso639_2 + '.js', contents: new Buffer(contents.join('\n'), 'utf-8') }));
+ emitter.queue(new File({ path: bundle + '.nls.' + language.id + '.js', contents: Buffer.from(contents.join('\n'), 'utf-8') }));
});
});
Object.keys(statistics).forEach(key => {
let value = statistics[key];
log(`${key} has ${value} untranslated strings.`);
});
- languageDirs.forEach(dir => {
- const language = dir.name;
- let iso639_2 = iso639_3_to_2[language];
- if (!iso639_2) {
- log(`\tCouldn't find iso639 2 mapping for language ${language}. Using default language instead.`);
- } else {
- let stats = statistics[iso639_2];
- if (Is.undef(stats)) {
- log(`\tNo translations found for language ${language}. Using default language instead.`);
- }
+ sortedLanguages.forEach(language => {
+ let stats = statistics[language.id];
+ if (Is.undef(stats)) {
+ log(`\tNo translations found for language ${language.id}. Using default language instead.`);
}
});
}
-export function processNlsFiles(opts: { fileHeader: string; languages: string[] }): ThroughStream {
- return through(function (file: File) {
+export function processNlsFiles(opts: { fileHeader: string; languages: Language[] }): ThroughStream {
+ return through(function (this: ThroughStream, file: File) {
let fileName = path.basename(file.path);
if (fileName === 'nls.metadata.json') {
let json = null;
@@ -539,40 +594,16 @@ export function processNlsFiles(opts: { fileHeader: string; languages: string[]
json = JSON.parse((file.contents).toString('utf8'));
} else {
this.emit('error', `Failed to read component file: ${file.relative}`);
+ return;
}
if (BundledFormat.is(json)) {
processCoreBundleFormat(opts.fileHeader, opts.languages, json, this);
}
}
- this.emit('data', file);
+ this.queue(file);
});
}
-export function prepareXlfFiles(projectName?: string, extensionName?: string): ThroughStream {
- return through(
- function (file: File) {
- if (!file.isBuffer()) {
- throw new Error(`Failed to read component file: ${file.relative}`);
- }
-
- const extension = path.extname(file.path);
- if (extension === '.json') {
- const json = JSON.parse((file.contents).toString('utf8'));
-
- if (BundledFormat.is(json)) {
- importBundleJson(file, json, this);
- } else if (PackageJsonFormat.is(json) || ModuleJsonFormat.is(json)) {
- importModuleOrPackageJson(file, json, projectName, this, extensionName);
- } else {
- throw new Error(`JSON format cannot be deduced for ${file.relative}.`);
- }
- } else if (extension === '.isl') {
- importIsl(file, this);
- }
- }
- );
-}
-
const editorProject: string = 'vscode-editor',
workbenchProject: string = 'vscode-workbench',
extensionsProject: string = 'vscode-extensions',
@@ -613,134 +644,190 @@ export function getResource(sourceFile: string): Resource {
}
-function importBundleJson(file: File, json: BundledFormat, stream: ThroughStream): void {
- let bundleXlfs: Map = Object.create(null);
+export function createXlfFilesForCoreBundle(): ThroughStream {
+ return through(function (this: ThroughStream, file: File) {
+ const basename = path.basename(file.path);
+ if (basename === 'nls.metadata.json') {
+ if (file.isBuffer()) {
+ const xlfs: Map = Object.create(null);
+ const json: BundledFormat = JSON.parse((file.contents as Buffer).toString('utf8'));
+ for (let coreModule in json.keys) {
+ const projectResource = getResource(coreModule);
+ const resource = projectResource.name;
+ const project = projectResource.project;
- for (let source in json.keys) {
- const projectResource = getResource(source);
- const resource = projectResource.name;
- const project = projectResource.project;
-
- const keys = json.keys[source];
- const messages = json.messages[source];
- if (keys.length !== messages.length) {
- throw new Error(`There is a mismatch between keys and messages in ${file.relative}`);
- }
-
- let xlf = bundleXlfs[resource] ? bundleXlfs[resource] : bundleXlfs[resource] = new XLF(project);
- xlf.addFile('src/' + source, keys, messages);
- }
-
- for (let resource in bundleXlfs) {
- const newFilePath = `${bundleXlfs[resource].project}/${resource.replace(/\//g, '_')}.xlf`;
- const xlfFile = new File({ path: newFilePath, contents: new Buffer(bundleXlfs[resource].toString(), 'utf-8') });
- stream.emit('data', xlfFile);
- }
-}
-
-// Keeps existing XLF instances and a state of how many files were already processed for faster file emission
-var extensions: Map<{ xlf: XLF, processed: number }> = Object.create(null);
-function importModuleOrPackageJson(file: File, json: ModuleJsonFormat | PackageJsonFormat, projectName: string, stream: ThroughStream, extensionName?: string): void {
- if (ModuleJsonFormat.is(json) && json['keys'].length !== json['messages'].length) {
- throw new Error(`There is a mismatch between keys and messages in ${file.relative}`);
- }
-
- // Prepare the source path for attribute in XLF & extract messages from JSON
- const formattedSourcePath = file.relative.replace(/\\/g, '/');
- const messages = Object.keys(json).map((key) => json[key].toString());
-
- // Stores the amount of localization files to be transformed to XLF before the emission
- let localizationFilesCount,
- originalFilePath;
- // If preparing XLF for external extension, then use different glob pattern and source path
- if (extensionName) {
- localizationFilesCount = glob.sync('**/*.nls.json').length;
- originalFilePath = `${formattedSourcePath.substr(0, formattedSourcePath.length - '.nls.json'.length)}`;
- } else {
- // Used for vscode/extensions folder
- extensionName = formattedSourcePath.split('/')[0];
- localizationFilesCount = glob.sync(`./extensions/${extensionName}/**/*.nls.json`).length;
- originalFilePath = `extensions/${formattedSourcePath.substr(0, formattedSourcePath.length - '.nls.json'.length)}`;
- }
-
- let extension = extensions[extensionName] ?
- extensions[extensionName] : extensions[extensionName] = { xlf: new XLF(projectName), processed: 0 };
-
- // .nls.json can come with empty array of keys and messages, check for it
- if (ModuleJsonFormat.is(json) && json.keys.length !== 0) {
- extension.xlf.addFile(originalFilePath, json.keys, json.messages);
- } else if (PackageJsonFormat.is(json) && Object.keys(json).length !== 0) {
- extension.xlf.addFile(originalFilePath, Object.keys(json), messages);
- }
-
- // Check if XLF is populated with file nodes to emit it
- if (++extensions[extensionName].processed === localizationFilesCount) {
- const newFilePath = path.join(projectName, extensionName + '.xlf');
- const xlfFile = new File({ path: newFilePath, contents: new Buffer(extension.xlf.toString(), 'utf-8') });
- stream.emit('data', xlfFile);
- }
-}
-
-function importIsl(file: File, stream: ThroughStream) {
- let projectName: string,
- resourceFile: string;
- if (path.basename(file.path) === 'Default.isl') {
- projectName = setupProject;
- resourceFile = 'setup_default.xlf';
- } else {
- projectName = workbenchProject;
- resourceFile = 'setup_messages.xlf';
- }
-
- let xlf = new XLF(projectName),
- keys: string[] = [],
- messages: string[] = [];
-
- let model = new TextModel(file.contents.toString());
- let inMessageSection = false;
- model.lines.forEach(line => {
- if (line.length === 0) {
- return;
- }
- let firstChar = line.charAt(0);
- switch (firstChar) {
- case ';':
- // Comment line;
+ const keys = json.keys[coreModule];
+ const messages = json.messages[coreModule];
+ if (keys.length !== messages.length) {
+ this.emit('error', `There is a mismatch between keys and messages in ${file.relative} for module ${coreModule}`);
+ return;
+ } else {
+ let xlf = xlfs[resource];
+ if (!xlf) {
+ xlf = new XLF(project);
+ xlfs[resource] = xlf;
+ }
+ xlf.addFile(`src/${coreModule}`, keys, messages);
+ }
+ }
+ for (let resource in xlfs) {
+ const xlf = xlfs[resource];
+ const filePath = `${xlf.project}/${resource.replace(/\//g, '_')}.xlf`;
+ const xlfFile = new File({
+ path: filePath,
+ contents: Buffer.from(xlf.toString(), 'utf8')
+ });
+ this.queue(xlfFile);
+ }
+ } else {
+ this.emit('error', new Error(`File ${file.relative} is not using a buffer content`));
return;
- case '[':
- inMessageSection = '[Messages]' === line || '[CustomMessages]' === line;
- return;
- }
- if (!inMessageSection) {
- return;
- }
- let sections: string[] = line.split('=');
- if (sections.length !== 2) {
- throw new Error(`Badly formatted message found: ${line}`);
- } else {
- let key = sections[0];
- let value = sections[1];
- if (key.length > 0 && value.length > 0) {
- keys.push(key);
- messages.push(value);
}
+ } else {
+ this.emit('error', new Error(`File ${file.relative} is not a core meta data file.`));
+ return;
}
});
+}
- const originalPath = file.path.substring(file.cwd.length + 1, file.path.split('.')[0].length).replace(/\\/g, '/');
- xlf.addFile(originalPath, keys, messages);
+export function createXlfFilesForExtensions(): ThroughStream {
+ let counter: number = 0;
+ let folderStreamEnded: boolean = false;
+ let folderStreamEndEmitted: boolean = false;
+ return through(function (this: ThroughStream, extensionFolder: File) {
+ const folderStream = this;
+ const stat = fs.statSync(extensionFolder.path);
+ if (!stat.isDirectory()) {
+ return;
+ }
+ let extensionName = path.basename(extensionFolder.path);
+ if (extensionName === 'node_modules') {
+ return;
+ }
+ counter++;
+ let _xlf: XLF;
+ function getXlf() {
+ if (!_xlf) {
+ _xlf = new XLF(extensionsProject);
+ }
+ return _xlf;
+ }
+ gulp.src([`./extensions/${extensionName}/package.nls.json`, `./extensions/${extensionName}/**/nls.metadata.json`]).pipe(through(function (file: File) {
+ if (file.isBuffer()) {
+ const buffer: Buffer = file.contents as Buffer;
+ const basename = path.basename(file.path);
+ if (basename === 'package.nls.json') {
+ const json: PackageJsonFormat = JSON.parse(buffer.toString('utf8'));
+ const keys = Object.keys(json);
+ const messages = keys.map((key) => {
+ const value = json[key];
+ if (Is.string(value)) {
+ return value;
+ } else if (value) {
+ return value.message;
+ } else {
+ return `Unknown message for key: ${key}`;
+ }
+ });
+ getXlf().addFile(`extensions/${extensionName}/package`, keys, messages);
+ } else if (basename === 'nls.metadata.json') {
+ const json: BundledExtensionFormat = JSON.parse(buffer.toString('utf8'));
+ const relPath = path.relative(`./extensions/${extensionName}`, path.dirname(file.path));
+ for (let file in json) {
+ const fileContent = json[file];
+ getXlf().addFile(`extensions/${extensionName}/${relPath}/${file}`, fileContent.keys, fileContent.messages);
+ }
+ } else {
+ this.emit('error', new Error(`${file.path} is not a valid extension nls file`));
+ return;
+ }
+ }
+ }, function () {
+ if (_xlf) {
+ let xlfFile = new File({
+ path: path.join(extensionsProject, extensionName + '.xlf'),
+ contents: Buffer.from(_xlf.toString(), 'utf8')
+ });
+ folderStream.queue(xlfFile);
+ }
+ this.queue(null);
+ counter--;
+ if (counter === 0 && folderStreamEnded && !folderStreamEndEmitted) {
+ folderStreamEndEmitted = true;
+ folderStream.queue(null);
+ }
+ }));
+ }, function () {
+ folderStreamEnded = true;
+ if (counter === 0) {
+ folderStreamEndEmitted = true;
+ this.queue(null);
+ }
+ });
+}
- // Emit only upon all ISL files combined into single XLF instance
- const newFilePath = path.join(projectName, resourceFile);
- const xlfFile = new File({ path: newFilePath, contents: new Buffer(xlf.toString(), 'utf-8') });
- stream.emit('data', xlfFile);
+export function createXlfFilesForIsl(): ThroughStream {
+ return through(function (this: ThroughStream, file: File) {
+ let projectName: string,
+ resourceFile: string;
+ if (path.basename(file.path) === 'Default.isl') {
+ projectName = setupProject;
+ resourceFile = 'setup_default.xlf';
+ } else {
+ projectName = workbenchProject;
+ resourceFile = 'setup_messages.xlf';
+ }
+
+ let xlf = new XLF(projectName),
+ keys: string[] = [],
+ messages: string[] = [];
+
+ let model = new TextModel(file.contents.toString());
+ let inMessageSection = false;
+ model.lines.forEach(line => {
+ if (line.length === 0) {
+ return;
+ }
+ let firstChar = line.charAt(0);
+ switch (firstChar) {
+ case ';':
+ // Comment line;
+ return;
+ case '[':
+ inMessageSection = '[Messages]' === line || '[CustomMessages]' === line;
+ return;
+ }
+ if (!inMessageSection) {
+ return;
+ }
+ let sections: string[] = line.split('=');
+ if (sections.length !== 2) {
+ throw new Error(`Badly formatted message found: ${line}`);
+ } else {
+ let key = sections[0];
+ let value = sections[1];
+ if (key.length > 0 && value.length > 0) {
+ keys.push(key);
+ messages.push(value);
+ }
+ }
+ });
+
+ const originalPath = file.path.substring(file.cwd.length + 1, file.path.split('.')[0].length).replace(/\\/g, '/');
+ xlf.addFile(originalPath, keys, messages);
+
+ // Emit only upon all ISL files combined into single XLF instance
+ const newFilePath = path.join(projectName, resourceFile);
+ const xlfFile = new File({ path: newFilePath, contents: Buffer.from(xlf.toString(), 'utf-8') });
+ this.queue(xlfFile);
+ });
}
export function pushXlfFiles(apiHostname: string, username: string, password: string): ThroughStream {
let tryGetPromises = [];
let updateCreatePromises = [];
- return through(function (file: File) {
+ return through(function (this: ThroughStream, file: File) {
const project = path.dirname(file.relative);
const fileName = path.basename(file.path);
const slug = fileName.substr(0, fileName.length - '.xlf'.length);
@@ -762,12 +849,95 @@ export function pushXlfFiles(apiHostname: string, username: string, password: st
// End the pipe only after all the communication with Transifex API happened
Promise.all(tryGetPromises).then(() => {
Promise.all(updateCreatePromises).then(() => {
- this.emit('end');
+ this.queue(null);
}).catch((reason) => { throw new Error(reason); });
}).catch((reason) => { throw new Error(reason); });
});
}
+function getAllResources(project: string, apiHostname: string, username: string, password: string): Promise {
+ return new Promise((resolve, reject) => {
+ const credentials = `${username}:${password}`;
+ const options = {
+ hostname: apiHostname,
+ path: `/api/2/project/${project}/resources`,
+ auth: credentials,
+ method: 'GET'
+ };
+
+ const request = https.request(options, (res) => {
+ let buffer: Buffer[] = [];
+ res.on('data', (chunk: Buffer) => buffer.push(chunk));
+ res.on('end', () => {
+ if (res.statusCode === 200) {
+ let json = JSON.parse(Buffer.concat(buffer).toString());
+ if (Array.isArray(json)) {
+ resolve(json.map(o => o.slug));
+ return;
+ }
+ reject(`Unexpected data format. Response code: ${res.statusCode}.`);
+ } else {
+ reject(`No resources in ${project} returned no data. Response code: ${res.statusCode}.`);
+ }
+ });
+ });
+ request.on('error', (err) => {
+ reject(`Failed to query resources in ${project} with the following error: ${err}. ${options.path}`);
+ });
+ request.end();
+ });
+}
+
+export function findObsoleteResources(apiHostname: string, username: string, password: string): ThroughStream {
+ let resourcesByProject: Map = Object.create(null);
+ resourcesByProject[extensionsProject] = [].concat(externalExtensionsWithTranslations); // clone
+
+ return through(function (this: ThroughStream, file: File) {
+ const project = path.dirname(file.relative);
+ const fileName = path.basename(file.path);
+ const slug = fileName.substr(0, fileName.length - '.xlf'.length);
+
+ let slugs = resourcesByProject[project];
+ if (!slugs) {
+ resourcesByProject[project] = slugs = [];
+ }
+ slugs.push(slug);
+ this.push(file);
+ }, function () {
+
+ const json = JSON.parse(fs.readFileSync('./build/lib/i18n.resources.json', 'utf8'));
+ let i18Resources = [...json.editor, ...json.workbench].map((r: Resource) => r.project + '/' + r.name.replace(/\//g, '_'));
+ let extractedResources = [];
+ for (let project of [workbenchProject, editorProject]) {
+ for (let resource of resourcesByProject[project]) {
+ if (resource !== 'setup_messages') {
+ extractedResources.push(project + '/' + resource);
+ }
+ }
+ }
+ if (i18Resources.length !== extractedResources.length) {
+ console.log(`[i18n] Obsolete resources in file 'build/lib/i18n.resources.json': JSON.stringify(${i18Resources.filter(p => extractedResources.indexOf(p) === -1)})`);
+ console.log(`[i18n] Missing resources in file 'build/lib/i18n.resources.json': JSON.stringify(${extractedResources.filter(p => i18Resources.indexOf(p) === -1)})`);
+ }
+
+ let promises = [];
+ for (let project in resourcesByProject) {
+ promises.push(
+ getAllResources(project, apiHostname, username, password).then(resources => {
+ let expectedResources = resourcesByProject[project];
+ let unusedResources = resources.filter(resource => resource && expectedResources.indexOf(resource) === -1);
+ if (unusedResources.length) {
+ console.log(`[transifex] Obsolete resources in project '${project}': ${unusedResources.join(', ')}`);
+ }
+ })
+ );
+ }
+ return Promise.all(promises).then(_ => {
+ this.push(null);
+ }).catch((reason) => { throw new Error(reason); });
+ });
+}
+
function tryGetResource(project: string, slug: string, apiHostname: string, credentials: string): Promise {
return new Promise((resolve, reject) => {
const options = {
@@ -873,42 +1043,46 @@ function updateResource(project: string, slug: string, xlfFile: File, apiHostnam
});
}
-function obtainProjectResources(projectName: string): Resource[] {
- let resources: Resource[] = [];
+// cache resources
+let _coreAndExtensionResources: Resource[];
- if (projectName === editorProject) {
- const json = fs.readFileSync('./build/lib/i18n.resources.json', 'utf8');
- resources = JSON.parse(json).editor;
- } else if (projectName === workbenchProject) {
- const json = fs.readFileSync('./build/lib/i18n.resources.json', 'utf8');
- resources = JSON.parse(json).workbench;
- } else if (projectName === extensionsProject) {
- let extensionsToLocalize: string[] = glob.sync('./extensions/**/*.nls.json').map(extension => extension.split('/')[2]);
- let resourcesToPull: string[] = [];
+export function pullCoreAndExtensionsXlfFiles(apiHostname: string, username: string, password: string, language: Language, externalExtensions?: Map): NodeJS.ReadableStream {
+ if (!_coreAndExtensionResources) {
+ _coreAndExtensionResources = [];
+ // editor and workbench
+ const json = JSON.parse(fs.readFileSync('./build/lib/i18n.resources.json', 'utf8'));
+ _coreAndExtensionResources.push(...json.editor);
+ _coreAndExtensionResources.push(...json.workbench);
- extensionsToLocalize.forEach(extension => {
- if (resourcesToPull.indexOf(extension) === -1) { // remove duplicate elements returned by glob
- resourcesToPull.push(extension);
- resources.push({ name: extension, project: projectName });
- }
+ // extensions
+ let extensionsToLocalize = Object.create(null);
+ glob.sync('./extensions/**/*.nls.json', ).forEach(extension => extensionsToLocalize[extension.split('/')[2]] = true);
+ glob.sync('./extensions/*/node_modules/vscode-nls', ).forEach(extension => extensionsToLocalize[extension.split('/')[2]] = true);
+
+ Object.keys(extensionsToLocalize).forEach(extension => {
+ _coreAndExtensionResources.push({ name: extension, project: extensionsProject });
});
- } else if (projectName === setupProject) {
- resources.push({ name: 'setup_default', project: setupProject });
- }
- return resources;
+ if (externalExtensions) {
+ for (let resourceName in externalExtensions) {
+ _coreAndExtensionResources.push({ name: resourceName, project: extensionsProject });
+ }
+ }
+ }
+ return pullXlfFiles(apiHostname, username, password, language, _coreAndExtensionResources);
}
-export function pullXlfFiles(projectName: string, apiHostname: string, username: string, password: string, languages: string[], resources?: Resource[]): NodeJS.ReadableStream {
- if (!resources) {
- resources = obtainProjectResources(projectName);
- }
- if (!resources) {
- throw new Error('Transifex projects and resources must be defined to be able to pull translations from Transifex.');
+export function pullSetupXlfFiles(apiHostname: string, username: string, password: string, language: Language, includeDefault: boolean): NodeJS.ReadableStream {
+ let setupResources = [{ name: 'setup_messages', project: workbenchProject }];
+ if (includeDefault) {
+ setupResources.push({ name: 'setup_default', project: setupProject });
}
+ return pullXlfFiles(apiHostname, username, password, language, setupResources);
+}
+function pullXlfFiles(apiHostname: string, username: string, password: string, language: Language, resources: Resource[]): NodeJS.ReadableStream {
const credentials = `${username}:${password}`;
- let expectedTranslationsCount = languages.length * resources.length;
+ let expectedTranslationsCount = resources.length;
let translationsRetrieved = 0, called = false;
return readable(function (count, callback) {
@@ -920,133 +1094,203 @@ export function pullXlfFiles(projectName: string, apiHostname: string, username:
if (!called) {
called = true;
const stream = this;
-
- // Retrieve XLF files from main projects
- languages.map(function (language) {
- resources.map(function (resource) {
- retrieveResource(language, resource, apiHostname, credentials).then((file: File) => {
+ resources.map(function (resource) {
+ retrieveResource(language, resource, apiHostname, credentials).then((file: File) => {
+ if (file) {
stream.emit('data', file);
- translationsRetrieved++;
- }).catch(error => { throw new Error(error); });
- });
+ }
+ translationsRetrieved++;
+ }).catch(error => { throw new Error(error); });
});
}
callback();
});
}
+const limiter = new Limiter(NUMBER_OF_CONCURRENT_DOWNLOADS);
-function retrieveResource(language: string, resource: Resource, apiHostname, credentials): Promise {
- return new Promise((resolve, reject) => {
+function retrieveResource(language: Language, resource: Resource, apiHostname, credentials): Promise {
+ return limiter.queue(() => new Promise((resolve, reject) => {
const slug = resource.name.replace(/\//g, '_');
const project = resource.project;
- const iso639 = language.toLowerCase();
+ let transifexLanguageId = language.id === 'ps' ? 'en' : language.transifexId || language.id;
const options = {
hostname: apiHostname,
- path: `/api/2/project/${project}/resource/${slug}/translation/${iso639}?file&mode=onlyreviewed`,
+ path: `/api/2/project/${project}/resource/${slug}/translation/${transifexLanguageId}?file&mode=onlyreviewed`,
auth: credentials,
+ port: 443,
method: 'GET'
};
+ console.log('[transifex] Fetching ' + options.path);
let request = https.request(options, (res) => {
let xlfBuffer: Buffer[] = [];
res.on('data', (chunk: Buffer) => xlfBuffer.push(chunk));
res.on('end', () => {
if (res.statusCode === 200) {
- resolve(new File({ contents: Buffer.concat(xlfBuffer), path: `${project}/${iso639_2_to_3[language]}/${slug}.xlf` }));
+ resolve(new File({ contents: Buffer.concat(xlfBuffer), path: `${project}/${slug}.xlf` }));
+ } else if (res.statusCode === 404) {
+ console.log(`[transifex] ${slug} in ${project} returned no data.`);
+ resolve(null);
+ } else {
+ reject(`${slug} in ${project} returned no data. Response code: ${res.statusCode}.`);
}
- reject(`${slug} in ${project} returned no data. Response code: ${res.statusCode}.`);
});
});
request.on('error', (err) => {
- reject(`Failed to query resource ${slug} with the following error: ${err}`);
+ reject(`Failed to query resource ${slug} with the following error: ${err}. ${options.path}`);
});
request.end();
- });
+ }));
}
-export function prepareJsonFiles(): ThroughStream {
+export function prepareI18nFiles(): ThroughStream {
let parsePromises: Promise[] = [];
- return through(function (xlf: File) {
+ return through(function (this: ThroughStream, xlf: File) {
let stream = this;
let parsePromise = XLF.parse(xlf.contents.toString());
parsePromises.push(parsePromise);
parsePromise.then(
- function (resolvedFiles) {
+ resolvedFiles => {
resolvedFiles.forEach(file => {
- let messages = file.messages, translatedFile;
-
- // ISL file path always starts with 'build/'
- if (/^build\//.test(file.originalFilePath)) {
- const defaultLanguages = { 'zh-hans': true, 'zh-hant': true, 'ko': true };
- if (path.basename(file.originalFilePath) === 'Default' && !defaultLanguages[file.language]) {
- return;
- }
-
- translatedFile = createIslFile('..', file.originalFilePath, messages, iso639_2_to_3[file.language]);
- } else {
- translatedFile = createI18nFile(iso639_2_to_3[file.language], file.originalFilePath, messages);
- }
-
- stream.emit('data', translatedFile);
+ let translatedFile = createI18nFile(file.originalFilePath, file.messages);
+ stream.queue(translatedFile);
});
- },
- function (rejectReason) {
- throw new Error(`XLF parsing error: ${rejectReason}`);
}
);
}, function () {
Promise.all(parsePromises)
- .then(() => { this.emit('end'); })
+ .then(() => { this.queue(null); })
.catch(reason => { throw new Error(reason); });
});
}
-function createI18nFile(base: string, originalFilePath: string, messages: Map): File {
- let content = [
- '/*---------------------------------------------------------------------------------------------',
- ' * Copyright (c) Microsoft Corporation. All rights reserved.',
- ' * Licensed under the Source EULA. See License.txt in the project root for license information.',
- ' *--------------------------------------------------------------------------------------------*/',
- '// Do not edit this file. It is machine generated.'
- ].join('\n') + '\n' + JSON.stringify(messages, null, '\t').replace(/\r\n/g, '\n');
+function createI18nFile(originalFilePath: string, messages: any): File {
+ let result = Object.create(null);
+ result[''] = [
+ '--------------------------------------------------------------------------------------------',
+ 'Copyright (c) Microsoft Corporation. All rights reserved.',
+ 'Licensed under the Source EULA. See License.txt in the project root for license information.',
+ '--------------------------------------------------------------------------------------------',
+ 'Do not edit this file. It is machine generated.'
+ ];
+ for (let key of Object.keys(messages)) {
+ result[key] = messages[key];
+ }
+ let content = JSON.stringify(result, null, '\t').replace(/\r\n/g, '\n');
return new File({
- path: path.join(base, originalFilePath + '.i18n.json'),
- contents: new Buffer(content, 'utf8')
+ path: path.join(originalFilePath + '.i18n.json'),
+ contents: Buffer.from(content, 'utf8')
});
}
+interface I18nPack {
+ version: string;
+ contents: {
+ [path: string]: Map;
+ };
+}
-const languageNames: Map = {
- 'chs': 'Simplified Chinese',
- 'cht': 'Traditional Chinese',
- 'kor': 'Korean'
-};
+const i18nPackVersion = "1.0.0";
-const languageIds: Map = {
- 'chs': '$0804',
- 'cht': '$0404',
- 'kor': '$0412'
-};
+export interface TranslationPath {
+ id: string;
+ resourceName: string;
+}
-const encodings: Map = {
- 'chs': 'CP936',
- 'cht': 'CP950',
- 'jpn': 'CP932',
- 'kor': 'CP949',
- 'deu': 'CP1252',
- 'fra': 'CP1252',
- 'esn': 'CP1252',
- 'rus': 'CP1251',
- 'ita': 'CP1252',
- 'ptb': 'CP1252',
- 'hun': 'CP1250',
- 'trk': 'CP1254'
-};
+export function pullI18nPackFiles(apiHostname: string, username: string, password: string, language: Language, resultingTranslationPaths: TranslationPath[]): NodeJS.ReadableStream {
+ return pullCoreAndExtensionsXlfFiles(apiHostname, username, password, language, externalExtensionsWithTranslations)
+ .pipe(prepareI18nPackFiles(externalExtensionsWithTranslations, resultingTranslationPaths, language.id === 'ps'));
+}
-function createIslFile(base: string, originalFilePath: string, messages: Map, language: string): File {
+export function prepareI18nPackFiles(externalExtensions: Map, resultingTranslationPaths: TranslationPath[], pseudo = false): NodeJS.ReadWriteStream {
+ let parsePromises: Promise[] = [];
+ let mainPack: I18nPack = { version: i18nPackVersion, contents: {} };
+ let extensionsPacks: Map = {};
+ return through(function (this: ThroughStream, xlf: File) {
+ let stream = this;
+ let project = path.dirname(xlf.path);
+ let resource = path.basename(xlf.path, '.xlf');
+ let contents = xlf.contents.toString();
+ let parsePromise = pseudo ? XLF.parsePseudo(contents) : XLF.parse(contents);
+ parsePromises.push(parsePromise);
+ parsePromise.then(
+ resolvedFiles => {
+ resolvedFiles.forEach(file => {
+ const path = file.originalFilePath;
+ const firstSlash = path.indexOf('/');
+
+ if (project === extensionsProject) {
+ let extPack = extensionsPacks[resource];
+ if (!extPack) {
+ extPack = extensionsPacks[resource] = { version: i18nPackVersion, contents: {} };
+ }
+ const externalId = externalExtensions[resource];
+ if (!externalId) { // internal extension: remove 'extensions/extensionId/' segnent
+ const secondSlash = path.indexOf('/', firstSlash + 1);
+ extPack.contents[path.substr(secondSlash + 1)] = file.messages;
+ } else {
+ extPack.contents[path] = file.messages;
+ }
+ } else {
+ mainPack.contents[path.substr(firstSlash + 1)] = file.messages;
+ }
+ });
+ }
+ );
+ }, function () {
+ Promise.all(parsePromises)
+ .then(() => {
+ const translatedMainFile = createI18nFile('./main', mainPack);
+ resultingTranslationPaths.push({ id: 'vscode', resourceName: 'main.i18n.json' });
+
+ this.queue(translatedMainFile);
+ for (let extension in extensionsPacks) {
+ const translatedExtFile = createI18nFile(`./extensions/${extension}`, extensionsPacks[extension]);
+ this.queue(translatedExtFile);
+
+ const externalExtensionId = externalExtensions[extension];
+ if (externalExtensionId) {
+ resultingTranslationPaths.push({ id: externalExtensionId, resourceName: `extensions/${extension}.i18n.json` });
+ } else {
+ resultingTranslationPaths.push({ id: `vscode.${extension}`, resourceName: `extensions/${extension}.i18n.json` });
+ }
+
+ }
+ this.queue(null);
+ })
+ .catch(reason => { throw new Error(reason); });
+ });
+}
+
+export function prepareIslFiles(language: Language, innoSetupConfig: InnoSetup): ThroughStream {
+ let parsePromises: Promise[] = [];
+
+ return through(function (this: ThroughStream, xlf: File) {
+ let stream = this;
+ let parsePromise = XLF.parse(xlf.contents.toString());
+ parsePromises.push(parsePromise);
+ parsePromise.then(
+ resolvedFiles => {
+ resolvedFiles.forEach(file => {
+ if (path.basename(file.originalFilePath) === 'Default' && !innoSetupConfig.defaultInfo) {
+ return;
+ }
+ let translatedFile = createIslFile(file.originalFilePath, file.messages, language, innoSetupConfig);
+ stream.queue(translatedFile);
+ });
+ }
+ );
+ }, function () {
+ Promise.all(parsePromises)
+ .then(() => { this.queue(null); })
+ .catch(reason => { throw new Error(reason); });
+ });
+}
+
+function createIslFile(originalFilePath: string, messages: Map, language: Language, innoSetup: InnoSetup): File {
let content: string[] = [];
let originalContent: TextModel;
if (path.basename(originalFilePath) === 'Default') {
@@ -1054,13 +1298,12 @@ function createIslFile(base: string, originalFilePath: string, messages: Map {
if (line.length > 0) {
let firstChar = line.charAt(0);
if (firstChar === '[' || firstChar === ';') {
if (line === '; *** Inno Setup version 5.5.3+ English messages ***') {
- content.push(`; *** Inno Setup version 5.5.3+ ${languageNames[language]} messages ***`);
+ content.push(`; *** Inno Setup version 5.5.3+ ${innoSetup.defaultInfo.name} messages ***`);
} else {
content.push(line);
}
@@ -1070,11 +1313,11 @@ function createIslFile(base: string, originalFilePath: string, messages: Map').replace(/&/g, '&');
+}
+
+function pseudify(message: string) {
+ return '\uFF3B' + message.replace(/[aouei]/g, '$&$&') + '\uFF3D';
}
\ No newline at end of file
diff --git a/build/lib/nls.js b/build/lib/nls.js
index 2975c0dc52..67ef0476b2 100644
--- a/build/lib/nls.js
+++ b/build/lib/nls.js
@@ -79,7 +79,7 @@ function isImportNode(node) {
function fileFrom(file, contents, path) {
if (path === void 0) { path = file.path; }
return new File({
- contents: new Buffer(contents),
+ contents: Buffer.from(contents),
base: file.base,
cwd: file.cwd,
path: path
diff --git a/build/lib/nls.ts b/build/lib/nls.ts
index 45b34b3c32..a9b824fd2c 100644
--- a/build/lib/nls.ts
+++ b/build/lib/nls.ts
@@ -131,7 +131,7 @@ module nls {
export function fileFrom(file: File, contents: string, path: string = file.path) {
return new File({
- contents: new Buffer(contents),
+ contents: Buffer.from(contents),
base: file.base,
cwd: file.cwd,
path: path
diff --git a/build/lib/optimize.js b/build/lib/optimize.js
index d437e7a4f7..a75e31708d 100644
--- a/build/lib/optimize.js
+++ b/build/lib/optimize.js
@@ -59,7 +59,7 @@ function loader(bundledFileHeader, bundleLoader) {
this.emit('data', new VinylFile({
path: 'fake',
base: '',
- contents: new Buffer(bundledFileHeader)
+ contents: Buffer.from(bundledFileHeader)
}));
this.emit('data', data);
}
@@ -98,7 +98,7 @@ function toConcatStream(bundledFileHeader, sources, dest) {
return new VinylFile({
path: source.path ? root + '/' + source.path.replace(/\\/g, '/') : 'fake',
base: base,
- contents: new Buffer(source.contents)
+ contents: Buffer.from(source.contents)
});
});
return es.readArray(treatedSources)
@@ -141,7 +141,7 @@ function optimizeTask(opts) {
bundleInfoArray.push(new VinylFile({
path: 'bundleInfo.json',
base: '.',
- contents: new Buffer(JSON.stringify(result.bundleData, null, '\t'))
+ contents: Buffer.from(JSON.stringify(result.bundleData, null, '\t'))
}));
}
es.readArray(bundleInfoArray).pipe(bundleInfoStream);
@@ -174,7 +174,6 @@ function optimizeTask(opts) {
};
}
exports.optimizeTask = optimizeTask;
-;
/**
* Wrap around uglify and allow the preserveComments function
* to have a file "context" to include our copyright only once per file.
@@ -237,4 +236,3 @@ function minifyTask(src, sourceMapBaseUrl) {
};
}
exports.minifyTask = minifyTask;
-;
diff --git a/build/lib/optimize.ts b/build/lib/optimize.ts
index b290db31f5..924a7409a1 100644
--- a/build/lib/optimize.ts
+++ b/build/lib/optimize.ts
@@ -31,7 +31,7 @@ function log(prefix: string, message: string): void {
}
// {{SQL CARBON EDIT}}
-export function loaderConfig(emptyPaths: string[]) {
+export function loaderConfig(emptyPaths?: string[]) {
const result = {
paths: {
'vs': 'out-build/vs',
@@ -73,7 +73,7 @@ function loader(bundledFileHeader: string, bundleLoader: boolean): NodeJS.ReadWr
this.emit('data', new VinylFile({
path: 'fake',
base: '',
- contents: new Buffer(bundledFileHeader)
+ contents: Buffer.from(bundledFileHeader)
}));
this.emit('data', data);
} else {
@@ -117,7 +117,7 @@ function toConcatStream(bundledFileHeader: string, sources: bundle.IFile[], dest
return new VinylFile({
path: source.path ? root + '/' + source.path.replace(/\\/g, '/') : 'fake',
base: base,
- contents: new Buffer(source.contents)
+ contents: Buffer.from(source.contents)
});
});
@@ -165,7 +165,7 @@ export interface IOptimizeTaskOpts {
/**
* (languages to process)
*/
- languages: string[];
+ languages: i18n.Language[];
}
export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStream {
const entryPoints = opts.entryPoints;
@@ -201,7 +201,7 @@ export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStr
bundleInfoArray.push(new VinylFile({
path: 'bundleInfo.json',
base: '.',
- contents: new Buffer(JSON.stringify(result.bundleData, null, '\t'))
+ contents: Buffer.from(JSON.stringify(result.bundleData, null, '\t'))
}));
}
es.readArray(bundleInfoArray).pipe(bundleInfoStream);
@@ -241,7 +241,7 @@ export function optimizeTask(opts: IOptimizeTaskOpts): () => NodeJS.ReadWriteStr
}))
.pipe(gulp.dest(out));
};
-};
+}
declare class FileWithCopyright extends VinylFile {
public __hasOurCopyright: boolean;
@@ -295,7 +295,7 @@ function uglifyWithCopyrights(): NodeJS.ReadWriteStream {
return es.duplex(input, output);
}
-export function minifyTask(src: string, sourceMapBaseUrl: string): (cb: any) => void {
+export function minifyTask(src: string, sourceMapBaseUrl?: string): (cb: any) => void {
const sourceMappingURL = sourceMapBaseUrl && (f => `${sourceMapBaseUrl}/${f.relative}.map`);
return cb => {
@@ -326,4 +326,4 @@ export function minifyTask(src: string, sourceMapBaseUrl: string): (cb: any) =>
cb(err);
});
};
-};
+}
diff --git a/build/lib/typings/event-stream.d.ts b/build/lib/typings/event-stream.d.ts
index 7e5ccee5e1..d79ac9183d 100644
--- a/build/lib/typings/event-stream.d.ts
+++ b/build/lib/typings/event-stream.d.ts
@@ -1,7 +1,14 @@
declare module "event-stream" {
import { Stream } from 'stream';
- import { ThroughStream } from 'through';
+ import { ThroughStream as _ThroughStream} from 'through';
import { MapStream } from 'map-stream';
+ import * as File from 'vinyl';
+
+ export interface ThroughStream extends _ThroughStream {
+ queue(data: File | null);
+ push(data: File | null);
+ paused: boolean;
+ }
function merge(streams: Stream[]): ThroughStream;
function merge(...streams: Stream[]): ThroughStream;
diff --git a/build/lib/util.js b/build/lib/util.js
index f3437f0cb6..a81408fadb 100644
--- a/build/lib/util.js
+++ b/build/lib/util.js
@@ -143,7 +143,7 @@ function loadSourcemaps() {
cb(null, f);
return;
}
- f.contents = new Buffer(contents.replace(/\/\/# sourceMappingURL=(.*)$/g, ''), 'utf8');
+ f.contents = Buffer.from(contents.replace(/\/\/# sourceMappingURL=(.*)$/g, ''), 'utf8');
fs.readFile(path.join(path.dirname(f.path), lastMatch[1]), 'utf8', function (err, contents) {
if (err) {
return cb(err);
@@ -160,7 +160,7 @@ function stripSourceMappingURL() {
var output = input
.pipe(es.mapSync(function (f) {
var contents = f.contents.toString('utf8');
- f.contents = new Buffer(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, ''), 'utf8');
+ f.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, ''), 'utf8');
return f;
}));
return es.duplex(input, output);
@@ -173,7 +173,6 @@ function rimraf(dir) {
if (!err) {
return cb();
}
- ;
if (err.code === 'ENOTEMPTY' && ++retries < 5) {
return setTimeout(function () { return retry(cb); }, 10);
}
diff --git a/build/lib/util.ts b/build/lib/util.ts
index ac2dd31254..9fe54ac0f1 100644
--- a/build/lib/util.ts
+++ b/build/lib/util.ts
@@ -28,7 +28,7 @@ export interface IStreamProvider {
(cancellationToken?: ICancellationToken): NodeJS.ReadWriteStream;
}
-export function incremental(streamProvider: IStreamProvider, initial: NodeJS.ReadWriteStream, supportsCancellation: boolean): NodeJS.ReadWriteStream {
+export function incremental(streamProvider: IStreamProvider, initial: NodeJS.ReadWriteStream, supportsCancellation?: boolean): NodeJS.ReadWriteStream {
const input = es.through();
const output = es.through();
let state = 'idle';
@@ -129,7 +129,7 @@ export function skipDirectories(): NodeJS.ReadWriteStream {
});
}
-export function cleanNodeModule(name: string, excludes: string[], includes: string[]): NodeJS.ReadWriteStream {
+export function cleanNodeModule(name: string, excludes: string[], includes?: string[]): NodeJS.ReadWriteStream {
const toGlob = (path: string) => '**/node_modules/' + name + (path ? '/' + path : '');
const negate = (str: string) => '!' + str;
@@ -190,7 +190,7 @@ export function loadSourcemaps(): NodeJS.ReadWriteStream {
return;
}
- f.contents = new Buffer(contents.replace(/\/\/# sourceMappingURL=(.*)$/g, ''), 'utf8');
+ f.contents = Buffer.from(contents.replace(/\/\/# sourceMappingURL=(.*)$/g, ''), 'utf8');
fs.readFile(path.join(path.dirname(f.path), lastMatch[1]), 'utf8', (err, contents) => {
if (err) { return cb(err); }
@@ -209,7 +209,7 @@ export function stripSourceMappingURL(): NodeJS.ReadWriteStream {
const output = input
.pipe(es.mapSync(f => {
const contents = (f.contents).toString('utf8');
- f.contents = new Buffer(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, ''), 'utf8');
+ f.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, ''), 'utf8');
return f;
}));
@@ -223,7 +223,7 @@ export function rimraf(dir: string): (cb: any) => void {
_rimraf(dir, { maxBusyTries: 1 }, (err: any) => {
if (!err) {
return cb();
- };
+ }
if (err.code === 'ENOTEMPTY' && ++retries < 5) {
return setTimeout(() => retry(cb), 10);
diff --git a/build/lib/watch/index.js b/build/lib/watch/index.js
index 527a644b72..07e8803211 100644
--- a/build/lib/watch/index.js
+++ b/build/lib/watch/index.js
@@ -9,7 +9,7 @@ const es = require('event-stream');
function handleDeletions() {
return es.mapSync(f => {
if (/\.ts$/.test(f.relative) && !f.contents) {
- f.contents = new Buffer('');
+ f.contents = Buffer.from('');
f.stat = { mtime: new Date() };
}
diff --git a/build/lib/watch/watch-nsfw.js b/build/lib/watch/watch-nsfw.js
index bae517a291..13f3fcab32 100644
--- a/build/lib/watch/watch-nsfw.js
+++ b/build/lib/watch/watch-nsfw.js
@@ -30,12 +30,12 @@ function watch(root) {
path: path,
base: root
});
-
+ //@ts-ignore
file.event = type;
result.emit('data', file);
}
- nsfw(root, function(events) {
+ nsfw(root, function (events) {
for (var i = 0; i < events.length; i++) {
var e = events[i];
var changeType = e.action;
@@ -47,16 +47,16 @@ function watch(root) {
handleEvent(path.join(e.directory, e.file), toChangeType(changeType));
}
}
- }).then(function(watcher) {
+ }).then(function (watcher) {
watcher.start();
- });
+ });
- return result;
+ return result;
}
var cache = Object.create(null);
-module.exports = function(pattern, options) {
+module.exports = function (pattern, options) {
options = options || {};
var cwd = path.normalize(options.cwd || process.cwd());
@@ -66,7 +66,7 @@ module.exports = function(pattern, options) {
watcher = cache[cwd] = watch(cwd);
}
- var rebase = !options.base ? es.through() : es.mapSync(function(f) {
+ var rebase = !options.base ? es.through() : es.mapSync(function (f) {
f.base = options.base;
return f;
});
@@ -74,13 +74,13 @@ module.exports = function(pattern, options) {
return watcher
.pipe(filter(['**', '!.git{,/**}'])) // ignore all things git
.pipe(filter(pattern))
- .pipe(es.map(function(file, cb) {
- fs.stat(file.path, function(err, stat) {
+ .pipe(es.map(function (file, cb) {
+ fs.stat(file.path, function (err, stat) {
if (err && err.code === 'ENOENT') { return cb(null, file); }
if (err) { return cb(); }
if (!stat.isFile()) { return cb(); }
- fs.readFile(file.path, function(err, contents) {
+ fs.readFile(file.path, function (err, contents) {
if (err && err.code === 'ENOENT') { return cb(null, file); }
if (err) { return cb(); }
diff --git a/build/lib/watch/watch-win32.js b/build/lib/watch/watch-win32.js
index 2893ff6169..4ceb09c166 100644
--- a/build/lib/watch/watch-win32.js
+++ b/build/lib/watch/watch-win32.js
@@ -24,7 +24,8 @@ function watch(root) {
var result = es.through();
var child = cp.spawn(watcherPath, [root]);
- child.stdout.on('data', function(data) {
+ child.stdout.on('data', function (data) {
+ // @ts-ignore
var lines = data.toString('utf8').split('\n');
for (var i = 0; i < lines.length; i++) {
var line = lines[i].trim();
@@ -46,17 +47,17 @@ function watch(root) {
path: changePathFull,
base: root
});
-
+ //@ts-ignore
file.event = toChangeType(changeType);
result.emit('data', file);
}
});
- child.stderr.on('data', function(data) {
+ child.stderr.on('data', function (data) {
result.emit('error', data);
});
- child.on('exit', function(code) {
+ child.on('exit', function (code) {
result.emit('error', 'Watcher died with code ' + code);
child = null;
});
@@ -70,7 +71,7 @@ function watch(root) {
var cache = Object.create(null);
-module.exports = function(pattern, options) {
+module.exports = function (pattern, options) {
options = options || {};
var cwd = path.normalize(options.cwd || process.cwd());
diff --git a/build/monaco/LICENSE b/build/monaco/LICENSE
index 1df65d6ea3..0b52fb74a7 100644
--- a/build/monaco/LICENSE
+++ b/build/monaco/LICENSE
@@ -1 +1,21 @@
-See project root directory
\ No newline at end of file
+The Source EULA
+
+Copyright (c) 2016 Microsoft Corporation
+
+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.
diff --git a/build/monaco/ThirdPartyNotices.txt b/build/monaco/ThirdPartyNotices.txt
index 45eeffb9f3..bf7dd4a715 100644
--- a/build/monaco/ThirdPartyNotices.txt
+++ b/build/monaco/ThirdPartyNotices.txt
@@ -32,7 +32,7 @@ END OF winjs NOTICES AND INFORMATION
%% string_scorer version 0.1.20 (https://github.com/joshaven/string_score)
=========================================
-This software is released under the MIT license:
+This software is released under the Source EULA:
Copyright (c) Joshaven Potter
@@ -60,7 +60,7 @@ END OF string_scorer NOTICES AND INFORMATION
%% chjj-marked NOTICES AND INFORMATION BEGIN HERE
=========================================
-The MIT License (MIT)
+The Source EULA
Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/)
diff --git a/build/monaco/monaco.d.ts.recipe b/build/monaco/monaco.d.ts.recipe
index 30689943c1..1e03407dff 100644
--- a/build/monaco/monaco.d.ts.recipe
+++ b/build/monaco/monaco.d.ts.recipe
@@ -62,19 +62,24 @@ export interface ICommandHandler {
#include(vs/editor/standalone/browser/colorizer): IColorizerOptions, IColorizerElementOptions
#include(vs/base/common/scrollable): ScrollbarVisibility
#include(vs/platform/theme/common/themeService): ThemeColor
-#includeAll(vs/editor/common/editorCommon;IMode=>languages.IMode;LanguageIdentifier=>languages.LanguageIdentifier;editorOptions.=>): ISelection, IScrollEvent
+#includeAll(vs/editor/common/model;LanguageIdentifier=>languages.LanguageIdentifier): IScrollEvent
+#includeAll(vs/editor/common/editorCommon;editorOptions.=>): IScrollEvent
#includeAll(vs/editor/common/model/textModelEvents):
#includeAll(vs/editor/common/controller/cursorEvents):
#includeAll(vs/editor/common/config/editorOptions):
#includeAll(vs/editor/browser/editorBrowser;editorCommon.=>;editorOptions.=>):
#include(vs/editor/common/config/fontInfo): FontInfo, BareFontInfo
+
+//compatibility:
+export type IReadOnlyModel = ITextModel;
+export type IModel = ITextModel;
}
declare module monaco.languages {
-#includeAll(vs/editor/standalone/browser/standaloneLanguages;modes.=>;editorCommon.=>editor.;IMarkerData=>editor.IMarkerData):
+#includeAll(vs/editor/standalone/browser/standaloneLanguages;modes.=>;editorCommon.=>editor.;model.=>editor.;IMarkerData=>editor.IMarkerData):
#includeAll(vs/editor/common/modes/languageConfiguration):
-#includeAll(vs/editor/common/modes;editorCommon.IRange=>IRange;editorCommon.IPosition=>IPosition;editorCommon.=>editor.;IMarkerData=>editor.IMarkerData):
+#includeAll(vs/editor/common/modes;editorCommon.IRange=>IRange;editorCommon.IPosition=>IPosition;editorCommon.=>editor.;IMarkerData=>editor.IMarkerData;model.=>editor.):
#include(vs/editor/common/services/modeService): ILanguageExtensionPoint
#includeAll(vs/editor/standalone/common/monarch/monarchTypes):
diff --git a/build/npm/postinstall.js b/build/npm/postinstall.js
index 219a7b3d7f..c1039d0594 100644
--- a/build/npm/postinstall.js
+++ b/build/npm/postinstall.js
@@ -26,10 +26,11 @@ yarnInstall('extensions'); // node modules shared by all extensions
const extensions = [
'vscode-colorize-tests',
'json',
- 'mssql',
+ 'mssql',
'configuration-editing',
'extension-editing',
'markdown',
+ 'markdown-basics',
'git',
'merge-conflict',
'insights-default',
@@ -42,6 +43,7 @@ extensions.forEach(extension => yarnInstall(`extensions/${extension}`));
function yarnInstallBuildDependencies() {
// make sure we install the deps of build/lib/watch for the system installed
// node, since that is the driver of gulp
+ //@ts-ignore
const env = Object.assign({}, process.env);
const watchPath = path.join(path.dirname(__dirname), 'lib', 'watch');
const yarnrcPath = path.join(watchPath, '.yarnrc');
@@ -59,4 +61,5 @@ runtime "${runtime}"`;
}
yarnInstall(`build`); // node modules required for build
+yarnInstall('test/smoke'); // node modules required for smoketest
yarnInstallBuildDependencies(); // node modules for watching, specific to host node version, not electron
\ No newline at end of file
diff --git a/build/npm/update-all-grammars.js b/build/npm/update-all-grammars.js
index 8ca08de9a6..861496f1b9 100644
--- a/build/npm/update-all-grammars.js
+++ b/build/npm/update-all-grammars.js
@@ -4,9 +4,11 @@
*--------------------------------------------------------------------------------------------*/
const cp = require('child_process');
-const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
+const fs = require('fs');
+const path = require('path');
function updateGrammar(location) {
+ const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
const result = cp.spawnSync(npm, ['run', 'update-grammar'], {
cwd: location,
stdio: 'inherit'
@@ -17,50 +19,17 @@ function updateGrammar(location) {
}
}
-const extensions = [
- 'bat',
- 'clojure',
- 'coffeescript',
- 'cpp',
- 'csharp',
- 'css',
- 'diff',
- 'docker',
- 'fsharp',
- 'gitsyntax',
- 'go',
- 'groovy',
- 'handlebars',
- 'hlsl',
- 'html',
- 'ini',
- 'java',
- // 'javascript', updated through JavaScript
- 'json',
- 'less',
- 'lua',
- 'make',
- 'markdown',
- 'objective-c',
- 'perl',
- 'php',
- // 'powershell', grammar not ready yet, @daviwil will ping when ready
- 'pug',
- 'python',
- 'r',
- 'razor',
- 'ruby',
- 'rust',
- 'scss',
- 'shaderlab',
- 'shellscript',
- 'sql',
- 'swift',
- 'typescript',
- 'vb',
- 'xml',
- 'yaml'
-];
+const allExtensionFolders = fs.readdirSync('extensions');
+const extensions = allExtensionFolders.filter(e => {
+ try {
+ let packageJSON = JSON.parse(fs.readFileSync(path.join('extensions', e, 'package.json')).toString());
+ return packageJSON && packageJSON.scripts && packageJSON.scripts['update-grammar'];
+ } catch (e) {
+ return false;
+ }
+});
+
+console.log(`Updating ${extensions.length} grammars...`);
extensions.forEach(extension => updateGrammar(`extensions/${extension}`));
@@ -70,4 +39,5 @@ if (process.platform === 'win32') {
cp.spawn('.\scripts\test-integration.bat', [], { env: process.env, stdio: 'inherit' });
} else {
cp.spawn('/bin/bash', ['./scripts/test-integration.sh'], { env: process.env, stdio: 'inherit' });
-}
\ No newline at end of file
+}
+
diff --git a/build/npm/update-grammar.js b/build/npm/update-grammar.js
index df6fe0c29b..f6490f626e 100644
--- a/build/npm/update-grammar.js
+++ b/build/npm/update-grammar.js
@@ -14,14 +14,19 @@ var url = require('url');
function getOptions(urlString) {
var _url = url.parse(urlString);
+ var headers = {
+ 'User-Agent': 'VSCode'
+ };
+ var token = process.env['GITHUB_TOKEN'];
+ if (token) {
+ headers['Authorization'] = 'token ' + token
+ }
return {
protocol: _url.protocol,
host: _url.host,
port: _url.port,
path: _url.path,
- headers: {
- 'User-Agent': 'NodeJS'
- }
+ headers: headers
};
}
@@ -32,12 +37,16 @@ function download(url, redirectCount) {
response.on('data', function (data) {
content += data.toString();
}).on('end', function () {
+ if (response.statusCode === 403 && response.headers['x-ratelimit-remaining'] === '0') {
+ e('GitHub API rate exceeded. Set GITHUB_TOKEN environment variable to increase rate limit.');
+ return;
+ }
let count = redirectCount || 0;
if (count < 5 && response.statusCode >= 300 && response.statusCode <= 303 || response.statusCode === 307) {
let location = response.headers['location'];
if (location) {
console.log("Redirected " + url + " to " + location);
- download(location, count+1).then(c, e);
+ download(location, count + 1).then(c, e);
return;
}
}
@@ -59,17 +68,13 @@ function getCommitSha(repoId, repoPath) {
commitDate: lastCommit.commit.author.date
});
} catch (e) {
- console.error("Failed extracting the SHA: " + content);
- return Promise.resolve(null);
+ return Promise.reject(new Error("Failed extracting the SHA: " + content));
}
- }, function () {
- console.error('Failed loading ' + commitInfo);
- return Promise.resolve(null);
});
}
-exports.update = function (repoId, repoPath, dest, modifyGrammar) {
- var contentPath = 'https://raw.githubusercontent.com/' + repoId + '/master/' + repoPath;
+exports.update = function (repoId, repoPath, dest, modifyGrammar, version = 'master') {
+ var contentPath = 'https://raw.githubusercontent.com/' + repoId + `/${version}/` + repoPath;
console.log('Reading from ' + contentPath);
return download(contentPath).then(function (content) {
var ext = path.extname(repoPath);
@@ -81,8 +86,7 @@ exports.update = function (repoId, repoPath, dest, modifyGrammar) {
} else if (ext === '.json') {
grammar = JSON.parse(content);
} else {
- console.error('Unknown file extension: ' + ext);
- return;
+ return Promise.reject(new Error('Unknown file extension: ' + ext));
}
if (modifyGrammar) {
modifyGrammar(grammar);
@@ -99,8 +103,10 @@ exports.update = function (repoId, repoPath, dest, modifyGrammar) {
if (info) {
result.version = 'https://github.com/' + repoId + '/commit/' + info.commitSha;
}
- for (let key in grammar) {
- if (!result.hasOwnProperty(key)) {
+
+ let keys = ['name', 'scopeName', 'comment', 'injections', 'patterns', 'repository'];
+ for (let key of keys) {
+ if (grammar.hasOwnProperty(key)) {
result[key] = grammar[key];
}
}
@@ -113,11 +119,14 @@ exports.update = function (repoId, repoPath, dest, modifyGrammar) {
console.log('Updated ' + path.basename(dest));
}
} catch (e) {
- console.error(e);
+ return Promise.reject(e);
}
});
- }, console.error);
+ }, console.error).catch(e => {
+ console.error(e);
+ process.exit(1);
+ });
};
if (path.basename(process.argv[1]) === 'update-grammar.js') {
diff --git a/build/npm/update-localization-extension.js b/build/npm/update-localization-extension.js
new file mode 100644
index 0000000000..5e656907d0
--- /dev/null
+++ b/build/npm/update-localization-extension.js
@@ -0,0 +1,69 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+'use strict';
+
+let i18n = require("../lib/i18n");
+
+let fs = require("fs");
+let path = require("path");
+let vfs = require("vinyl-fs");
+let rimraf = require('rimraf');
+
+function update(idOrPath) {
+ if (!idOrPath) {
+ throw new Error('Argument must be the location of the localization extension.');
+ }
+ let locExtFolder = idOrPath;
+ if (/^\w{2}(-\w+)?$/.test(idOrPath)) {
+ locExtFolder = '../vscode-language-pack-' + idOrPath;
+ }
+ let locExtStat = fs.statSync(locExtFolder);
+ if (!locExtStat || !locExtStat.isDirectory) {
+ throw new Error('No directory found at ' + idOrPath);
+ }
+ let packageJSON = JSON.parse(fs.readFileSync(path.join(locExtFolder, 'package.json')).toString());
+ let contributes = packageJSON['contributes'];
+ if (!contributes) {
+ throw new Error('The extension must define a "localizations" contribution in the "package.json"');
+ }
+ let localizations = contributes['localizations'];
+ if (!localizations) {
+ throw new Error('The extension must define a "localizations" contribution of type array in the "package.json"');
+ }
+
+ localizations.forEach(function (localization) {
+ if (!localization.languageId || !localization.languageName || !localization.localizedLanguageName) {
+ throw new Error('Each localization contribution must define "languageId", "languageName" and "localizedLanguageName" properties.');
+ }
+ let server = localization.server || 'www.transifex.com';
+ let userName = localization.userName || 'api';
+ let apiToken = process.env.TRANSIFEX_API_TOKEN;
+ let languageId = localization.transifexId || localization.languageId;
+ let translationDataFolder = path.join(locExtFolder, 'translations');
+
+ if (fs.existsSync(translationDataFolder) && fs.existsSync(path.join(translationDataFolder, 'main.i18n.json'))) {
+ console.log('Clearing \'' + translationDataFolder + '\'...');
+ rimraf.sync(translationDataFolder);
+ }
+
+ console.log('Downloading translations for \'' + languageId + '\' to \'' + translationDataFolder + '\'...');
+ const translationPaths = [];
+ i18n.pullI18nPackFiles(server, userName, apiToken, { id: languageId }, translationPaths)
+ .pipe(vfs.dest(translationDataFolder)).on('end', function () {
+ localization.translations = [];
+ for (let tp of translationPaths) {
+ localization.translations.push({ id: tp.id, path: `./translations/${tp.resourceName}`});
+ }
+ fs.writeFileSync(path.join(locExtFolder, 'package.json'), JSON.stringify(packageJSON, null, '\t'));
+ });
+
+ });
+
+
+}
+if (path.basename(process.argv[1]) === 'update-localization-extension.js') {
+ update(process.argv[2]);
+}
diff --git a/build/package.json b/build/package.json
index c2c3162c25..0415c4e1be 100644
--- a/build/package.json
+++ b/build/package.json
@@ -21,8 +21,9 @@
"xml2js": "^0.4.17"
},
"scripts": {
- "compile": "tsc",
- "watch": "tsc --watch",
- "postinstall": "npm run compile"
+ "compile": "tsc -p tsconfig.build.json",
+ "watch": "tsc -p tsconfig.build.json --watch",
+ "postinstall": "npm run compile",
+ "npmCheckJs": "tsc --noEmit"
}
}
\ No newline at end of file
diff --git a/build/tfs/common/node.sh b/build/tfs/common/node.sh
index 23404689de..cc1bb74d01 100644
--- a/build/tfs/common/node.sh
+++ b/build/tfs/common/node.sh
@@ -4,9 +4,9 @@ set -e
# setup nvm
if [[ "$OSTYPE" == "darwin"* ]]; then
export NVM_DIR=~/.nvm
- source $(brew --prefix nvm)/nvm.sh
+ source $(brew --prefix nvm)/nvm.sh --no-use
else
- source $NVM_DIR/nvm.sh
+ source $NVM_DIR/nvm.sh --no-use
fi
# install node
diff --git a/build/tfs/common/publish.ts b/build/tfs/common/publish.ts
index f03132b7cd..650c7d3ef1 100644
--- a/build/tfs/common/publish.ts
+++ b/build/tfs/common/publish.ts
@@ -70,6 +70,7 @@ interface Asset {
hash: string;
sha256hash: string;
size: number;
+ supportsFastUpdate?: boolean;
}
function createOrUpdate(commit: string, quality: string, platform: string, type: string, release: NewDocument, asset: Asset, isUpdate: boolean): Promise {
@@ -203,17 +204,30 @@ async function publish(commit: string, quality: string, platform: string, type:
// mooncake is fussy and far away, this is needed!
mooncakeBlobService.defaultClientRequestTimeoutInMs = 10 * 60 * 1000;
- await assertContainer(mooncakeBlobService, quality);
+ await Promise.all([
+ assertContainer(blobService, quality),
+ assertContainer(mooncakeBlobService, quality)
+ ]);
- const mooncakeBlobExists = await doesAssetExist(mooncakeBlobService, quality, blobName);
+ const [blobExists, moooncakeBlobExists] = await Promise.all([
+ doesAssetExist(blobService, quality, blobName),
+ doesAssetExist(mooncakeBlobService, quality, blobName)
+ ]);
- if (!mooncakeBlobExists) {
+ const promises = [];
+
+ if (!blobExists) {
+ promises.push(uploadBlob(blobService, quality, blobName, file));
+ }
+
+ if (!moooncakeBlobExists) {
promises.push(uploadBlob(mooncakeBlobService, quality, blobName, file));
}
} else {
console.log('Skipping Mooncake publishing.');
}
+
if (promises.length === 0) {
console.log(`Blob ${quality}, ${blobName} already exists, not publishing again.`);
return;
@@ -240,6 +254,13 @@ async function publish(commit: string, quality: string, platform: string, type:
size
};
+ // Remove this if we ever need to rollback fast updates for windows
+ if (/win32/.test(platform)) {
+ asset.supportsFastUpdate = true;
+ }
+
+ console.log('Asset:', JSON.stringify(asset, null, ' '));
+
const release = {
id: commit,
timestamp: (new Date()).getTime(),
diff --git a/build/tfs/darwin/build.sh b/build/tfs/darwin/build.sh
index b7d45aad6e..9c0b7a6f52 100644
--- a/build/tfs/darwin/build.sh
+++ b/build/tfs/darwin/build.sh
@@ -19,6 +19,9 @@ step "Install dependencies" \
step "Hygiene" \
npm run gulp -- hygiene
+step "Monaco Editor Check" \
+ ./node_modules/.bin/tsc -p ./src/tsconfig.monaco.json --noEmit
+
step "Mix in repository from vscode-distro" \
npm run gulp -- mixin
diff --git a/build/tfs/linux/build.sh b/build/tfs/linux/build.sh
index 9d9b33de8a..e23049b5cf 100644
--- a/build/tfs/linux/build.sh
+++ b/build/tfs/linux/build.sh
@@ -22,6 +22,9 @@ step "Install dependencies" \
step "Hygiene" \
npm run gulp -- hygiene
+step "Monaco Editor Check" \
+ ./node_modules/.bin/tsc -p ./src/tsconfig.monaco.json --noEmit
+
step "Mix in repository from vscode-distro" \
npm run gulp -- mixin
diff --git a/build/tfs/win32/1_build.ps1 b/build/tfs/win32/1_build.ps1
index 0dac2d1fcb..0fcb56c1b9 100644
--- a/build/tfs/win32/1_build.ps1
+++ b/build/tfs/win32/1_build.ps1
@@ -24,6 +24,10 @@ step "Hygiene" {
exec { & npm run gulp -- hygiene }
}
+step "Monaco Editor Check" {
+ exec { & .\node_modules\.bin\tsc -p .\src\tsconfig.monaco.json --noEmit }
+}
+
$env:VSCODE_MIXIN_PASSWORD = $mixinPassword
step "Mix in repository from vscode-distro" {
exec { & npm run gulp -- mixin }
@@ -41,6 +45,10 @@ step "Build minified" {
exec { & npm run gulp -- "vscode-win32-$global:arch-min" }
}
+step "Copy Inno updater" {
+ exec { & npm run gulp -- "vscode-win32-$global:arch-copy-inno-updater" }
+}
+
# step "Create loader snapshot" {
# exec { & node build\lib\snapshotLoader.js --arch=$global:arch }
# }
diff --git a/build/tfs/win32/node.ps1 b/build/tfs/win32/node.ps1
index fdfe25ae36..14ccd0008b 100644
--- a/build/tfs/win32/node.ps1
+++ b/build/tfs/win32/node.ps1
@@ -1,7 +1,7 @@
# install node
$env:Path = $env:NVM_HOME + ";" + $env:NVM_SYMLINK + ";" + $env:Path
$NodeVersion = "8.9.1"
-nvm install $NodeVersion
-nvm use $NodeVersion
-npm install -g yarn
+# nvm install $NodeVersion
+# nvm use $NodeVersion
+# npm install -g yarn
$env:Path = $env:NVM_HOME + "\v" + $NodeVersion + ";" + $env:Path
\ No newline at end of file
diff --git a/build/tsconfig.build.json b/build/tsconfig.build.json
new file mode 100644
index 0000000000..2402a09288
--- /dev/null
+++ b/build/tsconfig.build.json
@@ -0,0 +1,7 @@
+{
+ "extends": "./tsconfig.json",
+ "compilerOptions": {
+ "allowJs": false,
+ "checkJs": false
+ }
+}
\ No newline at end of file
diff --git a/build/tsconfig.json b/build/tsconfig.json
index 04f3963055..b68c9b6daf 100644
--- a/build/tsconfig.json
+++ b/build/tsconfig.json
@@ -7,7 +7,12 @@
"preserveConstEnums": true,
"sourceMap": false,
"experimentalDecorators": true,
- "newLine": "LF"
+ "newLine": "LF",
+ // enable JavaScript type checking for the language service
+ // use the tsconfig.build.json for compiling wich disable JavaScript
+ // type checking so that JavaScript file are not transpiled
+ "allowJs": true,
+ "checkJs": true
},
"exclude": [
"node_modules/**"
diff --git a/build/tslint.json b/build/tslint.json
index a85e98b95d..1527527913 100644
--- a/build/tslint.json
+++ b/build/tslint.json
@@ -9,5 +9,6 @@
"always"
],
"triple-equals": true
- }
+ },
+ "defaultSeverity": "warning"
}
\ No newline at end of file
diff --git a/build/win32/OSSREADME.json b/build/win32/OSSREADME.json
new file mode 100644
index 0000000000..e1dbed4b2c
--- /dev/null
+++ b/build/win32/OSSREADME.json
@@ -0,0 +1,1794 @@
+[
+ {
+ "name": "dtolnay/isatty",
+ "version": "0.1.6",
+ "repositoryUrl": "https://github.com/dtolnay/isatty",
+ "licenseDetail": [
+ "Copyright (c) 2016",
+ "",
+ "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": "rust-num/num-integer",
+ "version": "0.1.35",
+ "repositoryUrl": "https://github.com/rust-num/num-integer",
+ "licenseDetail": [
+ "Copyright (c) 2014 The Rust Project 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": "rust-lang-nursery/lazy-static.rs",
+ "version": "1.0.0",
+ "repositoryUrl": "https://github.com/rust-lang-nursery/lazy-static.rs",
+ "licenseDetail": [
+ "Copyright (c) 2010 The Rust Project 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": "rust-lang/libc",
+ "version": "0.2.36",
+ "repositoryUrl": "https://github.com/rust-lang/libc",
+ "licenseDetail": [
+ "Copyright (c) 2014 The Rust Project 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",
+ "",
+ "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": "mrhooray/crc-rs",
+ "version": "1.7.0",
+ "repositoryUrl": "https://github.com/mrhooray/crc-rs.git",
+ "licenseDetail": [
+ "MIT License",
+ "",
+ "Copyright (c) 2017 crc-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": "rust-num/num",
+ "version": "0.1.41",
+ "repositoryUrl": "https://github.com/rust-num/num",
+ "licenseDetail": [
+ "Copyright (c) 2014 The Rust Project 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": "BurntSushi/byteorder",
+ "version": "1.2.1",
+ "repositoryUrl": "https://github.com/BurntSushi/byteorder",
+ "licenseDetail": [
+ "The Source EULA",
+ "",
+ "Copyright (c) 2015 Andrew Gallant",
+ "",
+ "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": "rust-num/num-traits",
+ "version": "0.1.42",
+ "repositoryUrl": "https://github.com/rust-num/num-traits",
+ "licenseDetail": [
+ "Copyright (c) 2014 The Rust Project 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": "slog-rs/slog",
+ "version": "2.1.1",
+ "repositoryUrl": "https://github.com/slog-rs/slog",
+ "licenseDetail": [
+ "Copyright (c) 2014 The Rust Project 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": "rust-num/num-iter",
+ "version": "0.1.34",
+ "repositoryUrl": "https://github.com/rust-num/num-iter",
+ "licenseDetail": [
+ "Copyright (c) 2014 The Rust Project 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": "vitiral/build_const",
+ "version": "0.2.0",
+ "repositoryUrl": "https://github.com/vitiral/build_const",
+ "licenseDetail": [
+ "The Source EULA",
+ "",
+ "Copyright (c) 2017 Garrett Berg, vitiral@gmail.com",
+ "",
+ "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": "redox-os/termios",
+ "version": "0.1.1",
+ "repositoryUrl": "https://github.com/redox-os/termios",
+ "licenseDetail": [
+ "MIT License",
+ "",
+ "Copyright (c) 2017 Redox OS",
+ "",
+ "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": "redox-os/syscall",
+ "version": "0.1.37",
+ "repositoryUrl": "https://github.com/redox-os/syscall",
+ "licenseDetail": [
+ "Copyright (c) 2017 Redox OS Developers",
+ "",
+ "MIT License",
+ "",
+ "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": "Stebalien/term",
+ "version": "0.4.6",
+ "repositoryUrl": "https://github.com/Stebalien/term",
+ "licenseDetail": [
+ "Copyright (c) 2014 The Rust Project 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": "chronotope/chrono",
+ "version": "0.4.0",
+ "repositoryUrl": "https://github.com/chronotope/chrono",
+ "licenseDetail": [
+ "Rust-chrono is dual-licensed under The Source EULA [1] and",
+ "Apache 2.0 License [2]. Copyright (c) 2014--2017, Kang Seonghoon and",
+ "contributors.",
+ "",
+ "Nota Bene: This is same as the Rust Project's own license.",
+ "",
+ "",
+ "[1]: , which is reproduced below:",
+ "",
+ "~~~~",
+ "The Source EULA",
+ "",
+ "Copyright (c) 2014, Kang Seonghoon.",
+ "",
+ "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.",
+ "~~~~",
+ "",
+ "",
+ "[2]: , which is reproduced below:",
+ "",
+ "~~~~",
+ " Apache License",
+ " Version 2.0, January 2004",
+ " http://www.apache.org/licenses/",
+ "",
+ "TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION",
+ "",
+ "1. Definitions.",
+ "",
+ " \"License\" shall mean the terms and conditions for use, reproduction,",
+ " and distribution as defined by Sections 1 through 9 of this document.",
+ "",
+ " \"Licensor\" shall mean the copyright owner or entity authorized by",
+ " the copyright owner that is granting the License.",
+ "",
+ " \"Legal Entity\" shall mean the union of the acting entity and all",
+ " other entities that control, are controlled by, or are under common",
+ " control with that entity. For the purposes of this definition,",
+ " \"control\" means (i) the power, direct or indirect, to cause the",
+ " direction or management of such entity, whether by contract or",
+ " otherwise, or (ii) ownership of fifty percent (50%) or more of the",
+ " outstanding shares, or (iii) beneficial ownership of such entity.",
+ "",
+ " \"You\" (or \"Your\") shall mean an individual or Legal Entity",
+ " exercising permissions granted by this License.",
+ "",
+ " \"Source\" form shall mean the preferred form for making modifications,",
+ " including but not limited to software source code, documentation",
+ " source, and configuration files.",
+ "",
+ " \"Object\" form shall mean any form resulting from mechanical",
+ " transformation or translation of a Source form, including but",
+ " not limited to compiled object code, generated documentation,",
+ " and conversions to other media types.",
+ "",
+ " \"Work\" shall mean the work of authorship, whether in Source or",
+ " Object form, made available under the License, as indicated by a",
+ " copyright notice that is included in or attached to the work",
+ " (an example is provided in the Appendix below).",
+ "",
+ " \"Derivative Works\" shall mean any work, whether in Source or Object",
+ " form, that is based on (or derived from) the Work and for which the",
+ " editorial revisions, annotations, elaborations, or other modifications",
+ " represent, as a whole, an original work of authorship. For the purposes",
+ " of this License, Derivative Works shall not include works that remain",
+ " separable from, or merely link (or bind by name) to the interfaces of,",
+ " the Work and Derivative Works thereof.",
+ "",
+ " \"Contribution\" shall mean any work of authorship, including",
+ " the original version of the Work and any modifications or additions",
+ " to that Work or Derivative Works thereof, that is intentionally",
+ " submitted to Licensor for inclusion in the Work by the copyright owner",
+ " or by an individual or Legal Entity authorized to submit on behalf of",
+ " the copyright owner. For the purposes of this definition, \"submitted\"",
+ " means any form of electronic, verbal, or written communication sent",
+ " to the Licensor or its representatives, including but not limited to",
+ " communication on electronic mailing lists, source code control systems,",
+ " and issue tracking systems that are managed by, or on behalf of, the",
+ " Licensor for the purpose of discussing and improving the Work, but",
+ " excluding communication that is conspicuously marked or otherwise",
+ " designated in writing by the copyright owner as \"Not a Contribution.\"",
+ "",
+ " \"Contributor\" shall mean Licensor and any individual or Legal Entity",
+ " on behalf of whom a Contribution has been received by Licensor and",
+ " subsequently incorporated within the Work.",
+ "",
+ "2. Grant of Copyright License. Subject to the terms and conditions of",
+ " this License, each Contributor hereby grants to You a perpetual,",
+ " worldwide, non-exclusive, no-charge, royalty-free, irrevocable",
+ " copyright license to reproduce, prepare Derivative Works of,",
+ " publicly display, publicly perform, sublicense, and distribute the",
+ " Work and such Derivative Works in Source or Object form.",
+ "",
+ "3. Grant of Patent License. Subject to the terms and conditions of",
+ " this License, each Contributor hereby grants to You a perpetual,",
+ " worldwide, non-exclusive, no-charge, royalty-free, irrevocable",
+ " (except as stated in this section) patent license to make, have made,",
+ " use, offer to sell, sell, import, and otherwise transfer the Work,",
+ " where such license applies only to those patent claims licensable",
+ " by such Contributor that are necessarily infringed by their",
+ " Contribution(s) alone or by combination of their Contribution(s)",
+ " with the Work to which such Contribution(s) was submitted. If You",
+ " institute patent litigation against any entity (including a",
+ " cross-claim or counterclaim in a lawsuit) alleging that the Work",
+ " or a Contribution incorporated within the Work constitutes direct",
+ " or contributory patent infringement, then any patent licenses",
+ " granted to You under this License for that Work shall terminate",
+ " as of the date such litigation is filed.",
+ "",
+ "4. Redistribution. You may reproduce and distribute copies of the",
+ " Work or Derivative Works thereof in any medium, with or without",
+ " modifications, and in Source or Object form, provided that You",
+ " meet the following conditions:",
+ "",
+ " (a) You must give any other recipients of the Work or",
+ " Derivative Works a copy of this License; and",
+ "",
+ " (b) You must cause any modified files to carry prominent notices",
+ " stating that You changed the files; and",
+ "",
+ " (c) You must retain, in the Source form of any Derivative Works",
+ " that You distribute, all copyright, patent, trademark, and",
+ " attribution notices from the Source form of the Work,",
+ " excluding those notices that do not pertain to any part of",
+ " the Derivative Works; and",
+ "",
+ " (d) If the Work includes a \"NOTICE\" text file as part of its",
+ " distribution, then any Derivative Works that You distribute must",
+ " include a readable copy of the attribution notices contained",
+ " within such NOTICE file, excluding those notices that do not",
+ " pertain to any part of the Derivative Works, in at least one",
+ " of the following places: within a NOTICE text file distributed",
+ " as part of the Derivative Works; within the Source form or",
+ " documentation, if provided along with the Derivative Works; or,",
+ " within a display generated by the Derivative Works, if and",
+ " wherever such third-party notices normally appear. The contents",
+ " of the NOTICE file are for informational purposes only and",
+ " do not modify the License. You may add Your own attribution",
+ " notices within Derivative Works that You distribute, alongside",
+ " or as an addendum to the NOTICE text from the Work, provided",
+ " that such additional attribution notices cannot be construed",
+ " as modifying the License.",
+ "",
+ " You may add Your own copyright statement to Your modifications and",
+ " may provide additional or different license terms and conditions",
+ " for use, reproduction, or distribution of Your modifications, or",
+ " for any such Derivative Works as a whole, provided Your use,",
+ " reproduction, and distribution of the Work otherwise complies with",
+ " the conditions stated in this License.",
+ "",
+ "5. Submission of Contributions. Unless You explicitly state otherwise,",
+ " any Contribution intentionally submitted for inclusion in the Work",
+ " by You to the Licensor shall be under the terms and conditions of",
+ " this License, without any additional terms or conditions.",
+ " Notwithstanding the above, nothing herein shall supersede or modify",
+ " the terms of any separate license agreement you may have executed",
+ " with Licensor regarding such Contributions.",
+ "",
+ "6. Trademarks. This License does not grant permission to use the trade",
+ " names, trademarks, service marks, or product names of the Licensor,",
+ " except as required for reasonable and customary use in describing the",
+ " origin of the Work and reproducing the content of the NOTICE file.",
+ "",
+ "7. Disclaimer of Warranty. Unless required by applicable law or",
+ " agreed to in writing, Licensor provides the Work (and each",
+ " Contributor provides its Contributions) on an \"AS IS\" BASIS,",
+ " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or",
+ " implied, including, without limitation, any warranties or conditions",
+ " of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A",
+ " PARTICULAR PURPOSE. You are solely responsible for determining the",
+ " appropriateness of using or redistributing the Work and assume any",
+ " risks associated with Your exercise of permissions under this License.",
+ "",
+ "8. Limitation of Liability. In no event and under no legal theory,",
+ " whether in tort (including negligence), contract, or otherwise,",
+ " unless required by applicable law (such as deliberate and grossly",
+ " negligent acts) or agreed to in writing, shall any Contributor be",
+ " liable to You for damages, including any direct, indirect, special,",
+ " incidental, or consequential damages of any character arising as a",
+ " result of this License or out of the use or inability to use the",
+ " Work (including but not limited to damages for loss of goodwill,",
+ " work stoppage, computer failure or malfunction, or any and all",
+ " other commercial damages or losses), even if such Contributor",
+ " has been advised of the possibility of such damages.",
+ "",
+ "9. Accepting Warranty or Additional Liability. While redistributing",
+ " the Work or Derivative Works thereof, You may choose to offer,",
+ " and charge a fee for, acceptance of support, warranty, indemnity,",
+ " or other liability obligations and/or rights consistent with this",
+ " License. However, in accepting such obligations, You may act only",
+ " on Your own behalf and on Your sole responsibility, not on behalf",
+ " of any other Contributor, and only if You agree to indemnify,",
+ " defend, and hold each Contributor harmless for any liability",
+ " incurred by, or claims asserted against, such Contributor by reason",
+ " of your accepting any such warranty or additional liability.",
+ "",
+ "END OF TERMS AND CONDITIONS",
+ "",
+ "APPENDIX: How to apply the Apache License to your work.",
+ "",
+ " To apply the Apache License to your work, attach the following",
+ " boilerplate notice, with the fields enclosed by brackets \"[]\"",
+ " replaced with your own identifying information. (Don't include",
+ " the brackets!) The text should be enclosed in the appropriate",
+ " comment syntax for the file format. We also recommend that a",
+ " file or class name and description of purpose be included on the",
+ " same \"printed page\" as the copyright notice for easier",
+ " identification within third-party archives.",
+ "",
+ "Copyright [yyyy] [name of copyright owner]",
+ "",
+ "Licensed under the Apache License, Version 2.0 (the \"License\");",
+ "you may not use this file except in compliance with the License.",
+ "You may obtain a copy of the License at",
+ "",
+ "\thttp://www.apache.org/licenses/LICENSE-2.0",
+ "",
+ "Unless required by applicable law or agreed to in writing, software",
+ "distributed under the License is distributed on an \"AS IS\" BASIS,",
+ "WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.",
+ "See the License for the specific language governing permissions and",
+ "limitations under the License.",
+ "~~~~"
+ ],
+ "isProd": true
+ },
+ {
+ "name": "Amanieu/thread_local-rs",
+ "version": "0.3.5",
+ "repositoryUrl": "https://github.com/Amanieu/thread_local-rs",
+ "licenseDetail": [
+ "Copyright (c) 2016 The Rust Project 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": "Sgeo/take_mut",
+ "version": "0.2.0",
+ "repositoryUrl": "https://github.com/Sgeo/take_mut",
+ "licenseDetail": [
+ "The Source EULA",
+ "",
+ "Copyright (c) 2016 Sgeo",
+ "",
+ "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": "reem/rust-void",
+ "version": "1.0.2",
+ "repositoryUrl": "https://github.com/reem/rust-void.git",
+ "licenseDetail": [
+ "Copyright (c) 2015 The rust-void 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": "reem/rust-unreachable",
+ "version": "1.0.0",
+ "repositoryUrl": "https://github.com/reem/rust-unreachable.git",
+ "licenseDetail": [
+ "Copyright (c) 2015 The rust-unreachable 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": "rust-lang/time",
+ "version": "0.1.39",
+ "repositoryUrl": "https://github.com/rust-lang/time",
+ "licenseDetail": [
+ "Copyright (c) 2014 The Rust Project 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": "ticki/termion",
+ "version": "1.5.1",
+ "repositoryUrl": "https://github.com/ticki/termion",
+ "licenseDetail": [
+ "The Source EULA",
+ "",
+ "Copyright (c) 2016 Ticki",
+ "",
+ "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",
+ "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.3.4",
+ "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.1.1",
+ "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.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.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": "slog-rs/async",
+ "version": "2.2.0",
+ "repositoryUrl": "https://github.com/slog-rs/async",
+ "licenseDetail": [
+ "Mozilla Public License Version 2.0",
+ "==================================",
+ "",
+ "1. Definitions",
+ "--------------",
+ "",
+ "1.1. \"Contributor\"",
+ " means each individual or legal entity that creates, contributes to",
+ " the creation of, or owns Covered Software.",
+ "",
+ "1.2. \"Contributor Version\"",
+ " means the combination of the Contributions of others (if any) used",
+ " by a Contributor and that particular Contributor's Contribution.",
+ "",
+ "1.3. \"Contribution\"",
+ " means Covered Software of a particular Contributor.",
+ "",
+ "1.4. \"Covered Software\"",
+ " means Source Code Form to which the initial Contributor has attached",
+ " the notice in Exhibit A, the Executable Form of such Source Code",
+ " Form, and Modifications of such Source Code Form, in each case",
+ " including portions thereof.",
+ "",
+ "1.5. \"Incompatible With Secondary Licenses\"",
+ " means",
+ "",
+ " (a) that the initial Contributor has attached the notice described",
+ " in Exhibit B to the Covered Software; or",
+ "",
+ " (b) that the Covered Software was made available under the terms of",
+ " version 1.1 or earlier of the License, but not also under the",
+ " terms of a Secondary License.",
+ "",
+ "1.6. \"Executable Form\"",
+ " means any form of the work other than Source Code Form.",
+ "",
+ "1.7. \"Larger Work\"",
+ " means a work that combines Covered Software with other material, in ",
+ " a separate file or files, that is not Covered Software.",
+ "",
+ "1.8. \"License\"",
+ " means this document.",
+ "",
+ "1.9. \"Licensable\"",
+ " means having the right to grant, to the maximum extent possible,",
+ " whether at the time of the initial grant or subsequently, any and",
+ " all of the rights conveyed by this License.",
+ "",
+ "1.10. \"Modifications\"",
+ " means any of the following:",
+ "",
+ " (a) any file in Source Code Form that results from an addition to,",
+ " deletion from, or modification of the contents of Covered",
+ " Software; or",
+ "",
+ " (b) any new file in Source Code Form that contains any Covered",
+ " Software.",
+ "",
+ "1.11. \"Patent Claims\" of a Contributor",
+ " means any patent claim(s), including without limitation, method,",
+ " process, and apparatus claims, in any patent Licensable by such",
+ " Contributor that would be infringed, but for the grant of the",
+ " License, by the making, using, selling, offering for sale, having",
+ " made, import, or transfer of either its Contributions or its",
+ " Contributor Version.",
+ "",
+ "1.12. \"Secondary License\"",
+ " means either the GNU General Public License, Version 2.0, the GNU",
+ " Lesser General Public License, Version 2.1, the GNU Affero General",
+ " Public License, Version 3.0, or any later versions of those",
+ " licenses.",
+ "",
+ "1.13. \"Source Code Form\"",
+ " means the form of the work preferred for making modifications.",
+ "",
+ "1.14. \"You\" (or \"Your\")",
+ " means an individual or a legal entity exercising rights under this",
+ " License. For legal entities, \"You\" includes any entity that",
+ " controls, is controlled by, or is under common control with You. For",
+ " purposes of this definition, \"control\" means (a) the power, direct",
+ " or indirect, to cause the direction or management of such entity,",
+ " whether by contract or otherwise, or (b) ownership of more than",
+ " fifty percent (50%) of the outstanding shares or beneficial",
+ " ownership of such entity.",
+ "",
+ "2. License Grants and Conditions",
+ "--------------------------------",
+ "",
+ "2.1. Grants",
+ "",
+ "Each Contributor hereby grants You a world-wide, royalty-free,",
+ "non-exclusive license:",
+ "",
+ "(a) under intellectual property rights (other than patent or trademark)",
+ " Licensable by such Contributor to use, reproduce, make available,",
+ " modify, display, perform, distribute, and otherwise exploit its",
+ " Contributions, either on an unmodified basis, with Modifications, or",
+ " as part of a Larger Work; and",
+ "",
+ "(b) under Patent Claims of such Contributor to make, use, sell, offer",
+ " for sale, have made, import, and otherwise transfer either its",
+ " Contributions or its Contributor Version.",
+ "",
+ "2.2. Effective Date",
+ "",
+ "The licenses granted in Section 2.1 with respect to any Contribution",
+ "become effective for each Contribution on the date the Contributor first",
+ "distributes such Contribution.",
+ "",
+ "2.3. Limitations on Grant Scope",
+ "",
+ "The licenses granted in this Section 2 are the only rights granted under",
+ "this License. No additional rights or licenses will be implied from the",
+ "distribution or licensing of Covered Software under this License.",
+ "Notwithstanding Section 2.1(b) above, no patent license is granted by a",
+ "Contributor:",
+ "",
+ "(a) for any code that a Contributor has removed from Covered Software;",
+ " or",
+ "",
+ "(b) for infringements caused by: (i) Your and any other third party's",
+ " modifications of Covered Software, or (ii) the combination of its",
+ " Contributions with other software (except as part of its Contributor",
+ " Version); or",
+ "",
+ "(c) under Patent Claims infringed by Covered Software in the absence of",
+ " its Contributions.",
+ "",
+ "This License does not grant any rights in the trademarks, service marks,",
+ "or logos of any Contributor (except as may be necessary to comply with",
+ "the notice requirements in Section 3.4).",
+ "",
+ "2.4. Subsequent Licenses",
+ "",
+ "No Contributor makes additional grants as a result of Your choice to",
+ "distribute the Covered Software under a subsequent version of this",
+ "License (see Section 10.2) or under the terms of a Secondary License (if",
+ "permitted under the terms of Section 3.3).",
+ "",
+ "2.5. Representation",
+ "",
+ "Each Contributor represents that the Contributor believes its",
+ "Contributions are its original creation(s) or it has sufficient rights",
+ "to grant the rights to its Contributions conveyed by this License.",
+ "",
+ "2.6. Fair Use",
+ "",
+ "This License is not intended to limit any rights You have under",
+ "applicable copyright doctrines of fair use, fair dealing, or other",
+ "equivalents.",
+ "",
+ "2.7. Conditions",
+ "",
+ "Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted",
+ "in Section 2.1.",
+ "",
+ "3. Responsibilities",
+ "-------------------",
+ "",
+ "3.1. Distribution of Source Form",
+ "",
+ "All distribution of Covered Software in Source Code Form, including any",
+ "Modifications that You create or to which You contribute, must be under",
+ "the terms of this License. You must inform recipients that the Source",
+ "Code Form of the Covered Software is governed by the terms of this",
+ "License, and how they can obtain a copy of this License. You may not",
+ "attempt to alter or restrict the recipients' rights in the Source Code",
+ "Form.",
+ "",
+ "3.2. Distribution of Executable Form",
+ "",
+ "If You distribute Covered Software in Executable Form then:",
+ "",
+ "(a) such Covered Software must also be made available in Source Code",
+ " Form, as described in Section 3.1, and You must inform recipients of",
+ " the Executable Form how they can obtain a copy of such Source Code",
+ " Form by reasonable means in a timely manner, at a charge no more",
+ " than the cost of distribution to the recipient; and",
+ "",
+ "(b) You may distribute such Executable Form under the terms of this",
+ " License, or sublicense it under different terms, provided that the",
+ " license for the Executable Form does not attempt to limit or alter",
+ " the recipients' rights in the Source Code Form under this License.",
+ "",
+ "3.3. Distribution of a Larger Work",
+ "",
+ "You may create and distribute a Larger Work under terms of Your choice,",
+ "provided that You also comply with the requirements of this License for",
+ "the Covered Software. If the Larger Work is a combination of Covered",
+ "Software with a work governed by one or more Secondary Licenses, and the",
+ "Covered Software is not Incompatible With Secondary Licenses, this",
+ "License permits You to additionally distribute such Covered Software",
+ "under the terms of such Secondary License(s), so that the recipient of",
+ "the Larger Work may, at their option, further distribute the Covered",
+ "Software under the terms of either this License or such Secondary",
+ "License(s).",
+ "",
+ "3.4. Notices",
+ "",
+ "You may not remove or alter the substance of any license notices",
+ "(including copyright notices, patent notices, disclaimers of warranty,",
+ "or limitations of liability) contained within the Source Code Form of",
+ "the Covered Software, except that You may alter any license notices to",
+ "the extent required to remedy known factual inaccuracies.",
+ "",
+ "3.5. Application of Additional Terms",
+ "",
+ "You may choose to offer, and to charge a fee for, warranty, support,",
+ "indemnity or liability obligations to one or more recipients of Covered",
+ "Software. However, You may do so only on Your own behalf, and not on",
+ "behalf of any Contributor. You must make it absolutely clear that any",
+ "such warranty, support, indemnity, or liability obligation is offered by",
+ "You alone, and You hereby agree to indemnify every Contributor for any",
+ "liability incurred by such Contributor as a result of warranty, support,",
+ "indemnity or liability terms You offer. You may include additional",
+ "disclaimers of warranty and limitations of liability specific to any",
+ "jurisdiction.",
+ "",
+ "4. Inability to Comply Due to Statute or Regulation",
+ "---------------------------------------------------",
+ "",
+ "If it is impossible for You to comply with any of the terms of this",
+ "License with respect to some or all of the Covered Software due to",
+ "statute, judicial order, or regulation then You must: (a) comply with",
+ "the terms of this License to the maximum extent possible; and (b)",
+ "describe the limitations and the code they affect. Such description must",
+ "be placed in a text file included with all distributions of the Covered",
+ "Software under this License. Except to the extent prohibited by statute",
+ "or regulation, such description must be sufficiently detailed for a",
+ "recipient of ordinary skill to be able to understand it.",
+ "",
+ "5. Termination",
+ "--------------",
+ "",
+ "5.1. The rights granted under this License will terminate automatically",
+ "if You fail to comply with any of its terms. However, if You become",
+ "compliant, then the rights granted under this License from a particular",
+ "Contributor are reinstated (a) provisionally, unless and until such",
+ "Contributor explicitly and finally terminates Your grants, and (b) on an",
+ "ongoing basis, if such Contributor fails to notify You of the",
+ "non-compliance by some reasonable means prior to 60 days after You have",
+ "come back into compliance. Moreover, Your grants from a particular",
+ "Contributor are reinstated on an ongoing basis if such Contributor",
+ "notifies You of the non-compliance by some reasonable means, this is the",
+ "first time You have received notice of non-compliance with this License",
+ "from such Contributor, and You become compliant prior to 30 days after",
+ "Your receipt of the notice.",
+ "",
+ "5.2. If You initiate litigation against any entity by asserting a patent",
+ "infringement claim (excluding declaratory judgment actions,",
+ "counter-claims, and cross-claims) alleging that a Contributor Version",
+ "directly or indirectly infringes any patent, then the rights granted to",
+ "You by any and all Contributors for the Covered Software under Section",
+ "2.1 of this License shall terminate.",
+ "",
+ "5.3. In the event of termination under Sections 5.1 or 5.2 above, all",
+ "end user license agreements (excluding distributors and resellers) which",
+ "have been validly granted by You or Your distributors under this License",
+ "prior to termination shall survive termination.",
+ "",
+ "************************************************************************",
+ "* *",
+ "* 6. Disclaimer of Warranty *",
+ "* ------------------------- *",
+ "* *",
+ "* Covered Software is provided under this License on an \"as is\" *",
+ "* basis, without warranty of any kind, either expressed, implied, or *",
+ "* statutory, including, without limitation, warranties that the *",
+ "* Covered Software is free of defects, merchantable, fit for a *",
+ "* particular purpose or non-infringing. The entire risk as to the *",
+ "* quality and performance of the Covered Software is with You. *",
+ "* Should any Covered Software prove defective in any respect, You *",
+ "* (not any Contributor) assume the cost of any necessary servicing, *",
+ "* repair, or correction. This disclaimer of warranty constitutes an *",
+ "* essential part of this License. No use of any Covered Software is *",
+ "* authorized under this License except under this disclaimer. *",
+ "* *",
+ "************************************************************************",
+ "",
+ "************************************************************************",
+ "* *",
+ "* 7. Limitation of Liability *",
+ "* -------------------------- *",
+ "* *",
+ "* Under no circumstances and under no legal theory, whether tort *",
+ "* (including negligence), contract, or otherwise, shall any *",
+ "* Contributor, or anyone who distributes Covered Software as *",
+ "* permitted above, be liable to You for any direct, indirect, *",
+ "* special, incidental, or consequential damages of any character *",
+ "* including, without limitation, damages for lost profits, loss of *",
+ "* goodwill, work stoppage, computer failure or malfunction, or any *",
+ "* and all other commercial damages or losses, even if such party *",
+ "* shall have been informed of the possibility of such damages. This *",
+ "* limitation of liability shall not apply to liability for death or *",
+ "* personal injury resulting from such party's negligence to the *",
+ "* extent applicable law prohibits such limitation. Some *",
+ "* jurisdictions do not allow the exclusion or limitation of *",
+ "* incidental or consequential damages, so this exclusion and *",
+ "* limitation may not apply to You. *",
+ "* *",
+ "************************************************************************",
+ "",
+ "8. Litigation",
+ "-------------",
+ "",
+ "Any litigation relating to this License may be brought only in the",
+ "courts of a jurisdiction where the defendant maintains its principal",
+ "place of business and such litigation shall be governed by laws of that",
+ "jurisdiction, without reference to its conflict-of-law provisions.",
+ "Nothing in this Section shall prevent a party's ability to bring",
+ "cross-claims or counter-claims.",
+ "",
+ "9. Miscellaneous",
+ "----------------",
+ "",
+ "This License represents the complete agreement concerning the subject",
+ "matter hereof. If any provision of this License is held to be",
+ "unenforceable, such provision shall be reformed only to the extent",
+ "necessary to make it enforceable. Any law or regulation which provides",
+ "that the language of a contract shall be construed against the drafter",
+ "shall not be used to construe this License against a Contributor.",
+ "",
+ "10. Versions of the License",
+ "---------------------------",
+ "",
+ "10.1. New Versions",
+ "",
+ "Mozilla Foundation is the license steward. Except as provided in Section",
+ "10.3, no one other than the license steward has the right to modify or",
+ "publish new versions of this License. Each version will be given a",
+ "distinguishing version number.",
+ "",
+ "10.2. Effect of New Versions",
+ "",
+ "You may distribute the Covered Software under the terms of the version",
+ "of the License under which You originally received the Covered Software,",
+ "or under the terms of any subsequent version published by the license",
+ "steward.",
+ "",
+ "10.3. Modified Versions",
+ "",
+ "If you create software not governed by this License, and you want to",
+ "create a new license for such software, you may create and use a",
+ "modified version of this License if you rename the license and remove",
+ "any references to the name of the license steward (except to note that",
+ "such modified license differs from this License).",
+ "",
+ "10.4. Distributing Source Code Form that is Incompatible With Secondary",
+ "Licenses",
+ "",
+ "If You choose to distribute Source Code Form that is Incompatible With",
+ "Secondary Licenses under the terms of this version of the License, the",
+ "notice described in Exhibit B of this License must be attached.",
+ "",
+ "Exhibit A - Source Code Form License Notice",
+ "-------------------------------------------",
+ "",
+ " This Source Code Form is subject to the terms of the Mozilla Public",
+ " License, v. 2.0. If a copy of the MPL was not distributed with this",
+ " file, You can obtain one at http://mozilla.org/MPL/2.0/.",
+ "",
+ "If it is not possible or desirable to put the notice in a particular",
+ "file, then You may include the notice in a location (such as a LICENSE",
+ "file in a relevant directory) where a recipient would be likely to look",
+ "for such a notice.",
+ "",
+ "You may add additional accurate notices of copyright ownership.",
+ "",
+ "Exhibit B - \"Incompatible With Secondary Licenses\" Notice",
+ "---------------------------------------------------------",
+ "",
+ " This Source Code Form is \"Incompatible With Secondary Licenses\", as",
+ " defined by the Mozilla Public License, v. 2.0."
+ ],
+ "isProd": true
+ },
+ {
+ "name": "slog-rs/term",
+ "version": "2.3.0",
+ "repositoryUrl": "https://github.com/slog-rs/term",
+ "licenseDetail": [
+ "Mozilla Public License Version 2.0",
+ "==================================",
+ "",
+ "1. Definitions",
+ "--------------",
+ "",
+ "1.1. \"Contributor\"",
+ " means each individual or legal entity that creates, contributes to",
+ " the creation of, or owns Covered Software.",
+ "",
+ "1.2. \"Contributor Version\"",
+ " means the combination of the Contributions of others (if any) used",
+ " by a Contributor and that particular Contributor's Contribution.",
+ "",
+ "1.3. \"Contribution\"",
+ " means Covered Software of a particular Contributor.",
+ "",
+ "1.4. \"Covered Software\"",
+ " means Source Code Form to which the initial Contributor has attached",
+ " the notice in Exhibit A, the Executable Form of such Source Code",
+ " Form, and Modifications of such Source Code Form, in each case",
+ " including portions thereof.",
+ "",
+ "1.5. \"Incompatible With Secondary Licenses\"",
+ " means",
+ "",
+ " (a) that the initial Contributor has attached the notice described",
+ " in Exhibit B to the Covered Software; or",
+ "",
+ " (b) that the Covered Software was made available under the terms of",
+ " version 1.1 or earlier of the License, but not also under the",
+ " terms of a Secondary License.",
+ "",
+ "1.6. \"Executable Form\"",
+ " means any form of the work other than Source Code Form.",
+ "",
+ "1.7. \"Larger Work\"",
+ " means a work that combines Covered Software with other material, in ",
+ " a separate file or files, that is not Covered Software.",
+ "",
+ "1.8. \"License\"",
+ " means this document.",
+ "",
+ "1.9. \"Licensable\"",
+ " means having the right to grant, to the maximum extent possible,",
+ " whether at the time of the initial grant or subsequently, any and",
+ " all of the rights conveyed by this License.",
+ "",
+ "1.10. \"Modifications\"",
+ " means any of the following:",
+ "",
+ " (a) any file in Source Code Form that results from an addition to,",
+ " deletion from, or modification of the contents of Covered",
+ " Software; or",
+ "",
+ " (b) any new file in Source Code Form that contains any Covered",
+ " Software.",
+ "",
+ "1.11. \"Patent Claims\" of a Contributor",
+ " means any patent claim(s), including without limitation, method,",
+ " process, and apparatus claims, in any patent Licensable by such",
+ " Contributor that would be infringed, but for the grant of the",
+ " License, by the making, using, selling, offering for sale, having",
+ " made, import, or transfer of either its Contributions or its",
+ " Contributor Version.",
+ "",
+ "1.12. \"Secondary License\"",
+ " means either the GNU General Public License, Version 2.0, the GNU",
+ " Lesser General Public License, Version 2.1, the GNU Affero General",
+ " Public License, Version 3.0, or any later versions of those",
+ " licenses.",
+ "",
+ "1.13. \"Source Code Form\"",
+ " means the form of the work preferred for making modifications.",
+ "",
+ "1.14. \"You\" (or \"Your\")",
+ " means an individual or a legal entity exercising rights under this",
+ " License. For legal entities, \"You\" includes any entity that",
+ " controls, is controlled by, or is under common control with You. For",
+ " purposes of this definition, \"control\" means (a) the power, direct",
+ " or indirect, to cause the direction or management of such entity,",
+ " whether by contract or otherwise, or (b) ownership of more than",
+ " fifty percent (50%) of the outstanding shares or beneficial",
+ " ownership of such entity.",
+ "",
+ "2. License Grants and Conditions",
+ "--------------------------------",
+ "",
+ "2.1. Grants",
+ "",
+ "Each Contributor hereby grants You a world-wide, royalty-free,",
+ "non-exclusive license:",
+ "",
+ "(a) under intellectual property rights (other than patent or trademark)",
+ " Licensable by such Contributor to use, reproduce, make available,",
+ " modify, display, perform, distribute, and otherwise exploit its",
+ " Contributions, either on an unmodified basis, with Modifications, or",
+ " as part of a Larger Work; and",
+ "",
+ "(b) under Patent Claims of such Contributor to make, use, sell, offer",
+ " for sale, have made, import, and otherwise transfer either its",
+ " Contributions or its Contributor Version.",
+ "",
+ "2.2. Effective Date",
+ "",
+ "The licenses granted in Section 2.1 with respect to any Contribution",
+ "become effective for each Contribution on the date the Contributor first",
+ "distributes such Contribution.",
+ "",
+ "2.3. Limitations on Grant Scope",
+ "",
+ "The licenses granted in this Section 2 are the only rights granted under",
+ "this License. No additional rights or licenses will be implied from the",
+ "distribution or licensing of Covered Software under this License.",
+ "Notwithstanding Section 2.1(b) above, no patent license is granted by a",
+ "Contributor:",
+ "",
+ "(a) for any code that a Contributor has removed from Covered Software;",
+ " or",
+ "",
+ "(b) for infringements caused by: (i) Your and any other third party's",
+ " modifications of Covered Software, or (ii) the combination of its",
+ " Contributions with other software (except as part of its Contributor",
+ " Version); or",
+ "",
+ "(c) under Patent Claims infringed by Covered Software in the absence of",
+ " its Contributions.",
+ "",
+ "This License does not grant any rights in the trademarks, service marks,",
+ "or logos of any Contributor (except as may be necessary to comply with",
+ "the notice requirements in Section 3.4).",
+ "",
+ "2.4. Subsequent Licenses",
+ "",
+ "No Contributor makes additional grants as a result of Your choice to",
+ "distribute the Covered Software under a subsequent version of this",
+ "License (see Section 10.2) or under the terms of a Secondary License (if",
+ "permitted under the terms of Section 3.3).",
+ "",
+ "2.5. Representation",
+ "",
+ "Each Contributor represents that the Contributor believes its",
+ "Contributions are its original creation(s) or it has sufficient rights",
+ "to grant the rights to its Contributions conveyed by this License.",
+ "",
+ "2.6. Fair Use",
+ "",
+ "This License is not intended to limit any rights You have under",
+ "applicable copyright doctrines of fair use, fair dealing, or other",
+ "equivalents.",
+ "",
+ "2.7. Conditions",
+ "",
+ "Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted",
+ "in Section 2.1.",
+ "",
+ "3. Responsibilities",
+ "-------------------",
+ "",
+ "3.1. Distribution of Source Form",
+ "",
+ "All distribution of Covered Software in Source Code Form, including any",
+ "Modifications that You create or to which You contribute, must be under",
+ "the terms of this License. You must inform recipients that the Source",
+ "Code Form of the Covered Software is governed by the terms of this",
+ "License, and how they can obtain a copy of this License. You may not",
+ "attempt to alter or restrict the recipients' rights in the Source Code",
+ "Form.",
+ "",
+ "3.2. Distribution of Executable Form",
+ "",
+ "If You distribute Covered Software in Executable Form then:",
+ "",
+ "(a) such Covered Software must also be made available in Source Code",
+ " Form, as described in Section 3.1, and You must inform recipients of",
+ " the Executable Form how they can obtain a copy of such Source Code",
+ " Form by reasonable means in a timely manner, at a charge no more",
+ " than the cost of distribution to the recipient; and",
+ "",
+ "(b) You may distribute such Executable Form under the terms of this",
+ " License, or sublicense it under different terms, provided that the",
+ " license for the Executable Form does not attempt to limit or alter",
+ " the recipients' rights in the Source Code Form under this License.",
+ "",
+ "3.3. Distribution of a Larger Work",
+ "",
+ "You may create and distribute a Larger Work under terms of Your choice,",
+ "provided that You also comply with the requirements of this License for",
+ "the Covered Software. If the Larger Work is a combination of Covered",
+ "Software with a work governed by one or more Secondary Licenses, and the",
+ "Covered Software is not Incompatible With Secondary Licenses, this",
+ "License permits You to additionally distribute such Covered Software",
+ "under the terms of such Secondary License(s), so that the recipient of",
+ "the Larger Work may, at their option, further distribute the Covered",
+ "Software under the terms of either this License or such Secondary",
+ "License(s).",
+ "",
+ "3.4. Notices",
+ "",
+ "You may not remove or alter the substance of any license notices",
+ "(including copyright notices, patent notices, disclaimers of warranty,",
+ "or limitations of liability) contained within the Source Code Form of",
+ "the Covered Software, except that You may alter any license notices to",
+ "the extent required to remedy known factual inaccuracies.",
+ "",
+ "3.5. Application of Additional Terms",
+ "",
+ "You may choose to offer, and to charge a fee for, warranty, support,",
+ "indemnity or liability obligations to one or more recipients of Covered",
+ "Software. However, You may do so only on Your own behalf, and not on",
+ "behalf of any Contributor. You must make it absolutely clear that any",
+ "such warranty, support, indemnity, or liability obligation is offered by",
+ "You alone, and You hereby agree to indemnify every Contributor for any",
+ "liability incurred by such Contributor as a result of warranty, support,",
+ "indemnity or liability terms You offer. You may include additional",
+ "disclaimers of warranty and limitations of liability specific to any",
+ "jurisdiction.",
+ "",
+ "4. Inability to Comply Due to Statute or Regulation",
+ "---------------------------------------------------",
+ "",
+ "If it is impossible for You to comply with any of the terms of this",
+ "License with respect to some or all of the Covered Software due to",
+ "statute, judicial order, or regulation then You must: (a) comply with",
+ "the terms of this License to the maximum extent possible; and (b)",
+ "describe the limitations and the code they affect. Such description must",
+ "be placed in a text file included with all distributions of the Covered",
+ "Software under this License. Except to the extent prohibited by statute",
+ "or regulation, such description must be sufficiently detailed for a",
+ "recipient of ordinary skill to be able to understand it.",
+ "",
+ "5. Termination",
+ "--------------",
+ "",
+ "5.1. The rights granted under this License will terminate automatically",
+ "if You fail to comply with any of its terms. However, if You become",
+ "compliant, then the rights granted under this License from a particular",
+ "Contributor are reinstated (a) provisionally, unless and until such",
+ "Contributor explicitly and finally terminates Your grants, and (b) on an",
+ "ongoing basis, if such Contributor fails to notify You of the",
+ "non-compliance by some reasonable means prior to 60 days after You have",
+ "come back into compliance. Moreover, Your grants from a particular",
+ "Contributor are reinstated on an ongoing basis if such Contributor",
+ "notifies You of the non-compliance by some reasonable means, this is the",
+ "first time You have received notice of non-compliance with this License",
+ "from such Contributor, and You become compliant prior to 30 days after",
+ "Your receipt of the notice.",
+ "",
+ "5.2. If You initiate litigation against any entity by asserting a patent",
+ "infringement claim (excluding declaratory judgment actions,",
+ "counter-claims, and cross-claims) alleging that a Contributor Version",
+ "directly or indirectly infringes any patent, then the rights granted to",
+ "You by any and all Contributors for the Covered Software under Section",
+ "2.1 of this License shall terminate.",
+ "",
+ "5.3. In the event of termination under Sections 5.1 or 5.2 above, all",
+ "end user license agreements (excluding distributors and resellers) which",
+ "have been validly granted by You or Your distributors under this License",
+ "prior to termination shall survive termination.",
+ "",
+ "************************************************************************",
+ "* *",
+ "* 6. Disclaimer of Warranty *",
+ "* ------------------------- *",
+ "* *",
+ "* Covered Software is provided under this License on an \"as is\" *",
+ "* basis, without warranty of any kind, either expressed, implied, or *",
+ "* statutory, including, without limitation, warranties that the *",
+ "* Covered Software is free of defects, merchantable, fit for a *",
+ "* particular purpose or non-infringing. The entire risk as to the *",
+ "* quality and performance of the Covered Software is with You. *",
+ "* Should any Covered Software prove defective in any respect, You *",
+ "* (not any Contributor) assume the cost of any necessary servicing, *",
+ "* repair, or correction. This disclaimer of warranty constitutes an *",
+ "* essential part of this License. No use of any Covered Software is *",
+ "* authorized under this License except under this disclaimer. *",
+ "* *",
+ "************************************************************************",
+ "",
+ "************************************************************************",
+ "* *",
+ "* 7. Limitation of Liability *",
+ "* -------------------------- *",
+ "* *",
+ "* Under no circumstances and under no legal theory, whether tort *",
+ "* (including negligence), contract, or otherwise, shall any *",
+ "* Contributor, or anyone who distributes Covered Software as *",
+ "* permitted above, be liable to You for any direct, indirect, *",
+ "* special, incidental, or consequential damages of any character *",
+ "* including, without limitation, damages for lost profits, loss of *",
+ "* goodwill, work stoppage, computer failure or malfunction, or any *",
+ "* and all other commercial damages or losses, even if such party *",
+ "* shall have been informed of the possibility of such damages. This *",
+ "* limitation of liability shall not apply to liability for death or *",
+ "* personal injury resulting from such party's negligence to the *",
+ "* extent applicable law prohibits such limitation. Some *",
+ "* jurisdictions do not allow the exclusion or limitation of *",
+ "* incidental or consequential damages, so this exclusion and *",
+ "* limitation may not apply to You. *",
+ "* *",
+ "************************************************************************",
+ "",
+ "8. Litigation",
+ "-------------",
+ "",
+ "Any litigation relating to this License may be brought only in the",
+ "courts of a jurisdiction where the defendant maintains its principal",
+ "place of business and such litigation shall be governed by laws of that",
+ "jurisdiction, without reference to its conflict-of-law provisions.",
+ "Nothing in this Section shall prevent a party's ability to bring",
+ "cross-claims or counter-claims.",
+ "",
+ "9. Miscellaneous",
+ "----------------",
+ "",
+ "This License represents the complete agreement concerning the subject",
+ "matter hereof. If any provision of this License is held to be",
+ "unenforceable, such provision shall be reformed only to the extent",
+ "necessary to make it enforceable. Any law or regulation which provides",
+ "that the language of a contract shall be construed against the drafter",
+ "shall not be used to construe this License against a Contributor.",
+ "",
+ "10. Versions of the License",
+ "---------------------------",
+ "",
+ "10.1. New Versions",
+ "",
+ "Mozilla Foundation is the license steward. Except as provided in Section",
+ "10.3, no one other than the license steward has the right to modify or",
+ "publish new versions of this License. Each version will be given a",
+ "distinguishing version number.",
+ "",
+ "10.2. Effect of New Versions",
+ "",
+ "You may distribute the Covered Software under the terms of the version",
+ "of the License under which You originally received the Covered Software,",
+ "or under the terms of any subsequent version published by the license",
+ "steward.",
+ "",
+ "10.3. Modified Versions",
+ "",
+ "If you create software not governed by this License, and you want to",
+ "create a new license for such software, you may create and use a",
+ "modified version of this License if you rename the license and remove",
+ "any references to the name of the license steward (except to note that",
+ "such modified license differs from this License).",
+ "",
+ "10.4. Distributing Source Code Form that is Incompatible With Secondary",
+ "Licenses",
+ "",
+ "If You choose to distribute Source Code Form that is Incompatible With",
+ "Secondary Licenses under the terms of this version of the License, the",
+ "notice described in Exhibit B of this License must be attached.",
+ "",
+ "Exhibit A - Source Code Form License Notice",
+ "-------------------------------------------",
+ "",
+ " This Source Code Form is subject to the terms of the Mozilla Public",
+ " License, v. 2.0. If a copy of the MPL was not distributed with this",
+ " file, You can obtain one at http://mozilla.org/MPL/2.0/.",
+ "",
+ "If it is not possible or desirable to put the notice in a particular",
+ "file, then You may include the notice in a location (such as a LICENSE",
+ "file in a relevant directory) where a recipient would be likely to look",
+ "for such a notice.",
+ "",
+ "You may add additional accurate notices of copyright ownership.",
+ "",
+ "Exhibit B - \"Incompatible With Secondary Licenses\" Notice",
+ "---------------------------------------------------------",
+ "",
+ " This Source Code Form is \"Incompatible With Secondary Licenses\", as",
+ " defined by the Mozilla Public License, v. 2.0."
+ ],
+ "isProd": true
+ }
+]
diff --git a/build/win32/code.iss b/build/win32/code.iss
index 56e4096cc6..ce16574030 100644
--- a/build/win32/code.iss
+++ b/build/win32/code.iss
@@ -19,7 +19,7 @@ OutputDir={#OutputDir}
OutputBaseFilename=SqlOpsStudioSetup
Compression=lzma
SolidCompression=yes
-AppMutex={#AppMutex}
+AppMutex={code:GetAppMutex}
SetupMutex={#AppMutex}setup
WizardImageFile={#RepoDir}\resources\win32\inno-big.bmp
WizardSmallImageFile={#RepoDir}\resources\win32\inno-small.bmp
@@ -52,8 +52,13 @@ Type: filesandordirs; Name: "{app}\resources\app\out"; Check: IsNotUpdate
Type: filesandordirs; Name: "{app}\resources\app\plugins"; Check: IsNotUpdate
Type: filesandordirs; Name: "{app}\resources\app\extensions"; Check: IsNotUpdate
Type: filesandordirs; Name: "{app}\resources\app\node_modules"; Check: IsNotUpdate
+Type: filesandordirs; Name: "{app}\resources\app\node_modules.asar.unpacked"; Check: IsNotUpdate
+Type: files; Name: "{app}\resources\app\node_modules.asar"; Check: IsNotUpdate
Type: files; Name: "{app}\resources\app\Credits_45.0.2454.85.html"; Check: IsNotUpdate
+[UninstallDelete]
+Type: filesandordirs; Name: "{app}\_"
+
[Tasks]
Name: "quicklaunchicon"; Description: "{cm:CreateQuickLaunchIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked; OnlyBelowVersion: 0,6.1
Name: "addtopath"; Description: "{cm:AddToPath}"; GroupDescription: "{cm:Other}"
@@ -138,6 +143,48 @@ begin
Result := True;
end;
+function GetAppMutex(Value: string): string;
+begin
+ if IsBackgroundUpdate() then
+ Result := ''
+ else
+ Result := '{#AppMutex}';
+end;
+
+function GetDestDir(Value: string): string;
+begin
+ if IsBackgroundUpdate() then
+ Result := ExpandConstant('{app}\_')
+ else
+ Result := ExpandConstant('{app}');
+end;
+
+function BoolToStr(Value: Boolean): String;
+begin
+ if Value then
+ Result := 'true'
+ else
+ Result := 'false';
+end;
+
+procedure CurStepChanged(CurStep: TSetupStep);
+var
+ UpdateResultCode: Integer;
+begin
+ if IsBackgroundUpdate() and (CurStep = ssPostInstall) then
+ begin
+ CreateMutex('{#AppMutex}-ready');
+
+ while (CheckForMutexes('{#AppMutex}')) do
+ begin
+ Log('Application is still running, waiting');
+ Sleep(1000);
+ end;
+
+ Exec(ExpandConstant('{app}\tools\inno_updater.exe'), ExpandConstant('"{app}\{#ExeBasename}.exe" ' + BoolToStr(LockFileExists())), '', SW_SHOW, ewWaitUntilTerminated, UpdateResultCode);
+ end;
+end;
+
// http://stackoverflow.com/a/23838239/261019
procedure Explode(var Dest: TArrayOfString; Text: String; Separator: String);
var
diff --git a/build/win32/inno_updater.exe b/build/win32/inno_updater.exe
new file mode 100644
index 0000000000..a896061751
Binary files /dev/null and b/build/win32/inno_updater.exe differ
diff --git a/build/win32/vcruntime140.dll b/build/win32/vcruntime140.dll
new file mode 100644
index 0000000000..d26d294897
Binary files /dev/null and b/build/win32/vcruntime140.dll differ
diff --git a/build/yarn.lock b/build/yarn.lock
index 7eb9b3025e..214f60fb46 100644
--- a/build/yarn.lock
+++ b/build/yarn.lock
@@ -27,8 +27,8 @@
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-0.0.29.tgz#fbcfd330573b912ef59eeee14602bface630754b"
"@types/node@*":
- version "9.6.0"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.0.tgz#d3480ee666df9784b1001a1872a2f6ccefb6c2d7"
+ version "8.0.51"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.51.tgz#b31d716fb8d58eeb95c068a039b9b6292817d5fb"
"@types/node@8.0.33":
version "8.0.33"
@@ -44,6 +44,13 @@ agent-base@4, agent-base@^4.1.0:
dependencies:
es6-promisify "^5.0.0"
+ajv@^4.9.1:
+ version "4.11.8"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
+ dependencies:
+ co "^4.6.0"
+ json-stable-stringify "^1.0.1"
+
ajv@^5.1.0:
version "5.5.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
@@ -159,19 +166,19 @@ aws4@^1.2.1, aws4@^1.6.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
azure-storage@^2.1.0:
- version "2.8.1"
- resolved "https://registry.yarnpkg.com/azure-storage/-/azure-storage-2.8.1.tgz#ecb9d050ef1395e79ffbb652c02fe643687bec63"
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/azure-storage/-/azure-storage-2.6.0.tgz#84747ee54a4bd194bb960f89f3eff89d67acf1cf"
dependencies:
browserify-mime "~1.2.9"
extend "~1.2.1"
json-edm-parser "0.1.2"
md5.js "1.3.4"
readable-stream "~2.0.0"
- request "~2.83.0"
+ request "~2.81.0"
underscore "~1.8.3"
uuid "^3.0.0"
- validator "~9.4.1"
- xml2js "0.2.8"
+ validator "~3.35.0"
+ xml2js "0.2.7"
xmlbuilder "0.4.3"
balanced-match@^1.0.0:
@@ -324,12 +331,18 @@ color-support@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2"
-combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5:
+combined-stream@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818"
dependencies:
delayed-stream "~1.0.0"
+combined-stream@^1.0.5, combined-stream@~1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.5.tgz#938370a57b4a51dea2c77c15d5c5fdf895164009"
+ dependencies:
+ delayed-stream "~1.0.0"
+
commander@2.11.0:
version "2.11.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563"
@@ -554,14 +567,10 @@ extglob@^0.3.1:
dependencies:
is-extglob "^1.0.0"
-extsprintf@1.3.0:
+extsprintf@1.3.0, extsprintf@^1.2.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
-extsprintf@^1.2.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
-
fancy-log@^1.1.0:
version "1.3.2"
resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.2.tgz#f41125e3d84f2e7d89a43d06d958c8f78be16be1"
@@ -873,6 +882,10 @@ gulplog@^1.0.0:
dependencies:
glogg "^1.0.0"
+har-schema@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
+
har-schema@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
@@ -886,6 +899,13 @@ har-validator@~2.0.6:
is-my-json-valid "^2.12.4"
pinkie-promise "^2.0.0"
+har-validator@~4.2.1:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
+ dependencies:
+ ajv "^4.9.1"
+ har-schema "^1.0.5"
+
har-validator@~5.0.3:
version "5.0.3"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.0.3.tgz#ba402c266194f15956ef15e0fcf242993f6a7dfd"
@@ -970,8 +990,8 @@ http-signature@~1.2.0:
sshpk "^1.7.0"
https-proxy-agent@^2.1.1:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.0.tgz#7fbba856be8cd677986f42ebd3664f6317257887"
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0"
dependencies:
agent-base "^4.1.0"
debug "^3.1.0"
@@ -1131,7 +1151,7 @@ json-schema@0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
-json-stable-stringify@^1.0.0:
+json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
dependencies:
@@ -1318,19 +1338,29 @@ micromatch@^2.3.7:
parse-glob "^3.0.4"
regex-cache "^0.4.2"
+mime-db@~1.30.0:
+ version "1.30.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01"
+
mime-db@~1.33.0:
version "1.33.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
-mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.7:
+mime-types@^2.1.12, mime-types@~2.1.7:
+ version "2.1.17"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a"
+ dependencies:
+ mime-db "~1.30.0"
+
+mime-types@~2.1.17:
version "2.1.18"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8"
dependencies:
mime-db "~1.33.0"
mime@^1.3.4:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6"
"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.4:
version "3.0.4"
@@ -1461,6 +1491,10 @@ pend@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
+performance-now@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
+
performance-now@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
@@ -1517,6 +1551,10 @@ qs@~6.3.0:
version "6.3.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.2.tgz#e75bd5f6e268122a2a0e0bda630b2550c166502c"
+qs@~6.4.0:
+ version "6.4.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
+
qs@~6.5.1:
version "6.5.1"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8"
@@ -1663,32 +1701,32 @@ request@~2.79.0:
tunnel-agent "~0.4.1"
uuid "^3.0.0"
-request@~2.83.0:
- version "2.83.0"
- resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356"
+request@~2.81.0:
+ version "2.81.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
dependencies:
- aws-sign2 "~0.7.0"
- aws4 "^1.6.0"
+ aws-sign2 "~0.6.0"
+ aws4 "^1.2.1"
caseless "~0.12.0"
combined-stream "~1.0.5"
- extend "~3.0.1"
+ extend "~3.0.0"
forever-agent "~0.6.1"
- form-data "~2.3.1"
- har-validator "~5.0.3"
- hawk "~6.0.2"
- http-signature "~1.2.0"
+ form-data "~2.1.1"
+ har-validator "~4.2.1"
+ hawk "~3.1.3"
+ http-signature "~1.1.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
json-stringify-safe "~5.0.1"
- mime-types "~2.1.17"
- oauth-sign "~0.8.2"
- performance-now "^2.1.0"
- qs "~6.5.1"
- safe-buffer "^5.1.1"
- stringstream "~0.0.5"
- tough-cookie "~2.3.3"
+ mime-types "~2.1.7"
+ oauth-sign "~0.8.1"
+ performance-now "^0.2.0"
+ qs "~6.4.0"
+ safe-buffer "^5.0.1"
+ stringstream "~0.0.4"
+ tough-cookie "~2.3.0"
tunnel-agent "^0.6.0"
- uuid "^3.1.0"
+ uuid "^3.0.0"
requires-port@~1.0.0:
version "1.0.0"
@@ -1704,9 +1742,9 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
-sax@0.5.x:
- version "0.5.8"
- resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.8.tgz#d472db228eb331c2506b0e8c15524adb939d12c1"
+sax@0.5.2:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/sax/-/sax-0.5.2.tgz#735ffaa39a1cff8ffb9598f0223abdb03a9fb2ea"
sax@>=0.6.0:
version "1.2.4"
@@ -1770,8 +1808,8 @@ split@0.3:
through "2"
sshpk@^1.7.0:
- version "1.14.1"
- resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.1.tgz#130f5975eddad963f1d56f92b9ac6c51fa9f83eb"
+ version "1.13.1"
+ resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3"
dependencies:
asn1 "~0.2.3"
assert-plus "^1.0.0"
@@ -1914,7 +1952,13 @@ to-absolute-glob@^0.1.1:
dependencies:
extend-shallow "^2.0.1"
-tough-cookie@~2.3.0, tough-cookie@~2.3.3:
+tough-cookie@~2.3.0:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.3.tgz#0b618a5565b6dea90bf3425d04d55edc475a7561"
+ dependencies:
+ punycode "^1.4.1"
+
+tough-cookie@~2.3.3:
version "2.3.4"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655"
dependencies:
@@ -1967,7 +2011,11 @@ util-deprecate@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
-uuid@^3.0.0, uuid@^3.1.0:
+uuid@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"
+
+uuid@^3.1.0:
version "3.2.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14"
@@ -1975,9 +2023,9 @@ vali-date@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/vali-date/-/vali-date-1.0.0.tgz#1b904a59609fb328ef078138420934f6b86709a6"
-validator@~9.4.1:
- version "9.4.1"
- resolved "https://registry.yarnpkg.com/validator/-/validator-9.4.1.tgz#abf466d398b561cd243050112c6ff1de6cc12663"
+validator@~3.35.0:
+ version "3.35.0"
+ resolved "https://registry.yarnpkg.com/validator/-/validator-3.35.0.tgz#3f07249402c1fc8fc093c32c6e43d72a79cca1dc"
verror@1.10.0:
version "1.10.0"
@@ -2085,11 +2133,11 @@ wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
-xml2js@0.2.8:
- version "0.2.8"
- resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.2.8.tgz#9b81690931631ff09d1957549faf54f4f980b3c2"
+xml2js@0.2.7:
+ version "0.2.7"
+ resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.2.7.tgz#1838518bb01741cae0878bab4915e494c32306af"
dependencies:
- sax "0.5.x"
+ sax "0.5.2"
xml2js@^0.4.17:
version "0.4.19"
@@ -2103,8 +2151,8 @@ xmlbuilder@0.4.3:
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-0.4.3.tgz#c4614ba74e0ad196e609c9272cd9e1ddb28a8a58"
xmlbuilder@~9.0.1:
- version "9.0.7"
- resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
+ version "9.0.4"
+ resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.4.tgz#519cb4ca686d005a8420d3496f3f0caeecca580f"
"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.0, xtend@~4.0.1:
version "4.0.1"
diff --git a/extensions/bat/package.json b/extensions/bat/package.json
index d9f1cba592..c54d1a4ce5 100644
--- a/extensions/bat/package.json
+++ b/extensions/bat/package.json
@@ -1,6 +1,8 @@
{
"name": "bat",
- "version": "0.1.0",
+ "displayName": "%displayName%",
+ "description": "%description%",
+ "version": "1.0.0",
"publisher": "vscode",
"engines": { "vscode": "*" },
"scripts": {
diff --git a/extensions/bat/package.nls.json b/extensions/bat/package.nls.json
new file mode 100644
index 0000000000..c5052ca021
--- /dev/null
+++ b/extensions/bat/package.nls.json
@@ -0,0 +1,4 @@
+{
+ "displayName": "Windows Bat Language Basics",
+ "description": "Provides snippets, syntax highlighting, bracket matching and folding in Windows batch files."
+}
\ No newline at end of file
diff --git a/extensions/bat/syntaxes/Batch File.tmLanguage b/extensions/bat/syntaxes/Batch File.tmLanguage
deleted file mode 100644
index 7f0a106142..0000000000
--- a/extensions/bat/syntaxes/Batch File.tmLanguage
+++ /dev/null
@@ -1,169 +0,0 @@
-
-
-
-
- uuid
- E07EC438-7B75-4437-8AA1-DA94C1E6EACC
- patterns
-
-
- name
- keyword.command.dosbatch
- match
- \b(?i)(?:append|assoc|at|attrib|break|cacls|cd|chcp|chdir|chkdsk|chkntfs|cls|cmd|color|comp|compact|convert|copy|date|del|dir|diskcomp|diskcopy|doskey|echo|endlocal|erase|fc|find|findstr|format|ftype|graftabl|help|keyb|label|md|mkdir|mode|more|move|path|pause|popd|print|prompt|pushd|rd|recover|ren|rename|replace|restore|rmdir|set|setlocal|shift|sort|start|subst|time|title|tree|type|ver|verify|vol|xcopy)\b
-
-
- name
- keyword.control.statement.dosbatch
- match
- \b(?i)(?:goto|call|exit)\b
-
-
- name
- keyword.control.conditional.if.dosbatch
- match
- \b(?i)if\s+((not)\s+)(exist|defined|errorlevel|cmdextversion)\b
-
-
- name
- keyword.control.conditional.dosbatch
- match
- \b(?i)(?:if|else)\b
-
-
- name
- keyword.control.repeat.dosbatch
- match
- \b(?i)for\b
-
-
- name
- keyword.operator.dosbatch
- match
- \b(?:EQU|NEQ|LSS|LEQ|GTR|GEQ)\b
-
-
- name
- comment.line.rem.dosbatch
- match
- \b(?i)rem(?:$|\s.*$)
-
-
- name
- comment.line.colons.dosbatch
- match
- \s*:\s*:.*$
-
-
- captures
-
- 1
-
- name
- variable.parameter.function.begin.shell
-
-
- name
- variable.parameter.function.dosbatch
- match
- (?i)(%)(~(?:f|d|p|n|x|s|a|t|z|\$[^:]*:)*)?\d
-
-
- captures
-
- 1
-
- name
- variable.other.parsetime.begin.shell
-
- 2
-
- name
- variable.other.parsetime.end.shell
-
-
- name
- variable.other.parsetime.dosbatch
- match
- (%)[^%]+(%)|(%%)[^%]+(%%)
-
-
- captures
-
- 1
-
- name
- variable.parameter.loop.begin.shell
-
-
- name
- variable.parameter.loop.dosbatch
- match
- (?i)(%%)(~(?:f|d|p|n|x|s|a|t|z|\$[^:]*:)*)?[a-z]
-
-
- captures
-
- 1
-
- name
- variable.other.delayed.begin.shell
-
- 2
-
- name
- variable.other.delayed.end.shell
-
-
- name
- variable.other.delayed.dosbatch
- match
- (!)[^!]+(!)
-
-
- begin
- "
- endCaptures
-
- 0
-
- name
- punctuation.definition.string.end.shell
-
-
- beginCaptures
-
- 0
-
- name
- punctuation.definition.string.begin.shell
-
-
- name
- string.quoted.double.dosbatch
- end
- "|$
-
-
- name
- keyword.operator.pipe.dosbatch
- match
- [|]
-
-
- name
- keyword.operator.redirect.shell
- match
- &>|\d*>&\d*|\d*(>>|>|<)|\d*<&|\d*<>
-
-
- name
- Batch File
- scopeName
- source.dosbatch
- fileTypes
-
- bat
-
-
-
\ No newline at end of file
diff --git a/extensions/bat/syntaxes/batchfile.tmLanguage.json b/extensions/bat/syntaxes/batchfile.tmLanguage.json
index ce6870deea..2aee0692ad 100644
--- a/extensions/bat/syntaxes/batchfile.tmLanguage.json
+++ b/extensions/bat/syntaxes/batchfile.tmLanguage.json
@@ -4,13 +4,9 @@
"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/mmims/language-batchfile/commit/40b605c75db3967a24b7015f6d3a885360b84e28",
- "scopeName": "source.batchfile",
+ "version": "https://github.com/mmims/language-batchfile/commit/3dd105c31484e5975144478dac1aa91d8f51e528",
"name": "Batch File",
- "fileTypes": [
- "bat",
- "cmd"
- ],
+ "scopeName": "source.batchfile",
"patterns": [
{
"include": "#commands"
@@ -454,11 +450,15 @@
{
"begin": "\\(",
"beginCaptures": {
- "0": "punctuation.section.group.begin.batchfile"
+ "0": {
+ "name": "punctuation.section.group.begin.batchfile"
+ }
},
"end": "\\)",
"endCaptures": {
- "0": "punctuation.section.group.end.batchfile"
+ "0": {
+ "name": "punctuation.section.group.end.batchfile"
+ }
},
"name": "meta.group.batchfile",
"patterns": [
diff --git a/extensions/configuration-editing/npm-shrinkwrap.json b/extensions/configuration-editing/npm-shrinkwrap.json
deleted file mode 100644
index fd5b19bc40..0000000000
--- a/extensions/configuration-editing/npm-shrinkwrap.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "name": "configuration-editing",
- "version": "0.0.1",
- "dependencies": {
- "jsonc-parser": {
- "version": "0.3.1",
- "from": "jsonc-parser@0.3.1"
- },
- "vscode-nls": {
- "version": "2.0.2",
- "from": "vscode-nls@>=2.0.2 <3.0.0",
- "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-2.0.2.tgz"
- }
- }
-}
diff --git a/extensions/configuration-editing/package.json b/extensions/configuration-editing/package.json
index 9659fdcbc9..817d50a451 100644
--- a/extensions/configuration-editing/package.json
+++ b/extensions/configuration-editing/package.json
@@ -1,6 +1,8 @@
{
"name": "configuration-editing",
- "version": "0.0.1",
+ "displayName": "%displayName%",
+ "description": "%description%",
+ "version": "1.0.0",
"publisher": "vscode",
"engines": {
"vscode": "^1.0.0"
@@ -10,7 +12,8 @@
"Other"
],
"activationEvents": [
- "onLanguage:json", "onLanguage:jsonc"
+ "onLanguage:json",
+ "onLanguage:jsonc"
],
"main": "./out/extension",
"scripts": {
@@ -18,8 +21,8 @@
"watch": "gulp watch-extension:configuration-editing"
},
"dependencies": {
- "jsonc-parser": "^0.3.1",
- "vscode-nls": "^2.0.1"
+ "jsonc-parser": "^1.0.0",
+ "vscode-nls": "^3.2.1"
},
"contributes": {
"jsonValidation": [
@@ -67,6 +70,10 @@
"fileMatch": "%APP_SETTINGS_HOME%/snippets/*.json",
"url": "vscode://schemas/snippets"
},
+ {
+ "fileMatch": "**/*.code-snippets",
+ "url": "vscode://schemas/global-snippets"
+ },
{
"fileMatch": "/.vscode/extensions.json",
"url": "vscode://schemas/extensions"
@@ -76,4 +83,4 @@
"devDependencies": {
"@types/node": "7.0.4"
}
-}
+}
\ No newline at end of file
diff --git a/extensions/configuration-editing/package.nls.json b/extensions/configuration-editing/package.nls.json
new file mode 100644
index 0000000000..b8c247a9de
--- /dev/null
+++ b/extensions/configuration-editing/package.nls.json
@@ -0,0 +1,4 @@
+{
+ "displayName": "Configuration Editing",
+ "description": "Provides capabilities (advanced IntelliSense, auto-fixing) in configuration files like settings, launch and extension recommendation files."
+}
\ No newline at end of file
diff --git a/extensions/configuration-editing/src/extension.ts b/extensions/configuration-editing/src/extension.ts
index 2759604e06..a484cee34f 100644
--- a/extensions/configuration-editing/src/extension.ts
+++ b/extensions/configuration-editing/src/extension.ts
@@ -2,16 +2,14 @@
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-
'use strict';
+import * as nls from 'vscode-nls';
+const localize = nls.loadMessageBundle();
import * as vscode from 'vscode';
-import { getLocation, visit, parse } from 'jsonc-parser';
+import { getLocation, visit, parse, ParseErrorCode } from 'jsonc-parser';
import * as path from 'path';
import { SettingsDocument } from './settingsDocumentHelper';
-import * as nls from 'vscode-nls';
-
-const localize = nls.loadMessageBundle();
const decoration = vscode.window.createTextEditorDecorationType({
color: '#9e9e9e'
@@ -20,7 +18,6 @@ const decoration = vscode.window.createTextEditorDecorationType({
let pendingLaunchJsonDecoration: NodeJS.Timer;
export function activate(context: vscode.ExtensionContext): void {
-
//keybindings.json command-suggestions
context.subscriptions.push(registerKeybindingsCompletions());
@@ -41,6 +38,45 @@ export function activate(context: vscode.ExtensionContext): void {
}
}, null, context.subscriptions));
updateLaunchJsonDecorations(vscode.window.activeTextEditor);
+
+ context.subscriptions.push(vscode.workspace.onWillSaveTextDocument(e => {
+ if (!e.document.fileName.endsWith('/settings.json')) {
+ return;
+ }
+
+ autoFixSettingsJSON(e);
+ }));
+}
+
+function autoFixSettingsJSON(willSaveEvent: vscode.TextDocumentWillSaveEvent): void {
+ const document = willSaveEvent.document;
+ const text = document.getText();
+ const edit = new vscode.WorkspaceEdit();
+
+ let lastEndOfSomething = -1;
+ visit(text, {
+ onArrayEnd(offset: number, length: number): void {
+ lastEndOfSomething = offset + length;
+ },
+
+ onLiteralValue(value: any, offset: number, length: number): void {
+ lastEndOfSomething = offset + length;
+ },
+
+ onObjectEnd(offset: number, length: number): void {
+ lastEndOfSomething = offset + length;
+ },
+
+ onError(error: ParseErrorCode, offset: number, length: number): void {
+ if (error === ParseErrorCode.CommaExpected && lastEndOfSomething > -1) {
+ const fixPosition = document.positionAt(lastEndOfSomething);
+ edit.insert(document.uri, fixPosition, ',');
+ }
+ }
+ });
+
+ willSaveEvent.waitUntil(
+ vscode.workspace.applyEdit(edit));
}
function registerKeybindingsCompletions(): vscode.Disposable {
diff --git a/extensions/configuration-editing/src/settingsDocumentHelper.ts b/extensions/configuration-editing/src/settingsDocumentHelper.ts
index 9369181fcf..1bc215ec79 100644
--- a/extensions/configuration-editing/src/settingsDocumentHelper.ts
+++ b/extensions/configuration-editing/src/settingsDocumentHelper.ts
@@ -60,26 +60,26 @@ export class SettingsDocument {
private provideFilesAssociationsCompletionItems(location: Location, range: vscode.Range): vscode.ProviderResult {
const completions: vscode.CompletionItem[] = [];
- // Key
- if (location.path.length === 1) {
- completions.push(this.newSnippetCompletionItem({
- label: localize('assocLabelFile', "Files with Extension"),
- documentation: localize('assocDescriptionFile', "Map all files matching the glob pattern in their filename to the language with the given identifier."),
- snippet: location.isAtPropertyKey ? '"*.${1:extension}": "${2:language}"' : '{ "*.${1:extension}": "${2:language}" }',
- range
- }));
+ if (location.path.length === 2) {
+ // Key
+ if (!location.isAtPropertyKey || location.path[1] === '') {
+ completions.push(this.newSnippetCompletionItem({
+ label: localize('assocLabelFile', "Files with Extension"),
+ documentation: localize('assocDescriptionFile', "Map all files matching the glob pattern in their filename to the language with the given identifier."),
+ snippet: location.isAtPropertyKey ? '"*.${1:extension}": "${2:language}"' : '{ "*.${1:extension}": "${2:language}" }',
+ range
+ }));
- completions.push(this.newSnippetCompletionItem({
- label: localize('assocLabelPath', "Files with Path"),
- documentation: localize('assocDescriptionPath', "Map all files matching the absolute path glob pattern in their path to the language with the given identifier."),
- snippet: location.isAtPropertyKey ? '"/${1:path to file}/*.${2:extension}": "${3:language}"' : '{ "/${1:path to file}/*.${2:extension}": "${3:language}" }',
- range
- }));
- }
-
- // Value
- else if (location.path.length === 2 && !location.isAtPropertyKey) {
- return this.provideLanguageCompletionItems(location, range);
+ completions.push(this.newSnippetCompletionItem({
+ label: localize('assocLabelPath', "Files with Path"),
+ documentation: localize('assocDescriptionPath', "Map all files matching the absolute path glob pattern in their path to the language with the given identifier."),
+ snippet: location.isAtPropertyKey ? '"/${1:path to file}/*.${2:extension}": "${3:language}"' : '{ "/${1:path to file}/*.${2:extension}": "${3:language}" }',
+ range
+ }));
+ } else {
+ // Value
+ return this.provideLanguageCompletionItems(location, range);
+ }
}
return Promise.resolve(completions);
diff --git a/extensions/configuration-editing/tsconfig.json b/extensions/configuration-editing/tsconfig.json
index 23392904de..84b75434d2 100644
--- a/extensions/configuration-editing/tsconfig.json
+++ b/extensions/configuration-editing/tsconfig.json
@@ -6,9 +6,10 @@
"lib": [
"es2015"
],
- "strict": true
+ "strict": true,
+ "noUnusedLocals": true
},
"include": [
"src/**/*"
]
-}
+}
\ No newline at end of file
diff --git a/extensions/configuration-editing/yarn.lock b/extensions/configuration-editing/yarn.lock
index b1e6a363c9..29d3d43ae8 100644
--- a/extensions/configuration-editing/yarn.lock
+++ b/extensions/configuration-editing/yarn.lock
@@ -6,12 +6,10 @@
version "7.0.4"
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.4.tgz#9aabc135979ded383325749f508894c662948c8b"
-jsonc-parser@^0.3.1:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-0.3.1.tgz#6ebf5c75224368d4b07ef4c26f9434e657472e95"
- dependencies:
- vscode-nls "^2.0.2"
+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@^2.0.1, 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"
diff --git a/extensions/declares.d.ts b/extensions/declares.d.ts
deleted file mode 100644
index c15a532cf3..0000000000
--- a/extensions/declares.d.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-/*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the Source EULA. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-
-///
-
-// Declaring the following because the code gets compiled with es5, which lack definitions for console and timers.
-declare var console: {
- assert(value: any, message?: string, ...optionalParams: any[]): void;
- dir(obj: any, options?: { showHidden?: boolean, depth?: number, colors?: boolean }): void;
- error(message?: any, ...optionalParams: any[]): void;
- info(message?: any, ...optionalParams: any[]): void;
- log(message?: any, ...optionalParams: any[]): void;
- time(label: string): void;
- timeEnd(label: string): void;
- trace(message?: any, ...optionalParams: any[]): void;
- warn(message?: any, ...optionalParams: any[]): void;
-};
-
-
-// ---- ES6 promise ------------------------------------------------------
-
-/**
- * Represents the completion of an asynchronous operation.
- */
-interface Promise extends Thenable {
- /**
- * Attaches callbacks for the resolution and/or rejection of the Promise.
- * @param onfulfilled The callback to execute when the Promise is resolved.
- * @param onrejected The callback to execute when the Promise is rejected.
- * @returns A Promise for the completion of which ever callback is executed.
- */
- then(onfulfilled?: (value: T) => TResult | Thenable, onrejected?: (reason: any) => TResult | Thenable): Promise;
- then(onfulfilled?: (value: T) => TResult | Thenable, onrejected?: (reason: any) => void): Promise;
-
- /**
- * Attaches a callback for only the rejection of the Promise.
- * @param onrejected The callback to execute when the Promise is rejected.
- * @returns A Promise for the completion of the callback.
- */
- catch(onrejected?: (reason: any) => T | Thenable): Promise;
-
- // [Symbol.toStringTag]: string;
-}
-
-interface PromiseConstructor {
- // /**
- // * A reference to the prototype.
- // */
- // prototype: Promise;
-
- /**
- * Creates a new Promise.
- * @param executor A callback used to initialize the promise. This callback is passed two arguments:
- * a resolve callback used to resolve the promise with a value or the result of another promise,
- * and a reject callback used to reject the promise with a provided reason or error.
- */
- new (executor: (resolve: (value?: T | Thenable) => void, reject: (reason?: any) => void) => void): Promise;
-
- /**
- * Creates a Promise that is resolved with an array of results when all of the provided Promises
- * resolve, or rejected when any Promise is rejected.
- * @param values An array of Promises.
- * @returns A new Promise.
- */
- all(values: Array>): Promise;
-
- /**
- * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
- * or rejected.
- * @param values An array of Promises.
- * @returns A new Promise.
- */
- race(values: Array>): Promise;
-
- /**
- * Creates a new rejected promise for the provided reason.
- * @param reason The reason the promise was rejected.
- * @returns A new rejected Promise.
- */
- reject(reason: any): Promise;
-
- /**
- * Creates a new rejected promise for the provided reason.
- * @param reason The reason the promise was rejected.
- * @returns A new rejected Promise.
- */
- reject(reason: any): Promise;
-
- /**
- * Creates a new resolved promise for the provided value.
- * @param value A promise.
- * @returns A promise whose internal state matches the provided promise.
- */
- resolve(value: T | Thenable): Promise;
-
- /**
- * Creates a new resolved promise.
- * @returns A resolved promise.
- */
- resolve(): Promise;
-
- // [Symbol.species]: Function;
-}
-
-declare var Promise: PromiseConstructor;
diff --git a/extensions/diff/.vscodeignore b/extensions/diff/.vscodeignore
deleted file mode 100644
index 77ab386fc7..0000000000
--- a/extensions/diff/.vscodeignore
+++ /dev/null
@@ -1 +0,0 @@
-test/**
\ No newline at end of file
diff --git a/extensions/diff/package.json b/extensions/diff/package.json
deleted file mode 100644
index a62e57243c..0000000000
--- a/extensions/diff/package.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "name": "diff",
- "version": "0.1.0",
- "publisher": "vscode",
- "engines": { "vscode": "*" },
- "scripts": {
- "update-grammar": "node ../../build/npm/update-grammar.js textmate/diff.tmbundle Syntaxes/Diff.plist ./syntaxes/diff.tmLanguage.json"
- },
- "contributes": {
- "languages": [
- {
- "id": "diff",
- "aliases": ["Diff", "diff" ],
- "extensions": [".diff", ".patch", ".rej"],
- "configuration": "./language-configuration.json"
- }
- ],
- "grammars": [
- {
- "language": "diff",
- "scopeName": "source.diff",
- "path": "./syntaxes/diff.tmLanguage.json"
- }
- ]
- }
-}
\ No newline at end of file
diff --git a/extensions/diff/syntaxes/diff.tmLanguage b/extensions/diff/syntaxes/diff.tmLanguage
deleted file mode 100644
index d0c5d15437..0000000000
--- a/extensions/diff/syntaxes/diff.tmLanguage
+++ /dev/null
@@ -1,268 +0,0 @@
-
-
-
-
- fileTypes
-
- patch
- diff
- rej
-
- firstLineMatch
- (?x)^
- (===\ modified\ file
- |==== \s* // .+ \s - \s .+ \s+ ====
- |Index:\
- |---\ [^%\n]
- |\*\*\*.*\d{4}\s*$
- |\d+(,\d+)* (a|d|c) \d+(,\d+)* $
- |diff\ --git\
- |commit\ [0-9a-f]{40}$
- )
- keyEquivalent
- ^~D
- name
- Diff
- patterns
-
-
- captures
-
- 1
-
- name
- punctuation.definition.separator.diff
-
-
- match
- ^((\*{15})|(={67})|(-{3}))$\n?
- name
- meta.separator.diff
-
-
- match
- ^\d+(,\d+)*(a|d|c)\d+(,\d+)*$\n?
- name
- meta.diff.range.normal
-
-
- captures
-
- 1
-
- name
- punctuation.definition.range.diff
-
- 2
-
- name
- meta.toc-list.line-number.diff
-
- 3
-
- name
- punctuation.definition.range.diff
-
-
- match
- ^(@@)\s*(.+?)\s*(@@)($\n?)?
- name
- meta.diff.range.unified
-
-
- captures
-
- 3
-
- name
- punctuation.definition.range.diff
-
- 4
-
- name
- punctuation.definition.range.diff
-
- 6
-
- name
- punctuation.definition.range.diff
-
- 7
-
- name
- punctuation.definition.range.diff
-
-
- match
- ^(((\-{3}) .+ (\-{4}))|((\*{3}) .+ (\*{4})))$\n?
- name
- meta.diff.range.context
-
-
- match
- ^diff --git a/.*$\n?
- name
- meta.diff.header.git
-
-
- match
- ^diff (-|\S+\s+\S+).*$\n?
- name
- meta.diff.header.command
-
-
- captures
-
- 4
-
- name
- punctuation.definition.from-file.diff
-
- 6
-
- name
- punctuation.definition.from-file.diff
-
- 7
-
- name
- punctuation.definition.from-file.diff
-
-
- match
- (^(((-{3}) .+)|((\*{3}) .+))$\n?|^(={4}) .+(?= - ))
- name
- meta.diff.header.from-file
-
-
- captures
-
- 2
-
- name
- punctuation.definition.to-file.diff
-
- 3
-
- name
- punctuation.definition.to-file.diff
-
- 4
-
- name
- punctuation.definition.to-file.diff
-
-
- match
- (^(\+{3}) .+$\n?| (-) .* (={4})$\n?)
- name
- meta.diff.header.to-file
-
-
- captures
-
- 3
-
- name
- punctuation.definition.inserted.diff
-
- 6
-
- name
- punctuation.definition.inserted.diff
-
-
- match
- ^(((>)( .*)?)|((\+).*))$\n?
- name
- markup.inserted.diff
-
-
- captures
-
- 1
-
- name
- punctuation.definition.inserted.diff
-
-
- match
- ^(!).*$\n?
- name
- markup.changed.diff
-
-
- captures
-
- 3
-
- name
- punctuation.definition.inserted.diff
-
- 6
-
- name
- punctuation.definition.inserted.diff
-
-
- match
- ^(((<)( .*)?)|((-).*))$\n?
- name
- markup.deleted.diff
-
-
- begin
- ^(#)
- captures
-
- 1
-
- name
- punctuation.definition.comment.diff
-
-
- comment
- Git produces unified diffs with embedded comments"
- end
- \n
- name
- comment.line.number-sign.diff
-
-
- match
- ^index [0-9a-f]{7,40}\.\.[0-9a-f]{7,40}.*$\n?
- name
- meta.diff.index.git
-
-
- captures
-
- 1
-
- name
- punctuation.separator.key-value.diff
-
- 2
-
- name
- meta.toc-list.file-name.diff
-
-
- match
- ^Index(:) (.+)$\n?
- name
- meta.diff.index
-
-
- match
- ^Only in .*: .*$\n?
- name
- meta.diff.only-in
-
-
- scopeName
- source.diff
- uuid
- 7E848FF4-708E-11D9-97B4-0011242E4184
-
-
diff --git a/extensions/diff/test/colorize-fixtures/test.diff b/extensions/diff/test/colorize-fixtures/test.diff
deleted file mode 100644
index f8805a8987..0000000000
--- a/extensions/diff/test/colorize-fixtures/test.diff
+++ /dev/null
@@ -1,19 +0,0 @@
---- lao Sat Jan 26 23:30:39 1991
-+++ tzu Sat Jan 26 23:30:50 1991
-@@ -1,7 +1,6 @@
--The Way that can be told of is not the eternal Way;
--The name that can be named is not the eternal name.
- The Nameless is the origin of Heaven and Earth;
--The Named is the mother of all things.
-+The named is the mother of all things.
-+
- Therefore let there always be non-being,
- so we may see their subtlety,
- And let there always be being,
-@@ -9,3 +8,6 @@
- The two are the same,
- But after they are produced,
- they have different names.
-+They both may be called deep and profound.
-+Deeper and more profound,
-+The door of all subtleties!
\ No newline at end of file
diff --git a/extensions/diff/test/colorize-results/test_diff.json b/extensions/diff/test/colorize-results/test_diff.json
deleted file mode 100644
index 26ab2f4fb0..0000000000
--- a/extensions/diff/test/colorize-results/test_diff.json
+++ /dev/null
@@ -1,398 +0,0 @@
-[
- {
- "c": "---",
- "t": "source.diff meta.diff.header.from-file punctuation.definition.from-file.diff",
- "r": {
- "dark_plus": "meta.diff.header: #569CD6",
- "light_plus": "meta.diff.header: #000080",
- "dark_vs": "meta.diff.header: #569CD6",
- "light_vs": "meta.diff.header: #000080",
- "hc_black": "meta.diff.header: #000080"
- }
- },
- {
- "c": " lao\tSat Jan 26 23:30:39 1991",
- "t": "source.diff meta.diff.header.from-file",
- "r": {
- "dark_plus": "meta.diff.header: #569CD6",
- "light_plus": "meta.diff.header: #000080",
- "dark_vs": "meta.diff.header: #569CD6",
- "light_vs": "meta.diff.header: #000080",
- "hc_black": "meta.diff.header: #000080"
- }
- },
- {
- "c": "+++",
- "t": "source.diff meta.diff.header.to-file punctuation.definition.to-file.diff",
- "r": {
- "dark_plus": "meta.diff.header: #569CD6",
- "light_plus": "meta.diff.header: #000080",
- "dark_vs": "meta.diff.header: #569CD6",
- "light_vs": "meta.diff.header: #000080",
- "hc_black": "meta.diff.header: #000080"
- }
- },
- {
- "c": " tzu\tSat Jan 26 23:30:50 1991",
- "t": "source.diff meta.diff.header.to-file",
- "r": {
- "dark_plus": "meta.diff.header: #569CD6",
- "light_plus": "meta.diff.header: #000080",
- "dark_vs": "meta.diff.header: #569CD6",
- "light_vs": "meta.diff.header: #000080",
- "hc_black": "meta.diff.header: #000080"
- }
- },
- {
- "c": "@@",
- "t": "source.diff meta.diff.range.unified punctuation.definition.range.diff",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": " ",
- "t": "source.diff meta.diff.range.unified",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": "-1,7 +1,6",
- "t": "source.diff meta.diff.range.unified meta.toc-list.line-number.diff",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": " ",
- "t": "source.diff meta.diff.range.unified",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": "@@",
- "t": "source.diff meta.diff.range.unified punctuation.definition.range.diff",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": "-",
- "t": "source.diff markup.deleted.diff punctuation.definition.deleted.diff",
- "r": {
- "dark_plus": "markup.deleted: #CE9178",
- "light_plus": "markup.deleted: #A31515",
- "dark_vs": "markup.deleted: #CE9178",
- "light_vs": "markup.deleted: #A31515",
- "hc_black": "markup.deleted: #CE9178"
- }
- },
- {
- "c": "The Way that can be told of is not the eternal Way;",
- "t": "source.diff markup.deleted.diff",
- "r": {
- "dark_plus": "markup.deleted: #CE9178",
- "light_plus": "markup.deleted: #A31515",
- "dark_vs": "markup.deleted: #CE9178",
- "light_vs": "markup.deleted: #A31515",
- "hc_black": "markup.deleted: #CE9178"
- }
- },
- {
- "c": "-",
- "t": "source.diff markup.deleted.diff punctuation.definition.deleted.diff",
- "r": {
- "dark_plus": "markup.deleted: #CE9178",
- "light_plus": "markup.deleted: #A31515",
- "dark_vs": "markup.deleted: #CE9178",
- "light_vs": "markup.deleted: #A31515",
- "hc_black": "markup.deleted: #CE9178"
- }
- },
- {
- "c": "The name that can be named is not the eternal name.",
- "t": "source.diff markup.deleted.diff",
- "r": {
- "dark_plus": "markup.deleted: #CE9178",
- "light_plus": "markup.deleted: #A31515",
- "dark_vs": "markup.deleted: #CE9178",
- "light_vs": "markup.deleted: #A31515",
- "hc_black": "markup.deleted: #CE9178"
- }
- },
- {
- "c": " The Nameless is the origin of Heaven and Earth;",
- "t": "source.diff",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": "-",
- "t": "source.diff markup.deleted.diff punctuation.definition.deleted.diff",
- "r": {
- "dark_plus": "markup.deleted: #CE9178",
- "light_plus": "markup.deleted: #A31515",
- "dark_vs": "markup.deleted: #CE9178",
- "light_vs": "markup.deleted: #A31515",
- "hc_black": "markup.deleted: #CE9178"
- }
- },
- {
- "c": "The Named is the mother of all things.",
- "t": "source.diff markup.deleted.diff",
- "r": {
- "dark_plus": "markup.deleted: #CE9178",
- "light_plus": "markup.deleted: #A31515",
- "dark_vs": "markup.deleted: #CE9178",
- "light_vs": "markup.deleted: #A31515",
- "hc_black": "markup.deleted: #CE9178"
- }
- },
- {
- "c": "+",
- "t": "source.diff markup.inserted.diff punctuation.definition.inserted.diff",
- "r": {
- "dark_plus": "markup.inserted: #B5CEA8",
- "light_plus": "markup.inserted: #09885A",
- "dark_vs": "markup.inserted: #B5CEA8",
- "light_vs": "markup.inserted: #09885A",
- "hc_black": "markup.inserted: #B5CEA8"
- }
- },
- {
- "c": "The named is the mother of all things.",
- "t": "source.diff markup.inserted.diff",
- "r": {
- "dark_plus": "markup.inserted: #B5CEA8",
- "light_plus": "markup.inserted: #09885A",
- "dark_vs": "markup.inserted: #B5CEA8",
- "light_vs": "markup.inserted: #09885A",
- "hc_black": "markup.inserted: #B5CEA8"
- }
- },
- {
- "c": "+",
- "t": "source.diff markup.inserted.diff punctuation.definition.inserted.diff",
- "r": {
- "dark_plus": "markup.inserted: #B5CEA8",
- "light_plus": "markup.inserted: #09885A",
- "dark_vs": "markup.inserted: #B5CEA8",
- "light_vs": "markup.inserted: #09885A",
- "hc_black": "markup.inserted: #B5CEA8"
- }
- },
- {
- "c": " Therefore let there always be non-being,",
- "t": "source.diff",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": " so we may see their subtlety,",
- "t": "source.diff",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": " And let there always be being,",
- "t": "source.diff",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": "@@",
- "t": "source.diff meta.diff.range.unified punctuation.definition.range.diff",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": " ",
- "t": "source.diff meta.diff.range.unified",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": "-9,3 +8,6",
- "t": "source.diff meta.diff.range.unified meta.toc-list.line-number.diff",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": " ",
- "t": "source.diff meta.diff.range.unified",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": "@@",
- "t": "source.diff meta.diff.range.unified punctuation.definition.range.diff",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": " The two are the same,",
- "t": "source.diff",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": " But after they are produced,",
- "t": "source.diff",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": " they have different names.",
- "t": "source.diff",
- "r": {
- "dark_plus": "default: #D4D4D4",
- "light_plus": "default: #000000",
- "dark_vs": "default: #D4D4D4",
- "light_vs": "default: #000000",
- "hc_black": "default: #FFFFFF"
- }
- },
- {
- "c": "+",
- "t": "source.diff markup.inserted.diff punctuation.definition.inserted.diff",
- "r": {
- "dark_plus": "markup.inserted: #B5CEA8",
- "light_plus": "markup.inserted: #09885A",
- "dark_vs": "markup.inserted: #B5CEA8",
- "light_vs": "markup.inserted: #09885A",
- "hc_black": "markup.inserted: #B5CEA8"
- }
- },
- {
- "c": "They both may be called deep and profound.",
- "t": "source.diff markup.inserted.diff",
- "r": {
- "dark_plus": "markup.inserted: #B5CEA8",
- "light_plus": "markup.inserted: #09885A",
- "dark_vs": "markup.inserted: #B5CEA8",
- "light_vs": "markup.inserted: #09885A",
- "hc_black": "markup.inserted: #B5CEA8"
- }
- },
- {
- "c": "+",
- "t": "source.diff markup.inserted.diff punctuation.definition.inserted.diff",
- "r": {
- "dark_plus": "markup.inserted: #B5CEA8",
- "light_plus": "markup.inserted: #09885A",
- "dark_vs": "markup.inserted: #B5CEA8",
- "light_vs": "markup.inserted: #09885A",
- "hc_black": "markup.inserted: #B5CEA8"
- }
- },
- {
- "c": "Deeper and more profound,",
- "t": "source.diff markup.inserted.diff",
- "r": {
- "dark_plus": "markup.inserted: #B5CEA8",
- "light_plus": "markup.inserted: #09885A",
- "dark_vs": "markup.inserted: #B5CEA8",
- "light_vs": "markup.inserted: #09885A",
- "hc_black": "markup.inserted: #B5CEA8"
- }
- },
- {
- "c": "+",
- "t": "source.diff markup.inserted.diff punctuation.definition.inserted.diff",
- "r": {
- "dark_plus": "markup.inserted: #B5CEA8",
- "light_plus": "markup.inserted: #09885A",
- "dark_vs": "markup.inserted: #B5CEA8",
- "light_vs": "markup.inserted: #09885A",
- "hc_black": "markup.inserted: #B5CEA8"
- }
- },
- {
- "c": "The door of all subtleties!",
- "t": "source.diff markup.inserted.diff",
- "r": {
- "dark_plus": "markup.inserted: #B5CEA8",
- "light_plus": "markup.inserted: #09885A",
- "dark_vs": "markup.inserted: #B5CEA8",
- "light_vs": "markup.inserted: #09885A",
- "hc_black": "markup.inserted: #B5CEA8"
- }
- }
-]
\ No newline at end of file
diff --git a/extensions/docker/package.json b/extensions/docker/package.json
index e58f082641..41df24723f 100644
--- a/extensions/docker/package.json
+++ b/extensions/docker/package.json
@@ -1,6 +1,8 @@
{
"name": "docker",
- "version": "0.1.0",
+ "displayName": "%displayName%",
+ "description": "%description%",
+ "version": "1.0.0",
"publisher": "vscode",
"engines": { "vscode": "*" },
"scripts": {
diff --git a/extensions/docker/package.nls.json b/extensions/docker/package.nls.json
new file mode 100644
index 0000000000..2a38ca3da6
--- /dev/null
+++ b/extensions/docker/package.nls.json
@@ -0,0 +1,4 @@
+{
+ "displayName": "Docker Language Basics",
+ "description": "Provides syntax highlighting and bracket matching in Docker files."
+}
\ No newline at end of file
diff --git a/extensions/docker/syntaxes/docker.tmLanguage.json b/extensions/docker/syntaxes/docker.tmLanguage.json
index 44a028e785..f7f414636c 100644
--- a/extensions/docker/syntaxes/docker.tmLanguage.json
+++ b/extensions/docker/syntaxes/docker.tmLanguage.json
@@ -5,10 +5,8 @@
"Once accepted there, we are happy to receive an update request."
],
"version": "https://github.com/moby/moby/commit/abd39744c6f3ed854500e423f5fabf952165161f",
- "fileTypes": [
- "Dockerfile"
- ],
"name": "Dockerfile",
+ "scopeName": "source.dockerfile",
"patterns": [
{
"captures": {
@@ -100,7 +98,5 @@
"comment": "comment.line",
"match": "^(\\s*)((#).*$\\n?)"
}
- ],
- "scopeName": "source.dockerfile",
- "uuid": "a39d8795-59d2-49af-aa00-fe74ee29576e"
+ ]
}
\ No newline at end of file
diff --git a/extensions/extension-editing/npm-shrinkwrap.json b/extensions/extension-editing/npm-shrinkwrap.json
deleted file mode 100644
index 2cfa863b62..0000000000
--- a/extensions/extension-editing/npm-shrinkwrap.json
+++ /dev/null
@@ -1,62 +0,0 @@
-{
- "name": "extension-editing",
- "version": "0.0.1",
- "dependencies": {
- "@types/node": {
- "version": "6.0.78",
- "from": "@types/node@>=6.0.46 <7.0.0",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-6.0.78.tgz",
- "dev": true
- },
- "argparse": {
- "version": "1.0.9",
- "from": "argparse@>=1.0.7 <2.0.0",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz"
- },
- "entities": {
- "version": "1.1.1",
- "from": "entities@>=1.1.1 <1.2.0",
- "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz"
- },
- "jsonc-parser": {
- "version": "0.3.1",
- "from": "jsonc-parser@>=0.3.1 <0.4.0",
- "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-0.3.1.tgz"
- },
- "linkify-it": {
- "version": "2.0.3",
- "from": "linkify-it@>=2.0.0 <3.0.0",
- "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.0.3.tgz"
- },
- "markdown-it": {
- "version": "8.3.1",
- "from": "markdown-it@>=8.3.1 <9.0.0",
- "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.3.1.tgz"
- },
- "mdurl": {
- "version": "1.0.1",
- "from": "mdurl@>=1.0.1 <2.0.0",
- "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz"
- },
- "parse5": {
- "version": "3.0.2",
- "from": "parse5@>=3.0.2 <4.0.0",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.2.tgz"
- },
- "sprintf-js": {
- "version": "1.0.3",
- "from": "sprintf-js@>=1.0.2 <1.1.0",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz"
- },
- "uc.micro": {
- "version": "1.0.3",
- "from": "uc.micro@>=1.0.3 <2.0.0",
- "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.3.tgz"
- },
- "vscode-nls": {
- "version": "2.0.2",
- "from": "vscode-nls@>=2.0.1 <3.0.0",
- "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-2.0.2.tgz"
- }
- }
-}
diff --git a/extensions/extension-editing/package.json b/extensions/extension-editing/package.json
index 3dbda782d6..b5feab96d7 100644
--- a/extensions/extension-editing/package.json
+++ b/extensions/extension-editing/package.json
@@ -1,6 +1,8 @@
{
"name": "extension-editing",
- "version": "0.0.1",
+ "displayName": "%displayName%",
+ "description": "%description%",
+ "version": "1.0.0",
"publisher": "vscode",
"engines": {
"vscode": "^1.4.0"
@@ -20,10 +22,10 @@
"watch": "gulp watch-extension:extension-editing"
},
"dependencies": {
- "jsonc-parser": "^0.3.1",
+ "jsonc-parser": "^1.0.0",
"markdown-it": "^8.3.1",
"parse5": "^3.0.2",
- "vscode-nls": "^2.0.1"
+ "vscode-nls": "^3.2.1"
},
"contributes": {
"jsonValidation": [
diff --git a/extensions/extension-editing/package.nls.json b/extensions/extension-editing/package.nls.json
new file mode 100644
index 0000000000..9265e6a3c9
--- /dev/null
+++ b/extensions/extension-editing/package.nls.json
@@ -0,0 +1,4 @@
+{
+ "displayName": "Package File Editing",
+ "description": "Provides IntelliSense for VS Code extension points and linting capabilities in package.json files."
+}
\ No newline at end of file
diff --git a/extensions/extension-editing/src/extensionLinter.ts b/extensions/extension-editing/src/extensionLinter.ts
index 8f0eb85ad9..36d312d7df 100644
--- a/extensions/extension-editing/src/extensionLinter.ts
+++ b/extensions/extension-editing/src/extensionLinter.ts
@@ -6,8 +6,10 @@
import * as fs from 'fs';
import * as path from 'path';
-import { parseTree, findNodeAtLocation, Node as JsonNode } from 'jsonc-parser';
import * as nls from 'vscode-nls';
+const localize = nls.loadMessageBundle();
+
+import { parseTree, findNodeAtLocation, Node as JsonNode } from 'jsonc-parser';
import * as MarkdownItType from 'markdown-it';
import { languages, workspace, Disposable, TextDocument, Uri, Diagnostic, Range, DiagnosticSeverity, Position } from 'vscode';
@@ -15,8 +17,6 @@ import { languages, workspace, Disposable, TextDocument, Uri, Diagnostic, Range,
const product = require('../../../product.json');
const allowedBadgeProviders: string[] = (product.extensionAllowedBadgeProviders || []).map(s => s.toLowerCase());
-const localize = nls.loadMessageBundle();
-
const httpsRequired = localize('httpsRequired', "Images must use the HTTPS protocol.");
const svgsNotValid = localize('svgsNotValid', "SVGs are not a valid image source.");
const embeddedSvgsNotValid = localize('embeddedSvgsNotValid', "Embedded SVGs are not a valid image source.");
diff --git a/extensions/extension-editing/yarn.lock b/extensions/extension-editing/yarn.lock
index b7d1eacebe..350fdcb5fe 100644
--- a/extensions/extension-editing/yarn.lock
+++ b/extensions/extension-editing/yarn.lock
@@ -20,11 +20,9 @@ entities@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0"
-jsonc-parser@^0.3.1:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-0.3.1.tgz#6ebf5c75224368d4b07ef4c26f9434e657472e95"
- dependencies:
- vscode-nls "^2.0.2"
+jsonc-parser@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-1.0.0.tgz#ddcc864ae708e60a7a6dd36daea00172fa8d9272"
linkify-it@^2.0.0:
version "2.0.3"
@@ -33,8 +31,8 @@ linkify-it@^2.0.0:
uc.micro "^1.0.1"
markdown-it@^8.3.1:
- version "8.3.1"
- resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.3.1.tgz#2f4b622948ccdc193d66f3ca2d43125ac4ac7323"
+ version "8.4.0"
+ resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-8.4.0.tgz#e2400881bf171f7018ed1bd9da441dac8af6306d"
dependencies:
argparse "^1.0.7"
entities "~1.1.1"
@@ -60,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@^2.0.1, 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"
diff --git a/extensions/git/.vscodeignore b/extensions/git/.vscodeignore
index bbb6314c1b..436567b7d6 100644
--- a/extensions/git/.vscodeignore
+++ b/extensions/git/.vscodeignore
@@ -1,4 +1,5 @@
src/**
test/**
out/test/**
-tsconfig.json
\ No newline at end of file
+tsconfig.json
+build/**
\ No newline at end of file
diff --git a/extensions/git/OSSREADME.json b/extensions/git/OSSREADME.json
index 0e3ddd52fa..533d6ea683 100644
--- a/extensions/git/OSSREADME.json
+++ b/extensions/git/OSSREADME.json
@@ -1,29 +1,52 @@
// ATTENTION - THIS DIRECTORY CONTAINS THIRD PARTY OPEN SOURCE MATERIALS:
-[{
- "name": "textmate/git.tmbundle",
- "version": "0.0.0",
- "license": "MIT",
- "repositoryURL": "https://github.com/textmate/git.tmbundle",
- "licenseDetail": [
- "Copyright (c) 2008 Tim Harper",
- "",
- "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."
- ]
-}]
\ No newline at end of file
+[
+ {
+ "name": "textmate/git.tmbundle",
+ "version": "0.0.0",
+ "license": "MIT",
+ "repositoryURL": "https://github.com/textmate/git.tmbundle",
+ "licenseDetail": [
+ "Copyright (c) 2008 Tim Harper",
+ "",
+ "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."
+ ]
+ },
+ {
+ "name": "textmate/diff.tmbundle",
+ "version": "0.0.0",
+ "license": "TextMate Bundle License",
+ "repositoryURL": "https://github.com/textmate/diff.tmbundle",
+ "licenseDetail": [
+ "Copyright (c) textmate-diff.tmbundle project authors",
+ "",
+ "If not otherwise specified (see below), files in this repository fall under the following license:",
+ "",
+ "Permission to copy, use, modify, sell and distribute this",
+ "software is granted. This software is provided \"as is\" without",
+ "express or implied warranty, and with no claim as to its",
+ "suitability for any purpose.",
+ "",
+ "An exception is made for files in readable text which contain their own license information,",
+ "or files where an accompanying file exists (in the same directory) with a \"-license\" suffix added",
+ "to the base-name name of the original file, and an extension of txt, html, or similar. For example",
+ "\"tidy\" is accompanied by \"tidy-license.txt\"."
+ ]
+ }
+]
\ No newline at end of file
diff --git a/extensions/git/README.md b/extensions/git/README.md
new file mode 100644
index 0000000000..b97ec81e9a
--- /dev/null
+++ b/extensions/git/README.md
@@ -0,0 +1,2 @@
+# Git integration for Visual Studio Code
+
diff --git a/extensions/git/build/update-grammars.js b/extensions/git/build/update-grammars.js
new file mode 100644
index 0000000000..2aa490561e
--- /dev/null
+++ b/extensions/git/build/update-grammars.js
@@ -0,0 +1,16 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+'use strict';
+
+var updateGrammar = require('../../../build/npm/update-grammar');
+
+updateGrammar.update('textmate/git.tmbundle', 'Syntaxes/Git%20Commit%20Message.tmLanguage', './syntaxes/git-commit.tmLanguage.json');
+updateGrammar.update('textmate/git.tmbundle', 'Syntaxes/Git%20Rebase%20Message.tmLanguage', './syntaxes/git-rebase.tmLanguage.json');
+updateGrammar.update('textmate/diff.tmbundle', 'Syntaxes/Diff.plist', './syntaxes/diff.tmLanguage.json');
+
+
+
+
+
diff --git a/extensions/gitsyntax/git-commit.language-configuration.json b/extensions/git/languages/diff.language-configuration.json
similarity index 100%
rename from extensions/gitsyntax/git-commit.language-configuration.json
rename to extensions/git/languages/diff.language-configuration.json
diff --git a/extensions/gitsyntax/git-rebase.language-configuration.json b/extensions/git/languages/git-commit.language-configuration.json
similarity index 100%
rename from extensions/gitsyntax/git-rebase.language-configuration.json
rename to extensions/git/languages/git-commit.language-configuration.json
diff --git a/extensions/diff/language-configuration.json b/extensions/git/languages/git-rebase.language-configuration.json
similarity index 58%
rename from extensions/diff/language-configuration.json
rename to extensions/git/languages/git-rebase.language-configuration.json
index da6ed54715..b61fbe63d3 100644
--- a/extensions/diff/language-configuration.json
+++ b/extensions/git/languages/git-rebase.language-configuration.json
@@ -1,7 +1,7 @@
{
"comments": {
- "lineComment": "//",
- "blockComment": [ "/*", "*/" ]
+ "lineComment": "#",
+ "blockComment": [ "#", " " ]
},
"brackets": [
["{", "}"],
diff --git a/extensions/git/npm-shrinkwrap.json b/extensions/git/npm-shrinkwrap.json
deleted file mode 100644
index 9239e6181f..0000000000
--- a/extensions/git/npm-shrinkwrap.json
+++ /dev/null
@@ -1,36 +0,0 @@
-{
- "name": "git",
- "version": "0.0.1",
- "dependencies": {
- "applicationinsights": {
- "version": "0.18.0",
- "from": "applicationinsights@0.18.0",
- "resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-0.18.0.tgz"
- },
- "byline": {
- "version": "5.0.0",
- "from": "byline@latest",
- "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz"
- },
- "iconv-lite": {
- "version": "0.4.15",
- "from": "iconv-lite@0.4.15",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.15.tgz"
- },
- "vscode-extension-telemetry": {
- "version": "0.0.8",
- "from": "vscode-extension-telemetry@>=0.0.8 <0.0.9",
- "resolved": "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz"
- },
- "vscode-nls": {
- "version": "2.0.2",
- "from": "vscode-nls@>=2.0.1 <3.0.0",
- "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-2.0.2.tgz"
- },
- "winreg": {
- "version": "1.2.3",
- "from": "winreg@1.2.3",
- "resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.3.tgz"
- }
- }
-}
diff --git a/extensions/git/package.json b/extensions/git/package.json
index 2d5b4e3886..8928bbace1 100644
--- a/extensions/git/package.json
+++ b/extensions/git/package.json
@@ -1,9 +1,9 @@
{
"name": "git",
+ "displayName": "%displayName%",
+ "description": "%description%",
"publisher": "vscode",
- "displayName": "git",
- "description": "Git",
- "version": "0.0.1",
+ "version": "1.0.0",
"engines": {
"vscode": "^1.5.0"
},
@@ -16,9 +16,11 @@
"*"
],
"main": "./out/main",
+ "icon": "resources/icons/git.png",
"scripts": {
"compile": "gulp compile-extension:git",
- "watch": "gulp watch-extension:git"
+ "watch": "gulp watch-extension:git",
+ "update-grammar": "node ./build/update-grammars.js"
},
"contributes": {
"commands": [
@@ -68,6 +70,15 @@
"dark": "resources/icons/dark/open-file.svg"
}
},
+ {
+ "command": "git.openFile2",
+ "title": "%command.openFile%",
+ "category": "Git",
+ "icon": {
+ "light": "resources/icons/light/open-file-mono.svg",
+ "dark": "resources/icons/dark/open-file-mono.svg"
+ }
+ },
{
"command": "git.openHEADFile",
"title": "%command.openHEADFile%",
@@ -327,35 +338,35 @@
},
{
"command": "git.close",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.refresh",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.openFile",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.openHEADFile",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.openChange",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.stage",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.stageAll",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.stageSelectedRanges",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.stageChange",
@@ -363,155 +374,159 @@
},
{
"command": "git.revertSelectedRanges",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.revertChange",
"when": "false"
},
+ {
+ "command": "git.openFile2",
+ "when": "false"
+ },
{
"command": "git.unstage",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.unstageAll",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.unstageSelectedRanges",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.clean",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0 && !gitFreshRepository"
},
{
"command": "git.cleanAll",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0 && !gitFreshRepository"
},
{
"command": "git.commit",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.commitStaged",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.commitStagedSigned",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.commitStagedAmend",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.commitAll",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.commitAllSigned",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.commitAllAmend",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.undoCommit",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.checkout",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.branch",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.deleteBranch",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.renameBranch",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.pull",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.pullFrom",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.pullRebase",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.pullFrom",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.merge",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.createTag",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.fetch",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.push",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.pushTo",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.pushWithTags",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.sync",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.syncRebase",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.publish",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.showOutput",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled"
},
{
"command": "git.ignore",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.stashIncludeUntracked",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.stash",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.stashPop",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
},
{
"command": "git.stashPopLatest",
- "when": "gitOpenRepositoryCount != 0"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0"
}
],
"scm/title": [
@@ -618,7 +633,7 @@
{
"command": "git.cleanAll",
"group": "4_stage",
- "when": "scmProvider == git"
+ "when": "scmProvider == git && !gitFreshRepository"
},
{
"command": "git.stashIncludeUntracked",
@@ -676,7 +691,7 @@
},
{
"command": "git.cleanAll",
- "when": "scmProvider == git && scmResourceGroup == workingTree",
+ "when": "scmProvider == git && scmResourceGroup == workingTree && !gitFreshRepository",
"group": "1_modification"
},
{
@@ -686,7 +701,7 @@
},
{
"command": "git.cleanAll",
- "when": "scmProvider == git && scmResourceGroup == workingTree",
+ "when": "scmProvider == git && scmResourceGroup == workingTree && !gitFreshRepository",
"group": "inline"
},
{
@@ -701,11 +716,21 @@
"when": "scmProvider == git && scmResourceGroup == merge",
"group": "1_modification"
},
+ {
+ "command": "git.openFile",
+ "when": "scmProvider == git && scmResourceGroup == merge",
+ "group": "navigation"
+ },
{
"command": "git.stage",
"when": "scmProvider == git && scmResourceGroup == merge",
"group": "inline"
},
+ {
+ "command": "git.openFile2",
+ "when": "scmProvider == git && scmResourceGroup == merge && config.git.showInlineOpenFileAction",
+ "group": "inline0"
+ },
{
"command": "git.openChange",
"when": "scmProvider == git && scmResourceGroup == index",
@@ -731,6 +756,11 @@
"when": "scmProvider == git && scmResourceGroup == index",
"group": "inline"
},
+ {
+ "command": "git.openFile2",
+ "when": "scmProvider == git && scmResourceGroup == index && config.git.showInlineOpenFileAction",
+ "group": "inline0"
+ },
{
"command": "git.openChange",
"when": "scmProvider == git && scmResourceGroup == workingTree",
@@ -753,12 +783,12 @@
},
{
"command": "git.clean",
- "when": "scmProvider == git && scmResourceGroup == workingTree",
+ "when": "scmProvider == git && scmResourceGroup == workingTree && !gitFreshRepository",
"group": "1_modification"
},
{
"command": "git.clean",
- "when": "scmProvider == git && scmResourceGroup == workingTree",
+ "when": "scmProvider == git && scmResourceGroup == workingTree && !gitFreshRepository",
"group": "inline"
},
{
@@ -766,6 +796,11 @@
"when": "scmProvider == git && scmResourceGroup == workingTree",
"group": "inline"
},
+ {
+ "command": "git.openFile2",
+ "when": "scmProvider == git && scmResourceGroup == workingTree && config.git.showInlineOpenFileAction",
+ "group": "inline0"
+ },
{
"command": "git.ignore",
"when": "scmProvider == git && scmResourceGroup == workingTree",
@@ -776,27 +811,27 @@
{
"command": "git.openFile",
"group": "navigation",
- "when": "gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme != extension && resourceScheme != merge-conflict.conflict-diff"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
},
{
"command": "git.openChange",
"group": "navigation",
- "when": "gitOpenRepositoryCount != 0 && !isInDiffEditor && resourceScheme == file"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0 && !isInDiffEditor && resourceScheme == file"
},
{
"command": "git.stageSelectedRanges",
"group": "2_git@1",
- "when": "gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme != merge-conflict.conflict-diff"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
},
{
"command": "git.unstageSelectedRanges",
"group": "2_git@2",
- "when": "gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme != merge-conflict.conflict-diff"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
},
{
"command": "git.revertSelectedRanges",
"group": "2_git@3",
- "when": "gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme != merge-conflict.conflict-diff"
+ "when": "config.git.enabled && gitOpenRepositoryCount != 0 && isInDiffEditor && resourceScheme =~ /^git$|^file$/"
}
],
"scm/change/title": [
@@ -828,6 +863,11 @@
"default": null,
"isExecutable": true
},
+ "git.autoRepositoryDetection": {
+ "type": "boolean",
+ "description": "%config.autoRepositoryDetection%",
+ "default": true
+ },
"git.autorefresh": {
"type": "boolean",
"description": "%config.autorefresh%",
@@ -898,6 +938,32 @@
"type": "boolean",
"default": true,
"description": "%config.decorations.enabled%"
+ },
+ "git.promptToSaveFilesBeforeCommit": {
+ "type": "boolean",
+ "default": false,
+ "description": "%config.promptToSaveFilesBeforeCommit%"
+ },
+ "git.showInlineOpenFileAction": {
+ "type": "boolean",
+ "default": true,
+ "description": "%config.showInlineOpenFileAction%"
+ },
+ "git.inputValidation": {
+ "type": "string",
+ "enum": [
+ "always",
+ "warn",
+ "off"
+ ],
+ "default": "warn",
+ "description": "%config.inputValidation%"
+ },
+ "git.detectSubmodules": {
+ "type": "boolean",
+ "scope": "resource",
+ "default": true,
+ "description": "%config.detectSubmodules%"
}
}
},
@@ -946,15 +1012,86 @@
"dark": "#6c6cc4",
"highContrast": "#6c6cc4"
}
+ },
+ {
+ "id": "gitDecoration.submoduleResourceForeground",
+ "description": "%colors.submodule%",
+ "defaults": {
+ "light": "#1258a7",
+ "dark": "#8db9e2",
+ "highContrast": "#8db9e2"
+ }
}
- ]
+ ],
+ "languages": [
+ {
+ "id": "git-commit",
+ "aliases": [
+ "Git Commit Message",
+ "git-commit"
+ ],
+ "filenames": [
+ "COMMIT_EDITMSG",
+ "MERGE_MSG"
+ ],
+ "configuration": "./languages/git-commit.language-configuration.json"
+ },
+ {
+ "id": "git-rebase",
+ "aliases": [
+ "Git Rebase Message",
+ "git-rebase"
+ ],
+ "filenames": [
+ "git-rebase-todo"
+ ],
+ "configuration": "./languages/git-rebase.language-configuration.json"
+ },
+ {
+ "id": "diff",
+ "aliases": [
+ "Diff",
+ "diff"
+ ],
+ "extensions": [
+ ".patch",
+ ".diff",
+ ".rej"
+ ],
+ "configuration": "./languages/diff.language-configuration.json"
+ }
+ ],
+ "grammars": [
+ {
+ "language": "git-commit",
+ "scopeName": "text.git-commit",
+ "path": "./syntaxes/git-commit.tmLanguage.json"
+ },
+ {
+ "language": "git-rebase",
+ "scopeName": "text.git-rebase",
+ "path": "./syntaxes/git-rebase.tmLanguage.json"
+ },
+ {
+ "language": "diff",
+ "scopeName": "source.diff",
+ "path": "./syntaxes/diff.tmLanguage.json"
+ }
+ ],
+ "configurationDefaults": {
+ "[git-commit]": {
+ "editor.rulers": [
+ 72
+ ]
+ }
+ }
},
"dependencies": {
"byline": "^5.0.0",
"file-type": "^7.2.0",
"iconv-lite": "0.4.19",
- "vscode-extension-telemetry": "0.0.8",
- "vscode-nls": "2.0.2",
+ "vscode-extension-telemetry": "0.0.15",
+ "vscode-nls": "^3.2.1",
"which": "^1.3.0"
},
"devDependencies": {
@@ -965,4 +1102,4 @@
"@types/which": "^1.0.28",
"mocha": "^3.2.0"
}
-}
+}
\ No newline at end of file
diff --git a/extensions/git/package.nls.json b/extensions/git/package.nls.json
index c72fc11253..6910adcbda 100644
--- a/extensions/git/package.nls.json
+++ b/extensions/git/package.nls.json
@@ -1,4 +1,6 @@
{
+ "displayName": "Git",
+ "description": "Git SCM Integration",
"command.clone": "Clone",
"command.init": "Initialize Repository",
"command.close": "Close Repository",
@@ -49,12 +51,13 @@
"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.autorefresh": "Whether auto refreshing is enabled",
"config.autofetch": "Whether auto fetching is enabled",
"config.enableLongCommitWarning": "Whether long commit messages should be warned about",
"config.confirmSync": "Confirm before synchronizing git repositories",
"config.countBadge": "Controls the git badge counter. `all` counts all changes. `tracked` counts only the tracked changes. `off` turns it off.",
- "config.checkoutType": "Controls what type of branches are listed when running `Checkout to...`. `all` shows all refs, `local` shows only the local branchs, `tags` shows only tags and `remote` shows only remote branches.",
+ "config.checkoutType": "Controls what type of branches are listed when running `Checkout to...`. `all` shows all refs, `local` shows only the local branches, `tags` shows only tags and `remote` shows only remote branches.",
"config.ignoreLegacyWarning": "Ignores the legacy Git warning",
"config.ignoreMissingGitWarning": "Ignores the warning when Git is missing",
"config.ignoreLimitWarning": "Ignores the warning when there are too many changes in a repository",
@@ -63,9 +66,14 @@
"config.enableCommitSigning": "Enables commit signing with GPG.",
"config.discardAllScope": "Controls what changes are discarded by the `Discard all changes` command. `all` discards all changes. `tracked` discards only tracked files. `prompt` shows a prompt dialog every time the action is run.",
"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.inputValidation": "Controls when to show commit message input validation.",
+ "config.detectSubmodules": "Controls whether to automatically detect git submodules.",
"colors.modified": "Color for modified resources.",
"colors.deleted": "Color for deleted resources.",
"colors.untracked": "Color for untracked resources.",
"colors.ignored": "Color for ignored resources.",
- "colors.conflict": "Color for resources with conflicts."
+ "colors.conflict": "Color for resources with conflicts.",
+ "colors.submodule": "Color for submodule resources."
}
\ No newline at end of file
diff --git a/extensions/git/resources/icons/dark/open-file-mono.svg b/extensions/git/resources/icons/dark/open-file-mono.svg
new file mode 100644
index 0000000000..830727e70b
--- /dev/null
+++ b/extensions/git/resources/icons/dark/open-file-mono.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/extensions/git/resources/icons/git.png b/extensions/git/resources/icons/git.png
new file mode 100644
index 0000000000..51f4ae5404
Binary files /dev/null and b/extensions/git/resources/icons/git.png differ
diff --git a/extensions/git/resources/icons/light/open-file-mono.svg b/extensions/git/resources/icons/light/open-file-mono.svg
new file mode 100644
index 0000000000..fa3f245b75
--- /dev/null
+++ b/extensions/git/resources/icons/light/open-file-mono.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/extensions/git/resources/icons/light/open-file.svg b/extensions/git/resources/icons/light/open-file.svg
index fccdf83d46..d23a23c6b5 100644
--- a/extensions/git/resources/icons/light/open-file.svg
+++ b/extensions/git/resources/icons/light/open-file.svg
@@ -1,3 +1 @@
-
-]>
\ No newline at end of file
+
\ No newline at end of file
diff --git a/extensions/git/src/api.ts b/extensions/git/src/api.ts
index c510069177..2f4065bbd2 100644
--- a/extensions/git/src/api.ts
+++ b/extensions/git/src/api.ts
@@ -6,7 +6,7 @@
'use strict';
import { Model } from './model';
-import { SourceControlInputBox, Uri } from 'vscode';
+import { Uri } from 'vscode';
export interface InputBox {
value: string;
diff --git a/extensions/git/src/autofetch.ts b/extensions/git/src/autofetch.ts
index 5d4ba069c8..52f1ab3d72 100644
--- a/extensions/git/src/autofetch.ts
+++ b/extensions/git/src/autofetch.ts
@@ -5,7 +5,7 @@
'use strict';
-import { workspace, Disposable, EventEmitter, Memento, window, MessageItem, ConfigurationTarget, commands, Uri } from 'vscode';
+import { workspace, Disposable, EventEmitter, Memento, window, MessageItem, ConfigurationTarget } from 'vscode';
import { GitErrorCodes } from './git';
import { Repository, Operation } from './repository';
import { eventToPromise, filterEvent, onceEvent } from './util';
@@ -54,20 +54,14 @@ export class AutoFetcher {
}
const yes: MessageItem = { title: localize('yes', "Yes") };
- const readMore: MessageItem = { title: localize('read more', "Read More") };
const no: MessageItem = { isCloseAffordance: true, title: localize('no', "No") };
const askLater: MessageItem = { title: localize('not now', "Ask Me Later") };
- const result = await window.showInformationMessage(localize('suggest auto fetch', "Would you like Code to periodically run `git fetch`?"), yes, readMore, no, askLater);
+ const result = await window.showInformationMessage(localize('suggest auto fetch', "Would you like Code to [periodically run 'git fetch']({0})?", 'https://go.microsoft.com/fwlink/?linkid=865294'), yes, no, askLater);
if (result === askLater) {
return;
}
- if (result === readMore) {
- commands.executeCommand('vscode.open', Uri.parse('https://go.microsoft.com/fwlink/?linkid=865294'));
- return this.onFirstGoodRemoteOperation();
- }
-
if (result === yes) {
const gitConfig = workspace.getConfiguration('git');
gitConfig.update('autofetch', true, ConfigurationTarget.Global);
diff --git a/extensions/git/src/commands.ts b/extensions/git/src/commands.ts
index 68ccde085f..d51f0a25aa 100644
--- a/extensions/git/src/commands.ts
+++ b/extensions/git/src/commands.ts
@@ -10,9 +10,10 @@ import { Ref, RefType, Git, GitErrorCodes, Branch } from './git';
import { Repository, Resource, Status, CommitOptions, ResourceGroupType } from './repository';
import { Model } from './model';
import { toGitUri, fromGitUri } from './uri';
-import { grep } from './util';
-import { applyLineChanges, intersectDiffWithRange, toLineRanges, invertLineChange } from './staging';
+import { grep, isDescendant } from './util';
+import { applyLineChanges, intersectDiffWithRange, toLineRanges, invertLineChange, getModifiedRange } from './staging';
import * as path from 'path';
+import { lstat, Stats } from 'fs';
import * as os from 'os';
import TelemetryReporter from 'vscode-extension-telemetry';
import * as nls from 'vscode-nls';
@@ -168,8 +169,28 @@ export class CommandCenter {
}
private async _openResource(resource: Resource, preview?: boolean, preserveFocus?: boolean, preserveSelection?: boolean): Promise {
- const left = await this.getLeftResource(resource);
- const right = await this.getRightResource(resource);
+ let stat: Stats | undefined;
+
+ try {
+ stat = await new Promise((c, e) => lstat(resource.resourceUri.fsPath, (err, stat) => err ? e(err) : c(stat)));
+ } catch (err) {
+ // noop
+ }
+
+ let left: Uri | undefined;
+ let right: Uri | undefined;
+
+ if (stat && stat.isDirectory()) {
+ const repository = this.model.getRepositoryForSubmodule(resource.resourceUri);
+
+ if (repository) {
+ right = toGitUri(resource.resourceUri, resource.resourceGroupType === ResourceGroupType.Index ? 'index' : 'wt', { submoduleOf: repository.root });
+ }
+ } else {
+ left = await this.getLeftResource(resource);
+ right = await this.getRightResource(resource);
+ }
+
const title = this.getTitle(resource);
if (!right) {
@@ -216,7 +237,7 @@ export class CommandCenter {
}
const { size, object } = await repository.lstree(gitRef, uri.fsPath);
- const { mimetype, encoding } = await repository.detectObjectType(object);
+ const { mimetype } = await repository.detectObjectType(object);
if (mimetype === 'text/plain') {
return toGitUri(uri, ref);
@@ -330,7 +351,6 @@ export class CommandCenter {
const config = workspace.getConfiguration('git');
let value = config.get('defaultCloneDirectory') || os.homedir();
- value = value.replace(/^~/, os.homedir());
const parentPath = await window.showInputBox({
prompt: localize('parent', "Parent Directory"),
@@ -358,11 +378,10 @@ export class CommandCenter {
statusBarItem.command = cancelCommandId;
statusBarItem.show();
- const clonePromise = this.git.clone(url, parentPath, tokenSource.token);
+ const clonePromise = this.git.clone(url, parentPath.replace(/^~/, os.homedir()), tokenSource.token);
try {
window.withProgress({ location: ProgressLocation.SourceControl, title: localize('cloning', "Cloning git repository...") }, () => clonePromise);
- // window.withProgress({ location: ProgressLocation.Window, title: localize('cloning', "Cloning git repository...") }, () => clonePromise);
const repositoryPath = await clonePromise;
@@ -484,7 +503,10 @@ export class CommandCenter {
}
if (resource) {
- uris = [...resourceStates.map(r => r.resourceUri), resource.resourceUri];
+ const resources = ([resource, ...resourceStates] as Resource[])
+ .filter(r => r.type !== Status.DELETED && r.type !== Status.INDEX_DELETED);
+
+ uris = resources.map(r => r.resourceUri);
}
}
@@ -511,6 +533,11 @@ export class CommandCenter {
}
}
+ @command('git.openFile2')
+ async openFile2(arg?: Resource | Uri, ...resourceStates: SourceControlResourceState[]): Promise {
+ this.openFile(arg, ...resourceStates);
+ }
+
@command('git.openHEADFile')
async openHEADFile(arg?: Resource | Uri): Promise {
let resource: Resource | undefined = undefined;
@@ -709,10 +736,7 @@ export class CommandCenter {
const modifiedDocument = textEditor.document;
const selections = textEditor.selections;
const selectedChanges = changes.filter(change => {
- const modifiedRange = change.modifiedEndLineNumber === 0
- ? new Range(modifiedDocument.lineAt(change.modifiedStartLineNumber - 1).range.end, modifiedDocument.lineAt(change.modifiedStartLineNumber).range.start)
- : new Range(modifiedDocument.lineAt(change.modifiedStartLineNumber - 1).range.start, modifiedDocument.lineAt(change.modifiedEndLineNumber - 1).range.end);
-
+ const modifiedRange = getModifiedRange(modifiedDocument, change);
return selections.every(selection => !selection.intersection(modifiedRange));
});
@@ -940,6 +964,29 @@ export class CommandCenter {
opts?: CommitOptions
): Promise {
const config = workspace.getConfiguration('git');
+ const promptToSaveFilesBeforeCommit = config.get('promptToSaveFilesBeforeCommit') === true;
+
+ if (promptToSaveFilesBeforeCommit) {
+ const unsavedTextDocuments = workspace.textDocuments
+ .filter(d => !d.isUntitled && d.isDirty && isDescendant(repository.root, d.uri.fsPath));
+
+ if (unsavedTextDocuments.length > 0) {
+ const message = unsavedTextDocuments.length === 1
+ ? localize('unsaved files single', "The following file is unsaved: {0}.\n\nWould you like to save it before comitting?", path.basename(unsavedTextDocuments[0].uri.fsPath))
+ : localize('unsaved files', "There are {0} unsaved files.\n\nWould you like to save them before comitting?", unsavedTextDocuments.length);
+ const saveAndCommit = localize('save and commit', "Save All & Commit");
+ const commit = localize('commit', "Commit Anyway");
+ const pick = await window.showWarningMessage(message, { modal: true }, saveAndCommit, commit);
+
+ if (pick === saveAndCommit) {
+ await Promise.all(unsavedTextDocuments.map(d => d.save()));
+ await repository.status();
+ } else if (pick !== commit) {
+ return false; // do not commit on cancel
+ }
+ }
+ }
+
const enableSmartCommit = config.get('enableSmartCommit') === true;
const enableCommitSigning = config.get('enableCommitSigning') === true;
const noStagedChanges = repository.indexGroup.resourceStates.length === 0;
@@ -963,6 +1010,8 @@ export class CommandCenter {
if (!opts) {
opts = { all: noStagedChanges };
+ } else if (!opts.all && noStagedChanges) {
+ opts = { ...opts, all: true };
}
// enable signing of commits if configurated
@@ -996,8 +1045,14 @@ export class CommandCenter {
return message;
}
+ let value: string | undefined = undefined;
+
+ if (opts && opts.amend && repository.HEAD && repository.HEAD.commit) {
+ value = (await repository.getCommit(repository.HEAD.commit)).message;
+ }
+
return await window.showInputBox({
- value: opts && opts.defaultMsg,
+ value,
placeHolder: localize('commit message', "Commit message"),
prompt: localize('provide commit message', "Please provide a commit message"),
ignoreFocusOut: true
@@ -1041,15 +1096,7 @@ export class CommandCenter {
@command('git.commitStagedAmend', { repository: true })
async commitStagedAmend(repository: Repository): Promise {
- let msg;
- if (repository.HEAD) {
- if (repository.HEAD.commit) {
- let id = repository.HEAD.commit;
- let commit = await repository.getCommit(id);
- msg = commit.message;
- }
- }
- await this.commitWithAnyInput(repository, { all: false, amend: true, defaultMsg: msg });
+ await this.commitWithAnyInput(repository, { all: false, amend: true });
}
@command('git.commitAll', { repository: true })
@@ -1267,25 +1314,26 @@ export class CommandCenter {
return;
}
- const picks = remotes.map(r => ({ label: r.name, description: r.url }));
+ const remotePicks = remotes.map(r => ({ label: r.name, description: r.url }));
const placeHolder = localize('pick remote pull repo', "Pick a remote to pull the branch from");
- const pick = await window.showQuickPick(picks, { placeHolder });
+ const remotePick = await window.showQuickPick(remotePicks, { placeHolder });
- if (!pick) {
+ if (!remotePick) {
return;
}
- const branchName = await window.showInputBox({
- placeHolder: localize('branch name', "Branch name"),
- prompt: localize('provide branch name', "Please provide a branch name"),
- ignoreFocusOut: true
- });
+ const remoteRefs = repository.refs;
+ const remoteRefsFiltered = remoteRefs.filter(r => (r.remote === remotePick.label));
+ const branchPicks = remoteRefsFiltered.map(r => ({ label: r.name })) as { label: string; description: string }[];
+ const branchPick = await window.showQuickPick(branchPicks, { placeHolder });
- if (!branchName) {
+ if (!branchPick) {
return;
}
- repository.pull(false, pick.label, branchName);
+ const remoteCharCnt = remotePick.label.length;
+
+ repository.pull(false, remotePick.label, branchPick.label.slice(remoteCharCnt + 1));
}
@command('git.pull', { repository: true })
@@ -1321,7 +1369,27 @@ export class CommandCenter {
return;
}
- await repository.push();
+ if (!repository.HEAD || !repository.HEAD.name) {
+ window.showWarningMessage(localize('nobranch', "Please check out a branch to push to a remote."));
+ return;
+ }
+
+ try {
+ await repository.push();
+ } catch (err) {
+ if (err.gitErrorCode !== GitErrorCodes.NoUpstreamBranch) {
+ throw err;
+ }
+
+ const branchName = repository.HEAD.name;
+ const message = localize('confirm publish branch', "The branch '{0}' has no upstream branch. Would you like to publish this branch?", branchName);
+ const yes = localize('ok', "OK");
+ const pick = await window.showWarningMessage(message, { modal: true }, yes);
+
+ if (pick === yes) {
+ await this.publish(repository);
+ }
+ }
}
@command('git.pushWithTags', { repository: true })
@@ -1377,7 +1445,7 @@ export class CommandCenter {
if (shouldPrompt) {
const message = localize('sync is unpredictable', "This action will push and pull commits to and from '{0}'.", HEAD.upstream);
const yes = localize('ok', "OK");
- const neverAgain = localize('never again', "OK, Never Show Again");
+ const neverAgain = localize('never again', "OK, Don't Show Again");
const pick = await window.showWarningMessage(message, { modal: true }, yes, neverAgain);
if (pick === neverAgain) {
@@ -1465,7 +1533,10 @@ export class CommandCenter {
}
private async _stash(repository: Repository, includeUntracked = false): Promise {
- if (repository.workingTreeGroup.resourceStates.length === 0) {
+ const noUnstagedChanges = repository.workingTreeGroup.resourceStates.length === 0;
+ const noStagedChanges = repository.indexGroup.resourceStates.length === 0;
+
+ if (noUnstagedChanges && noStagedChanges) {
window.showInformationMessage(localize('no changes stash', "There are no changes to stash."));
return;
}
@@ -1641,13 +1712,18 @@ export class CommandCenter {
const isSingleResource = arg instanceof Uri;
const groups = resources.reduce((result, resource) => {
- const repository = this.model.getRepository(resource);
+ let repository = this.model.getRepository(resource);
if (!repository) {
console.warn('Could not find git repository for ', resource);
return result;
}
+ // Could it be a submodule?
+ if (resource.fsPath === repository.root) {
+ repository = this.model.getRepositoryForSubmodule(resource) || repository;
+ }
+
const tuple = result.filter(p => p.repository === repository)[0];
if (tuple) {
diff --git a/extensions/git/src/contentProvider.ts b/extensions/git/src/contentProvider.ts
index d2219bf02e..e75e5418ef 100644
--- a/extensions/git/src/contentProvider.ts
+++ b/extensions/git/src/contentProvider.ts
@@ -52,7 +52,7 @@ export class GitContentProvider {
return;
}
- this._onDidChange.fire(toGitUri(uri, '', true));
+ this._onDidChange.fire(toGitUri(uri, '', { replaceFileExtension: true }));
}
@debounce(1100)
@@ -83,6 +83,18 @@ export class GitContentProvider {
}
async provideTextDocumentContent(uri: Uri): Promise {
+ let { path, ref, submoduleOf } = fromGitUri(uri);
+
+ if (submoduleOf) {
+ const repository = this.model.getRepository(submoduleOf);
+
+ if (!repository) {
+ return '';
+ }
+
+ return await repository.diff(path, { cached: ref === 'index' });
+ }
+
const repository = this.model.getRepository(uri);
if (!repository) {
@@ -95,8 +107,6 @@ export class GitContentProvider {
this.cache[cacheKey] = cacheValue;
- let { path, ref } = fromGitUri(uri);
-
if (ref === '~') {
const fileUri = Uri.file(path);
const uriString = fileUri.toString();
diff --git a/extensions/git/src/decorationProvider.ts b/extensions/git/src/decorationProvider.ts
index bdd5b81e27..32ef1521c6 100644
--- a/extensions/git/src/decorationProvider.ts
+++ b/extensions/git/src/decorationProvider.ts
@@ -6,35 +6,48 @@
'use strict';
import { window, workspace, Uri, Disposable, Event, EventEmitter, DecorationData, DecorationProvider, ThemeColor } from 'vscode';
+import * as path from 'path';
import { Repository, GitResourceGroup, Status } from './repository';
import { Model } from './model';
import { debounce } from './decorators';
-import { filterEvent } from './util';
+import { filterEvent, dispose, anyEvent, fireEvent } from './util';
+import { GitErrorCodes } from './git';
+
+type Callback = { resolve: (status: boolean) => void, reject: (err: any) => void };
class GitIgnoreDecorationProvider implements DecorationProvider {
- private readonly _onDidChangeDecorations = new EventEmitter();
- readonly onDidChangeDecorations: Event = this._onDidChangeDecorations.event;
-
- private checkIgnoreQueue = new Map void, reject: (err: any) => void }>();
+ readonly onDidChangeDecorations: Event;
+ private queue = new Map; }>();
private disposables: Disposable[] = [];
- constructor(private repository: Repository) {
- this.disposables.push(
- window.registerDecorationProvider(this),
- filterEvent(workspace.onDidSaveTextDocument, e => e.fileName.endsWith('.gitignore'))(_ => this._onDidChangeDecorations.fire())
- //todo@joh -> events when the ignore status actually changes, not only when the file changes
- );
- }
+ constructor(private model: Model) {
+ //todo@joh -> events when the ignore status actually changes, not only when the file changes
+ this.onDidChangeDecorations = fireEvent(anyEvent(
+ filterEvent(workspace.onDidSaveTextDocument, e => e.fileName.endsWith('.gitignore')),
+ model.onDidOpenRepository,
+ model.onDidCloseRepository
+ ));
- dispose(): void {
- this.disposables.forEach(d => d.dispose());
- this.checkIgnoreQueue.clear();
+ this.disposables.push(window.registerDecorationProvider(this));
}
provideDecoration(uri: Uri): Promise {
+ const repository = this.model.getRepository(uri);
+
+ if (!repository) {
+ return Promise.resolve(undefined);
+ }
+
+ let queueItem = this.queue.get(repository.root);
+
+ if (!queueItem) {
+ queueItem = { repository, queue: new Map() };
+ this.queue.set(repository.root, queueItem);
+ }
+
return new Promise((resolve, reject) => {
- this.checkIgnoreQueue.set(uri.fsPath, { resolve, reject });
+ queueItem!.queue.set(uri.fsPath, { resolve, reject });
this.checkIgnoreSoon();
}).then(ignored => {
if (ignored) {
@@ -48,23 +61,42 @@ class GitIgnoreDecorationProvider implements DecorationProvider {
@debounce(500)
private checkIgnoreSoon(): void {
- const queue = new Map(this.checkIgnoreQueue.entries());
- this.checkIgnoreQueue.clear();
- this.repository.checkIgnore([...queue.keys()]).then(ignoreSet => {
- for (const [key, value] of queue.entries()) {
- value.resolve(ignoreSet.has(key));
- }
- }, err => {
- console.error(err);
- for (const [, value] of queue.entries()) {
- value.reject(err);
- }
- });
+ const queue = new Map(this.queue.entries());
+ this.queue.clear();
+
+ for (const [, item] of queue) {
+ const paths = [...item.queue.keys()];
+
+ item.repository.checkIgnore(paths).then(ignoreSet => {
+ for (const [key, value] of item.queue.entries()) {
+ value.resolve(ignoreSet.has(key));
+ }
+ }, err => {
+ if (err.gitErrorCode !== GitErrorCodes.IsInSubmodule) {
+ console.error(err);
+ }
+
+ for (const [, value] of item.queue.entries()) {
+ value.reject(err);
+ }
+ });
+ }
+ }
+
+ dispose(): void {
+ this.disposables.forEach(d => d.dispose());
+ this.queue.clear();
}
}
class GitDecorationProvider implements DecorationProvider {
+ private static SubmoduleDecorationData: DecorationData = {
+ title: 'Submodule',
+ abbreviation: 'S',
+ color: new ThemeColor('gitDecoration.submoduleResourceForeground')
+ };
+
private readonly _onDidChangeDecorations = new EventEmitter();
readonly onDidChangeDecorations: Event = this._onDidChangeDecorations.event;
@@ -80,6 +112,8 @@ class GitDecorationProvider implements DecorationProvider {
private onDidRunGitStatus(): void {
let newDecorations = new Map();
+
+ this.collectSubmoduleDecorationData(newDecorations);
this.collectDecorationData(this.repository.indexGroup, newDecorations);
this.collectDecorationData(this.repository.workingTreeGroup, newDecorations);
this.collectDecorationData(this.repository.mergeGroup, newDecorations);
@@ -101,6 +135,12 @@ class GitDecorationProvider implements DecorationProvider {
});
}
+ private collectSubmoduleDecorationData(bucket: Map): void {
+ for (const submodule of this.repository.submodules) {
+ bucket.set(Uri.file(path.join(this.repository.root, submodule.path)).toString(), GitDecorationProvider.SubmoduleDecorationData);
+ }
+ }
+
provideDecoration(uri: Uri): DecorationData | undefined {
return this.decorations.get(uri.toString());
}
@@ -113,17 +153,21 @@ class GitDecorationProvider implements DecorationProvider {
export class GitDecorations {
- private configListener: Disposable;
- private modelListener: Disposable[] = [];
+ private disposables: Disposable[] = [];
+ private modelDisposables: Disposable[] = [];
private providers = new Map();
constructor(private model: Model) {
- this.configListener = workspace.onDidChangeConfiguration(e => e.affectsConfiguration('git.decorations.enabled') && this.update());
+ this.disposables.push(new GitIgnoreDecorationProvider(model));
+
+ const onEnablementChange = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git.decorations.enabled'));
+ onEnablementChange(this.update, this, this.disposables);
this.update();
}
private update(): void {
const enabled = workspace.getConfiguration('git').get('decorations.enabled');
+
if (enabled) {
this.enable();
} else {
@@ -132,26 +176,25 @@ export class GitDecorations {
}
private enable(): void {
- this.modelListener = [];
- this.model.onDidOpenRepository(this.onDidOpenRepository, this, this.modelListener);
- this.model.onDidCloseRepository(this.onDidCloseRepository, this, this.modelListener);
+ this.model.onDidOpenRepository(this.onDidOpenRepository, this, this.modelDisposables);
+ this.model.onDidCloseRepository(this.onDidCloseRepository, this, this.modelDisposables);
this.model.repositories.forEach(this.onDidOpenRepository, this);
}
private disable(): void {
- this.modelListener.forEach(d => d.dispose());
+ this.modelDisposables = dispose(this.modelDisposables);
this.providers.forEach(value => value.dispose());
this.providers.clear();
}
private onDidOpenRepository(repository: Repository): void {
const provider = new GitDecorationProvider(repository);
- const ignoreProvider = new GitIgnoreDecorationProvider(repository);
- this.providers.set(repository, Disposable.from(provider, ignoreProvider));
+ this.providers.set(repository, provider);
}
private onDidCloseRepository(repository: Repository): void {
const provider = this.providers.get(repository);
+
if (provider) {
provider.dispose();
this.providers.delete(repository);
@@ -159,9 +202,7 @@ export class GitDecorations {
}
dispose(): void {
- this.configListener.dispose();
- this.modelListener.forEach(d => d.dispose());
- this.providers.forEach(value => value.dispose);
- this.providers.clear();
+ this.disable();
+ this.disposables = dispose(this.disposables);
}
}
diff --git a/extensions/git/src/decorators.ts b/extensions/git/src/decorators.ts
index c646c6731b..27fa414295 100644
--- a/extensions/git/src/decorators.ts
+++ b/extensions/git/src/decorators.ts
@@ -78,7 +78,7 @@ function _throttle(fn: Function, key: string): Function {
export const throttle = decorate(_throttle);
-function _sequentialize(fn: Function, key: string): Function {
+function _sequentialize(fn: Function, key: string): Function {
const currentKey = `__$sequence$${key}`;
return function (this: any, ...args: any[]) {
diff --git a/extensions/git/src/git.ts b/extensions/git/src/git.ts
index 4ec4e93469..4fac914dec 100644
--- a/extensions/git/src/git.ts
+++ b/extensions/git/src/git.ts
@@ -16,7 +16,7 @@ import * as filetype from 'file-type';
import { assign, uniqBy, groupBy, denodeify, IDisposable, toDisposable, dispose, mkdirp, readBytes, detectUnicodeEncoding, Encoding, onceEvent } from './util';
import { CancellationToken } from 'vscode';
-const readfile = denodeify(fs.readFile);
+const readfile = denodeify(fs.readFile);
export interface IGit {
path: string;
@@ -267,6 +267,7 @@ export class GitError {
this.message = data.error.message;
} else {
this.error = void 0;
+ this.message = '';
}
this.message = this.message || data.message || 'Git error';
@@ -325,7 +326,9 @@ export const GitErrorCodes = {
BranchAlreadyExists: 'BranchAlreadyExists',
NoLocalChanges: 'NoLocalChanges',
NoStashFound: 'NoStashFound',
- LocalChangesOverwritten: 'LocalChangesOverwritten'
+ LocalChangesOverwritten: 'LocalChangesOverwritten',
+ NoUpstreamBranch: 'NoUpstreamBranch',
+ IsInSubmodule: 'IsInSubmodule'
};
function getGitErrorCode(stderr: string): string | undefined {
@@ -359,7 +362,6 @@ function getGitErrorCode(stderr: string): string | undefined {
export class Git {
private gitPath: string;
- private version: string;
private env: any;
private _onOutput = new EventEmitter();
@@ -367,7 +369,6 @@ export class Git {
constructor(options: IGitOptions) {
this.gitPath = options.gitPath;
- this.version = options.version;
this.env = options.env || {};
}
@@ -460,7 +461,7 @@ export class Git {
});
if (options.log !== false) {
- this.log(`git ${args.join(' ')}\n`);
+ this.log(`> git ${args.join(' ')}\n`);
}
return cp.spawn(this.gitPath, args, options);
@@ -542,6 +543,72 @@ export class GitStatusParser {
}
}
+export interface Submodule {
+ name: string;
+ path: string;
+ url: string;
+}
+
+export function parseGitmodules(raw: string): Submodule[] {
+ const regex = /\r?\n/g;
+ let position = 0;
+ let match: RegExpExecArray | null = null;
+
+ const result: Submodule[] = [];
+ let submodule: Partial = {};
+
+ function parseLine(line: string): void {
+ const sectionMatch = /^\s*\[submodule "([^"]+)"\]\s*$/.exec(line);
+
+ if (sectionMatch) {
+ if (submodule.name && submodule.path && submodule.url) {
+ result.push(submodule as Submodule);
+ }
+
+ const name = sectionMatch[1];
+
+ if (name) {
+ submodule = { name };
+ return;
+ }
+ }
+
+ if (!submodule) {
+ return;
+ }
+
+ const propertyMatch = /^\s*(\w+) = (.*)$/.exec(line);
+
+ if (!propertyMatch) {
+ return;
+ }
+
+ const [, key, value] = propertyMatch;
+
+ switch (key) {
+ case 'path': submodule.path = value; break;
+ case 'url': submodule.url = value; break;
+ }
+ }
+
+ while (match = regex.exec(raw)) {
+ parseLine(raw.substring(position, match.index));
+ position = match.index + match[0].length;
+ }
+
+ parseLine(raw.substring(position));
+
+ if (submodule.name && submodule.path && submodule.url) {
+ result.push(submodule as Submodule);
+ }
+
+ return result;
+}
+
+export interface DiffOptions {
+ cached?: boolean;
+}
+
export class Repository {
constructor(
@@ -611,7 +678,7 @@ export class Repository {
return stdout;
}
- async lstree(treeish: string, path: string): Promise<{ mode: number, object: string, size: number }> {
+ async lstree(treeish: string, path: string): Promise<{ mode: string, object: string, size: number }> {
if (!treeish) { // index
const { stdout } = await this.run(['ls-files', '--stage', '--', path]);
@@ -625,7 +692,7 @@ export class Repository {
const catFile = await this.run(['cat-file', '-s', object]);
const size = parseInt(catFile.stdout);
- return { mode: parseInt(mode), object, size };
+ return { mode, object, size };
}
const { stdout } = await this.run(['ls-tree', '-l', treeish, '--', path]);
@@ -637,7 +704,7 @@ export class Repository {
}
const [, mode, , object, size] = match;
- return { mode: parseInt(mode), object, size: parseInt(size) };
+ return { mode, object, size: parseInt(size) };
}
async detectObjectType(object: string): Promise<{ mimetype: string, encoding?: string }> {
@@ -680,6 +747,19 @@ export class Repository {
}
}
+ async diff(path: string, options: DiffOptions = {}): Promise {
+ const args = ['diff'];
+
+ if (options.cached) {
+ args.push('--cached');
+ }
+
+ args.push('--', path);
+
+ const result = await this.run(args);
+ return result.stdout;
+ }
+
async add(paths: string[]): Promise {
const args = ['add', '-A', '--'];
@@ -706,7 +786,16 @@ export class Repository {
});
}
- await this.run(['update-index', '--cacheinfo', '100644', hash, path]);
+ let mode: string;
+
+ try {
+ const details = await this.lstree('HEAD', path);
+ mode = details.mode;
+ } catch (err) {
+ mode = '100644';
+ }
+
+ await this.run(['update-index', '--cacheinfo', mode, hash, path]);
}
async checkout(treeish: string, paths: string[]): Promise {
@@ -953,6 +1042,8 @@ export class Repository {
err.gitErrorCode = GitErrorCodes.PushRejected;
} else if (/Could not read from remote repository/.test(err.stderr || '')) {
err.gitErrorCode = GitErrorCodes.RemoteConnectionError;
+ } else if (/^fatal: The current branch .* has no upstream branch/.test(err.stderr || '')) {
+ err.gitErrorCode = GitErrorCodes.NoUpstreamBranch;
}
throw err;
@@ -1067,7 +1158,7 @@ export class Repository {
}
async getRefs(): Promise
[ {
- const result = await this.run(['for-each-ref', '--format', '%(refname) %(objectname)']);
+ const result = await this.run(['for-each-ref', '--format', '%(refname) %(objectname)', '--sort', '-committerdate']);
const fn = (line: string): Ref | null => {
let match: RegExpExecArray | null;
@@ -1186,4 +1277,24 @@ export class Repository {
return { hash: match[1], message: match[2] };
}
+
+ async updateSubmodules(paths: string[]): Promise {
+ const args = ['submodule', 'update', '--', ...paths];
+ await this.run(args);
+ }
+
+ async getSubmodules(): Promise {
+ const gitmodulesPath = path.join(this.root, '.gitmodules');
+
+ try {
+ const gitmodulesRaw = await readfile(gitmodulesPath, 'utf8');
+ return parseGitmodules(gitmodulesRaw);
+ } catch (err) {
+ if (/ENOENT/.test(err.message)) {
+ return [];
+ }
+
+ throw err;
+ }
+ }
}
diff --git a/extensions/git/src/main.ts b/extensions/git/src/main.ts
index 0e90397114..94ca406da7 100644
--- a/extensions/git/src/main.ts
+++ b/extensions/git/src/main.ts
@@ -6,7 +6,7 @@
'use strict';
import * as nls from 'vscode-nls';
-const localize = nls.config(process.env.VSCODE_NLS_CONFIG)();
+const localize = nls.loadMessageBundle();
import { ExtensionContext, workspace, window, Disposable, commands, Uri, OutputChannel } from 'vscode';
import { findGit, Git, IGit } from './git';
import { Model } from './model';
@@ -14,21 +14,19 @@ import { CommandCenter } from './commands';
import { GitContentProvider } from './contentProvider';
import { GitDecorations } from './decorationProvider';
import { Askpass } from './askpass';
-import { toDisposable } from './util';
+import { toDisposable, filterEvent, eventToPromise } from './util';
import TelemetryReporter from 'vscode-extension-telemetry';
import { API, createApi } from './api';
-async function init(context: ExtensionContext, outputChannel: OutputChannel, disposables: Disposable[]): Promise {
- const { name, version, aiKey } = require(context.asAbsolutePath('./package.json')) as { name: string, version: string, aiKey: string };
- const telemetryReporter: TelemetryReporter = new TelemetryReporter(name, version, aiKey);
- disposables.push(telemetryReporter);
+let telemetryReporter: TelemetryReporter;
+async function init(context: ExtensionContext, outputChannel: OutputChannel, disposables: Disposable[]): Promise {
const pathHint = workspace.getConfiguration('git').get('path');
const info = await findGit(pathHint, path => outputChannel.appendLine(localize('looking', "Looking for git in: {0}", path)));
const askpass = new Askpass();
const env = await askpass.getEnv();
const git = new Git({ gitPath: info.path, version: info.version, env });
- const model = new Model(git, context.globalState);
+ const model = new Model(git, context.globalState, outputChannel);
disposables.push(model);
const onRepository = () => commands.executeCommand('setContext', 'gitOpenRepositoryCount', `${model.repositories.length}`);
@@ -38,7 +36,15 @@ async function init(context: ExtensionContext, outputChannel: OutputChannel, dis
outputChannel.appendLine(localize('using git', "Using git {0} from {1}", info.version, info.path));
- const onOutput = (str: string) => outputChannel.append(str);
+ const onOutput = (str: string) => {
+ const lines = str.split(/\r?\n/mg);
+
+ while (/^\s*$/.test(lines[lines.length - 1])) {
+ lines.pop();
+ }
+
+ outputChannel.appendLine(lines.join('\n'));
+ };
git.onOutput.addListener('log', onOutput);
disposables.push(toDisposable(() => git.onOutput.removeListener('log', onOutput)));
@@ -77,7 +83,7 @@ async function _activate(context: ExtensionContext, disposables: Disposable[]):
outputChannel.show();
const download = localize('downloadgit', "Download Git");
- const neverShowAgain = localize('neverShowAgain', "Don't show again");
+ const neverShowAgain = localize('neverShowAgain', "Don't Show Again");
const choice = await window.showWarningMessage(
localize('notfound', "Git not found. Install it or configure it using the 'git.path' setting."),
download,
@@ -93,11 +99,30 @@ async function _activate(context: ExtensionContext, disposables: Disposable[]):
}
export function activate(context: ExtensionContext): API {
+ const config = workspace.getConfiguration('git', null);
+ const enabled = config.get('enabled');
+
const disposables: Disposable[] = [];
context.subscriptions.push(new Disposable(() => Disposable.from(...disposables).dispose()));
- const activatePromise = _activate(context, disposables);
- const modelPromise = activatePromise.then(model => model || Promise.reject('Git model not found'));
+ const { name, version, aiKey } = require(context.asAbsolutePath('./package.json')) as { name: string, version: string, aiKey: string };
+ telemetryReporter = new TelemetryReporter(name, version, aiKey);
+
+ let activatePromise: Promise;
+
+ if (enabled) {
+ activatePromise = _activate(context, disposables);
+ } else {
+ const onConfigChange = filterEvent(workspace.onDidChangeConfiguration, e => e.affectsConfiguration('git'));
+ const onEnabled = filterEvent(onConfigChange, () => workspace.getConfiguration('git', null).get('enabled') === true);
+
+ activatePromise = eventToPromise(onEnabled)
+ .then(() => _activate(context, disposables));
+ }
+
+ const modelPromise = activatePromise
+ .then(model => model || Promise.reject('Git model not found'));
+
activatePromise.catch(err => console.error(err));
return createApi(modelPromise);
@@ -123,7 +148,7 @@ async function checkGitVersion(info: IGit): Promise {
}
const update = localize('updateGit', "Update Git");
- const neverShowAgain = localize('neverShowAgain', "Don't show again");
+ const neverShowAgain = localize('neverShowAgain', "Don't Show Again");
const choice = await window.showWarningMessage(
localize('git20', "You seem to have git {0} installed. Code works best with git >= 2", info.version),
@@ -139,3 +164,7 @@ async function checkGitVersion(info: IGit): Promise {
// {{SQL CARBON EDIT}}
*/
}
+
+export function deactivate(): Promise {
+ return telemetryReporter ? telemetryReporter.dispose() : Promise.resolve(null);
+}
diff --git a/extensions/git/src/model.ts b/extensions/git/src/model.ts
index 48924f0573..6958f46d00 100644
--- a/extensions/git/src/model.ts
+++ b/extensions/git/src/model.ts
@@ -5,10 +5,10 @@
'use strict';
-import { workspace, WorkspaceFoldersChangeEvent, Uri, window, Event, EventEmitter, QuickPickItem, Disposable, SourceControl, SourceControlResourceGroup, TextEditor, Memento, ConfigurationChangeEvent } from 'vscode';
+import { workspace, WorkspaceFoldersChangeEvent, Uri, window, Event, EventEmitter, QuickPickItem, Disposable, SourceControl, SourceControlResourceGroup, TextEditor, Memento, OutputChannel } from 'vscode';
import { Repository, RepositoryState } from './repository';
import { memoize, sequentialize, debounce } from './decorators';
-import { dispose, anyEvent, filterEvent, IDisposable, isDescendant } from './util';
+import { dispose, anyEvent, filterEvent, isDescendant, firstIndex } from './util';
import { Git, GitErrorCodes } from './git';
import * as path from 'path';
import * as fs from 'fs';
@@ -28,7 +28,7 @@ class RepositoryPick implements QuickPickItem {
.join(' ');
}
- constructor(public readonly repository: Repository) { }
+ constructor(public readonly repository: Repository, public readonly index: number) { }
}
export interface ModelChangeEvent {
@@ -66,7 +66,7 @@ export class Model {
private disposables: Disposable[] = [];
- constructor(private git: Git, private globalState: Memento) {
+ constructor(private git: Git, private globalState: Memento, private outputChannel: OutputChannel) {
workspace.onDidChangeWorkspaceFolders(this.onDidChangeWorkspaceFolders, this, this.disposables);
this.onDidChangeWorkspaceFolders({ added: workspace.workspaceFolders || [], removed: [] });
@@ -93,17 +93,25 @@ export class Model {
private async scanWorkspaceFolders(): Promise {
for (const folder of workspace.workspaceFolders || []) {
const root = folder.uri.fsPath;
- const children = await new Promise((c, e) => fs.readdir(root, (err, r) => err ? e(err) : c(r)));
- children
- .filter(child => child !== '.git')
- .forEach(child => this.tryOpenRepository(path.join(root, child)));
+ try {
+ const children = await new Promise((c, e) => fs.readdir(root, (err, r) => err ? e(err) : c(r)));
+
+ children
+ .filter(child => child !== '.git')
+ .forEach(child => this.tryOpenRepository(path.join(root, child)));
+ } catch (err) {
+ // noop
+ }
}
}
private onPossibleGitRepositoryChange(uri: Uri): void {
- const possibleGitRepositoryPath = uri.fsPath.replace(/\.git.*$/, '');
- this.possibleGitRepositoryPaths.add(possibleGitRepositoryPath);
+ this.eventuallyScanPossibleGitRepository(uri.fsPath.replace(/\.git.*$/, ''));
+ }
+
+ private eventuallyScanPossibleGitRepository(path: string) {
+ this.possibleGitRepositoryPaths.add(path);
this.eventuallyScanPossibleGitRepositories();
}
@@ -150,6 +158,13 @@ export class Model {
}
private onDidChangeVisibleTextEditors(editors: TextEditor[]): void {
+ const config = workspace.getConfiguration('git');
+ const enabled = config.get('autoRepositoryDetection') === true;
+
+ if (!enabled) {
+ return;
+ }
+
editors.forEach(editor => {
const uri = editor.document.uri;
@@ -181,11 +196,13 @@ export class Model {
}
try {
- const repositoryRoot = await this.git.getRepositoryRoot(path);
+ const rawRoot = await this.git.getRepositoryRoot(path);
// This can happen whenever `path` has the wrong case sensitivity in
// case insensitive file systems
// https://github.com/Microsoft/vscode/issues/33498
+ const repositoryRoot = Uri.file(rawRoot).fsPath;
+
if (this.getRepository(repositoryRoot)) {
return;
}
@@ -203,15 +220,31 @@ export class Model {
}
private open(repository: Repository): void {
+ this.outputChannel.appendLine(`Open repository: ${repository.root}`);
+
const onDidDisappearRepository = filterEvent(repository.onDidChangeState, state => state === RepositoryState.Disposed);
const disappearListener = onDidDisappearRepository(() => dispose());
const changeListener = repository.onDidChangeRepository(uri => this._onDidChangeRepository.fire({ repository, uri }));
const originalResourceChangeListener = repository.onDidChangeOriginalResource(uri => this._onDidChangeOriginalResource.fire({ repository, uri }));
+ const checkForSubmodules = () => {
+ if (repository.submodules.length > 10) {
+ window.showWarningMessage(localize('too many submodules', "The '{0}' repository has {1} submodules which won't be opened automatically. You can still open each one individually by opening a file within.", path.basename(repository.root), repository.submodules.length));
+ statusListener.dispose();
+ return;
+ }
+
+ this.scanSubmodules(repository);
+ };
+
+ const statusListener = repository.onDidRunGitStatus(checkForSubmodules);
+ checkForSubmodules();
+
const dispose = () => {
disappearListener.dispose();
changeListener.dispose();
originalResourceChangeListener.dispose();
+ statusListener.dispose();
repository.dispose();
this.openRepositories = this.openRepositories.filter(e => e !== openRepository);
@@ -223,6 +256,20 @@ export class Model {
this._onDidOpenRepository.fire(repository);
}
+ private scanSubmodules(repository: Repository): void {
+ const shouldScanSubmodules = workspace
+ .getConfiguration('git', Uri.file(repository.root))
+ .get('detectSubmodules') === true;
+
+ if (!shouldScanSubmodules) {
+ return;
+ }
+
+ repository.submodules
+ .map(r => path.join(repository.root, r.path))
+ .forEach(p => this.eventuallyScanPossibleGitRepository(p));
+ }
+
close(repository: Repository): void {
const openRepository = this.getOpenRepository(repository);
@@ -230,6 +277,7 @@ export class Model {
return;
}
+ this.outputChannel.appendLine(`Close repository: ${repository.root}`);
openRepository.dispose();
}
@@ -238,7 +286,16 @@ export class Model {
throw new Error(localize('no repositories', "There are no available repositories"));
}
- const picks = this.openRepositories.map(e => new RepositoryPick(e.repository));
+ const picks = this.openRepositories.map((e, index) => new RepositoryPick(e.repository, index));
+ const active = window.activeTextEditor;
+ const repository = active && this.getRepository(active.document.fileName);
+ const index = firstIndex(picks, pick => pick.repository === repository);
+
+ // Move repository pick containing the active text editor to appear first
+ if (index > -1) {
+ picks.unshift(...picks.splice(index, 1));
+ }
+
const placeHolder = localize('pick repo', "Choose a repository");
const pick = await window.showQuickPick(picks, { placeHolder });
@@ -281,12 +338,21 @@ export class Model {
resourcePath = hint.fsPath;
}
- for (const liveRepository of this.openRepositories) {
- const relativePath = path.relative(liveRepository.repository.root, resourcePath);
-
- if (isDescendant(liveRepository.repository.root, resourcePath)) {
- return liveRepository;
+ outer:
+ for (const liveRepository of this.openRepositories.sort((a, b) => b.repository.root.length - a.repository.root.length)) {
+ if (!isDescendant(liveRepository.repository.root, resourcePath)) {
+ continue;
}
+
+ for (const submodule of liveRepository.repository.submodules) {
+ const submoduleRoot = path.join(liveRepository.repository.root, submodule.path);
+
+ if (isDescendant(submoduleRoot, resourcePath)) {
+ continue outer;
+ }
+ }
+
+ return liveRepository;
}
return undefined;
@@ -307,6 +373,20 @@ export class Model {
return undefined;
}
+ getRepositoryForSubmodule(submoduleUri: Uri): Repository | undefined {
+ for (const repository of this.repositories) {
+ for (const submodule of repository.submodules) {
+ const submodulePath = path.join(repository.root, submodule.path);
+
+ if (submodulePath === submoduleUri.fsPath) {
+ return repository;
+ }
+ }
+ }
+
+ return undefined;
+ }
+
dispose(): void {
const openRepositories = [...this.openRepositories];
openRepositories.forEach(r => r.dispose());
diff --git a/extensions/git/src/repository.ts b/extensions/git/src/repository.ts
index 0248bb96f6..8d8ff647a8 100644
--- a/extensions/git/src/repository.ts
+++ b/extensions/git/src/repository.ts
@@ -5,9 +5,9 @@
'use strict';
-import { Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor, DecorationData, Memento } from 'vscode';
-import { Repository as BaseRepository, Ref, Branch, Remote, Commit, GitErrorCodes, Stash, RefType, GitError } from './git';
-import { anyEvent, filterEvent, eventToPromise, dispose, find, isDescendant } from './util';
+import { commands, Uri, Command, EventEmitter, Event, scm, SourceControl, SourceControlInputBox, SourceControlResourceGroup, SourceControlResourceState, SourceControlResourceDecorations, SourceControlInputBoxValidation, Disposable, ProgressLocation, window, workspace, WorkspaceEdit, ThemeColor, DecorationData, Memento, SourceControlInputBoxValidationType } from 'vscode';
+import { Repository as BaseRepository, Ref, Branch, Remote, Commit, GitErrorCodes, Stash, RefType, GitError, Submodule, DiffOptions } from './git';
+import { anyEvent, filterEvent, eventToPromise, dispose, find, isDescendant, IDisposable, onceEvent, EmptyDisposable, debounceEvent } from './util';
import { memoize, throttle, debounce } from './decorators';
import { toGitUri } from './uri';
import { AutoFetcher } from './autofetch';
@@ -105,7 +105,7 @@ export class Resource implements SourceControlResourceState {
}
};
- private getIconPath(theme: string): Uri | undefined {
+ private getIconPath(theme: string): Uri {
switch (this.type) {
case Status.INDEX_MODIFIED: return Resource.Icons[theme].Modified;
case Status.MODIFIED: return Resource.Icons[theme].Modified;
@@ -123,7 +123,6 @@ export class Resource implements SourceControlResourceState {
case Status.DELETED_BY_US: return Resource.Icons[theme].Conflict;
case Status.BOTH_ADDED: return Resource.Icons[theme].Conflict;
case Status.BOTH_MODIFIED: return Resource.Icons[theme].Conflict;
- default: return void 0;
}
}
@@ -182,7 +181,7 @@ export class Resource implements SourceControlResourceState {
return { strikeThrough, faded, tooltip, light, dark, letter, color, source: 'git.resource' /*todo@joh*/ };
}
- get letter(): string | undefined {
+ get letter(): string {
switch (this.type) {
case Status.INDEX_MODIFIED:
case Status.MODIFIED:
@@ -207,12 +206,10 @@ export class Resource implements SourceControlResourceState {
case Status.BOTH_ADDED:
case Status.BOTH_MODIFIED:
return 'C';
- default:
- return undefined;
}
}
- get color(): ThemeColor | undefined {
+ get color(): ThemeColor {
switch (this.type) {
case Status.INDEX_MODIFIED:
case Status.MODIFIED:
@@ -235,8 +232,6 @@ export class Resource implements SourceControlResourceState {
case Status.BOTH_ADDED:
case Status.BOTH_MODIFIED:
return new ThemeColor('gitDecoration.conflictingResourceForeground');
- default:
- return undefined;
}
}
@@ -261,7 +256,7 @@ export class Resource implements SourceControlResourceState {
}
}
- get resourceDecoration(): DecorationData | undefined {
+ get resourceDecoration(): DecorationData {
const title = this.tooltip;
const abbreviation = this.letter;
const color = this.color;
@@ -280,6 +275,7 @@ export class Resource implements SourceControlResourceState {
export enum Operation {
Status = 'Status',
+ Diff = 'Diff',
Add = 'Add',
RevertFiles = 'RevertFiles',
Commit = 'Commit',
@@ -301,7 +297,8 @@ export enum Operation {
Tag = 'Tag',
Stash = 'Stash',
CheckIgnore = 'CheckIgnore',
- LSTree = 'LSTree'
+ LSTree = 'LSTree',
+ SubmoduleUpdate = 'SubmoduleUpdate'
}
function isReadOnly(operation: Operation): boolean {
@@ -330,6 +327,7 @@ function shouldShowProgress(operation: Operation): boolean {
export interface Operations {
isIdle(): boolean;
+ shouldShowProgress(): boolean;
isRunning(operation: Operation): boolean;
}
@@ -366,6 +364,18 @@ class OperationsImpl implements Operations {
return true;
}
+
+ shouldShowProgress(): boolean {
+ const operations = this.operations.keys();
+
+ for (const operation of operations) {
+ if (shouldShowProgress(operation)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
export interface CommitOptions {
@@ -373,7 +383,6 @@ export interface CommitOptions {
amend?: boolean;
signoff?: boolean;
signCommit?: boolean;
- defaultMsg?: string;
}
export interface GitResourceGroup extends SourceControlResourceGroup {
@@ -385,8 +394,33 @@ export interface OperationResult {
error: any;
}
+class ProgressManager {
+
+ private disposable: IDisposable = EmptyDisposable;
+
+ constructor(repository: Repository) {
+ const start = onceEvent(filterEvent(repository.onDidChangeOperations, () => repository.operations.shouldShowProgress()));
+ const end = onceEvent(filterEvent(debounceEvent(repository.onDidChangeOperations, 300), () => !repository.operations.shouldShowProgress()));
+
+ const setup = () => {
+ this.disposable = start(() => {
+ const promise = eventToPromise(end).then(() => setup());
+ window.withProgress({ location: ProgressLocation.SourceControl }, () => promise);
+ });
+ };
+
+ setup();
+ }
+
+ dispose(): void {
+ this.disposable.dispose();
+ }
+}
+
export class Repository implements Disposable {
+ private static readonly InputValidationLength = 72;
+
private _onDidChangeRepository = new EventEmitter();
readonly onDidChangeRepository: Event = this._onDidChangeRepository.event;
@@ -439,6 +473,11 @@ export class Repository implements Disposable {
return this._remotes;
}
+ private _submodules: Submodule[] = [];
+ get submodules(): Submodule[] {
+ return this._submodules;
+ }
+
private _operations = new OperationsImpl();
get operations(): Operations { return this._operations; }
@@ -474,7 +513,7 @@ export class Repository implements Disposable {
const onWorkspaceChange = anyEvent(fsWatcher.onDidChange, fsWatcher.onDidCreate, fsWatcher.onDidDelete);
const onRepositoryChange = filterEvent(onWorkspaceChange, uri => isDescendant(repository.root, uri.fsPath));
- const onRelevantRepositoryChange = filterEvent(onRepositoryChange, uri => !/\/\.git\/index\.lock$/.test(uri.path));
+ const onRelevantRepositoryChange = filterEvent(onRepositoryChange, uri => !/\/\.git(\/index\.lock)?$/.test(uri.path));
onRelevantRepositoryChange(this.onFSChange, this, this.disposables);
const onRelevantGitChange = filterEvent(onRelevantRepositoryChange, uri => /\/\.git\//.test(uri.path));
@@ -484,6 +523,7 @@ export class Repository implements Disposable {
this._sourceControl.inputBox.placeholder = localize('commitMessage', "Message (press {0} to commit)");
this._sourceControl.acceptInputCommand = { command: 'git.commitWithInput', title: localize('commit', "Commit"), arguments: [this._sourceControl] };
this._sourceControl.quickDiffProvider = this;
+ this._sourceControl.inputBox.validateInput = this.validateInput.bind(this);
this.disposables.push(this._sourceControl);
this._mergeGroup = this._sourceControl.createResourceGroup('merge', localize('merge changes', "Merge Changes"));
@@ -504,16 +544,56 @@ export class Repository implements Disposable {
statusBar.onDidChange(() => this._sourceControl.statusBarCommands = statusBar.commands, null, this.disposables);
this._sourceControl.statusBarCommands = statusBar.commands;
+ const progressManager = new ProgressManager(this);
+ this.disposables.push(progressManager);
+
this.updateCommitTemplate();
this.status();
}
+ validateInput(text: string, position: number): SourceControlInputBoxValidation | undefined {
+ const config = workspace.getConfiguration('git');
+ const setting = config.get<'always' | 'warn' | 'off'>('inputValidation');
+
+ if (setting === 'off') {
+ return;
+ }
+
+ let start = 0, end;
+ let match: RegExpExecArray | null;
+ const regex = /\r?\n/g;
+
+ while ((match = regex.exec(text)) && position > match.index) {
+ start = match.index + match[0].length;
+ }
+
+ end = match ? match.index : text.length;
+
+ const line = text.substring(start, end);
+
+ if (line.length <= Repository.InputValidationLength) {
+ if (setting !== 'always') {
+ return;
+ }
+
+ return {
+ message: localize('commitMessageCountdown', "{0} characters left in current line", Repository.InputValidationLength - line.length),
+ type: SourceControlInputBoxValidationType.Information
+ };
+ } else {
+ return {
+ message: localize('commitMessageWarning', "{0} characters over {1} in current line", line.length - Repository.InputValidationLength, Repository.InputValidationLength),
+ type: SourceControlInputBoxValidationType.Warning
+ };
+ }
+ }
+
provideOriginalResource(uri: Uri): Uri | undefined {
if (uri.scheme !== 'file') {
return;
}
- return toGitUri(uri, '', true);
+ return toGitUri(uri, '', { replaceFileExtension: true });
}
private async updateCommitTemplate(): Promise {
@@ -524,21 +604,15 @@ export class Repository implements Disposable {
}
}
- // @throttle
- // async init(): Promise {
- // if (this.state !== State.NotAGitRepository) {
- // return;
- // }
-
- // await this.git.init(this.workspaceRoot.fsPath);
- // await this.status();
- // }
-
@throttle
async status(): Promise {
await this.run(Operation.Status);
}
+ diff(path: string, options: DiffOptions = {}): Promise {
+ return this.run(Operation.Diff, () => this.repository.diff(path, options));
+ }
+
async add(resources: Uri[]): Promise {
await this.run(Operation.Add, () => this.repository.add(resources.map(r => r.fsPath)));
}
@@ -567,8 +641,18 @@ export class Repository implements Disposable {
await this.run(Operation.Clean, async () => {
const toClean: string[] = [];
const toCheckout: string[] = [];
+ const submodulesToUpdate: string[] = [];
resources.forEach(r => {
+ const fsPath = r.fsPath;
+
+ for (const submodule of this.submodules) {
+ if (path.join(this.root, submodule.path) === fsPath) {
+ submodulesToUpdate.push(fsPath);
+ return;
+ }
+ }
+
const raw = r.toString();
const scmResource = find(this.workingTreeGroup.resourceStates, sr => sr.resourceUri.toString() === raw);
@@ -579,11 +663,11 @@ export class Repository implements Disposable {
switch (scmResource.type) {
case Status.UNTRACKED:
case Status.IGNORED:
- toClean.push(r.fsPath);
+ toClean.push(fsPath);
break;
default:
- toCheckout.push(r.fsPath);
+ toCheckout.push(fsPath);
break;
}
});
@@ -598,6 +682,10 @@ export class Repository implements Disposable {
promises.push(this.repository.checkout('', toCheckout));
}
+ if (submodulesToUpdate.length > 0) {
+ promises.push(this.repository.updateSubmodules(submodulesToUpdate));
+ }
+
await Promise.all(promises);
});
}
@@ -702,15 +790,15 @@ export class Repository implements Disposable {
async buffer(ref: string, filePath: string): Promise {
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 encoding = configFiles.get('encoding');
+ // const configFiles = workspace.getConfiguration('files', Uri.file(filePath));
+ // const encoding = configFiles.get('encoding');
// TODO@joao: REsource config api
return await this.repository.buffer(`${ref}:${relativePath}`);
});
}
- lstree(ref: string, filePath: string): Promise<{ mode: number, object: string, size: number }> {
+ lstree(ref: string, filePath: string): Promise<{ mode: string, object: string, size: number }> {
return this.run(Operation.LSTree, () => this.repository.lstree(ref, filePath));
}
@@ -780,7 +868,11 @@ export class Repository implements Disposable {
// paths are separated by the null-character
resolve(new Set(data.split('\0')));
} else {
- reject(new GitError({ stdout: data, stderr, exitCode }));
+ if (/ is in submodule /.test(stderr)) {
+ reject(new GitError({ stdout: data, stderr, exitCode, gitErrorCode: GitErrorCodes.IsInSubmodule }));
+ } else {
+ reject(new GitError({ stdout: data, stderr, exitCode }));
+ }
}
};
@@ -807,37 +899,31 @@ export class Repository implements Disposable {
throw new Error('Repository not initialized');
}
- const run = async () => {
- let error: any = null;
+ let error: any = null;
- this._operations.start(operation);
- this._onRunOperation.fire(operation);
+ this._operations.start(operation);
+ this._onRunOperation.fire(operation);
- try {
- const result = await this.retryRun(runOperation);
+ try {
+ const result = await this.retryRun(runOperation);
- if (!isReadOnly(operation)) {
- await this.updateModelState();
- }
-
- return result;
- } catch (err) {
- error = err;
-
- if (err.gitErrorCode === GitErrorCodes.NotAGitRepository) {
- this.state = RepositoryState.Disposed;
- }
-
- throw err;
- } finally {
- this._operations.end(operation);
- this._onDidRunOperation.fire({ operation, error });
+ if (!isReadOnly(operation)) {
+ await this.updateModelState();
}
- };
- return shouldShowProgress(operation)
- ? window.withProgress({ location: ProgressLocation.SourceControl }, run)
- : run();
+ return result;
+ } catch (err) {
+ error = err;
+
+ if (err.gitErrorCode === GitErrorCodes.NotAGitRepository) {
+ this.state = RepositoryState.Disposed;
+ }
+
+ throw err;
+ } finally {
+ this._operations.end(operation);
+ this._onDidRunOperation.fire({ operation, error });
+ }
}
private async retryRun(runOperation: () => Promise = () => Promise.resolve(null)): Promise {
@@ -868,10 +954,9 @@ export class Repository implements Disposable {
this.isRepositoryHuge = didHitLimit;
if (didHitLimit && !shouldIgnore && !this.didWarnAboutLimit) {
- const ok = { title: localize('ok', "OK"), isCloseAffordance: true };
- const neverAgain = { title: localize('neveragain', "Never Show Again") };
+ const neverAgain = { title: localize('neveragain', "Don't Show Again") };
- window.showWarningMessage(localize('huge', "The git repository at '{0}' has too many active changes, only a subset of Git features will be enabled.", this.repository.root), ok, neverAgain).then(result => {
+ window.showWarningMessage(localize('huge', "The git repository at '{0}' has too many active changes, only a subset of Git features will be enabled.", this.repository.root), neverAgain).then(result => {
if (result === neverAgain) {
config.update('ignoreLimitWarning', true, false);
}
@@ -896,11 +981,12 @@ export class Repository implements Disposable {
// noop
}
- const [refs, remotes] = await Promise.all([this.repository.getRefs(), this.repository.getRemotes()]);
+ const [refs, remotes, submodules] = await Promise.all([this.repository.getRefs(), this.repository.getRemotes(), this.repository.getSubmodules()]);
this._HEAD = HEAD;
this._refs = refs;
this._remotes = remotes;
+ this._submodules = submodules;
const index: Resource[] = [];
const workingTree: Resource[] = [];
@@ -922,10 +1008,8 @@ export class Repository implements Disposable {
case 'UU': return merge.push(new Resource(ResourceGroupType.Merge, uri, Status.BOTH_MODIFIED, useIcons));
}
- let isModifiedInIndex = false;
-
switch (raw.x) {
- case 'M': index.push(new Resource(ResourceGroupType.Index, uri, Status.INDEX_MODIFIED, useIcons)); isModifiedInIndex = true; break;
+ case 'M': index.push(new Resource(ResourceGroupType.Index, uri, Status.INDEX_MODIFIED, useIcons)); break;
case 'A': index.push(new Resource(ResourceGroupType.Index, uri, Status.INDEX_ADDED, useIcons)); break;
case 'D': index.push(new Resource(ResourceGroupType.Index, uri, Status.INDEX_DELETED, useIcons)); break;
case 'R': index.push(new Resource(ResourceGroupType.Index, uri, Status.INDEX_RENAMED, useIcons, renameUri)); break;
@@ -954,13 +1038,9 @@ export class Repository implements Disposable {
this._sourceControl.count = count;
- // set context key
- let stateContextKey = '';
-
- switch (this.state) {
- case RepositoryState.Idle: stateContextKey = 'idle'; break;
- case RepositoryState.Disposed: stateContextKey = 'norepo'; break;
- }
+ // Disable `Discard All Changes` for "fresh" repositories
+ // https://github.com/Microsoft/vscode/issues/43066
+ commands.executeCommand('setContext', 'gitFreshRepository', !this._HEAD || !this._HEAD.commit);
this._onDidChangeStatus.fire();
}
diff --git a/extensions/git/src/staging.ts b/extensions/git/src/staging.ts
index 1dc7f451de..9015c38fb1 100644
--- a/extensions/git/src/staging.ts
+++ b/extensions/git/src/staging.ts
@@ -72,10 +72,16 @@ export function toLineRanges(selections: Selection[], textDocument: TextDocument
return result;
}
-function getModifiedRange(textDocument: TextDocument, diff: LineChange): Range {
- return diff.modifiedEndLineNumber === 0
- ? new Range(textDocument.lineAt(diff.modifiedStartLineNumber - 1).range.end, textDocument.lineAt(diff.modifiedStartLineNumber).range.start)
- : new Range(textDocument.lineAt(diff.modifiedStartLineNumber - 1).range.start, textDocument.lineAt(diff.modifiedEndLineNumber - 1).range.end);
+export function getModifiedRange(textDocument: TextDocument, diff: LineChange): Range {
+ if (diff.modifiedEndLineNumber === 0) {
+ if (diff.modifiedStartLineNumber === 0) {
+ return new Range(textDocument.lineAt(diff.modifiedStartLineNumber).range.end, textDocument.lineAt(diff.modifiedStartLineNumber).range.start);
+ } else {
+ return new Range(textDocument.lineAt(diff.modifiedStartLineNumber - 1).range.end, textDocument.lineAt(diff.modifiedStartLineNumber).range.start);
+ }
+ } else {
+ return new Range(textDocument.lineAt(diff.modifiedStartLineNumber - 1).range.start, textDocument.lineAt(diff.modifiedEndLineNumber - 1).range.end);
+ }
}
export function intersectDiffWithRange(textDocument: TextDocument, diff: LineChange, range: Range): LineChange | null {
diff --git a/extensions/git/src/test/git.test.ts b/extensions/git/src/test/git.test.ts
index 8499902aab..20420eb618 100644
--- a/extensions/git/src/test/git.test.ts
+++ b/extensions/git/src/test/git.test.ts
@@ -6,7 +6,7 @@
'use strict';
import 'mocha';
-import { GitStatusParser } from '../git';
+import { GitStatusParser, parseGitmodules } from '../git';
import * as assert from 'assert';
suite('git', () => {
@@ -135,4 +135,44 @@ suite('git', () => {
]);
});
});
+
+ suite('parseGitmodules', () => {
+ test('empty', () => {
+ assert.deepEqual(parseGitmodules(''), []);
+ });
+
+ test('sample', () => {
+ const sample = `[submodule "deps/spdlog"]
+ path = deps/spdlog
+ url = https://github.com/gabime/spdlog.git
+`;
+
+ assert.deepEqual(parseGitmodules(sample), [
+ { name: 'deps/spdlog', path: 'deps/spdlog', url: 'https://github.com/gabime/spdlog.git' }
+ ]);
+ });
+
+ test('big', () => {
+ const sample = `[submodule "deps/spdlog"]
+ path = deps/spdlog
+ url = https://github.com/gabime/spdlog.git
+[submodule "deps/spdlog2"]
+ path = deps/spdlog2
+ url = https://github.com/gabime/spdlog.git
+[submodule "deps/spdlog3"]
+ path = deps/spdlog3
+ url = https://github.com/gabime/spdlog.git
+[submodule "deps/spdlog4"]
+ path = deps/spdlog4
+ url = https://github.com/gabime/spdlog4.git
+`;
+
+ assert.deepEqual(parseGitmodules(sample), [
+ { name: 'deps/spdlog', path: 'deps/spdlog', url: 'https://github.com/gabime/spdlog.git' },
+ { name: 'deps/spdlog2', path: 'deps/spdlog2', url: 'https://github.com/gabime/spdlog.git' },
+ { name: 'deps/spdlog3', path: 'deps/spdlog3', url: 'https://github.com/gabime/spdlog.git' },
+ { name: 'deps/spdlog4', path: 'deps/spdlog4', url: 'https://github.com/gabime/spdlog4.git' }
+ ]);
+ });
+ });
});
\ No newline at end of file
diff --git a/extensions/git/src/uri.ts b/extensions/git/src/uri.ts
index 6a8e700f1e..8a2a0ea360 100644
--- a/extensions/git/src/uri.ts
+++ b/extensions/git/src/uri.ts
@@ -7,20 +7,45 @@
import { Uri } from 'vscode';
-export function fromGitUri(uri: Uri): { path: string; ref: string; } {
+export interface GitUriParams {
+ path: string;
+ ref: string;
+ submoduleOf?: string;
+}
+
+export function fromGitUri(uri: Uri): GitUriParams {
return JSON.parse(uri.query);
}
+export interface GitUriOptions {
+ replaceFileExtension?: boolean;
+ submoduleOf?: string;
+}
+
// As a mitigation for extensions like ESLint showing warnings and errors
// for git URIs, let's change the file extension of these uris to .git,
// when `replaceFileExtension` is true.
-export function toGitUri(uri: Uri, ref: string, replaceFileExtension = false): Uri {
+export function toGitUri(uri: Uri, ref: string, options: GitUriOptions = {}): Uri {
+ const params: GitUriParams = {
+ path: uri.fsPath,
+ ref
+ };
+
+ if (options.submoduleOf) {
+ params.submoduleOf = options.submoduleOf;
+ }
+
+ let path = uri.path;
+
+ if (options.replaceFileExtension) {
+ path = `${path}.git`;
+ } else if (options.submoduleOf) {
+ path = `${path}.diff`;
+ }
+
return uri.with({
scheme: 'git',
- path: replaceFileExtension ? `${uri.path}.git` : uri.path,
- query: JSON.stringify({
- path: uri.fsPath,
- ref
- })
+ path,
+ query: JSON.stringify(params)
});
}
\ No newline at end of file
diff --git a/extensions/git/src/util.ts b/extensions/git/src/util.ts
index b3a52079c5..c409a1d08c 100644
--- a/extensions/git/src/util.ts
+++ b/extensions/git/src/util.ts
@@ -34,6 +34,10 @@ export function combinedDisposable(disposables: IDisposable[]): IDisposable {
export const EmptyDisposable = toDisposable(() => null);
+export function fireEvent(event: Event): Event {
+ return (listener, thisArgs = null, disposables?) => event(_ => listener.call(thisArgs), null, disposables);
+}
+
export function mapEvent(event: Event, map: (i: I) => O): Event {
return (listener, thisArgs = null, disposables?) => event(i => listener.call(thisArgs, map(i)), null, disposables);
}
@@ -69,6 +73,16 @@ export function onceEvent(event: Event): Event {
};
}
+export function debounceEvent(event: Event, delay: number): Event {
+ return (listener, thisArgs = null, disposables?) => {
+ let timer: NodeJS.Timer;
+ return event(e => {
+ clearTimeout(timer);
+ timer = setTimeout(() => listener.call(thisArgs, e), delay);
+ }, null, disposables);
+ };
+}
+
export function eventToPromise(event: Event): Promise {
return new Promise(c => onceEvent(event)(c));
}
@@ -116,6 +130,10 @@ export function groupBy(arr: T[], fn: (el: T) => string): { [key: string]: T[
}, Object.create(null));
}
+export function denodeify(fn: Function): (a: A, b: B, c: C) => Promise;
+export function denodeify(fn: Function): (a: A, b: B) => Promise;
+export function denodeify(fn: Function): (a: A) => Promise;
+export function denodeify(fn: Function): (...args: any[]) => Promise;
export function denodeify(fn: Function): (...args: any[]) => Promise {
return (...args) => new Promise((c, e) => fn(...args, (err: any, r: any) => err ? e(err) : c(r)));
}
@@ -177,6 +195,16 @@ export function uniqueFilter(keyFn: (t: T) => string): (t: T) => boolean {
};
}
+export function firstIndex(array: T[], fn: (t: T) => boolean): number {
+ for (let i = 0; i < array.length; i++) {
+ if (fn(array[i])) {
+ return i;
+ }
+ }
+
+ return -1;
+}
+
export function find(array: T[], fn: (t: T) => boolean): T | undefined {
let result: T | undefined = undefined;
@@ -211,7 +239,7 @@ export async function grep(filename: string, pattern: RegExp): Promise
export function readBytes(stream: Readable, bytes: number): Promise {
return new Promise((complete, error) => {
let done = false;
- let buffer = new Buffer(bytes);
+ let buffer = Buffer.allocUnsafe(bytes);
let bytesRead = 0;
stream.on('data', (data: Buffer) => {
diff --git a/extensions/diff/syntaxes/diff.tmLanguage.json b/extensions/git/syntaxes/diff.tmLanguage.json
similarity index 90%
rename from extensions/diff/syntaxes/diff.tmLanguage.json
rename to extensions/git/syntaxes/diff.tmLanguage.json
index e0d60de108..d60bbb145f 100644
--- a/extensions/diff/syntaxes/diff.tmLanguage.json
+++ b/extensions/git/syntaxes/diff.tmLanguage.json
@@ -5,14 +5,8 @@
"Once accepted there, we are happy to receive an update request."
],
"version": "https://github.com/textmate/diff.tmbundle/commit/0593bb775eab1824af97ef2172fd38822abd97d7",
- "fileTypes": [
- "patch",
- "diff",
- "rej"
- ],
- "firstLineMatch": "(?x)^\n\t\t(===\\ modified\\ file\n\t\t|==== \\s* // .+ \\s - \\s .+ \\s+ ====\n\t\t|Index:\\ \n\t\t|---\\ [^%\\n]\n\t\t|\\*\\*\\*.*\\d{4}\\s*$\n\t\t|\\d+(,\\d+)* (a|d|c) \\d+(,\\d+)* $\n\t\t|diff\\ --git\\ \n\t\t|commit\\ [0-9a-f]{40}$\n\t\t)",
- "keyEquivalent": "^~D",
"name": "Diff",
+ "scopeName": "source.diff",
"patterns": [
{
"captures": {
@@ -162,7 +156,5 @@
"match": "^Only in .*: .*$\\n?",
"name": "meta.diff.only-in"
}
- ],
- "scopeName": "source.diff",
- "uuid": "7E848FF4-708E-11D9-97B4-0011242E4184"
+ ]
}
\ No newline at end of file
diff --git a/extensions/gitsyntax/syntaxes/git-commit.tmLanguage.json b/extensions/git/syntaxes/git-commit.tmLanguage.json
similarity index 95%
rename from extensions/gitsyntax/syntaxes/git-commit.tmLanguage.json
rename to extensions/git/syntaxes/git-commit.tmLanguage.json
index 5b2ccacd56..c2b8d628ab 100644
--- a/extensions/gitsyntax/syntaxes/git-commit.tmLanguage.json
+++ b/extensions/git/syntaxes/git-commit.tmLanguage.json
@@ -5,13 +5,8 @@
"Once accepted there, we are happy to receive an update request."
],
"version": "https://github.com/textmate/git.tmbundle/commit/93897a78c6e52bef13dadc0d4091d203c5facb40",
- "fileTypes": [
- "COMMIT_EDITMSG",
- "MERGE_MSG"
- ],
- "foldingStartMarker": "^\\+\\+\\+",
- "foldingStopMarker": "^---",
"name": "Git Commit Message",
+ "scopeName": "text.git-commit",
"patterns": [
{
"begin": "\\A(?!# Please enter the commit message)",
@@ -142,7 +137,5 @@
}
]
}
- },
- "scopeName": "text.git-commit",
- "uuid": "BFE83C06-8508-44BE-A975-95A57BF619A7"
+ }
}
\ No newline at end of file
diff --git a/extensions/gitsyntax/syntaxes/git-rebase.tmLanguage.json b/extensions/git/syntaxes/git-rebase.tmLanguage.json
similarity index 92%
rename from extensions/gitsyntax/syntaxes/git-rebase.tmLanguage.json
rename to extensions/git/syntaxes/git-rebase.tmLanguage.json
index 89ef957a1b..3ee481bede 100644
--- a/extensions/gitsyntax/syntaxes/git-rebase.tmLanguage.json
+++ b/extensions/git/syntaxes/git-rebase.tmLanguage.json
@@ -5,10 +5,8 @@
"Once accepted there, we are happy to receive an update request."
],
"version": "https://github.com/textmate/git.tmbundle/commit/d1db42c2d71948662098183a6df519fb53a7a15b",
- "fileTypes": [
- "git-rebase-todo"
- ],
"name": "Git Rebase Message",
+ "scopeName": "text.git-rebase",
"patterns": [
{
"captures": {
@@ -34,7 +32,5 @@
"match": "^\\s*(pick|p|reword|r|edit|e|squash|s|fixup|f|exec|x|drop|d)\\s+([0-9a-f]+)\\s+(.*)$",
"name": "meta.commit-command.git-rebase"
}
- ],
- "scopeName": "text.git-rebase",
- "uuid": "7F1CC209-5F6D-486A-8180-09FA282381A1"
+ ]
}
\ No newline at end of file
diff --git a/extensions/gitsyntax/test/colorize-fixtures/COMMIT_EDITMSG b/extensions/git/test/colorize-fixtures/COMMIT_EDITMSG
similarity index 100%
rename from extensions/gitsyntax/test/colorize-fixtures/COMMIT_EDITMSG
rename to extensions/git/test/colorize-fixtures/COMMIT_EDITMSG
diff --git a/extensions/git/test/colorize-fixtures/example.diff b/extensions/git/test/colorize-fixtures/example.diff
new file mode 100644
index 0000000000..256b719212
--- /dev/null
+++ b/extensions/git/test/colorize-fixtures/example.diff
@@ -0,0 +1,7 @@
+diff --git a/helloworld.txt b/helloworld.txt
+index e4f37c4..557db03 100644
+--- a/helloworld.txt
++++ b/helloworld.txt
+@@ -1 +1 @@
+-Hello world
++Hello World
\ No newline at end of file
diff --git a/extensions/gitsyntax/test/colorize-fixtures/git-rebase-todo b/extensions/git/test/colorize-fixtures/git-rebase-todo
similarity index 100%
rename from extensions/gitsyntax/test/colorize-fixtures/git-rebase-todo
rename to extensions/git/test/colorize-fixtures/git-rebase-todo
diff --git a/extensions/gitsyntax/test/colorize-results/COMMIT_EDITMSG.json b/extensions/git/test/colorize-results/COMMIT_EDITMSG.json
similarity index 100%
rename from extensions/gitsyntax/test/colorize-results/COMMIT_EDITMSG.json
rename to extensions/git/test/colorize-results/COMMIT_EDITMSG.json
diff --git a/extensions/git/test/colorize-results/example_diff.json b/extensions/git/test/colorize-results/example_diff.json
new file mode 100644
index 0000000000..07ec9f737b
--- /dev/null
+++ b/extensions/git/test/colorize-results/example_diff.json
@@ -0,0 +1,167 @@
+[
+ {
+ "c": "diff --git a/helloworld.txt b/helloworld.txt",
+ "t": "source.diff meta.diff.header.git",
+ "r": {
+ "dark_plus": "meta.diff.header: #569CD6",
+ "light_plus": "meta.diff.header: #000080",
+ "dark_vs": "meta.diff.header: #569CD6",
+ "light_vs": "meta.diff.header: #000080",
+ "hc_black": "meta.diff.header: #000080"
+ }
+ },
+ {
+ "c": "index e4f37c4..557db03 100644",
+ "t": "source.diff meta.diff.index.git",
+ "r": {
+ "dark_plus": "default: #D4D4D4",
+ "light_plus": "default: #000000",
+ "dark_vs": "default: #D4D4D4",
+ "light_vs": "default: #000000",
+ "hc_black": "default: #FFFFFF"
+ }
+ },
+ {
+ "c": "---",
+ "t": "source.diff meta.diff.header.from-file punctuation.definition.from-file.diff",
+ "r": {
+ "dark_plus": "meta.diff.header: #569CD6",
+ "light_plus": "meta.diff.header: #000080",
+ "dark_vs": "meta.diff.header: #569CD6",
+ "light_vs": "meta.diff.header: #000080",
+ "hc_black": "meta.diff.header: #000080"
+ }
+ },
+ {
+ "c": " a/helloworld.txt",
+ "t": "source.diff meta.diff.header.from-file",
+ "r": {
+ "dark_plus": "meta.diff.header: #569CD6",
+ "light_plus": "meta.diff.header: #000080",
+ "dark_vs": "meta.diff.header: #569CD6",
+ "light_vs": "meta.diff.header: #000080",
+ "hc_black": "meta.diff.header: #000080"
+ }
+ },
+ {
+ "c": "+++",
+ "t": "source.diff meta.diff.header.to-file punctuation.definition.to-file.diff",
+ "r": {
+ "dark_plus": "meta.diff.header: #569CD6",
+ "light_plus": "meta.diff.header: #000080",
+ "dark_vs": "meta.diff.header: #569CD6",
+ "light_vs": "meta.diff.header: #000080",
+ "hc_black": "meta.diff.header: #000080"
+ }
+ },
+ {
+ "c": " b/helloworld.txt",
+ "t": "source.diff meta.diff.header.to-file",
+ "r": {
+ "dark_plus": "meta.diff.header: #569CD6",
+ "light_plus": "meta.diff.header: #000080",
+ "dark_vs": "meta.diff.header: #569CD6",
+ "light_vs": "meta.diff.header: #000080",
+ "hc_black": "meta.diff.header: #000080"
+ }
+ },
+ {
+ "c": "@@",
+ "t": "source.diff meta.diff.range.unified punctuation.definition.range.diff",
+ "r": {
+ "dark_plus": "default: #D4D4D4",
+ "light_plus": "default: #000000",
+ "dark_vs": "default: #D4D4D4",
+ "light_vs": "default: #000000",
+ "hc_black": "default: #FFFFFF"
+ }
+ },
+ {
+ "c": " ",
+ "t": "source.diff meta.diff.range.unified",
+ "r": {
+ "dark_plus": "default: #D4D4D4",
+ "light_plus": "default: #000000",
+ "dark_vs": "default: #D4D4D4",
+ "light_vs": "default: #000000",
+ "hc_black": "default: #FFFFFF"
+ }
+ },
+ {
+ "c": "-1 +1",
+ "t": "source.diff meta.diff.range.unified meta.toc-list.line-number.diff",
+ "r": {
+ "dark_plus": "default: #D4D4D4",
+ "light_plus": "default: #000000",
+ "dark_vs": "default: #D4D4D4",
+ "light_vs": "default: #000000",
+ "hc_black": "default: #FFFFFF"
+ }
+ },
+ {
+ "c": " ",
+ "t": "source.diff meta.diff.range.unified",
+ "r": {
+ "dark_plus": "default: #D4D4D4",
+ "light_plus": "default: #000000",
+ "dark_vs": "default: #D4D4D4",
+ "light_vs": "default: #000000",
+ "hc_black": "default: #FFFFFF"
+ }
+ },
+ {
+ "c": "@@",
+ "t": "source.diff meta.diff.range.unified punctuation.definition.range.diff",
+ "r": {
+ "dark_plus": "default: #D4D4D4",
+ "light_plus": "default: #000000",
+ "dark_vs": "default: #D4D4D4",
+ "light_vs": "default: #000000",
+ "hc_black": "default: #FFFFFF"
+ }
+ },
+ {
+ "c": "-",
+ "t": "source.diff markup.deleted.diff punctuation.definition.deleted.diff",
+ "r": {
+ "dark_plus": "markup.deleted: #CE9178",
+ "light_plus": "markup.deleted: #A31515",
+ "dark_vs": "markup.deleted: #CE9178",
+ "light_vs": "markup.deleted: #A31515",
+ "hc_black": "markup.deleted: #CE9178"
+ }
+ },
+ {
+ "c": "Hello world",
+ "t": "source.diff markup.deleted.diff",
+ "r": {
+ "dark_plus": "markup.deleted: #CE9178",
+ "light_plus": "markup.deleted: #A31515",
+ "dark_vs": "markup.deleted: #CE9178",
+ "light_vs": "markup.deleted: #A31515",
+ "hc_black": "markup.deleted: #CE9178"
+ }
+ },
+ {
+ "c": "+",
+ "t": "source.diff markup.inserted.diff punctuation.definition.inserted.diff",
+ "r": {
+ "dark_plus": "markup.inserted: #B5CEA8",
+ "light_plus": "markup.inserted: #09885A",
+ "dark_vs": "markup.inserted: #B5CEA8",
+ "light_vs": "markup.inserted: #09885A",
+ "hc_black": "markup.inserted: #B5CEA8"
+ }
+ },
+ {
+ "c": "Hello World",
+ "t": "source.diff markup.inserted.diff",
+ "r": {
+ "dark_plus": "markup.inserted: #B5CEA8",
+ "light_plus": "markup.inserted: #09885A",
+ "dark_vs": "markup.inserted: #B5CEA8",
+ "light_vs": "markup.inserted: #09885A",
+ "hc_black": "markup.inserted: #B5CEA8"
+ }
+ }
+]
\ No newline at end of file
diff --git a/extensions/gitsyntax/test/colorize-results/git-rebase-todo.json b/extensions/git/test/colorize-results/git-rebase-todo.json
similarity index 100%
rename from extensions/gitsyntax/test/colorize-results/git-rebase-todo.json
rename to extensions/git/test/colorize-results/git-rebase-todo.json
diff --git a/extensions/git/tsconfig.json b/extensions/git/tsconfig.json
index ea7679c9ac..a7eca805f9 100644
--- a/extensions/git/tsconfig.json
+++ b/extensions/git/tsconfig.json
@@ -10,7 +10,8 @@
"./node_modules/@types"
],
"strict": true,
- "experimentalDecorators": true
+ "experimentalDecorators": true,
+ "noUnusedLocals": true
},
"include": [
"src/**/*"
diff --git a/extensions/git/yarn.lock b/extensions/git/yarn.lock
index a9d4c679d3..747060bcb3 100644
--- a/extensions/git/yarn.lock
+++ b/extensions/git/yarn.lock
@@ -30,9 +30,13 @@
version "1.0.28"
resolved "https://registry.yarnpkg.com/@types/which/-/which-1.0.28.tgz#016e387629b8817bed653fe32eab5d11279c8df6"
-applicationinsights@0.18.0:
- version "0.18.0"
- resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-0.18.0.tgz#162ebb48a383408bc4de44db32b417307f45bbc1"
+applicationinsights@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.1.tgz#53446b830fe8d5d619eee2a278b31d3d25030927"
+ dependencies:
+ diagnostic-channel "0.2.0"
+ diagnostic-channel-publishers "0.2.1"
+ zone.js "0.7.6"
balanced-match@^1.0.0:
version "1.0.0"
@@ -69,6 +73,16 @@ debug@2.6.8:
dependencies:
ms "2.0.0"
+diagnostic-channel-publishers@0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3"
+
+diagnostic-channel@0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz#cc99af9612c23fb1fff13612c72f2cbfaa8d5a17"
+ dependencies:
+ semver "^5.3.0"
+
diff@3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
@@ -229,22 +243,25 @@ path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+semver@^5.3.0:
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
+
supports-color@3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5"
dependencies:
has-flag "^1.0.0"
-vscode-extension-telemetry@0.0.8:
- version "0.0.8"
- resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz#2261bff986b6690a6f1f746a45ac5bd1f85d29e0"
+vscode-extension-telemetry@0.0.15:
+ version "0.0.15"
+ resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.15.tgz#685c32f3b67e8fb85ba689c1d7f88ff90ff87856"
dependencies:
- applicationinsights "0.18.0"
- winreg "1.2.3"
+ applicationinsights "1.0.1"
-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"
which@^1.3.0:
version "1.3.0"
@@ -252,10 +269,10 @@ which@^1.3.0:
dependencies:
isexe "^2.0.0"
-winreg@1.2.3:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/winreg/-/winreg-1.2.3.tgz#93ad116b2696da87d58f7265a8fcea5254a965d5"
-
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+
+zone.js@0.7.6:
+ version "0.7.6"
+ resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009"
diff --git a/extensions/gitsyntax/.vscodeignore b/extensions/gitsyntax/.vscodeignore
deleted file mode 100644
index 77ab386fc7..0000000000
--- a/extensions/gitsyntax/.vscodeignore
+++ /dev/null
@@ -1 +0,0 @@
-test/**
\ No newline at end of file
diff --git a/extensions/gitsyntax/OSSREADME.json b/extensions/gitsyntax/OSSREADME.json
deleted file mode 100644
index 0e3ddd52fa..0000000000
--- a/extensions/gitsyntax/OSSREADME.json
+++ /dev/null
@@ -1,29 +0,0 @@
-// ATTENTION - THIS DIRECTORY CONTAINS THIRD PARTY OPEN SOURCE MATERIALS:
-[{
- "name": "textmate/git.tmbundle",
- "version": "0.0.0",
- "license": "MIT",
- "repositoryURL": "https://github.com/textmate/git.tmbundle",
- "licenseDetail": [
- "Copyright (c) 2008 Tim Harper",
- "",
- "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."
- ]
-}]
\ No newline at end of file
diff --git a/extensions/gitsyntax/package.json b/extensions/gitsyntax/package.json
deleted file mode 100644
index 0040fe5547..0000000000
--- a/extensions/gitsyntax/package.json
+++ /dev/null
@@ -1,60 +0,0 @@
-{
- "name": "gitsyntax",
- "publisher": "vscode",
- "displayName": "gitsyntax",
- "description": "Git Syntax",
- "version": "0.0.1",
- "engines": {
- "vscode": "^1.5.0"
- },
- "categories": [
- "Other"
- ],
- "scripts": {
- "update-grammar": "node ../../build/npm/update-grammar.js textmate/git.tmbundle Syntaxes/Git%20Commit%20Message.tmLanguage ./syntaxes/git-commit.tmLanguage.json Syntaxes/Git%20Rebase%20Message.tmLanguage ./syntaxes/git-rebase.tmLanguage.json"
- },
- "contributes": {
- "languages": [
- {
- "id": "git-commit",
- "aliases": [
- "Git Commit Message",
- "git-commit"
- ],
- "filenames": [
- "COMMIT_EDITMSG",
- "MERGE_MSG"
- ],
- "configuration": "./git-commit.language-configuration.json"
- },
- {
- "id": "git-rebase",
- "aliases": [
- "Git Rebase Message",
- "git-rebase"
- ],
- "filenames": [
- "git-rebase-todo"
- ],
- "configuration": "./git-rebase.language-configuration.json"
- }
- ],
- "grammars": [
- {
- "language": "git-commit",
- "scopeName": "text.git-commit",
- "path": "./syntaxes/git-commit.tmLanguage.json"
- },
- {
- "language": "git-rebase",
- "scopeName": "text.git-rebase",
- "path": "./syntaxes/git-rebase.tmLanguage.json"
- }
- ],
- "configurationDefaults": {
- "[git-commit]": {
- "editor.rulers": [72]
- }
- }
- }
-}
\ No newline at end of file
diff --git a/extensions/json/client/src/jsonMain.ts b/extensions/json/client/src/jsonMain.ts
index 0ca5306a22..8f03ed140d 100644
--- a/extensions/json/client/src/jsonMain.ts
+++ b/extensions/json/client/src/jsonMain.ts
@@ -5,17 +5,16 @@
'use strict';
import * as path from 'path';
+import * as nls from 'vscode-nls';
+const localize = nls.loadMessageBundle();
-import { workspace, languages, ExtensionContext, extensions, Uri, TextDocument, ColorInformation, Color, ColorPresentation, LanguageConfiguration } from 'vscode';
+import { workspace, languages, ExtensionContext, extensions, Uri, LanguageConfiguration, TextDocument, FoldingRangeList, FoldingRange, Disposable } from 'vscode';
import { LanguageClient, LanguageClientOptions, RequestType, ServerOptions, TransportKind, NotificationType, DidChangeConfigurationNotification } from 'vscode-languageclient';
import TelemetryReporter from 'vscode-extension-telemetry';
-import { ConfigurationFeature } from 'vscode-languageclient/lib/configuration.proposed';
-import { DocumentColorRequest, DocumentColorParams, ColorPresentationParams, ColorPresentationRequest } from 'vscode-languageserver-protocol/lib/protocol.colorProvider.proposed';
+import { FoldingRangesRequest } from './protocol/foldingProvider.proposed';
-import * as nls from 'vscode-nls';
import { hash } from './utils/hash';
-let localize = nls.loadMessageBundle();
namespace VSCodeContentRequest {
export const type: RequestType = new RequestType('vscode/content');
@@ -45,8 +44,8 @@ interface Settings {
format?: { enable: boolean; };
};
http?: {
- proxy: string;
- proxyStrictSSL: boolean;
+ proxy?: string;
+ proxyStrictSSL?: boolean;
};
}
@@ -56,18 +55,22 @@ interface JSONSchemaSettings {
schema?: any;
}
+let telemetryReporter: TelemetryReporter | undefined;
+
+let foldingProviderRegistration: Disposable | undefined = void 0;
+const foldingSetting = 'json.experimental.syntaxFolding';
+
export function activate(context: ExtensionContext) {
let toDispose = context.subscriptions;
let packageInfo = getPackageInfo(context);
- let telemetryReporter: TelemetryReporter = packageInfo && new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
- toDispose.push(telemetryReporter);
+ telemetryReporter = packageInfo && new TelemetryReporter(packageInfo.name, packageInfo.version, packageInfo.aiKey);
// The server is implemented in node
let serverModule = context.asAbsolutePath(path.join('server', 'out', 'jsonServerMain.js'));
// The debug options for the server
- let debugOptions = { execArgv: ['--nolazy', '--inspect'] };
+ let debugOptions = { execArgv: ['--nolazy', '--inspect=6046'] };
// If the extension is launch in debug mode the debug server options are use
// Otherwise the run options are used
@@ -96,12 +99,12 @@ export function activate(context: ExtensionContext) {
// Create the language client and start the client.
let client = new LanguageClient('json', localize('jsonserver.name', 'JSON Language Server'), serverOptions, clientOptions);
- client.registerFeature(new ConfigurationFeature(client));
+ client.registerProposedFeatures();
let disposable = client.start();
toDispose.push(disposable);
client.onReady().then(() => {
- client.onTelemetry(e => {
+ disposable = client.onTelemetry(e => {
if (telemetryReporter) {
telemetryReporter.sendTelemetryEvent(e.key, e.data);
}
@@ -127,36 +130,13 @@ export function activate(context: ExtensionContext) {
client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociation(context));
- // register color provider
- toDispose.push(languages.registerColorProvider(documentSelector, {
- provideDocumentColors(document: TextDocument): Thenable {
- let params: DocumentColorParams = {
- textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document)
- };
- return client.sendRequest(DocumentColorRequest.type, params).then(symbols => {
- return symbols.map(symbol => {
- let range = client.protocol2CodeConverter.asRange(symbol.range);
- let color = new Color(symbol.color.red, symbol.color.green, symbol.color.blue, symbol.color.alpha);
- return new ColorInformation(range, color);
- });
- });
- },
- provideColorPresentations(color: Color, context): Thenable {
- let params: ColorPresentationParams = {
- textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(context.document),
- color: color,
- range: client.code2ProtocolConverter.asRange(context.range)
- };
- return client.sendRequest(ColorPresentationRequest.type, params).then(presentations => {
- return presentations.map(p => {
- let presentation = new ColorPresentation(p.label);
- presentation.textEdit = p.textEdit && client.protocol2CodeConverter.asTextEdit(p.textEdit);
- presentation.additionalTextEdits = p.additionalTextEdits && client.protocol2CodeConverter.asTextEdits(p.additionalTextEdits);
- return presentation;
- });
- });
+ initFoldingProvider();
+ toDispose.push(workspace.onDidChangeConfiguration(c => {
+ if (c.affectsConfiguration(foldingSetting)) {
+ initFoldingProvider();
}
}));
+ toDispose.push({ dispose: () => foldingProviderRegistration && foldingProviderRegistration.dispose() });
});
let languageConfiguration: LanguageConfiguration = {
@@ -168,6 +148,33 @@ export function activate(context: ExtensionContext) {
};
languages.setLanguageConfiguration('json', languageConfiguration);
languages.setLanguageConfiguration('jsonc', languageConfiguration);
+
+ function initFoldingProvider() {
+ let enable = workspace.getConfiguration().get(foldingSetting);
+ if (enable) {
+ if (!foldingProviderRegistration) {
+ foldingProviderRegistration = languages.registerFoldingProvider(documentSelector, {
+ provideFoldingRanges(document: TextDocument) {
+ return client.sendRequest(FoldingRangesRequest.type, { textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(document) }).then(res => {
+ if (res && Array.isArray(res.ranges)) {
+ return new FoldingRangeList(res.ranges.map(r => new FoldingRange(r.startLine, r.endLine, r.type)));
+ }
+ return null;
+ });
+ }
+ });
+ }
+ } else {
+ if (foldingProviderRegistration) {
+ foldingProviderRegistration.dispose();
+ foldingProviderRegistration = void 0;
+ }
+ }
+ }
+}
+
+export function deactivate(): Promise {
+ return telemetryReporter ? telemetryReporter.dispose() : Promise.resolve(null);
}
function getSchemaAssociation(context: ExtensionContext): ISchemaAssociations {
@@ -226,14 +233,14 @@ function getSettings(): Settings {
let schemaSetting = schemaSettingsById[url];
if (!schemaSetting) {
schemaSetting = schemaSettingsById[url] = { url, fileMatch: [] };
- settings.json.schemas.push(schemaSetting);
+ settings.json!.schemas!.push(schemaSetting);
}
let fileMatches = setting.fileMatch;
if (Array.isArray(fileMatches)) {
if (fileMatchPrefix) {
fileMatches = fileMatches.map(m => fileMatchPrefix + m);
}
- schemaSetting.fileMatch.push(...fileMatches);
+ schemaSetting.fileMatch!.push(...fileMatches);
}
if (setting.schema) {
schemaSetting.schema = setting.schema;
@@ -251,7 +258,7 @@ function getSettings(): Settings {
for (let folder of folders) {
let folderUri = folder.uri;
let schemaConfigInfo = workspace.getConfiguration('json', folderUri).inspect('schemas');
- let folderSchemas = schemaConfigInfo.workspaceFolderValue;
+ let folderSchemas = schemaConfigInfo!.workspaceFolderValue;
if (Array.isArray(folderSchemas)) {
let folderPath = folderUri.toString();
if (folderPath[folderPath.length - 1] !== '/') {
@@ -276,7 +283,7 @@ function getSchemaId(schema: JSONSchemaSettings, rootPath?: string) {
return url;
}
-function getPackageInfo(context: ExtensionContext): IPackageInfo {
+function getPackageInfo(context: ExtensionContext): IPackageInfo | undefined {
let extensionPackage = require(context.asAbsolutePath('./package.json'));
if (extensionPackage) {
return {
@@ -285,5 +292,5 @@ function getPackageInfo(context: ExtensionContext): IPackageInfo {
aiKey: extensionPackage.aiKey
};
}
- return null;
+ return void 0;
}
diff --git a/extensions/json/client/src/protocol/foldingProvider.proposed.ts b/extensions/json/client/src/protocol/foldingProvider.proposed.ts
new file mode 100644
index 0000000000..8906dc5aae
--- /dev/null
+++ b/extensions/json/client/src/protocol/foldingProvider.proposed.ts
@@ -0,0 +1,89 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { TextDocumentIdentifier } from 'vscode-languageserver-types';
+import { RequestType, TextDocumentRegistrationOptions, StaticRegistrationOptions } from 'vscode-languageserver-protocol';
+
+// ---- capabilities
+
+export interface FoldingProviderClientCapabilities {
+ /**
+ * The text document client capabilities
+ */
+ textDocument?: {
+ /**
+ * Capabilities specific to the foldingProvider
+ */
+ foldingProvider?: {
+ /**
+ * Whether implementation supports dynamic registration. If this is set to `true`
+ * the client supports the new `(FoldingProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions)`
+ * return value for the corresponding server capability as well.
+ */
+ dynamicRegistration?: boolean;
+ };
+ };
+}
+
+export interface FoldingProviderOptions {
+}
+
+export interface FoldingProviderServerCapabilities {
+ /**
+ * The server provides folding provider support.
+ */
+ foldingProvider?: FoldingProviderOptions | (FoldingProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions);
+}
+
+export interface FoldingRangeList {
+ /**
+ * The folding ranges.
+ */
+ ranges: FoldingRange[];
+}
+
+export enum FoldingRangeType {
+ /**
+ * Folding range for a comment
+ */
+ Comment = 'comment',
+ /**
+ * Folding range for a imports or includes
+ */
+ Imports = 'imports',
+ /**
+ * Folding range for a region (e.g. `#region`)
+ */
+ Region = 'region'
+}
+
+export interface FoldingRange {
+
+ /**
+ * The start line number
+ */
+ startLine: number;
+
+ /**
+ * The end line number
+ */
+ endLine: number;
+
+ /**
+ * The actual color value for this folding range.
+ */
+ type?: FoldingRangeType | string;
+}
+
+export interface FoldingRangeRequestParam {
+ /**
+ * The text document.
+ */
+ textDocument: TextDocumentIdentifier;
+}
+
+export namespace FoldingRangesRequest {
+ export const type: RequestType = new RequestType('textDocument/foldingRanges');
+}
diff --git a/extensions/json/client/tsconfig.json b/extensions/json/client/tsconfig.json
index d2f8f6376f..494973432e 100644
--- a/extensions/json/client/tsconfig.json
+++ b/extensions/json/client/tsconfig.json
@@ -1,11 +1,10 @@
{
"compilerOptions": {
- "target": "es5",
+ "target": "es6",
"module": "commonjs",
"outDir": "./out",
"noUnusedLocals": true,
- "lib": [
- "es5", "es2015.promise"
- ]
+ "lib": [ "es2016" ],
+ "strict": true
}
}
\ No newline at end of file
diff --git a/extensions/json/icons/json.png b/extensions/json/icons/json.png
new file mode 100644
index 0000000000..7774325427
Binary files /dev/null and b/extensions/json/icons/json.png differ
diff --git a/extensions/json/npm-shrinkwrap.json b/extensions/json/npm-shrinkwrap.json
deleted file mode 100644
index a9e20b252b..0000000000
--- a/extensions/json/npm-shrinkwrap.json
+++ /dev/null
@@ -1,46 +0,0 @@
-{
- "name": "json",
- "version": "0.1.0",
- "dependencies": {
- "applicationinsights": {
- "version": "0.18.0",
- "from": "applicationinsights@0.18.0",
- "resolved": "https://registry.npmjs.org/applicationinsights/-/applicationinsights-0.18.0.tgz"
- },
- "vscode-extension-telemetry": {
- "version": "0.0.8",
- "from": "vscode-extension-telemetry@>=0.0.8 <0.0.9",
- "resolved": "https://registry.npmjs.org/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz"
- },
- "vscode-jsonrpc": {
- "version": "3.5.0-next.2",
- "from": "vscode-jsonrpc@3.5.0-next.2",
- "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0-next.2.tgz"
- },
- "vscode-languageclient": {
- "version": "3.5.0-next.4",
- "from": "vscode-languageclient@3.5.0-next.4",
- "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-3.5.0-next.4.tgz"
- },
- "vscode-languageserver-protocol": {
- "version": "3.5.0-next.5",
- "from": "vscode-languageserver-protocol@3.5.0-next.5",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.0-next.5.tgz"
- },
- "vscode-languageserver-types": {
- "version": "3.5.0-next.2",
- "from": "vscode-languageserver-types@3.5.0-next.2",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0-next.2.tgz"
- },
- "vscode-nls": {
- "version": "2.0.2",
- "from": "vscode-nls@>=2.0.2 <3.0.0",
- "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-2.0.2.tgz"
- },
- "winreg": {
- "version": "1.2.3",
- "from": "winreg@1.2.3",
- "resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.3.tgz"
- }
- }
-}
diff --git a/extensions/json/package.json b/extensions/json/package.json
index afffbf02d8..c694c60267 100644
--- a/extensions/json/package.json
+++ b/extensions/json/package.json
@@ -1,13 +1,17 @@
{
"name": "json",
- "version": "0.1.0",
+ "displayName": "%displayName%",
+ "description": "%description%",
+ "version": "1.0.0",
"publisher": "vscode",
"aiKey": "AIF-d9b70cd4-b9f9-4d70-929b-a071c400b217",
"engines": {
"vscode": "0.10.x"
},
+ "icon": "icons/json.png",
"activationEvents": [
- "onLanguage:json", "onLanguage:jsonc"
+ "onLanguage:json",
+ "onLanguage:jsonc"
],
"enableProposedApi": true,
"main": "./client/out/jsonMain",
@@ -53,7 +57,8 @@
".code-workspace",
"language-configuration.json",
"icon-theme.json",
- "color-theme.json"
+ "color-theme.json",
+ ".code-snippets"
],
"filenames": [
"settings.json",
@@ -148,6 +153,11 @@
"default": true,
"description": "%json.colorDecorators.enable.desc%",
"deprecationMessage": "%json.colorDecorators.enable.deprecationMessage%"
+ },
+ "json.experimental.syntaxFolding": {
+ "type": "boolean",
+ "default": false,
+ "description": "%json.experimental.syntaxFolding%"
}
}
},
@@ -160,11 +170,11 @@
}
},
"dependencies": {
- "vscode-extension-telemetry": "0.0.8",
- "vscode-languageclient": "^3.5.0",
- "vscode-nls": "2.0.2"
+ "vscode-extension-telemetry": "0.0.15",
+ "vscode-languageclient": "4.0.0-next.9",
+ "vscode-nls": "^3.2.1"
},
"devDependencies": {
"@types/node": "7.0.43"
}
-}
\ No newline at end of file
+}
diff --git a/extensions/json/package.nls.json b/extensions/json/package.nls.json
index 31385fd819..3d268d7391 100644
--- a/extensions/json/package.nls.json
+++ b/extensions/json/package.nls.json
@@ -1,4 +1,6 @@
{
+ "displayName": "JSON Language Features",
+ "description": "Provides rich language support for JSON files.",
"json.schemas.desc": "Associate schemas to JSON files in the current project",
"json.schemas.url.desc": "A URL to a schema or a relative path to a schema in the current directory",
"json.schemas.fileMatch.desc": "An array of file patterns to match against when resolving JSON files to schemas.",
@@ -7,5 +9,6 @@
"json.format.enable.desc": "Enable/disable default JSON formatter (requires restart)",
"json.tracing.desc": "Traces the communication between VS Code and the JSON language server.",
"json.colorDecorators.enable.desc": "Enables or disables color decorators",
- "json.colorDecorators.enable.deprecationMessage": "The setting `json.colorDecorators.enable` has been deprecated in favor of `editor.colorDecorators`."
+ "json.colorDecorators.enable.deprecationMessage": "The setting `json.colorDecorators.enable` has been deprecated in favor of `editor.colorDecorators`.",
+ "json.experimental.syntaxFolding": "Enables/disables syntax aware folding markers."
}
\ No newline at end of file
diff --git a/extensions/json/server/npm-shrinkwrap.json b/extensions/json/server/npm-shrinkwrap.json
deleted file mode 100644
index daef1ef2fd..0000000000
--- a/extensions/json/server/npm-shrinkwrap.json
+++ /dev/null
@@ -1,81 +0,0 @@
-{
- "name": "vscode-json-languageserver",
- "version": "1.0.0",
- "dependencies": {
- "agent-base": {
- "version": "1.0.2",
- "from": "agent-base@>=1.0.1 <1.1.0",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-1.0.2.tgz"
- },
- "debug": {
- "version": "2.6.6",
- "from": "debug@>=2.0.0 <3.0.0",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.6.tgz"
- },
- "extend": {
- "version": "3.0.1",
- "from": "extend@>=3.0.0 <4.0.0",
- "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz"
- },
- "http-proxy-agent": {
- "version": "0.2.7",
- "from": "http-proxy-agent@>=0.2.6 <0.3.0",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-0.2.7.tgz"
- },
- "https-proxy-agent": {
- "version": "0.3.6",
- "from": "https-proxy-agent@>=0.3.5 <0.4.0",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-0.3.6.tgz"
- },
- "jsonc-parser": {
- "version": "1.0.0",
- "from": "jsonc-parser@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-1.0.0.tgz"
- },
- "ms": {
- "version": "0.7.3",
- "from": "ms@0.7.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.3.tgz"
- },
- "request-light": {
- "version": "0.2.1",
- "from": "request-light@0.2.1",
- "resolved": "https://registry.npmjs.org/request-light/-/request-light-0.2.1.tgz"
- },
- "vscode-json-languageservice": {
- "version": "3.0.0",
- "from": "vscode-json-languageservice@next",
- "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-3.0.0.tgz"
- },
- "vscode-jsonrpc": {
- "version": "3.5.0-next.2",
- "from": "vscode-jsonrpc@3.5.0-next.2",
- "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0-next.2.tgz"
- },
- "vscode-languageserver": {
- "version": "3.5.0-next.6",
- "from": "vscode-languageserver@3.5.0-next.6",
- "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-3.5.0-next.6.tgz"
- },
- "vscode-languageserver-protocol": {
- "version": "3.5.0-next.5",
- "from": "vscode-languageserver-protocol@3.5.0-next.5",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.0-next.5.tgz"
- },
- "vscode-languageserver-types": {
- "version": "3.5.0-next.2",
- "from": "vscode-languageserver-types@3.5.0-next.2",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0-next.2.tgz"
- },
- "vscode-nls": {
- "version": "2.0.2",
- "from": "vscode-nls@>=2.0.2 <3.0.0",
- "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-2.0.2.tgz"
- },
- "vscode-uri": {
- "version": "1.0.1",
- "from": "vscode-uri@>=1.0.0 <2.0.0",
- "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.1.tgz"
- }
- }
-}
diff --git a/extensions/json/server/package.json b/extensions/json/server/package.json
index a9a68b0a3c..c597f26e5c 100644
--- a/extensions/json/server/package.json
+++ b/extensions/json/server/package.json
@@ -8,11 +8,11 @@
"node": "*"
},
"dependencies": {
- "jsonc-parser": "^1.0.0",
- "request-light": "^0.2.1",
- "vscode-json-languageservice": "^3.0.4",
- "vscode-languageserver": "^3.5.0",
- "vscode-nls": "^2.0.2",
+ "jsonc-parser": "^1.0.1",
+ "request-light": "^0.2.2",
+ "vscode-json-languageservice": "^3.0.7",
+ "vscode-languageserver": "4.0.0-next.3",
+ "vscode-nls": "^3.2.1",
"vscode-uri": "^1.0.1"
},
"devDependencies": {
@@ -22,8 +22,8 @@
"compile": "gulp compile-extension:json-server",
"watch": "gulp watch-extension:json-server",
"install-service-next": "yarn add vscode-json-languageservice@next",
- "install-service-local": "npm install ../../../../vscode-json-languageservice -f",
+ "install-service-local": "yarn link vscode-json-languageservice",
"install-server-next": "yarn add vscode-languageserver@next",
- "install-server-local": "npm install ../../../../vscode-languageserver-node/server -f"
+ "install-server-local": "yarn link vscode-languageserver-server"
}
}
diff --git a/extensions/json/server/src/jsonServerMain.ts b/extensions/json/server/src/jsonServerMain.ts
index a54fc876b2..1431e8712b 100644
--- a/extensions/json/server/src/jsonServerMain.ts
+++ b/extensions/json/server/src/jsonServerMain.ts
@@ -17,12 +17,12 @@ import fs = require('fs');
import URI from 'vscode-uri';
import * as URL from 'url';
import Strings = require('./utils/strings');
-import { formatError, runSafe } from './utils/errors';
-import { JSONDocument, JSONSchema, LanguageSettings, getLanguageService, DocumentLanguageSettings } from 'vscode-json-languageservice';
+import { formatError, runSafe, runSafeAsync } from './utils/errors';
+import { JSONDocument, JSONSchema, getLanguageService, DocumentLanguageSettings, SchemaConfiguration } from 'vscode-json-languageservice';
import { getLanguageModelCache } from './languageModelCache';
+import { createScanner, SyntaxKind } from 'jsonc-parser';
-import * as nls from 'vscode-nls';
-nls.config(process.env['VSCODE_NLS_CONFIG']);
+import { FoldingRangeType, FoldingRangesRequest, FoldingRange, FoldingRangeList, FoldingProviderServerCapabilities } from './protocol/foldingProvider.proposed';
interface ISchemaAssociations {
[pattern: string]: string[];
@@ -43,7 +43,7 @@ namespace SchemaContentChangeNotification {
// Create a connection for the server
let connection: IConnection = createConnection();
-process.on('unhandledRejection', e => {
+process.on('unhandledRejection', (e: any) => {
connection.console.error(formatError(`Unhandled exception`, e));
});
@@ -65,7 +65,7 @@ let clientDynamicRegisterSupport = false;
connection.onInitialize((params: InitializeParams): InitializeResult => {
function hasClientCapability(...keys: string[]) {
- let c = params.capabilities;
+ let c = params.capabilities as any;
for (let i = 0; c && i < keys.length; i++) {
c = c[keys[i]];
}
@@ -74,14 +74,15 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
clientSnippetSupport = hasClientCapability('textDocument', 'completion', 'completionItem', 'snippetSupport');
clientDynamicRegisterSupport = hasClientCapability('workspace', 'symbol', 'dynamicRegistration');
- let capabilities: ServerCapabilities & CPServerCapabilities = {
+ let capabilities: ServerCapabilities & CPServerCapabilities & FoldingProviderServerCapabilities = {
// Tell the client that the server works in FULL text document sync mode
textDocumentSync: documents.syncKind,
- completionProvider: clientSnippetSupport ? { resolveProvider: true, triggerCharacters: ['"', ':'] } : null,
+ completionProvider: clientSnippetSupport ? { resolveProvider: true, triggerCharacters: ['"', ':'] } : void 0,
hoverProvider: true,
documentSymbolProvider: true,
documentRangeFormattingProvider: false,
- colorProvider: true
+ colorProvider: true,
+ foldingProvider: true
};
return { capabilities };
@@ -105,7 +106,7 @@ let schemaRequestService = (uri: string): Thenable => {
return connection.sendRequest(VSCodeContentRequest.type, uri).then(responseText => {
return responseText;
}, error => {
- return error.message;
+ return Promise.reject(error.message);
});
}
if (uri.indexOf('//schema.management.azure.com/') !== -1) {
@@ -149,9 +150,9 @@ interface JSONSchemaSettings {
schema?: JSONSchema;
}
-let jsonConfigurationSettings: JSONSchemaSettings[] = void 0;
-let schemaAssociations: ISchemaAssociations = void 0;
-let formatterRegistration: Thenable = null;
+let jsonConfigurationSettings: JSONSchemaSettings[] | undefined = void 0;
+let schemaAssociations: ISchemaAssociations | undefined = void 0;
+let formatterRegistration: Thenable | null = null;
// The settings have changed. Is send on server activation as well.
connection.onDidChangeConfiguration((change) => {
@@ -187,10 +188,10 @@ connection.onNotification(SchemaContentChangeNotification.type, uri => {
});
function updateConfiguration() {
- let languageSettings: LanguageSettings = {
+ let languageSettings = {
validate: true,
allowComments: true,
- schemas: []
+ schemas: new Array()
};
if (schemaAssociations) {
for (var pattern in schemaAssociations) {
@@ -232,7 +233,7 @@ documents.onDidClose(event => {
});
let pendingValidationRequests: { [uri: string]: NodeJS.Timer; } = {};
-const validationDelayMs = 200;
+const validationDelayMs = 500;
function cleanPendingValidation(textDocument: TextDocument): void {
let request = pendingValidationRequests[textDocument.uri];
@@ -295,7 +296,7 @@ function getJSONDocument(document: TextDocument): JSONDocument {
}
connection.onCompletion(textDocumentPosition => {
- return runSafe(() => {
+ return runSafeAsync(() => {
let document = documents.get(textDocumentPosition.textDocument.uri);
let jsonDocument = getJSONDocument(document);
return languageService.doComplete(document, textDocumentPosition.position, jsonDocument);
@@ -303,13 +304,13 @@ connection.onCompletion(textDocumentPosition => {
});
connection.onCompletionResolve(completionItem => {
- return runSafe(() => {
+ return runSafeAsync(() => {
return languageService.doResolve(completionItem);
- }, null, `Error while resolving completion proposal`);
+ }, completionItem, `Error while resolving completion proposal`);
});
connection.onHover(textDocumentPositionParams => {
- return runSafe(() => {
+ return runSafeAsync(() => {
let document = documents.get(textDocumentPositionParams.textDocument.uri);
let jsonDocument = getJSONDocument(document);
return languageService.doHover(document, textDocumentPositionParams.position, jsonDocument);
@@ -332,13 +333,13 @@ connection.onDocumentRangeFormatting(formatParams => {
});
connection.onRequest(DocumentColorRequest.type, params => {
- return runSafe(() => {
+ return runSafeAsync(() => {
let document = documents.get(params.textDocument.uri);
if (document) {
let jsonDocument = getJSONDocument(document);
return languageService.findDocumentColors(document, jsonDocument);
}
- return [];
+ return Promise.resolve([]);
}, [], `Error while computing document colors for ${params.textDocument.uri}`);
});
@@ -350,7 +351,86 @@ connection.onRequest(ColorPresentationRequest.type, params => {
return languageService.getColorPresentations(document, jsonDocument, params.color, params.range);
}
return [];
- }, [], `Error while computing color presentationsd for ${params.textDocument.uri}`);
+ }, [], `Error while computing color presentations for ${params.textDocument.uri}`);
+});
+
+connection.onRequest(FoldingRangesRequest.type, params => {
+ return runSafe(() => {
+ let document = documents.get(params.textDocument.uri);
+ if (document) {
+ let ranges: FoldingRange[] = [];
+ let stack: FoldingRange[] = [];
+ let prevStart = -1;
+ let scanner = createScanner(document.getText(), false);
+ let token = scanner.scan();
+ while (token !== SyntaxKind.EOF) {
+ switch (token) {
+ case SyntaxKind.OpenBraceToken:
+ case SyntaxKind.OpenBracketToken: {
+ let startLine = document.positionAt(scanner.getTokenOffset()).line;
+ let range = { startLine, endLine: startLine, type: token === SyntaxKind.OpenBraceToken ? 'object' : 'array' };
+ stack.push(range);
+ break;
+ }
+ case SyntaxKind.CloseBraceToken:
+ case SyntaxKind.CloseBracketToken: {
+ let type = token === SyntaxKind.CloseBraceToken ? 'object' : 'array';
+ if (stack.length > 0 && stack[stack.length - 1].type === type) {
+ let range = stack.pop();
+ let line = document.positionAt(scanner.getTokenOffset()).line;
+ if (range && line > range.startLine + 1 && prevStart !== range.startLine) {
+ range.endLine = line - 1;
+ ranges.push(range);
+ prevStart = range.startLine;
+ }
+ }
+ break;
+ }
+
+ case SyntaxKind.BlockCommentTrivia: {
+ let startLine = document.positionAt(scanner.getTokenOffset()).line;
+ let endLine = document.positionAt(scanner.getTokenOffset() + scanner.getTokenLength()).line;
+ if (startLine < endLine) {
+ ranges.push({ startLine, endLine, type: FoldingRangeType.Comment });
+ prevStart = startLine;
+ }
+ break;
+ }
+
+ case SyntaxKind.LineCommentTrivia: {
+ let text = document.getText().substr(scanner.getTokenOffset(), scanner.getTokenLength());
+ let m = text.match(/^\/\/\s*#(region\b)|(endregion\b)/);
+ if (m) {
+ let line = document.positionAt(scanner.getTokenOffset()).line;
+ if (m[1]) { // start pattern match
+ let range = { startLine: line, endLine: line, type: FoldingRangeType.Region };
+ stack.push(range);
+ } else {
+ let i = stack.length - 1;
+ while (i >= 0 && stack[i].type !== FoldingRangeType.Region) {
+ i--;
+ }
+ if (i >= 0) {
+ let range = stack[i];
+ stack.length = i;
+ if (line > range.startLine && prevStart !== range.startLine) {
+ range.endLine = line;
+ ranges.push(range);
+ prevStart = range.startLine;
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ }
+ token = scanner.scan();
+ }
+ return { ranges };
+ }
+ return null;
+ }, null, `Error while computing folding ranges for ${params.textDocument.uri}`);
});
// Listen on the connection
diff --git a/extensions/json/server/src/languageModelCache.ts b/extensions/json/server/src/languageModelCache.ts
index 074285d07c..f34cab67ab 100644
--- a/extensions/json/server/src/languageModelCache.ts
+++ b/extensions/json/server/src/languageModelCache.ts
@@ -16,7 +16,7 @@ export function getLanguageModelCache(maxEntries: number, cleanupIntervalTime
let languageModels: { [uri: string]: { version: number, languageId: string, cTime: number, languageModel: T } } = {};
let nModels = 0;
- let cleanupInterval = void 0;
+ let cleanupInterval: NodeJS.Timer | undefined = void 0;
if (cleanupIntervalTimeInSec > 0) {
cleanupInterval = setInterval(() => {
let cutoffTime = Date.now() - cleanupIntervalTimeInSec * 1000;
diff --git a/extensions/json/server/src/protocol/foldingProvider.proposed.ts b/extensions/json/server/src/protocol/foldingProvider.proposed.ts
new file mode 100644
index 0000000000..8906dc5aae
--- /dev/null
+++ b/extensions/json/server/src/protocol/foldingProvider.proposed.ts
@@ -0,0 +1,89 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the Source EULA. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { TextDocumentIdentifier } from 'vscode-languageserver-types';
+import { RequestType, TextDocumentRegistrationOptions, StaticRegistrationOptions } from 'vscode-languageserver-protocol';
+
+// ---- capabilities
+
+export interface FoldingProviderClientCapabilities {
+ /**
+ * The text document client capabilities
+ */
+ textDocument?: {
+ /**
+ * Capabilities specific to the foldingProvider
+ */
+ foldingProvider?: {
+ /**
+ * Whether implementation supports dynamic registration. If this is set to `true`
+ * the client supports the new `(FoldingProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions)`
+ * return value for the corresponding server capability as well.
+ */
+ dynamicRegistration?: boolean;
+ };
+ };
+}
+
+export interface FoldingProviderOptions {
+}
+
+export interface FoldingProviderServerCapabilities {
+ /**
+ * The server provides folding provider support.
+ */
+ foldingProvider?: FoldingProviderOptions | (FoldingProviderOptions & TextDocumentRegistrationOptions & StaticRegistrationOptions);
+}
+
+export interface FoldingRangeList {
+ /**
+ * The folding ranges.
+ */
+ ranges: FoldingRange[];
+}
+
+export enum FoldingRangeType {
+ /**
+ * Folding range for a comment
+ */
+ Comment = 'comment',
+ /**
+ * Folding range for a imports or includes
+ */
+ Imports = 'imports',
+ /**
+ * Folding range for a region (e.g. `#region`)
+ */
+ Region = 'region'
+}
+
+export interface FoldingRange {
+
+ /**
+ * The start line number
+ */
+ startLine: number;
+
+ /**
+ * The end line number
+ */
+ endLine: number;
+
+ /**
+ * The actual color value for this folding range.
+ */
+ type?: FoldingRangeType | string;
+}
+
+export interface FoldingRangeRequestParam {
+ /**
+ * The text document.
+ */
+ textDocument: TextDocumentIdentifier;
+}
+
+export namespace FoldingRangesRequest {
+ export const type: RequestType = new RequestType('textDocument/foldingRanges');
+}
diff --git a/extensions/json/server/src/utils/errors.ts b/extensions/json/server/src/utils/errors.ts
index 2d34f216ba..507e8a7bf6 100644
--- a/extensions/json/server/src/utils/errors.ts
+++ b/extensions/json/server/src/utils/errors.ts
@@ -16,16 +16,16 @@ export function formatError(message: string, err: any): string {
return message;
}
-export function runSafe(func: () => Thenable | T, errorVal: T, errorMessage: string): Thenable | T {
+export function runSafeAsync(func: () => Thenable, errorVal: T, errorMessage: string): Thenable {
+ let t = func();
+ return t.then(void 0, e => {
+ console.error(formatError(errorMessage, e));
+ return errorVal;
+ });
+}
+export function runSafe(func: () => T, errorVal: T, errorMessage: string): T {
try {
- let t = func();
- if (t instanceof Promise) {
- return t.then(void 0, e => {
- console.error(formatError(errorMessage, e));
- return errorVal;
- });
- }
- return t;
+ return func();
} catch (e) {
console.error(formatError(errorMessage, e));
return errorVal;
diff --git a/extensions/json/server/src/utils/uri.ts b/extensions/json/server/src/utils/uri.ts
deleted file mode 100644
index 332c486250..0000000000
--- a/extensions/json/server/src/utils/uri.ts
+++ /dev/null
@@ -1,351 +0,0 @@
-/*---------------------------------------------------------------------------------------------
- * Copyright (c) Microsoft Corporation. All rights reserved.
- * Licensed under the Source EULA. See License.txt in the project root for license information.
- *--------------------------------------------------------------------------------------------*/
-'use strict';
-
-function _encode(ch: string): string {
- return '%' + ch.charCodeAt(0).toString(16).toUpperCase();
-}
-
-// see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
-function encodeURIComponent2(str: string): string {
- return encodeURIComponent(str).replace(/[!'()*]/g, _encode);
-}
-
-function encodeNoop(str: string): string {
- return str;
-}
-
-
-/**
- * Uniform Resource Identifier (URI) http://tools.ietf.org/html/rfc3986.
- * This class is a simple parser which creates the basic component paths
- * (http://tools.ietf.org/html/rfc3986#section-3) with minimal validation
- * and encoding.
- *
- * foo://example.com:8042/over/there?name=ferret#nose
- * \_/ \______________/\_________/ \_________/ \__/
- * | | | | |
- * scheme authority path query fragment
- * | _____________________|__
- * / \ / \
- * urn:example:animal:ferret:nose
- *
- *
- */
-export default class URI {
-
- private static _empty = '';
- private static _slash = '/';
- private static _regexp = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/;
- private static _driveLetterPath = /^\/[a-zA-z]:/;
- private static _upperCaseDrive = /^(\/)?([A-Z]:)/;
-
- private _scheme: string;
- private _authority: string;
- private _path: string;
- private _query: string;
- private _fragment: string;
- private _formatted: string;
- private _fsPath: string;
-
- constructor() {
- this._scheme = URI._empty;
- this._authority = URI._empty;
- this._path = URI._empty;
- this._query = URI._empty;
- this._fragment = URI._empty;
-
- this._formatted = null;
- this._fsPath = null;
- }
-
- /**
- * scheme is the 'http' part of 'http://www.msft.com/some/path?query#fragment'.
- * The part before the first colon.
- */
- get scheme() {
- return this._scheme;
- }
-
- /**
- * authority is the 'www.msft.com' part of 'http://www.msft.com/some/path?query#fragment'.
- * The part between the first double slashes and the next slash.
- */
- get authority() {
- return this._authority;
- }
-
- /**
- * path is the '/some/path' part of 'http://www.msft.com/some/path?query#fragment'.
- */
- get path() {
- return this._path;
- }
-
- /**
- * query is the 'query' part of 'http://www.msft.com/some/path?query#fragment'.
- */
- get query() {
- return this._query;
- }
-
- /**
- * fragment is the 'fragment' part of 'http://www.msft.com/some/path?query#fragment'.
- */
- get fragment() {
- return this._fragment;
- }
-
- // ---- filesystem path -----------------------
-
- /**
- * Returns a string representing the corresponding file system path of this URI.
- * Will handle UNC paths and normalize windows drive letters to lower-case. Also
- * uses the platform specific path separator. Will *not* validate the path for
- * invalid characters and semantics. Will *not* look at the scheme of this URI.
- */
- get fsPath() {
- if (!this._fsPath) {
- var value: string;
- if (this._authority && this.scheme === 'file') {
- // unc path: file://shares/c$/far/boo
- value = `//${this._authority}${this._path}`;
- } else if (URI._driveLetterPath.test(this._path)) {
- // windows drive letter: file:///c:/far/boo
- value = this._path[1].toLowerCase() + this._path.substr(2);
- } else {
- // other path
- value = this._path;
- }
- if (process.platform === 'win32') {
- value = value.replace(/\//g, '\\');
- }
- this._fsPath = value;
- }
- return this._fsPath;
- }
-
- // ---- modify to new -------------------------
-
- public with(scheme: string, authority: string, path: string, query: string, fragment: string): URI {
- var ret = new URI();
- ret._scheme = scheme || this.scheme;
- ret._authority = authority || this.authority;
- ret._path = path || this.path;
- ret._query = query || this.query;
- ret._fragment = fragment || this.fragment;
- URI._validate(ret);
- return ret;
- }
-
- public withScheme(value: string): URI {
- return this.with(value, undefined, undefined, undefined, undefined);
- }
-
- public withAuthority(value: string): URI {
- return this.with(undefined, value, undefined, undefined, undefined);
- }
-
- public withPath(value: string): URI {
- return this.with(undefined, undefined, value, undefined, undefined);
- }
-
- public withQuery(value: string): URI {
- return this.with(undefined, undefined, undefined, value, undefined);
- }
-
- public withFragment(value: string): URI {
- return this.with(undefined, undefined, undefined, undefined, value);
- }
-
- // ---- parse & validate ------------------------
-
- public static parse(value: string): URI {
- const ret = new URI();
- const data = URI._parseComponents(value);
- ret._scheme = data.scheme;
- ret._authority = decodeURIComponent(data.authority);
- ret._path = decodeURIComponent(data.path);
- ret._query = decodeURIComponent(data.query);
- ret._fragment = decodeURIComponent(data.fragment);
- URI._validate(ret);
- return ret;
- }
-
- public static file(path: string): URI {
-
- const ret = new URI();
- ret._scheme = 'file';
-
- // normalize to fwd-slashes
- path = path.replace(/\\/g, URI._slash);
-
- // check for authority as used in UNC shares
- // or use the path as given
- if (path[0] === URI._slash && path[0] === path[1]) {
- let idx = path.indexOf(URI._slash, 2);
- if (idx === -1) {
- ret._authority = path.substring(2);
- } else {
- ret._authority = path.substring(2, idx);
- ret._path = path.substring(idx);
- }
- } else {
- ret._path = path;
- }
-
- // Ensure that path starts with a slash
- // or that it is at least a slash
- if (ret._path[0] !== URI._slash) {
- ret._path = URI._slash + ret._path;
- }
-
- URI._validate(ret);
-
- return ret;
- }
-
- private static _parseComponents(value: string): UriComponents {
-
- const ret: UriComponents = {
- scheme: URI._empty,
- authority: URI._empty,
- path: URI._empty,
- query: URI._empty,
- fragment: URI._empty,
- };
-
- const match = URI._regexp.exec(value);
- if (match) {
- ret.scheme = match[2] || ret.scheme;
- ret.authority = match[4] || ret.authority;
- ret.path = match[5] || ret.path;
- ret.query = match[7] || ret.query;
- ret.fragment = match[9] || ret.fragment;
- }
- return ret;
- }
-
- public static create(scheme?: string, authority?: string, path?: string, query?: string, fragment?: string): URI {
- return new URI().with(scheme, authority, path, query, fragment);
- }
-
- private static _validate(ret: URI): void {
-
- // validation
- // path, http://tools.ietf.org/html/rfc3986#section-3.3
- // If a URI contains an authority component, then the path component
- // must either be empty or begin with a slash ("/") character. If a URI
- // does not contain an authority component, then the path cannot begin
- // with two slash characters ("//").
- if (ret.authority && ret.path && ret.path[0] !== '/') {
- throw new Error('[UriError]: If a URI contains an authority component, then the path component must either be empty or begin with a slash ("/") character');
- }
- if (!ret.authority && ret.path.indexOf('//') === 0) {
- throw new Error('[UriError]: If a URI does not contain an authority component, then the path cannot begin with two slash characters ("//")');
- }
- }
-
- // ---- printing/externalize ---------------------------
-
- /**
- *
- * @param skipEncoding Do not encode the result, default is `false`
- */
- public toString(skipEncoding: boolean = false): string {
- if (!skipEncoding) {
- if (!this._formatted) {
- this._formatted = URI._asFormatted(this, false);
- }
- return this._formatted;
- } else {
- // we don't cache that
- return URI._asFormatted(this, true);
- }
- }
-
- private static _asFormatted(uri: URI, skipEncoding: boolean): string {
-
- const encoder = !skipEncoding
- ? encodeURIComponent2
- : encodeNoop;
-
- const parts: string[] = [];
-
- let { scheme, authority, path, query, fragment } = uri;
- if (scheme) {
- parts.push(scheme, ':');
- }
- if (authority || scheme === 'file') {
- parts.push('//');
- }
- if (authority) {
- authority = authority.toLowerCase();
- let idx = authority.indexOf(':');
- if (idx === -1) {
- parts.push(encoder(authority));
- } else {
- parts.push(encoder(authority.substr(0, idx)), authority.substr(idx));
- }
- }
- if (path) {
- // lower-case windown drive letters in /C:/fff
- const m = URI._upperCaseDrive.exec(path);
- if (m) {
- path = m[1] + m[2].toLowerCase() + path.substr(m[1].length + m[2].length);
- }
-
- // encode every segement but not slashes
- // make sure that # and ? are always encoded
- // when occurring in paths - otherwise the result
- // cannot be parsed back again
- let lastIdx = 0;
- while (true) {
- let idx = path.indexOf(URI._slash, lastIdx);
- if (idx === -1) {
- parts.push(encoder(path.substring(lastIdx)).replace(/[#?]/, _encode));
- break;
- }
- parts.push(encoder(path.substring(lastIdx, idx)).replace(/[#?]/, _encode), URI._slash);
- lastIdx = idx + 1;
- };
- }
- if (query) {
- parts.push('?', encoder(query));
- }
- if (fragment) {
- parts.push('#', encoder(fragment));
- }
-
- return parts.join(URI._empty);
- }
-
- public toJSON(): any {
- return {
- scheme: this.scheme,
- authority: this.authority,
- path: this.path,
- fsPath: this.fsPath,
- query: this.query,
- fragment: this.fragment,
- external: this.toString(),
- $mid: 1
- };
- }
-}
-
-interface UriComponents {
- scheme: string;
- authority: string;
- path: string;
- query: string;
- fragment: string;
-}
-
-interface UriState extends UriComponents {
- $mid: number;
- fsPath: string;
- external: string;
-}
diff --git a/extensions/json/server/tsconfig.json b/extensions/json/server/tsconfig.json
index e085b24514..5f15678fc5 100644
--- a/extensions/json/server/tsconfig.json
+++ b/extensions/json/server/tsconfig.json
@@ -8,7 +8,8 @@
"noUnusedLocals": true,
"lib": [
"es5", "es2015.promise"
- ]
+ ],
+ "strict": true
},
"include": [
"src/**/*"
diff --git a/extensions/json/server/yarn.lock b/extensions/json/server/yarn.lock
index b7fd490aa8..ac7f8a5021 100644
--- a/extensions/json/server/yarn.lock
+++ b/extensions/json/server/yarn.lock
@@ -6,9 +6,11 @@
version "7.0.43"
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c"
-agent-base@~1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-1.0.2.tgz#6890d3fb217004b62b70f8928e0fae5f8952a706"
+agent-base@4, agent-base@^4.1.0:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.1.2.tgz#80fa6cde440f4dcf9af2617cf246099b5d99f0c8"
+ dependencies:
+ es6-promisify "^5.0.0"
debug@2:
version "2.6.9"
@@ -16,77 +18,91 @@ debug@2:
dependencies:
ms "2.0.0"
-extend@3:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
-
-http-proxy-agent@^0.2.6:
- version "0.2.7"
- resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-0.2.7.tgz#e17fda65f0902d952ce7921e62c7ff8862655a5e"
+debug@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
dependencies:
- agent-base "~1.0.1"
- debug "2"
- extend "3"
+ ms "2.0.0"
-https-proxy-agent@^0.3.5:
- version "0.3.6"
- resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-0.3.6.tgz#713fa38e5d353f50eb14a342febe29033ed1619b"
+es6-promise@^4.0.3:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.1.1.tgz#8811e90915d9a0dba36274f0b242dbda78f9c92a"
+
+es6-promisify@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203"
dependencies:
- agent-base "~1.0.1"
- debug "2"
- extend "3"
+ es6-promise "^4.0.3"
-jsonc-parser@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-1.0.0.tgz#ddcc864ae708e60a7a6dd36daea00172fa8d9272"
+http-proxy-agent@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.0.0.tgz#46482a2f0523a4d6082551709f469cb3e4a85ff4"
+ dependencies:
+ agent-base "4"
+ debug "2"
+
+https-proxy-agent@2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.1.1.tgz#a7ce4382a1ba8266ee848578778122d491260fd9"
+ dependencies:
+ agent-base "^4.1.0"
+ debug "^3.1.0"
+
+jsonc-parser@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-1.0.1.tgz#7f8f296414e6e7c4a33b9e4914fc8c47e4421675"
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
-request-light@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.1.tgz#986f5a82893e9d1ca6a896ebe6f46c51c6b4557f"
+request-light@^0.2.2:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/request-light/-/request-light-0.2.2.tgz#53e48af32ad1514e45221ea5ece5ce782720f712"
dependencies:
- http-proxy-agent "^0.2.6"
- https-proxy-agent "^0.3.5"
+ http-proxy-agent "2.0.0"
+ https-proxy-agent "2.1.1"
vscode-nls "^2.0.2"
-vscode-json-languageservice@^3.0.4:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.0.4.tgz#293970ef3179d7793ffd25887acf158d93ff8733"
+vscode-json-languageservice@^3.0.7:
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-3.0.7.tgz#dc00117d51d4a7ac3bde9204afa701f962f00736"
dependencies:
- jsonc-parser "^1.0.0"
- vscode-languageserver-types "^3.5.0"
+ jsonc-parser "^1.0.1"
+ vscode-languageserver-types "^3.6.0-next.1"
vscode-nls "^2.0.2"
vscode-uri "^1.0.1"
-vscode-jsonrpc@^3.5.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0.tgz#87239d9e166b2d7352245b8a813597804c1d63aa"
+vscode-jsonrpc@^3.6.0-next.1:
+ version "3.6.0-next.1"
+ resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.6.0-next.1.tgz#3cb463dffe5842d6aec16718ca9252708cd6aabe"
-vscode-languageserver-protocol@^3.5.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.0.tgz#067c5cbe27709795398d119692c97ebba1452209"
+vscode-languageserver-protocol@^3.6.0-next.3:
+ version "3.6.0-next.4"
+ resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.6.0-next.4.tgz#5b9940e4d6afafd5b63f9731dbd3a9bcc65b3719"
dependencies:
- vscode-jsonrpc "^3.5.0"
- vscode-languageserver-types "^3.5.0"
+ vscode-jsonrpc "^3.6.0-next.1"
+ vscode-languageserver-types "^3.6.0-next.1"
-vscode-languageserver-types@^3.5.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz#e48d79962f0b8e02de955e3f524908e2b19c0374"
+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-languageserver@^3.5.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-3.5.0.tgz#d28099bc6ddda8c1dd16b707e454e1b1ddae0dba"
+vscode-languageserver@4.0.0-next.3:
+ version "4.0.0-next.3"
+ resolved "https://registry.yarnpkg.com/vscode-languageserver/-/vscode-languageserver-4.0.0-next.3.tgz#89a9ce5078e3a86a78e3551c3766194ce4295611"
dependencies:
- vscode-languageserver-protocol "^3.5.0"
+ vscode-languageserver-protocol "^3.6.0-next.3"
vscode-uri "^1.0.1"
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-uri@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-1.0.1.tgz#11a86befeac3c4aa3ec08623651a3c81a6d0bbc8"
diff --git a/extensions/json/syntaxes/JSON.tmLanguage.json b/extensions/json/syntaxes/JSON.tmLanguage.json
index f37355667b..910045be39 100644
--- a/extensions/json/syntaxes/JSON.tmLanguage.json
+++ b/extensions/json/syntaxes/JSON.tmLanguage.json
@@ -5,21 +5,8 @@
"Once accepted there, we are happy to receive an update request."
],
"version": "https://github.com/Microsoft/vscode-JSON.tmLanguage/commit/9bd83f1c252b375e957203f21793316203f61f70",
- "fileTypes": [
- "json",
- "sublime-settings",
- "sublime-menu",
- "sublime-keymap",
- "sublime-mousemap",
- "sublime-theme",
- "sublime-build",
- "sublime-project",
- "sublime-completions"
- ],
- "foldingStartMarker": "(?x) # turn on extended mode\n ^ # a line beginning with\n \\s* # some optional space\n [{\\[] # the start of an object or array\n (?! # but not followed by\n .* # whatever\n [}\\]] # and the close of an object or array\n ,? # an optional comma\n \\s* # some optional space\n $ # at the end of the line\n )\n | # ...or...\n [{\\[] # the start of an object or array\n \\s* # some optional space\n $ # at the end of the line",
- "foldingStopMarker": "(?x) # turn on extended mode\n ^ # a line beginning with\n \\s* # some optional space\n [}\\]] # and the close of an object or array",
- "keyEquivalent": "^~J",
"name": "JSON (Javascript Next)",
+ "scopeName": "source.json",
"patterns": [
{
"include": "#value"
@@ -222,7 +209,5 @@
}
]
}
- },
- "scopeName": "source.json",
- "uuid": "8f97457b-516e-48ce-83c7-08ae12fb327a"
+ }
}
\ No newline at end of file
diff --git a/extensions/json/yarn.lock b/extensions/json/yarn.lock
index 4ebd609217..926601edb2 100644
--- a/extensions/json/yarn.lock
+++ b/extensions/json/yarn.lock
@@ -6,42 +6,59 @@
version "7.0.43"
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.43.tgz#a187e08495a075f200ca946079c914e1a5fe962c"
-applicationinsights@0.18.0:
- version "0.18.0"
- resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-0.18.0.tgz#162ebb48a383408bc4de44db32b417307f45bbc1"
-
-vscode-extension-telemetry@0.0.8:
- version "0.0.8"
- resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.8.tgz#2261bff986b6690a6f1f746a45ac5bd1f85d29e0"
+applicationinsights@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-1.0.1.tgz#53446b830fe8d5d619eee2a278b31d3d25030927"
dependencies:
- applicationinsights "0.18.0"
- winreg "1.2.3"
+ diagnostic-channel "0.2.0"
+ diagnostic-channel-publishers "0.2.1"
+ zone.js "0.7.6"
-vscode-jsonrpc@^3.5.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.5.0.tgz#87239d9e166b2d7352245b8a813597804c1d63aa"
+diagnostic-channel-publishers@0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-0.2.1.tgz#8e2d607a8b6d79fe880b548bc58cc6beb288c4f3"
-vscode-languageclient@^3.5.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-3.5.0.tgz#36d02cc186a8365a4467719a290fb200a9ae490a"
+diagnostic-channel@0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-0.2.0.tgz#cc99af9612c23fb1fff13612c72f2cbfaa8d5a17"
dependencies:
- vscode-languageserver-protocol "^3.5.0"
+ semver "^5.3.0"
-vscode-languageserver-protocol@^3.5.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.5.0.tgz#067c5cbe27709795398d119692c97ebba1452209"
+semver@^5.3.0:
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
+
+vscode-extension-telemetry@0.0.15:
+ version "0.0.15"
+ resolved "https://registry.yarnpkg.com/vscode-extension-telemetry/-/vscode-extension-telemetry-0.0.15.tgz#685c32f3b67e8fb85ba689c1d7f88ff90ff87856"
dependencies:
- vscode-jsonrpc "^3.5.0"
- vscode-languageserver-types "^3.5.0"
+ applicationinsights "1.0.1"
-vscode-languageserver-types@^3.5.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.5.0.tgz#e48d79962f0b8e02de955e3f524908e2b19c0374"
+vscode-jsonrpc@^3.6.0-next.1:
+ version "3.6.0-next.1"
+ resolved "https://registry.yarnpkg.com/vscode-jsonrpc/-/vscode-jsonrpc-3.6.0-next.1.tgz#3cb463dffe5842d6aec16718ca9252708cd6aabe"
-vscode-nls@2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-2.0.2.tgz#808522380844b8ad153499af5c3b03921aea02da"
+vscode-languageclient@4.0.0-next.9:
+ version "4.0.0-next.9"
+ resolved "https://registry.yarnpkg.com/vscode-languageclient/-/vscode-languageclient-4.0.0-next.9.tgz#2a06568f46ee9de3490f85e227d3740a21a03d3a"
+ dependencies:
+ vscode-languageserver-protocol "^3.6.0-next.5"
-winreg@1.2.3:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/winreg/-/winreg-1.2.3.tgz#93ad116b2696da87d58f7265a8fcea5254a965d5"
+vscode-languageserver-protocol@^3.6.0-next.5:
+ version "3.6.0-next.5"
+ resolved "https://registry.yarnpkg.com/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.6.0-next.5.tgz#ed2ec2db759826f753c0a13977dfb2bedc4d31b3"
+ dependencies:
+ vscode-jsonrpc "^3.6.0-next.1"
+ vscode-languageserver-types "^3.6.0-next.1"
+
+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"
+
+zone.js@0.7.6:
+ version "0.7.6"
+ resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.7.6.tgz#fbbc39d3e0261d0986f1ba06306eb3aeb0d22009"
diff --git a/extensions/lib.core.d.ts b/extensions/lib.core.d.ts
deleted file mode 100644
index fb3fe52c13..0000000000
--- a/extensions/lib.core.d.ts
+++ /dev/null
@@ -1,3839 +0,0 @@
-/*! *****************************************************************************
-Copyright (c) Microsoft Corporation. All rights reserved.
-Licensed under the Apache License, Version 2.0 (the "License"); you may not use
-this file except in compliance with the License. You may obtain a copy of the
-License at http://www.apache.org/licenses/LICENSE-2.0
-
-THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
-WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
-MERCHANTABLITY OR NON-INFRINGEMENT.
-
-See the Apache Version 2.0 License for specific language governing permissions
-and limitations under the License.
-***************************************************************************** */
-
-///
-/////////////////////////////
-/// ECMAScript APIs
-/////////////////////////////
-
-declare var NaN: number;
-declare var Infinity: number;
-
-/**
- * Evaluates JavaScript code and executes it.
- * @param x A String value that contains valid JavaScript code.
- */
-declare function eval(x: string): any;
-
-/**
- * Converts A string to an integer.
- * @param s A string to convert into a number.
- * @param radix A value between 2 and 36 that specifies the base of the number in numString.
- * If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal.
- * All other strings are considered decimal.
- */
-declare function parseInt(s: string, radix?: number): number;
-
-/**
- * Converts a string to a floating-point number.
- * @param string A string that contains a floating-point number.
- */
-declare function parseFloat(string: string): number;
-
-/**
- * Returns a Boolean value that indicates whether a value is the reserved value NaN (not a number).
- * @param number A numeric value.
- */
-declare function isNaN(number: number): boolean;
-
-/**
- * Determines whether a supplied number is finite.
- * @param number Any numeric value.
- */
-declare function isFinite(number: number): boolean;
-
-/**
- * Gets the unencoded version of an encoded Uniform Resource Identifier (URI).
- * @param encodedURI A value representing an encoded URI.
- */
-declare function decodeURI(encodedURI: string): string;
-
-/**
- * Gets the unencoded version of an encoded component of a Uniform Resource Identifier (URI).
- * @param encodedURIComponent A value representing an encoded URI component.
- */
-declare function decodeURIComponent(encodedURIComponent: string): string;
-
-/**
- * Encodes a text string as a valid Uniform Resource Identifier (URI)
- * @param uri A value representing an encoded URI.
- */
-declare function encodeURI(uri: string): string;
-
-/**
- * Encodes a text string as a valid component of a Uniform Resource Identifier (URI).
- * @param uriComponent A value representing an encoded URI component.
- */
-declare function encodeURIComponent(uriComponent: string): string;
-
-interface PropertyDescriptor {
- configurable?: boolean;
- enumerable?: boolean;
- value?: any;
- writable?: boolean;
- get? (): any;
- set? (v: any): void;
-}
-
-interface PropertyDescriptorMap {
- [s: string]: PropertyDescriptor;
-}
-
-interface Object {
- /** The initial value of Object.prototype.constructor is the standard built-in Object constructor. */
- constructor: Function;
-
- /** Returns a string representation of an object. */
- toString(): string;
-
- /** Returns a date converted to a string using the current locale. */
- toLocaleString(): string;
-
- /** Returns the primitive value of the specified object. */
- valueOf(): Object;
-
- /**
- * Determines whether an object has a property with the specified name.
- * @param v A property name.
- */
- hasOwnProperty(v: string): boolean;
-
- /**
- * Determines whether an object exists in another object's prototype chain.
- * @param v Another object whose prototype chain is to be checked.
- */
- isPrototypeOf(v: Object): boolean;
-
- /**
- * Determines whether a specified property is enumerable.
- * @param v A property name.
- */
- propertyIsEnumerable(v: string): boolean;
-}
-
-interface ObjectConstructor {
- new (value?: any): Object;
- (): any;
- (value: any): any;
-
- /** A reference to the prototype for a class of objects. */
- prototype: Object;
-
- /**
- * Returns the prototype of an object.
- * @param o The object that references the prototype.
- */
- getPrototypeOf(o: any): any;
-
- /**
- * Gets the own property descriptor of the specified object.
- * An own property descriptor is one that is defined directly on the object and is not inherited from the object's prototype.
- * @param o Object that contains the property.
- * @param p Name of the property.
- */
- getOwnPropertyDescriptor(o: any, p: string): PropertyDescriptor;
-
- /**
- * Returns the names of the own properties of an object. The own properties of an object are those that are defined directly
- * on that object, and are not inherited from the object's prototype. The properties of an object include both fields (objects) and functions.
- * @param o Object that contains the own properties.
- */
- getOwnPropertyNames(o: any): string[];
-
- /**
- * Creates an object that has the specified prototype, and that optionally contains specified properties.
- * @param o Object to use as a prototype. May be null
- * @param properties JavaScript object that contains one or more property descriptors.
- */
- create(o: any, properties?: PropertyDescriptorMap): any;
-
- /**
- * Adds a property to an object, or modifies attributes of an existing property.
- * @param o Object on which to add or modify the property. This can be a native JavaScript object (that is, a user-defined object or a built in object) or a DOM object.
- * @param p The property name.
- * @param attributes Descriptor for the property. It can be for a data property or an accessor property.
- */
- defineProperty(o: any, p: string, attributes: PropertyDescriptor): any;
-
- /**
- * Adds one or more properties to an object, and/or modifies attributes of existing properties.
- * @param o Object on which to add or modify the properties. This can be a native JavaScript object or a DOM object.
- * @param properties JavaScript object that contains one or more descriptor objects. Each descriptor object describes a data property or an accessor property.
- */
- defineProperties(o: any, properties: PropertyDescriptorMap): any;
-
- /**
- * Prevents the modification of attributes of existing properties, and prevents the addition of new properties.
- * @param o Object on which to lock the attributes.
- */
- seal(o: T): T;
-
- /**
- * Prevents the modification of existing property attributes and values, and prevents the addition of new properties.
- * @param o Object on which to lock the attributes.
- */
- freeze(o: T): T;
-
- /**
- * Prevents the addition of new properties to an object.
- * @param o Object to make non-extensible.
- */
- preventExtensions(o: T): T;
-
- /**
- * Returns true if existing property attributes cannot be modified in an object and new properties cannot be added to the object.
- * @param o Object to test.
- */
- isSealed(o: any): boolean;
-
- /**
- * Returns true if existing property attributes and values cannot be modified in an object, and new properties cannot be added to the object.
- * @param o Object to test.
- */
- isFrozen(o: any): boolean;
-
- /**
- * Returns a value that indicates whether new properties can be added to an object.
- * @param o Object to test.
- */
- isExtensible(o: any): boolean;
-
- /**
- * Returns the names of the enumerable properties and methods of an object.
- * @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
- */
- keys(o: any): string[];
-}
-
-/**
- * Provides functionality common to all JavaScript objects.
- */
-declare var Object: ObjectConstructor;
-
-/**
- * Creates a new function.
- */
-interface Function {
- /**
- * Calls the function, substituting the specified object for the this value of the function, and the specified array for the arguments of the function.
- * @param thisArg The object to be used as the this object.
- * @param argArray A set of arguments to be passed to the function.
- */
- apply(thisArg: any, argArray?: any): any;
-
- /**
- * Calls a method of an object, substituting another object for the current object.
- * @param thisArg The object to be used as the current object.
- * @param argArray A list of arguments to be passed to the method.
- */
- call(thisArg: any, ...argArray: any[]): any;
-
- /**
- * For a given function, creates a bound function that has the same body as the original function.
- * The this object of the bound function is associated with the specified object, and has the specified initial parameters.
- * @param thisArg An object to which the this keyword can refer inside the new function.
- * @param argArray A list of arguments to be passed to the new function.
- */
- bind(thisArg: any, ...argArray: any[]): any;
-
- prototype: any;
- length: number;
-
- // Non-standard extensions
- arguments: any;
- caller: Function;
-}
-
-interface FunctionConstructor {
- /**
- * Creates a new function.
- * @param args A list of arguments the function accepts.
- */
- new (...args: string[]): Function;
- (...args: string[]): Function;
- prototype: Function;
-}
-
-declare var Function: FunctionConstructor;
-
-interface IArguments {
- [index: number]: any;
- length: number;
- callee: Function;
-}
-
-interface String {
- /** Returns a string representation of a string. */
- toString(): string;
-
- /**
- * Returns the character at the specified index.
- * @param pos The zero-based index of the desired character.
- */
- charAt(pos: number): string;
-
- /**
- * Returns the Unicode value of the character at the specified location.
- * @param index The zero-based index of the desired character. If there is no character at the specified index, NaN is returned.
- */
- charCodeAt(index: number): number;
-
- /**
- * Returns a string that contains the concatenation of two or more strings.
- * @param strings The strings to append to the end of the string.
- */
- concat(...strings: string[]): string;
-
- /**
- * Returns the position of the first occurrence of a substring.
- * @param searchString The substring to search for in the string
- * @param position The index at which to begin searching the String object. If omitted, search starts at the beginning of the string.
- */
- indexOf(searchString: string, position?: number): number;
-
- /**
- * Returns the last occurrence of a substring in the string.
- * @param searchString The substring to search for.
- * @param position The index at which to begin searching. If omitted, the search begins at the end of the string.
- */
- lastIndexOf(searchString: string, position?: number): number;
-
- /**
- * Determines whether two strings are equivalent in the current locale.
- * @param that String to compare to target string
- */
- localeCompare(that: string): number;
-
- /**
- * Matches a string with a regular expression, and returns an array containing the results of that search.
- * @param regexp A variable name or string literal containing the regular expression pattern and flags.
- */
- match(regexp: string): RegExpMatchArray;
-
- /**
- * Matches a string with a regular expression, and returns an array containing the results of that search.
- * @param regexp A regular expression object that contains the regular expression pattern and applicable flags.
- */
- match(regexp: RegExp): RegExpMatchArray;
-
- /**
- * Replaces text in a string, using a regular expression or search string.
- * @param searchValue A string that represents the regular expression.
- * @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.
- */
- replace(searchValue: string, replaceValue: string): string;
-
- /**
- * Replaces text in a string, using a regular expression or search string.
- * @param searchValue A string that represents the regular expression.
- * @param replacer A function that returns the replacement text.
- */
- replace(searchValue: string, replacer: (substring: string, ...args: any[]) => string): string;
-
- /**
- * Replaces text in a string, using a regular expression or search string.
- * @param searchValue A Regular Expression object containing the regular expression pattern and applicable flags.
- * @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.
- */
- replace(searchValue: RegExp, replaceValue: string): string;
-
- /**
- * Replaces text in a string, using a regular expression or search string.
- * @param searchValue A Regular Expression object containing the regular expression pattern and applicable flags
- * @param replacer A function that returns the replacement text.
- */
- replace(searchValue: RegExp, replacer: (substring: string, ...args: any[]) => string): string;
-
- /**
- * Finds the first substring match in a regular expression search.
- * @param regexp The regular expression pattern and applicable flags.
- */
- search(regexp: string): number;
-
- /**
- * Finds the first substring match in a regular expression search.
- * @param regexp The regular expression pattern and applicable flags.
- */
- search(regexp: RegExp): number;
-
- /**
- * Returns a section of a string.
- * @param start The index to the beginning of the specified portion of stringObj.
- * @param end The index to the end of the specified portion of stringObj. The substring includes the characters up to, but not including, the character indicated by end.
- * If this value is not specified, the substring continues to the end of stringObj.
- */
- slice(start?: number, end?: number): string;
-
- /**
- * Split a string into substrings using the specified separator and return them as an array.
- * @param separator A string that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned.
- * @param limit A value used to limit the number of elements returned in the array.
- */
- split(separator: string, limit?: number): string[];
-
- /**
- * Split a string into substrings using the specified separator and return them as an array.
- * @param separator A Regular Express that identifies character or characters to use in separating the string. If omitted, a single-element array containing the entire string is returned.
- * @param limit A value used to limit the number of elements returned in the array.
- */
- split(separator: RegExp, limit?: number): string[];
-
- /**
- * Returns the substring at the specified location within a String object.
- * @param start The zero-based index number indicating the beginning of the substring.
- * @param end Zero-based index number indicating the end of the substring. The substring includes the characters up to, but not including, the character indicated by end.
- * If end is omitted, the characters from start through the end of the original string are returned.
- */
- substring(start: number, end?: number): string;
-
- /** Converts all the alphabetic characters in a string to lowercase. */
- toLowerCase(): string;
-
- /** Converts all alphabetic characters to lowercase, taking into account the host environment's current locale. */
- toLocaleLowerCase(): string;
-
- /** Converts all the alphabetic characters in a string to uppercase. */
- toUpperCase(): string;
-
- /** Returns a string where all alphabetic characters have been converted to uppercase, taking into account the host environment's current locale. */
- toLocaleUpperCase(): string;
-
- /** Removes the leading and trailing white space and line terminator characters from a string. */
- trim(): string;
-
- /** Returns the length of a String object. */
- length: number;
-
- // IE extensions
- /**
- * Gets a substring beginning at the specified location and having the specified length.
- * @param from The starting position of the desired substring. The index of the first character in the string is zero.
- * @param length The number of characters to include in the returned substring.
- */
- substr(from: number, length?: number): string;
-
- /** Returns the primitive value of the specified object. */
- valueOf(): string;
-
- [index: number]: string;
-}
-
-interface StringConstructor {
- new (value?: any): String;
- (value?: any): string;
- prototype: String;
- fromCharCode(...codes: number[]): string;
-}
-
-/**
- * Allows manipulation and formatting of text strings and determination and location of substrings within strings.
- */
-declare var String: StringConstructor;
-
-interface Boolean {
- /** Returns the primitive value of the specified object. */
- valueOf(): boolean;
-}
-
-interface BooleanConstructor {
- new (value?: any): Boolean;
- (value?: any): boolean;
- prototype: Boolean;
-}
-
-declare var Boolean: BooleanConstructor;
-
-interface Number {
- /**
- * Returns a string representation of an object.
- * @param radix Specifies a radix for converting numeric values to strings. This value is only used for numbers.
- */
- toString(radix?: number): string;
-
- /**
- * Returns a string representing a number in fixed-point notation.
- * @param fractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.
- */
- toFixed(fractionDigits?: number): string;
-
- /**
- * Returns a string containing a number represented in exponential notation.
- * @param fractionDigits Number of digits after the decimal point. Must be in the range 0 - 20, inclusive.
- */
- toExponential(fractionDigits?: number): string;
-
- /**
- * Returns a string containing a number represented either in exponential or fixed-point notation with a specified number of digits.
- * @param precision Number of significant digits. Must be in the range 1 - 21, inclusive.
- */
- toPrecision(precision?: number): string;
-
- /** Returns the primitive value of the specified object. */
- valueOf(): number;
-}
-
-interface NumberConstructor {
- new (value?: any): Number;
- (value?: any): number;
- prototype: Number;
-
- /** The largest number that can be represented in JavaScript. Equal to approximately 1.79E+308. */
- MAX_VALUE: number;
-
- /** The closest number to zero that can be represented in JavaScript. Equal to approximately 5.00E-324. */
- MIN_VALUE: number;
-
- /**
- * A value that is not a number.
- * In equality comparisons, NaN does not equal any value, including itself. To test whether a value is equivalent to NaN, use the isNaN function.
- */
- NaN: number;
-
- /**
- * A value that is less than the largest negative number that can be represented in JavaScript.
- * JavaScript displays NEGATIVE_INFINITY values as -infinity.
- */
- NEGATIVE_INFINITY: number;
-
- /**
- * A value greater than the largest number that can be represented in JavaScript.
- * JavaScript displays POSITIVE_INFINITY values as infinity.
- */
- POSITIVE_INFINITY: number;
-}
-
-/** An object that represents a number of any kind. All JavaScript numbers are 64-bit floating-point numbers. */
-declare var Number: NumberConstructor;
-
-interface TemplateStringsArray extends Array {
- raw: string[];
-}
-
-interface Math {
- /** The mathematical constant e. This is Euler's number, the base of natural logarithms. */
- E: number;
- /** The natural logarithm of 10. */
- LN10: number;
- /** The natural logarithm of 2. */
- LN2: number;
- /** The base-2 logarithm of e. */
- LOG2E: number;
- /** The base-10 logarithm of e. */
- LOG10E: number;
- /** Pi. This is the ratio of the circumference of a circle to its diameter. */
- PI: number;
- /** The square root of 0.5, or, equivalently, one divided by the square root of 2. */
- SQRT1_2: number;
- /** The square root of 2. */
- SQRT2: number;
- /**
- * Returns the absolute value of a number (the value without regard to whether it is positive or negative).
- * For example, the absolute value of -5 is the same as the absolute value of 5.
- * @param x A numeric expression for which the absolute value is needed.
- */
- abs(x: number): number;
- /**
- * Returns the arc cosine (or inverse cosine) of a number.
- * @param x A numeric expression.
- */
- acos(x: number): number;
- /**
- * Returns the arcsine of a number.
- * @param x A numeric expression.
- */
- asin(x: number): number;
- /**
- * Returns the arctangent of a number.
- * @param x A numeric expression for which the arctangent is needed.
- */
- atan(x: number): number;
- /**
- * Returns the angle (in radians) from the X axis to a point.
- * @param y A numeric expression representing the cartesian y-coordinate.
- * @param x A numeric expression representing the cartesian x-coordinate.
- */
- atan2(y: number, x: number): number;
- /**
- * Returns the smallest number greater than or equal to its numeric argument.
- * @param x A numeric expression.
- */
- ceil(x: number): number;
- /**
- * Returns the cosine of a number.
- * @param x A numeric expression that contains an angle measured in radians.
- */
- cos(x: number): number;
- /**
- * Returns e (the base of natural logarithms) raised to a power.
- * @param x A numeric expression representing the power of e.
- */
- exp(x: number): number;
- /**
- * Returns the greatest number less than or equal to its numeric argument.
- * @param x A numeric expression.
- */
- floor(x: number): number;
- /**
- * Returns the natural logarithm (base e) of a number.
- * @param x A numeric expression.
- */
- log(x: number): number;
- /**
- * Returns the larger of a set of supplied numeric expressions.
- * @param values Numeric expressions to be evaluated.
- */
- max(...values: number[]): number;
- /**
- * Returns the smaller of a set of supplied numeric expressions.
- * @param values Numeric expressions to be evaluated.
- */
- min(...values: number[]): number;
- /**
- * Returns the value of a base expression taken to a specified power.
- * @param x The base value of the expression.
- * @param y The exponent value of the expression.
- */
- pow(x: number, y: number): number;
- /** Returns a pseudorandom number between 0 and 1. */
- random(): number;
- /**
- * Returns a supplied numeric expression rounded to the nearest number.
- * @param x The value to be rounded to the nearest number.
- */
- round(x: number): number;
- /**
- * Returns the sine of a number.
- * @param x A numeric expression that contains an angle measured in radians.
- */
- sin(x: number): number;
- /**
- * Returns the square root of a number.
- * @param x A numeric expression.
- */
- sqrt(x: number): number;
- /**
- * Returns the tangent of a number.
- * @param x A numeric expression that contains an angle measured in radians.
- */
- tan(x: number): number;
-}
-/** An intrinsic object that provides basic mathematics functionality and constants. */
-declare var Math: Math;
-
-/** Enables basic storage and retrieval of dates and times. */
-interface Date {
- /** Returns a string representation of a date. The format of the string depends on the locale. */
- toString(): string;
- /** Returns a date as a string value. */
- toDateString(): string;
- /** Returns a time as a string value. */
- toTimeString(): string;
- /** Returns a value as a string value appropriate to the host environment's current locale. */
- toLocaleString(): string;
- /** Returns a date as a string value appropriate to the host environment's current locale. */
- toLocaleDateString(): string;
- /** Returns a time as a string value appropriate to the host environment's current locale. */
- toLocaleTimeString(): string;
- /** Returns the stored time value in milliseconds since midnight, January 1, 1970 UTC. */
- valueOf(): number;
- /** Gets the time value in milliseconds. */
- getTime(): number;
- /** Gets the year, using local time. */
- getFullYear(): number;
- /** Gets the year using Universal Coordinated Time (UTC). */
- getUTCFullYear(): number;
- /** Gets the month, using local time. */
- getMonth(): number;
- /** Gets the month of a Date object using Universal Coordinated Time (UTC). */
- getUTCMonth(): number;
- /** Gets the day-of-the-month, using local time. */
- getDate(): number;
- /** Gets the day-of-the-month, using Universal Coordinated Time (UTC). */
- getUTCDate(): number;
- /** Gets the day of the week, using local time. */
- getDay(): number;
- /** Gets the day of the week using Universal Coordinated Time (UTC). */
- getUTCDay(): number;
- /** Gets the hours in a date, using local time. */
- getHours(): number;
- /** Gets the hours value in a Date object using Universal Coordinated Time (UTC). */
- getUTCHours(): number;
- /** Gets the minutes of a Date object, using local time. */
- getMinutes(): number;
- /** Gets the minutes of a Date object using Universal Coordinated Time (UTC). */
- getUTCMinutes(): number;
- /** Gets the seconds of a Date object, using local time. */
- getSeconds(): number;
- /** Gets the seconds of a Date object using Universal Coordinated Time (UTC). */
- getUTCSeconds(): number;
- /** Gets the milliseconds of a Date, using local time. */
- getMilliseconds(): number;
- /** Gets the milliseconds of a Date object using Universal Coordinated Time (UTC). */
- getUTCMilliseconds(): number;
- /** Gets the difference in minutes between the time on the local computer and Universal Coordinated Time (UTC). */
- getTimezoneOffset(): number;
- /**
- * Sets the date and time value in the Date object.
- * @param time A numeric value representing the number of elapsed milliseconds since midnight, January 1, 1970 GMT.
- */
- setTime(time: number): number;
- /**
- * Sets the milliseconds value in the Date object using local time.
- * @param ms A numeric value equal to the millisecond value.
- */
- setMilliseconds(ms: number): number;
- /**
- * Sets the milliseconds value in the Date object using Universal Coordinated Time (UTC).
- * @param ms A numeric value equal to the millisecond value.
- */
- setUTCMilliseconds(ms: number): number;
-
- /**
- * Sets the seconds value in the Date object using local time.
- * @param sec A numeric value equal to the seconds value.
- * @param ms A numeric value equal to the milliseconds value.
- */
- setSeconds(sec: number, ms?: number): number;
- /**
- * Sets the seconds value in the Date object using Universal Coordinated Time (UTC).
- * @param sec A numeric value equal to the seconds value.
- * @param ms A numeric value equal to the milliseconds value.
- */
- setUTCSeconds(sec: number, ms?: number): number;
- /**
- * Sets the minutes value in the Date object using local time.
- * @param min A numeric value equal to the minutes value.
- * @param sec A numeric value equal to the seconds value.
- * @param ms A numeric value equal to the milliseconds value.
- */
- setMinutes(min: number, sec?: number, ms?: number): number;
- /**
- * Sets the minutes value in the Date object using Universal Coordinated Time (UTC).
- * @param min A numeric value equal to the minutes value.
- * @param sec A numeric value equal to the seconds value.
- * @param ms A numeric value equal to the milliseconds value.
- */
- setUTCMinutes(min: number, sec?: number, ms?: number): number;
- /**
- * Sets the hour value in the Date object using local time.
- * @param hours A numeric value equal to the hours value.
- * @param min A numeric value equal to the minutes value.
- * @param sec A numeric value equal to the seconds value.
- * @param ms A numeric value equal to the milliseconds value.
- */
- setHours(hours: number, min?: number, sec?: number, ms?: number): number;
- /**
- * Sets the hours value in the Date object using Universal Coordinated Time (UTC).
- * @param hours A numeric value equal to the hours value.
- * @param min A numeric value equal to the minutes value.
- * @param sec A numeric value equal to the seconds value.
- * @param ms A numeric value equal to the milliseconds value.
- */
- setUTCHours(hours: number, min?: number, sec?: number, ms?: number): number;
- /**
- * Sets the numeric day-of-the-month value of the Date object using local time.
- * @param date A numeric value equal to the day of the month.
- */
- setDate(date: number): number;
- /**
- * Sets the numeric day of the month in the Date object using Universal Coordinated Time (UTC).
- * @param date A numeric value equal to the day of the month.
- */
- setUTCDate(date: number): number;
- /**
- * Sets the month value in the Date object using local time.
- * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively.
- * @param date A numeric value representing the day of the month. If this value is not supplied, the value from a call to the getDate method is used.
- */
- setMonth(month: number, date?: number): number;
- /**
- * Sets the month value in the Date object using Universal Coordinated Time (UTC).
- * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively.
- * @param date A numeric value representing the day of the month. If it is not supplied, the value from a call to the getUTCDate method is used.
- */
- setUTCMonth(month: number, date?: number): number;
- /**
- * Sets the year of the Date object using local time.
- * @param year A numeric value for the year.
- * @param month A zero-based numeric value for the month (0 for January, 11 for December). Must be specified if numDate is specified.
- * @param date A numeric value equal for the day of the month.
- */
- setFullYear(year: number, month?: number, date?: number): number;
- /**
- * Sets the year value in the Date object using Universal Coordinated Time (UTC).
- * @param year A numeric value equal to the year.
- * @param month A numeric value equal to the month. The value for January is 0, and other month values follow consecutively. Must be supplied if numDate is supplied.
- * @param date A numeric value equal to the day of the month.
- */
- setUTCFullYear(year: number, month?: number, date?: number): number;
- /** Returns a date converted to a string using Universal Coordinated Time (UTC). */
- toUTCString(): string;
- /** Returns a date as a string value in ISO format. */
- toISOString(): string;
- /** Used by the JSON.stringify method to enable the transformation of an object's data for JavaScript Object Notation (JSON) serialization. */
- toJSON(key?: any): string;
-}
-
-interface DateConstructor {
- new (): Date;
- new (value: number): Date;
- new (value: string): Date;
- new (year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): Date;
- (): string;
- prototype: Date;
- /**
- * Parses a string containing a date, and returns the number of milliseconds between that date and midnight, January 1, 1970.
- * @param s A date string
- */
- parse(s: string): number;
- /**
- * Returns the number of milliseconds between midnight, January 1, 1970 Universal Coordinated Time (UTC) (or GMT) and the specified date.
- * @param year The full year designation is required for cross-century date accuracy. If year is between 0 and 99 is used, then year is assumed to be 1900 + year.
- * @param month The month as an number between 0 and 11 (January to December).
- * @param date The date as an number between 1 and 31.
- * @param hours Must be supplied if minutes is supplied. An number from 0 to 23 (midnight to 11pm) that specifies the hour.
- * @param minutes Must be supplied if seconds is supplied. An number from 0 to 59 that specifies the minutes.
- * @param seconds Must be supplied if milliseconds is supplied. An number from 0 to 59 that specifies the seconds.
- * @param ms An number from 0 to 999 that specifies the milliseconds.
- */
- UTC(year: number, month: number, date?: number, hours?: number, minutes?: number, seconds?: number, ms?: number): number;
- now(): number;
-}
-
-declare var Date: DateConstructor;
-
-interface RegExpMatchArray extends Array {
- index?: number;
- input?: string;
-}
-
-interface RegExpExecArray extends Array {
- index: number;
- input: string;
-}
-
-interface RegExp {
- /**
- * Executes a search on a string using a regular expression pattern, and returns an array containing the results of that search.
- * @param string The String object or string literal on which to perform the search.
- */
- exec(string: string): RegExpExecArray;
-
- /**
- * Returns a Boolean value that indicates whether or not a pattern exists in a searched string.
- * @param string String on which to perform the search.
- */
- test(string: string): boolean;
-
- /** Returns a copy of the text of the regular expression pattern. Read-only. The regExp argument is a Regular expression object. It can be a variable name or a literal. */
- source: string;
-
- /** Returns a Boolean value indicating the state of the global flag (g) used with a regular expression. Default is false. Read-only. */
- global: boolean;
-
- /** Returns a Boolean value indicating the state of the ignoreCase flag (i) used with a regular expression. Default is false. Read-only. */
- ignoreCase: boolean;
-
- /** Returns a Boolean value indicating the state of the multiline flag (m) used with a regular expression. Default is false. Read-only. */
- multiline: boolean;
-
- lastIndex: number;
-
- // Non-standard extensions
- compile(): RegExp;
-}
-
-interface RegExpConstructor {
- new (pattern: string, flags?: string): RegExp;
- (pattern: string, flags?: string): RegExp;
- prototype: RegExp;
-
- // Non-standard extensions
- $1: string;
- $2: string;
- $3: string;
- $4: string;
- $5: string;
- $6: string;
- $7: string;
- $8: string;
- $9: string;
- lastMatch: string;
-}
-
-declare var RegExp: RegExpConstructor;
-
-interface Error {
- name: string;
- message: string;
-}
-
-interface ErrorConstructor {
- new (message?: string): Error;
- (message?: string): Error;
- prototype: Error;
-}
-
-declare var Error: ErrorConstructor;
-
-interface EvalError extends Error {
-}
-
-interface EvalErrorConstructor {
- new (message?: string): EvalError;
- (message?: string): EvalError;
- prototype: EvalError;
-}
-
-declare var EvalError: EvalErrorConstructor;
-
-interface RangeError extends Error {
-}
-
-interface RangeErrorConstructor {
- new (message?: string): RangeError;
- (message?: string): RangeError;
- prototype: RangeError;
-}
-
-declare var RangeError: RangeErrorConstructor;
-
-interface ReferenceError extends Error {
-}
-
-interface ReferenceErrorConstructor {
- new (message?: string): ReferenceError;
- (message?: string): ReferenceError;
- prototype: ReferenceError;
-}
-
-declare var ReferenceError: ReferenceErrorConstructor;
-
-interface SyntaxError extends Error {
-}
-
-interface SyntaxErrorConstructor {
- new (message?: string): SyntaxError;
- (message?: string): SyntaxError;
- prototype: SyntaxError;
-}
-
-declare var SyntaxError: SyntaxErrorConstructor;
-
-interface TypeError extends Error {
-}
-
-interface TypeErrorConstructor {
- new (message?: string): TypeError;
- (message?: string): TypeError;
- prototype: TypeError;
-}
-
-declare var TypeError: TypeErrorConstructor;
-
-interface URIError extends Error {
-}
-
-interface URIErrorConstructor {
- new (message?: string): URIError;
- (message?: string): URIError;
- prototype: URIError;
-}
-
-declare var URIError: URIErrorConstructor;
-
-interface JSON {
- /**
- * Converts a JavaScript Object Notation (JSON) string into an object.
- * @param text A valid JSON string.
- * @param reviver A function that transforms the results. This function is called for each member of the object.
- * If a member contains nested objects, the nested objects are transformed before the parent object is.
- */
- parse(text: string, reviver?: (key: any, value: any) => any): any;
- /**
- * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
- * @param value A JavaScript value, usually an object or array, to be converted.
- */
- stringify(value: any): string;
- /**
- * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
- * @param value A JavaScript value, usually an object or array, to be converted.
- * @param replacer A function that transforms the results.
- */
- stringify(value: any, replacer: (key: string, value: any) => any): string;
- /**
- * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
- * @param value A JavaScript value, usually an object or array, to be converted.
- * @param replacer Array that transforms the results.
- */
- stringify(value: any, replacer: any[]): string;
- /**
- * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
- * @param value A JavaScript value, usually an object or array, to be converted.
- * @param replacer A function that transforms the results.
- * @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
- */
- stringify(value: any, replacer: (key: string, value: any) => any, space: string | number): string;
- /**
- * Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
- * @param value A JavaScript value, usually an object or array, to be converted.
- * @param replacer Array that transforms the results.
- * @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
- */
- stringify(value: any, replacer: any[], space: string | number): string;
-}
-/**
- * An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.
- */
-declare var JSON: JSON;
-
-
-/////////////////////////////
-/// ECMAScript Array API (specially handled by compiler)
-/////////////////////////////
-
-interface Array {
- /**
- * Gets or sets the length of the array. This is a number one higher than the highest element defined in an array.
- */
- length: number;
- /**
- * Returns a string representation of an array.
- */
- toString(): string;
- toLocaleString(): string;
- /**
- * Appends new elements to an array, and returns the new length of the array.
- * @param items New elements of the Array.
- */
- push(...items: T[]): number;
- /**
- * Removes the last element from an array and returns it.
- */
- pop(): T;
- /**
- * Combines two or more arrays.
- * @param items Additional items to add to the end of array1.
- */
- concat(...items: U[]): T[];
- /**
- * Combines two or more arrays.
- * @param items Additional items to add to the end of array1.
- */
- concat(...items: T[]): T[];
- /**
- * Adds all the elements of an array separated by the specified separator string.
- * @param separator A string used to separate one element of an array from the next in the resulting String. If omitted, the array elements are separated with a comma.
- */
- join(separator?: string): string;
- /**
- * Reverses the elements in an Array.
- */
- reverse(): T[];
- /**
- * Removes the first element from an array and returns it.
- */
- shift(): T;
- /**
- * Returns a section of an array.
- * @param start The beginning of the specified portion of the array.
- * @param end The end of the specified portion of the array.
- */
- slice(start?: number, end?: number): T[];
-
- /**
- * Sorts an array.
- * @param compareFn The name of the function used to determine the order of the elements. If omitted, the elements are sorted in ascending, ASCII character order.
- */
- sort(compareFn?: (a: T, b: T) => number): T[];
-
- /**
- * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
- * @param start The zero-based location in the array from which to start removing elements.
- */
- splice(start: number): T[];
-
- /**
- * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
- * @param start The zero-based location in the array from which to start removing elements.
- * @param deleteCount The number of elements to remove.
- * @param items Elements to insert into the array in place of the deleted elements.
- */
- splice(start: number, deleteCount: number, ...items: T[]): T[];
-
- /**
- * Inserts new elements at the start of an array.
- * @param items Elements to insert at the start of the Array.
- */
- unshift(...items: T[]): number;
-
- /**
- * Returns the index of the first occurrence of a value in an array.
- * @param searchElement The value to locate in the array.
- * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.
- */
- indexOf(searchElement: T, fromIndex?: number): number;
-
- /**
- * Returns the index of the last occurrence of a specified value in an array.
- * @param searchElement The value to locate in the array.
- * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at the last index in the array.
- */
- lastIndexOf(searchElement: T, fromIndex?: number): number;
-
- /**
- * Determines whether all the members of an array satisfy the specified test.
- * @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
- */
- every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean;
-
- /**
- * Determines whether the specified callback function returns true for any element of an array.
- * @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
- */
- some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean;
-
- /**
- * Performs the specified action for each element in an array.
- * @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
- */
- forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void;
-
- /**
- * Calls a defined callback function on each element of an array, and returns an array that contains the results.
- * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
- */
- map(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
-
- /**
- * Returns the elements of an array that meet the condition specified in a callback function.
- * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
- */
- filter(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): T[];
-
- /**
- * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
- * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
- * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
- */
- reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T;
- /**
- * Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
- * @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
- * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
- */
- reduce(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;
-
- /**
- * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
- * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
- * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
- */
- reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T;
- /**
- * Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
- * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
- * @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
- */
- reduceRight(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U;
-
- [n: number]: T;
-}
-
-interface ArrayConstructor {
- new (arrayLength?: number): any[];
- new (arrayLength: number): T[];
- new (...items: T[]): T[];
- (arrayLength?: number): any[];
- (arrayLength: number): T[];
- (...items: T[]): T[];
- isArray(arg: any): arg is Array;
- prototype: Array;
-}
-
-declare var Array: ArrayConstructor;
-
-interface TypedPropertyDescriptor {
- enumerable?: boolean;
- configurable?: boolean;
- writable?: boolean;
- value?: T;
- get?: () => T;
- set?: (value: T) => void;
-}
-
-declare type ClassDecorator = (target: TFunction) => TFunction | void;
-declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;
-declare type MethodDecorator = (target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor) => TypedPropertyDescriptor | void;
-declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
-
-declare type PromiseConstructorLike = new (executor: (resolve: (value?: T | PromiseLike) => void, reject: (reason?: any) => void) => void) => PromiseLike;
-
-interface PromiseLike {
- /**
- * Attaches callbacks for the resolution and/or rejection of the Promise.
- * @param onfulfilled The callback to execute when the Promise is resolved.
- * @param onrejected The callback to execute when the Promise is rejected.
- * @returns A Promise for the completion of which ever callback is executed.
- */
- then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => TResult | PromiseLike): PromiseLike;
- then(onfulfilled?: (value: T) => TResult | PromiseLike, onrejected?: (reason: any) => void): PromiseLike;
-}
-
-interface ArrayLike {
- length: number;
- [n: number]: T;
-}
-
-
-/**
- * Represents a raw buffer of binary data, which is used to store data for the
- * different typed arrays. ArrayBuffers cannot be read from or written to directly,
- * but can be passed to a typed array or DataView Object to interpret the raw
- * buffer as needed.
- */
-interface ArrayBuffer {
- /**
- * Read-only. The length of the ArrayBuffer (in bytes).
- */
- byteLength: number;
-
- /**
- * Returns a section of an ArrayBuffer.
- */
- slice(begin:number, end?:number): ArrayBuffer;
-}
-
-interface ArrayBufferConstructor {
- prototype: ArrayBuffer;
- new (byteLength: number): ArrayBuffer;
- isView(arg: any): arg is ArrayBufferView;
-}
-declare var ArrayBuffer: ArrayBufferConstructor;
-
-interface ArrayBufferView {
- /**
- * The ArrayBuffer instance referenced by the array.
- */
- buffer: ArrayBuffer;
-
- /**
- * The length in bytes of the array.
- */
- byteLength: number;
-
- /**
- * The offset in bytes of the array.
- */
- byteOffset: number;
-}
-
-interface DataView {
- buffer: ArrayBuffer;
- byteLength: number;
- byteOffset: number;
- /**
- * Gets the Float32 value at the specified byte offset from the start of the view. There is
- * no alignment constraint; multi-byte values may be fetched from any offset.
- * @param byteOffset The place in the buffer at which the value should be retrieved.
- */
- getFloat32(byteOffset: number, littleEndian?: boolean): number;
-
- /**
- * Gets the Float64 value at the specified byte offset from the start of the view. There is
- * no alignment constraint; multi-byte values may be fetched from any offset.
- * @param byteOffset The place in the buffer at which the value should be retrieved.
- */
- getFloat64(byteOffset: number, littleEndian?: boolean): number;
-
- /**
- * Gets the Int8 value at the specified byte offset from the start of the view. There is
- * no alignment constraint; multi-byte values may be fetched from any offset.
- * @param byteOffset The place in the buffer at which the value should be retrieved.
- */
- getInt8(byteOffset: number): number;
-
- /**
- * Gets the Int16 value at the specified byte offset from the start of the view. There is
- * no alignment constraint; multi-byte values may be fetched from any offset.
- * @param byteOffset The place in the buffer at which the value should be retrieved.
- */
- getInt16(byteOffset: number, littleEndian?: boolean): number;
- /**
- * Gets the Int32 value at the specified byte offset from the start of the view. There is
- * no alignment constraint; multi-byte values may be fetched from any offset.
- * @param byteOffset The place in the buffer at which the value should be retrieved.
- */
- getInt32(byteOffset: number, littleEndian?: boolean): number;
-
- /**
- * Gets the Uint8 value at the specified byte offset from the start of the view. There is
- * no alignment constraint; multi-byte values may be fetched from any offset.
- * @param byteOffset The place in the buffer at which the value should be retrieved.
- */
- getUint8(byteOffset: number): number;
-
- /**
- * Gets the Uint16 value at the specified byte offset from the start of the view. There is
- * no alignment constraint; multi-byte values may be fetched from any offset.
- * @param byteOffset The place in the buffer at which the value should be retrieved.
- */
- getUint16(byteOffset: number, littleEndian?: boolean): number;
-
- /**
- * Gets the Uint32 value at the specified byte offset from the start of the view. There is
- * no alignment constraint; multi-byte values may be fetched from any offset.
- * @param byteOffset The place in the buffer at which the value should be retrieved.
- */
- getUint32(byteOffset: number, littleEndian?: boolean): number;
-
- /**
- * Stores an Float32 value at the specified byte offset from the start of the view.
- * @param byteOffset The place in the buffer at which the value should be set.
- * @param value The value to set.
- * @param littleEndian If false or undefined, a big-endian value should be written,
- * otherwise a little-endian value should be written.
- */
- setFloat32(byteOffset: number, value: number, littleEndian?: boolean): void;
-
- /**
- * Stores an Float64 value at the specified byte offset from the start of the view.
- * @param byteOffset The place in the buffer at which the value should be set.
- * @param value The value to set.
- * @param littleEndian If false or undefined, a big-endian value should be written,
- * otherwise a little-endian value should be written.
- */
- setFloat64(byteOffset: number, value: number, littleEndian?: boolean): void;
-
- /**
- * Stores an Int8 value at the specified byte offset from the start of the view.
- * @param byteOffset The place in the buffer at which the value should be set.
- * @param value The value to set.
- */
- setInt8(byteOffset: number, value: number): void;
-
- /**
- * Stores an Int16 value at the specified byte offset from the start of the view.
- * @param byteOffset The place in the buffer at which the value should be set.
- * @param value The value to set.
- * @param littleEndian If false or undefined, a big-endian value should be written,
- * otherwise a little-endian value should be written.
- */
- setInt16(byteOffset: number, value: number, littleEndian?: boolean): void;
-
- /**
- * Stores an Int32 value at the specified byte offset from the start of the view.
- * @param byteOffset The place in the buffer at which the value should be set.
- * @param value The value to set.
- * @param littleEndian If false or undefined, a big-endian value should be written,
- * otherwise a little-endian value should be written.
- */
- setInt32(byteOffset: number, value: number, littleEndian?: boolean): void;
-
- /**
- * Stores an Uint8 value at the specified byte offset from the start of the view.
- * @param byteOffset The place in the buffer at which the value should be set.
- * @param value The value to set.
- */
- setUint8(byteOffset: number, value: number): void;
-
- /**
- * Stores an Uint16 value at the specified byte offset from the start of the view.
- * @param byteOffset The place in the buffer at which the value should be set.
- * @param value The value to set.
- * @param littleEndian If false or undefined, a big-endian value should be written,
- * otherwise a little-endian value should be written.
- */
- setUint16(byteOffset: number, value: number, littleEndian?: boolean): void;
-
- /**
- * Stores an Uint32 value at the specified byte offset from the start of the view.
- * @param byteOffset The place in the buffer at which the value should be set.
- * @param value The value to set.
- * @param littleEndian If false or undefined, a big-endian value should be written,
- * otherwise a little-endian value should be written.
- */
- setUint32(byteOffset: number, value: number, littleEndian?: boolean): void;
-}
-
-interface DataViewConstructor {
- new (buffer: ArrayBuffer, byteOffset?: number, byteLength?: number): DataView;
-}
-declare var DataView: DataViewConstructor;
-
-/**
- * A typed array of 8-bit integer values. The contents are initialized to 0. If the requested
- * number of bytes could not be allocated an exception is raised.
- */
-interface Int8Array {
- /**
- * The size in bytes of each element in the array.
- */
- BYTES_PER_ELEMENT: number;
-
- /**
- * The ArrayBuffer instance referenced by the array.
- */
- buffer: ArrayBuffer;
-
- /**
- * The length in bytes of the array.
- */
- byteLength: number;
-
- /**
- * The offset in bytes of the array.
- */
- byteOffset: number;
-
- /**
- * Returns the this object after copying a section of the array identified by start and end
- * to the same array starting at position target
- * @param target If target is negative, it is treated as length+target where length is the
- * length of the array.
- * @param start If start is negative, it is treated as length+start. If end is negative, it
- * is treated as length+end.
- * @param end If not specified, length of the this object is used as its default value.
- */
- copyWithin(target: number, start: number, end?: number): Int8Array;
-
- /**
- * Determines whether all the members of an array satisfy the specified test.
- * @param callbackfn A function that accepts up to three arguments. The every method calls
- * the callbackfn function for each element in array1 until the callbackfn returns false,
- * or until the end of the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function.
- * If thisArg is omitted, undefined is used as the this value.
- */
- every(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): boolean;
-
- /**
- * Returns the this object after filling the section identified by start and end with value
- * @param value value to fill array section with
- * @param start index to start filling the array at. If start is negative, it is treated as
- * length+start where length is the length of the array.
- * @param end index to stop filling the array at. If end is negative, it is treated as
- * length+end.
- */
- fill(value: number, start?: number, end?: number): Int8Array;
-
- /**
- * Returns the elements of an array that meet the condition specified in a callback function.
- * @param callbackfn A function that accepts up to three arguments. The filter method calls
- * the callbackfn function one time for each element in the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function.
- * If thisArg is omitted, undefined is used as the this value.
- */
- filter(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): Int8Array;
-
- /**
- * Returns the value of the first element in the array where predicate is true, and undefined
- * otherwise.
- * @param predicate find calls predicate once for each element of the array, in ascending
- * order, until it finds one where predicate returns true. If such an element is found, find
- * immediately returns that element value. Otherwise, find returns undefined.
- * @param thisArg If provided, it will be used as the this value for each invocation of
- * predicate. If it is not provided, undefined is used instead.
- */
- find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number;
-
- /**
- * Returns the index of the first element in the array where predicate is true, and undefined
- * otherwise.
- * @param predicate find calls predicate once for each element of the array, in ascending
- * order, until it finds one where predicate returns true. If such an element is found, find
- * immediately returns that element value. Otherwise, find returns undefined.
- * @param thisArg If provided, it will be used as the this value for each invocation of
- * predicate. If it is not provided, undefined is used instead.
- */
- findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
-
- /**
- * Performs the specified action for each element in an array.
- * @param callbackfn A function that accepts up to three arguments. forEach calls the
- * callbackfn function one time for each element in the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function.
- * If thisArg is omitted, undefined is used as the this value.
- */
- forEach(callbackfn: (value: number, index: number, array: Int8Array) => void, thisArg?: any): void;
-
- /**
- * Returns the index of the first occurrence of a value in an array.
- * @param searchElement The value to locate in the array.
- * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
- * search starts at index 0.
- */
- indexOf(searchElement: number, fromIndex?: number): number;
-
- /**
- * Adds all the elements of an array separated by the specified separator string.
- * @param separator A string used to separate one element of an array from the next in the
- * resulting String. If omitted, the array elements are separated with a comma.
- */
- join(separator?: string): string;
-
- /**
- * Returns the index of the last occurrence of a value in an array.
- * @param searchElement The value to locate in the array.
- * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
- * search starts at index 0.
- */
- lastIndexOf(searchElement: number, fromIndex?: number): number;
-
- /**
- * The length of the array.
- */
- length: number;
-
- /**
- * Calls a defined callback function on each element of an array, and returns an array that
- * contains the results.
- * @param callbackfn A function that accepts up to three arguments. The map method calls the
- * callbackfn function one time for each element in the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function.
- * If thisArg is omitted, undefined is used as the this value.
- */
- map(callbackfn: (value: number, index: number, array: Int8Array) => number, thisArg?: any): Int8Array;
-
- /**
- * Calls the specified callback function for all the elements in an array. The return value of
- * the callback function is the accumulated result, and is provided as an argument in the next
- * call to the callback function.
- * @param callbackfn A function that accepts up to four arguments. The reduce method calls the
- * callbackfn function one time for each element in the array.
- * @param initialValue If initialValue is specified, it is used as the initial value to start
- * the accumulation. The first call to the callbackfn function provides this value as an argument
- * instead of an array value.
- */
- reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue?: number): number;
-
- /**
- * Calls the specified callback function for all the elements in an array. The return value of
- * the callback function is the accumulated result, and is provided as an argument in the next
- * call to the callback function.
- * @param callbackfn A function that accepts up to four arguments. The reduce method calls the
- * callbackfn function one time for each element in the array.
- * @param initialValue If initialValue is specified, it is used as the initial value to start
- * the accumulation. The first call to the callbackfn function provides this value as an argument
- * instead of an array value.
- */
- reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, initialValue: U): U;
-
- /**
- * Calls the specified callback function for all the elements in an array, in descending order.
- * The return value of the callback function is the accumulated result, and is provided as an
- * argument in the next call to the callback function.
- * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
- * the callbackfn function one time for each element in the array.
- * @param initialValue If initialValue is specified, it is used as the initial value to start
- * the accumulation. The first call to the callbackfn function provides this value as an
- * argument instead of an array value.
- */
- reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Int8Array) => number, initialValue?: number): number;
-
- /**
- * Calls the specified callback function for all the elements in an array, in descending order.
- * The return value of the callback function is the accumulated result, and is provided as an
- * argument in the next call to the callback function.
- * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
- * the callbackfn function one time for each element in the array.
- * @param initialValue If initialValue is specified, it is used as the initial value to start
- * the accumulation. The first call to the callbackfn function provides this value as an argument
- * instead of an array value.
- */
- reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Int8Array) => U, initialValue: U): U;
-
- /**
- * Reverses the elements in an Array.
- */
- reverse(): Int8Array;
-
- /**
- * Sets a value or an array of values.
- * @param index The index of the location to set.
- * @param value The value to set.
- */
- set(index: number, value: number): void;
-
- /**
- * Sets a value or an array of values.
- * @param array A typed or untyped array of values to set.
- * @param offset The index in the current array at which the values are to be written.
- */
- set(array: ArrayLike, offset?: number): void;
-
- /**
- * Returns a section of an array.
- * @param start The beginning of the specified portion of the array.
- * @param end The end of the specified portion of the array.
- */
- slice(start?: number, end?: number): Int8Array;
-
- /**
- * Determines whether the specified callback function returns true for any element of an array.
- * @param callbackfn A function that accepts up to three arguments. The some method calls the
- * callbackfn function for each element in array1 until the callbackfn returns true, or until
- * the end of the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function.
- * If thisArg is omitted, undefined is used as the this value.
- */
- some(callbackfn: (value: number, index: number, array: Int8Array) => boolean, thisArg?: any): boolean;
-
- /**
- * Sorts an array.
- * @param compareFn The name of the function used to determine the order of the elements. If
- * omitted, the elements are sorted in ascending, ASCII character order.
- */
- sort(compareFn?: (a: number, b: number) => number): Int8Array;
-
- /**
- * Gets a new Int8Array view of the ArrayBuffer store for this array, referencing the elements
- * at begin, inclusive, up to end, exclusive.
- * @param begin The index of the beginning of the array.
- * @param end The index of the end of the array.
- */
- subarray(begin: number, end?: number): Int8Array;
-
- /**
- * Converts a number to a string by using the current locale.
- */
- toLocaleString(): string;
-
- /**
- * Returns a string representation of an array.
- */
- toString(): string;
-
- [index: number]: number;
-}
-interface Int8ArrayConstructor {
- prototype: Int8Array;
- new (length: number): Int8Array;
- new (array: ArrayLike): Int8Array;
- new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Int8Array;
-
- /**
- * The size in bytes of each element in the array.
- */
- BYTES_PER_ELEMENT: number;
-
- /**
- * Returns a new array from a set of elements.
- * @param items A set of elements to include in the new array object.
- */
- of(...items: number[]): Int8Array;
-
- /**
- * Creates an array from an array-like or iterable object.
- * @param arrayLike An array-like or iterable object to convert to an array.
- * @param mapfn A mapping function to call on every element of the array.
- * @param thisArg Value of 'this' used to invoke the mapfn.
- */
- from(arrayLike: ArrayLike, mapfn?: (v: number, k: number) => number, thisArg?: any): Int8Array;
-
-}
-declare var Int8Array: Int8ArrayConstructor;
-
-/**
- * A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
- * requested number of bytes could not be allocated an exception is raised.
- */
-interface Uint8Array {
- /**
- * The size in bytes of each element in the array.
- */
- BYTES_PER_ELEMENT: number;
-
- /**
- * The ArrayBuffer instance referenced by the array.
- */
- buffer: ArrayBuffer;
-
- /**
- * The length in bytes of the array.
- */
- byteLength: number;
-
- /**
- * The offset in bytes of the array.
- */
- byteOffset: number;
-
- /**
- * Returns the this object after copying a section of the array identified by start and end
- * to the same array starting at position target
- * @param target If target is negative, it is treated as length+target where length is the
- * length of the array.
- * @param start If start is negative, it is treated as length+start. If end is negative, it
- * is treated as length+end.
- * @param end If not specified, length of the this object is used as its default value.
- */
- copyWithin(target: number, start: number, end?: number): Uint8Array;
-
- /**
- * Determines whether all the members of an array satisfy the specified test.
- * @param callbackfn A function that accepts up to three arguments. The every method calls
- * the callbackfn function for each element in array1 until the callbackfn returns false,
- * or until the end of the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function.
- * If thisArg is omitted, undefined is used as the this value.
- */
- every(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): boolean;
-
- /**
- * Returns the this object after filling the section identified by start and end with value
- * @param value value to fill array section with
- * @param start index to start filling the array at. If start is negative, it is treated as
- * length+start where length is the length of the array.
- * @param end index to stop filling the array at. If end is negative, it is treated as
- * length+end.
- */
- fill(value: number, start?: number, end?: number): Uint8Array;
-
- /**
- * Returns the elements of an array that meet the condition specified in a callback function.
- * @param callbackfn A function that accepts up to three arguments. The filter method calls
- * the callbackfn function one time for each element in the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function.
- * If thisArg is omitted, undefined is used as the this value.
- */
- filter(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): Uint8Array;
-
- /**
- * Returns the value of the first element in the array where predicate is true, and undefined
- * otherwise.
- * @param predicate find calls predicate once for each element of the array, in ascending
- * order, until it finds one where predicate returns true. If such an element is found, find
- * immediately returns that element value. Otherwise, find returns undefined.
- * @param thisArg If provided, it will be used as the this value for each invocation of
- * predicate. If it is not provided, undefined is used instead.
- */
- find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number;
-
- /**
- * Returns the index of the first element in the array where predicate is true, and undefined
- * otherwise.
- * @param predicate find calls predicate once for each element of the array, in ascending
- * order, until it finds one where predicate returns true. If such an element is found, find
- * immediately returns that element value. Otherwise, find returns undefined.
- * @param thisArg If provided, it will be used as the this value for each invocation of
- * predicate. If it is not provided, undefined is used instead.
- */
- findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
-
- /**
- * Performs the specified action for each element in an array.
- * @param callbackfn A function that accepts up to three arguments. forEach calls the
- * callbackfn function one time for each element in the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function.
- * If thisArg is omitted, undefined is used as the this value.
- */
- forEach(callbackfn: (value: number, index: number, array: Uint8Array) => void, thisArg?: any): void;
-
- /**
- * Returns the index of the first occurrence of a value in an array.
- * @param searchElement The value to locate in the array.
- * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
- * search starts at index 0.
- */
- indexOf(searchElement: number, fromIndex?: number): number;
-
- /**
- * Adds all the elements of an array separated by the specified separator string.
- * @param separator A string used to separate one element of an array from the next in the
- * resulting String. If omitted, the array elements are separated with a comma.
- */
- join(separator?: string): string;
-
- /**
- * Returns the index of the last occurrence of a value in an array.
- * @param searchElement The value to locate in the array.
- * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
- * search starts at index 0.
- */
- lastIndexOf(searchElement: number, fromIndex?: number): number;
-
- /**
- * The length of the array.
- */
- length: number;
-
- /**
- * Calls a defined callback function on each element of an array, and returns an array that
- * contains the results.
- * @param callbackfn A function that accepts up to three arguments. The map method calls the
- * callbackfn function one time for each element in the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function.
- * If thisArg is omitted, undefined is used as the this value.
- */
- map(callbackfn: (value: number, index: number, array: Uint8Array) => number, thisArg?: any): Uint8Array;
-
- /**
- * Calls the specified callback function for all the elements in an array. The return value of
- * the callback function is the accumulated result, and is provided as an argument in the next
- * call to the callback function.
- * @param callbackfn A function that accepts up to four arguments. The reduce method calls the
- * callbackfn function one time for each element in the array.
- * @param initialValue If initialValue is specified, it is used as the initial value to start
- * the accumulation. The first call to the callbackfn function provides this value as an argument
- * instead of an array value.
- */
- reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue?: number): number;
-
- /**
- * Calls the specified callback function for all the elements in an array. The return value of
- * the callback function is the accumulated result, and is provided as an argument in the next
- * call to the callback function.
- * @param callbackfn A function that accepts up to four arguments. The reduce method calls the
- * callbackfn function one time for each element in the array.
- * @param initialValue If initialValue is specified, it is used as the initial value to start
- * the accumulation. The first call to the callbackfn function provides this value as an argument
- * instead of an array value.
- */
- reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U): U;
-
- /**
- * Calls the specified callback function for all the elements in an array, in descending order.
- * The return value of the callback function is the accumulated result, and is provided as an
- * argument in the next call to the callback function.
- * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
- * the callbackfn function one time for each element in the array.
- * @param initialValue If initialValue is specified, it is used as the initial value to start
- * the accumulation. The first call to the callbackfn function provides this value as an
- * argument instead of an array value.
- */
- reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8Array) => number, initialValue?: number): number;
-
- /**
- * Calls the specified callback function for all the elements in an array, in descending order.
- * The return value of the callback function is the accumulated result, and is provided as an
- * argument in the next call to the callback function.
- * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
- * the callbackfn function one time for each element in the array.
- * @param initialValue If initialValue is specified, it is used as the initial value to start
- * the accumulation. The first call to the callbackfn function provides this value as an argument
- * instead of an array value.
- */
- reduceRight(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8Array) => U, initialValue: U): U;
-
- /**
- * Reverses the elements in an Array.
- */
- reverse(): Uint8Array;
-
- /**
- * Sets a value or an array of values.
- * @param index The index of the location to set.
- * @param value The value to set.
- */
- set(index: number, value: number): void;
-
- /**
- * Sets a value or an array of values.
- * @param array A typed or untyped array of values to set.
- * @param offset The index in the current array at which the values are to be written.
- */
- set(array: ArrayLike, offset?: number): void;
-
- /**
- * Returns a section of an array.
- * @param start The beginning of the specified portion of the array.
- * @param end The end of the specified portion of the array.
- */
- slice(start?: number, end?: number): Uint8Array;
-
- /**
- * Determines whether the specified callback function returns true for any element of an array.
- * @param callbackfn A function that accepts up to three arguments. The some method calls the
- * callbackfn function for each element in array1 until the callbackfn returns true, or until
- * the end of the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function.
- * If thisArg is omitted, undefined is used as the this value.
- */
- some(callbackfn: (value: number, index: number, array: Uint8Array) => boolean, thisArg?: any): boolean;
-
- /**
- * Sorts an array.
- * @param compareFn The name of the function used to determine the order of the elements. If
- * omitted, the elements are sorted in ascending, ASCII character order.
- */
- sort(compareFn?: (a: number, b: number) => number): Uint8Array;
-
- /**
- * Gets a new Uint8Array view of the ArrayBuffer store for this array, referencing the elements
- * at begin, inclusive, up to end, exclusive.
- * @param begin The index of the beginning of the array.
- * @param end The index of the end of the array.
- */
- subarray(begin: number, end?: number): Uint8Array;
-
- /**
- * Converts a number to a string by using the current locale.
- */
- toLocaleString(): string;
-
- /**
- * Returns a string representation of an array.
- */
- toString(): string;
-
- [index: number]: number;
-}
-
-interface Uint8ArrayConstructor {
- prototype: Uint8Array;
- new (length: number): Uint8Array;
- new (array: ArrayLike): Uint8Array;
- new (buffer: ArrayBuffer, byteOffset?: number, length?: number): Uint8Array;
-
- /**
- * The size in bytes of each element in the array.
- */
- BYTES_PER_ELEMENT: number;
-
- /**
- * Returns a new array from a set of elements.
- * @param items A set of elements to include in the new array object.
- */
- of(...items: number[]): Uint8Array;
-
- /**
- * Creates an array from an array-like or iterable object.
- * @param arrayLike An array-like or iterable object to convert to an array.
- * @param mapfn A mapping function to call on every element of the array.
- * @param thisArg Value of 'this' used to invoke the mapfn.
- */
- from(arrayLike: ArrayLike, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8Array;
-
-}
-declare var Uint8Array: Uint8ArrayConstructor;
-
-/**
- * A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0.
- * If the requested number of bytes could not be allocated an exception is raised.
- */
-interface Uint8ClampedArray {
- /**
- * The size in bytes of each element in the array.
- */
- BYTES_PER_ELEMENT: number;
-
- /**
- * The ArrayBuffer instance referenced by the array.
- */
- buffer: ArrayBuffer;
-
- /**
- * The length in bytes of the array.
- */
- byteLength: number;
-
- /**
- * The offset in bytes of the array.
- */
- byteOffset: number;
-
- /**
- * Returns the this object after copying a section of the array identified by start and end
- * to the same array starting at position target
- * @param target If target is negative, it is treated as length+target where length is the
- * length of the array.
- * @param start If start is negative, it is treated as length+start. If end is negative, it
- * is treated as length+end.
- * @param end If not specified, length of the this object is used as its default value.
- */
- copyWithin(target: number, start: number, end?: number): Uint8ClampedArray;
-
- /**
- * Determines whether all the members of an array satisfy the specified test.
- * @param callbackfn A function that accepts up to three arguments. The every method calls
- * the callbackfn function for each element in array1 until the callbackfn returns false,
- * or until the end of the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function.
- * If thisArg is omitted, undefined is used as the this value.
- */
- every(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg?: any): boolean;
-
- /**
- * Returns the this object after filling the section identified by start and end with value
- * @param value value to fill array section with
- * @param start index to start filling the array at. If start is negative, it is treated as
- * length+start where length is the length of the array.
- * @param end index to stop filling the array at. If end is negative, it is treated as
- * length+end.
- */
- fill(value: number, start?: number, end?: number): Uint8ClampedArray;
-
- /**
- * Returns the elements of an array that meet the condition specified in a callback function.
- * @param callbackfn A function that accepts up to three arguments. The filter method calls
- * the callbackfn function one time for each element in the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function.
- * If thisArg is omitted, undefined is used as the this value.
- */
- filter(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => boolean, thisArg?: any): Uint8ClampedArray;
-
- /**
- * Returns the value of the first element in the array where predicate is true, and undefined
- * otherwise.
- * @param predicate find calls predicate once for each element of the array, in ascending
- * order, until it finds one where predicate returns true. If such an element is found, find
- * immediately returns that element value. Otherwise, find returns undefined.
- * @param thisArg If provided, it will be used as the this value for each invocation of
- * predicate. If it is not provided, undefined is used instead.
- */
- find(predicate: (value: number, index: number, obj: Array) => boolean, thisArg?: any): number;
-
- /**
- * Returns the index of the first element in the array where predicate is true, and undefined
- * otherwise.
- * @param predicate find calls predicate once for each element of the array, in ascending
- * order, until it finds one where predicate returns true. If such an element is found, find
- * immediately returns that element value. Otherwise, find returns undefined.
- * @param thisArg If provided, it will be used as the this value for each invocation of
- * predicate. If it is not provided, undefined is used instead.
- */
- findIndex(predicate: (value: number) => boolean, thisArg?: any): number;
-
- /**
- * Performs the specified action for each element in an array.
- * @param callbackfn A function that accepts up to three arguments. forEach calls the
- * callbackfn function one time for each element in the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function.
- * If thisArg is omitted, undefined is used as the this value.
- */
- forEach(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => void, thisArg?: any): void;
-
- /**
- * Returns the index of the first occurrence of a value in an array.
- * @param searchElement The value to locate in the array.
- * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
- * search starts at index 0.
- */
- indexOf(searchElement: number, fromIndex?: number): number;
-
- /**
- * Adds all the elements of an array separated by the specified separator string.
- * @param separator A string used to separate one element of an array from the next in the
- * resulting String. If omitted, the array elements are separated with a comma.
- */
- join(separator?: string): string;
-
- /**
- * Returns the index of the last occurrence of a value in an array.
- * @param searchElement The value to locate in the array.
- * @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the
- * search starts at index 0.
- */
- lastIndexOf(searchElement: number, fromIndex?: number): number;
-
- /**
- * The length of the array.
- */
- length: number;
-
- /**
- * Calls a defined callback function on each element of an array, and returns an array that
- * contains the results.
- * @param callbackfn A function that accepts up to three arguments. The map method calls the
- * callbackfn function one time for each element in the array.
- * @param thisArg An object to which the this keyword can refer in the callbackfn function.
- * If thisArg is omitted, undefined is used as the this value.
- */
- map(callbackfn: (value: number, index: number, array: Uint8ClampedArray) => number, thisArg?: any): Uint8ClampedArray;
-
- /**
- * Calls the specified callback function for all the elements in an array. The return value of
- * the callback function is the accumulated result, and is provided as an argument in the next
- * call to the callback function.
- * @param callbackfn A function that accepts up to four arguments. The reduce method calls the
- * callbackfn function one time for each element in the array.
- * @param initialValue If initialValue is specified, it is used as the initial value to start
- * the accumulation. The first call to the callbackfn function provides this value as an argument
- * instead of an array value.
- */
- reduce(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number, initialValue?: number): number;
-
- /**
- * Calls the specified callback function for all the elements in an array. The return value of
- * the callback function is the accumulated result, and is provided as an argument in the next
- * call to the callback function.
- * @param callbackfn A function that accepts up to four arguments. The reduce method calls the
- * callbackfn function one time for each element in the array.
- * @param initialValue If initialValue is specified, it is used as the initial value to start
- * the accumulation. The first call to the callbackfn function provides this value as an argument
- * instead of an array value.
- */
- reduce(callbackfn: (previousValue: U, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => U, initialValue: U): U;
-
- /**
- * Calls the specified callback function for all the elements in an array, in descending order.
- * The return value of the callback function is the accumulated result, and is provided as an
- * argument in the next call to the callback function.
- * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
- * the callbackfn function one time for each element in the array.
- * @param initialValue If initialValue is specified, it is used as the initial value to start
- * the accumulation. The first call to the callbackfn function provides this value as an
- * argument instead of an array value.
- */
- reduceRight(callbackfn: (previousValue: number, currentValue: number, currentIndex: number, array: Uint8ClampedArray) => number, initialValue?: number): number;
-
- /**
- * Calls the specified callback function for all the elements in an array, in descending order.
- * The return value of the callback function is the accumulated result, and is provided as an
- * argument in the next call to the callback function.
- * @param callbackfn A function that accepts up to four arguments. The reduceRight method calls
- * the callbackfn function one time for each element in the array.
- * @param initialValue If initialValue is specified, it is used as the initial value to start
- * the accumulation. The first call to the callbackfn function provides this value as an argument
- * instead of an array value.
- */
- reduceRight]