Merge branch 'master' into aeschli/welcomeViewGroups

This commit is contained in:
Martin Aeschlimann 2020-09-24 14:12:27 +02:00
commit 80718e85da
208 changed files with 2260 additions and 7959 deletions

View file

@ -5,21 +5,21 @@
10 results - 2 files
src/vs/base/browser/dom.ts:
83 };
84
85: /** @deprecated ES6 - use classList*/
86 export function hasClass(node: HTMLElement | SVGElement, className: string): boolean { return _classList.hasClass(node, className); }
87: /** @deprecated ES6 - use classList*/
88 export function addClass(node: HTMLElement | SVGElement, className: string): void { return _classList.addClass(node, className); }
89: /** @deprecated ES6 - use classList*/
90 export function addClasses(node: HTMLElement | SVGElement, ...classNames: string[]): void { return _classList.addClasses(node, ...classNames); }
91: /** @deprecated ES6 - use classList*/
92 export function removeClass(node: HTMLElement | SVGElement, className: string): void { return _classList.removeClass(node, className); }
93: /** @deprecated ES6 - use classList*/
94 export function removeClasses(node: HTMLElement | SVGElement, ...classNames: string[]): void { return _classList.removeClasses(node, ...classNames); }
95: /** @deprecated ES6 - use classList*/
96 export function toggleClass(node: HTMLElement | SVGElement, className: string, shouldHaveIt?: boolean): void { return _classList.toggleClass(node, className, shouldHaveIt); }
97
74 };
75
76: /** @deprecated ES6 - use classList*/
77 export function hasClass(node: HTMLElement | SVGElement, className: string): boolean { return _classList.hasClass(node, className); }
78: /** @deprecated ES6 - use classList*/
79 export function addClass(node: HTMLElement | SVGElement, className: string): void { return _classList.addClass(node, className); }
80: /** @deprecated ES6 - use classList*/
81 export function addClasses(node: HTMLElement | SVGElement, ...classNames: string[]): void { return _classList.addClasses(node, ...classNames); }
82: /** @deprecated ES6 - use classList*/
83 export function removeClass(node: HTMLElement | SVGElement, className: string): void { return _classList.removeClass(node, className); }
84: /** @deprecated ES6 - use classList*/
85 export function removeClasses(node: HTMLElement | SVGElement, ...classNames: string[]): void { return _classList.removeClasses(node, ...classNames); }
86: /** @deprecated ES6 - use classList*/
87 export function toggleClass(node: HTMLElement | SVGElement, className: string, shouldHaveIt?: boolean): void { return _classList.toggleClass(node, className, shouldHaveIt); }
88
src/vs/base/common/strings.ts:
15

15
.vscode/settings.json vendored
View file

@ -43,9 +43,7 @@
}
],
"eslint.options": {
"rulePaths": [
"./build/lib/eslint"
]
"rulePaths": ["./build/lib/eslint"]
},
"typescript.tsdk": "node_modules/typescript/lib",
"npm.exclude": "**/extensions/**",
@ -55,15 +53,11 @@
"typescript.preferences.quoteStyle": "single",
"json.schemas": [
{
"fileMatch": [
"cgmanifest.json"
],
"fileMatch": ["cgmanifest.json"],
"url": "./.vscode/cgmanifest.schema.json"
},
{
"fileMatch": [
"cglicenses.json"
],
"fileMatch": ["cglicenses.json"],
"url": "./.vscode/cglicenses.schema.json"
}
],
@ -76,5 +70,8 @@
"[typescript]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"[javascript]": {
"editor.defaultFormatter": "vscode.typescript-language-features"
},
"typescript.tsc.autoDetect": "off"
}

1
build/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
*.js

View file

@ -25,6 +25,12 @@ steps:
vstsFeed: 'vscode-build-cache'
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
- script: |
set -e
yarn postinstall
displayName: Run postinstall scripts
condition: and(succeeded(), eq(variables['CacheRestored'], 'true'))
- script: |
yarn electron x64
displayName: Download Electron

View file

@ -34,6 +34,12 @@ steps:
vstsFeed: 'vscode-build-cache'
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
- script: |
set -e
yarn postinstall
displayName: Run postinstall scripts
condition: and(succeeded(), eq(variables['CacheRestored'], 'true'))
- script: |
yarn electron x64
displayName: Download Electron

View file

@ -32,6 +32,13 @@ steps:
vstsFeed: 'vscode-build-cache'
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
- powershell: |
. build/azure-pipelines/win32/exec.ps1
$ErrorActionPreference = "Stop"
exec { yarn postinstall }
displayName: Run postinstall scripts
condition: and(succeeded(), eq(variables['CacheRestored'], 'true'))
- powershell: |
yarn electron
displayName: Download Electron

View file

@ -1,61 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
const codesign = require("electron-osx-sign");
const path = require("path");
const util = require("../lib/util");
const product = require("../../product.json");
async function main() {
const buildDir = process.env['AGENT_BUILDDIRECTORY'];
const tempDir = process.env['AGENT_TEMPDIRECTORY'];
if (!buildDir) {
throw new Error('$AGENT_BUILDDIRECTORY not set');
}
if (!tempDir) {
throw new Error('$AGENT_TEMPDIRECTORY not set');
}
const baseDir = path.dirname(__dirname);
const appRoot = path.join(buildDir, 'VSCode-darwin');
const appName = product.nameLong + '.app';
const appFrameworkPath = path.join(appRoot, appName, 'Contents', 'Frameworks');
const helperAppBaseName = product.nameShort;
const gpuHelperAppName = helperAppBaseName + ' Helper (GPU).app';
const pluginHelperAppName = helperAppBaseName + ' Helper (Plugin).app';
const rendererHelperAppName = helperAppBaseName + ' Helper (Renderer).app';
const defaultOpts = {
app: path.join(appRoot, appName),
platform: 'darwin',
entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'app-entitlements.plist'),
'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'app-entitlements.plist'),
hardenedRuntime: true,
'pre-auto-entitlements': false,
'pre-embed-provisioning-profile': false,
keychain: path.join(tempDir, 'buildagent.keychain'),
version: util.getElectronVersion(),
identity: '99FM488X57',
'gatekeeper-assess': false
};
const appOpts = Object.assign(Object.assign({}, defaultOpts), {
// TODO(deepak1556): Incorrectly declared type in electron-osx-sign
ignore: (filePath) => {
return filePath.includes(gpuHelperAppName) ||
filePath.includes(pluginHelperAppName) ||
filePath.includes(rendererHelperAppName);
} });
const gpuHelperOpts = Object.assign(Object.assign({}, defaultOpts), { app: path.join(appFrameworkPath, gpuHelperAppName), entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-gpu-entitlements.plist'), 'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-gpu-entitlements.plist') });
const pluginHelperOpts = Object.assign(Object.assign({}, defaultOpts), { app: path.join(appFrameworkPath, pluginHelperAppName), entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-plugin-entitlements.plist'), 'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-plugin-entitlements.plist') });
const rendererHelperOpts = Object.assign(Object.assign({}, defaultOpts), { app: path.join(appFrameworkPath, rendererHelperAppName), entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-renderer-entitlements.plist'), 'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-renderer-entitlements.plist') });
await codesign.signAsync(gpuHelperOpts);
await codesign.signAsync(pluginHelperOpts);
await codesign.signAsync(rendererHelperOpts);
await codesign.signAsync(appOpts);
}
if (require.main === module) {
main().catch(err => {
console.error(err);
process.exit(1);
});
}

View file

@ -3,177 +3,33 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
const gulp = require('gulp');
const filter = require('gulp-filter');
const es = require('event-stream');
const gulpeslint = require('gulp-eslint');
const tsfmt = require('typescript-formatter');
const VinylFile = require('vinyl');
const vfs = require('vinyl-fs');
const path = require('path');
const fs = require('fs');
const pall = require('p-all');
const task = require('./lib/task');
/**
* Hygiene works by creating cascading subsets of all our files and
* passing them through a sequence of checks. Here are the current subsets,
* named according to the checks performed on them. Each subset contains
* the following one, as described in mathematical notation:
*
* all eol indentation copyright typescript
*/
const all = [
'*',
'build/**/*',
'extensions/**/*',
'scripts/**/*',
'src/**/*',
'test/**/*',
'!test/**/out/**',
'!**/node_modules/**'
];
const indentationFilter = [
'**',
// except specific files
'!**/ThirdPartyNotices.txt',
'!**/LICENSE.{txt,rtf}',
'!LICENSES.chromium.html',
'!**/LICENSE',
'!src/vs/nls.js',
'!src/vs/nls.build.js',
'!src/vs/css.js',
'!src/vs/css.build.js',
'!src/vs/loader.js',
'!src/vs/base/common/insane/insane.js',
'!src/vs/base/common/marked/marked.js',
'!src/vs/base/node/terminateProcess.sh',
'!src/vs/base/node/cpuUsage.sh',
'!test/unit/assert.js',
// except specific folders
'!test/automation/out/**',
'!test/smoke/out/**',
'!extensions/typescript-language-features/test-workspace/**',
'!extensions/vscode-api-tests/testWorkspace/**',
'!extensions/vscode-api-tests/testWorkspace2/**',
'!build/monaco/**',
'!build/win32/**',
// except multiple specific files
'!**/package.json',
'!**/yarn.lock',
'!**/yarn-error.log',
// except multiple specific folders
'!**/codicon/**',
'!**/fixtures/**',
'!**/lib/**',
'!extensions/**/out/**',
'!extensions/**/snippets/**',
'!extensions/**/syntaxes/**',
'!extensions/**/themes/**',
'!extensions/**/colorize-fixtures/**',
// 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,ico,icns,plist}',
'!build/{lib,download,darwin}/**/*.js',
'!build/**/*.sh',
'!build/azure-pipelines/**/*.js',
'!build/azure-pipelines/**/*.config',
'!**/Dockerfile',
'!**/Dockerfile.*',
'!**/*.Dockerfile',
'!**/*.dockerfile',
'!extensions/markdown-language-features/media/*.js'
];
const copyrightFilter = [
'**',
'!**/*.desktop',
'!**/*.json',
'!**/*.html',
'!**/*.template',
'!**/*.md',
'!**/*.bat',
'!**/*.cmd',
'!**/*.ico',
'!**/*.icns',
'!**/*.xml',
'!**/*.sh',
'!**/*.txt',
'!**/*.xpm',
'!**/*.opts',
'!**/*.disabled',
'!**/*.code-workspace',
'!**/*.js.map',
'!build/**/*.init',
'!resources/linux/snap/snapcraft.yaml',
'!resources/linux/snap/electron-launch',
'!resources/win32/bin/code.js',
'!resources/web/code-web.js',
'!resources/completions/**',
'!extensions/markdown-language-features/media/highlight.css',
'!extensions/html-language-features/server/src/modes/typescript/*',
'!extensions/*/server/bin/*',
'!src/vs/editor/test/node/classification/typescript-test.ts'
];
const jsHygieneFilter = [
'src/**/*.js',
'build/gulpfile.*.js',
'!src/vs/loader.js',
'!src/vs/css.js',
'!src/vs/nls.js',
'!src/vs/css.build.js',
'!src/vs/nls.build.js',
'!src/**/insane.js',
'!src/**/marked.js',
'!**/test/**'
];
const tsHygieneFilter = [
'src/**/*.ts',
'test/**/*.ts',
'extensions/**/*.ts',
'!**/fixtures/**',
'!**/typings/**',
'!**/node_modules/**',
'!extensions/typescript-basics/test/colorize-fixtures/**',
'!extensions/vscode-api-tests/testWorkspace/**',
'!extensions/vscode-api-tests/testWorkspace2/**',
'!extensions/**/*.test.ts',
'!extensions/html-language-features/server/lib/jquery.d.ts'
];
const copyrightHeaderLines = [
'/*---------------------------------------------------------------------------------------------',
' * Copyright (c) Microsoft Corporation. All rights reserved.',
' * Licensed under the MIT License. See License.txt in the project root for license information.',
' *--------------------------------------------------------------------------------------------*/'
];
const { all, jsHygieneFilter, tsHygieneFilter, hygiene } = require('./hygiene');
gulp.task('eslint', () => {
return vfs.src(all, { base: '.', follow: true, allowEmpty: true })
return vfs
.src(all, { base: '.', follow: true, allowEmpty: true })
.pipe(filter(jsHygieneFilter.concat(tsHygieneFilter)))
.pipe(gulpeslint({
configFile: '.eslintrc.json',
rulePaths: ['./build/lib/eslint']
}))
.pipe(
gulpeslint({
configFile: '.eslintrc.json',
rulePaths: ['./build/lib/eslint'],
})
)
.pipe(gulpeslint.formatEach('compact'))
.pipe(gulpeslint.results(results => {
if (results.warningCount > 0 || results.errorCount > 0) {
throw new Error('eslint failed with warnings and/or errors');
}
}));
.pipe(
gulpeslint.results((results) => {
if (results.warningCount > 0 || results.errorCount > 0) {
throw new Error('eslint failed with warnings and/or errors');
}
})
);
});
function checkPackageJSON(actualPath) {
@ -188,233 +44,25 @@ function checkPackageJSON(actualPath) {
continue;
}
if (depVersion !== rootDepVersion) {
this.emit('error', `The dependency ${depName} in '${actualPath}' (${depVersion}) is different than in the root package.json (${rootDepVersion})`);
this.emit(
'error',
`The dependency ${depName} in '${actualPath}' (${depVersion}) is different than in the root package.json (${rootDepVersion})`
);
}
}
}
const checkPackageJSONTask = task.define('check-package-json', () => {
return gulp.src('package.json')
.pipe(es.through(function () {
return gulp.src('package.json').pipe(
es.through(function () {
checkPackageJSON.call(this, 'remote/package.json');
checkPackageJSON.call(this, 'remote/web/package.json');
}));
})
);
});
gulp.task(checkPackageJSONTask);
function hygiene(some) {
let errorCount = 0;
const productJson = es.through(function (file) {
const product = JSON.parse(file.contents.toString('utf8'));
if (product.extensionsGallery) {
console.error('product.json: Contains "extensionsGallery"');
errorCount++;
}
this.emit('data', file);
});
const indentation = es.through(function (file) {
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
} else if (/^[\t]*[^\s]/.test(line)) {
// good indent
} else if (/^[\t]* \*/.test(line)) {
// block comment using an extra space
} else {
console.error(file.relative + '(' + (i + 1) + ',1): Bad whitespace indentation');
errorCount++;
}
});
this.emit('data', file);
});
const copyrights = es.through(function (file) {
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);
});
const formatting = es.map(function (file, cb) {
tsfmt.processString(file.path, file.contents.toString('utf8'), {
verify: false,
tsfmt: true,
// verbose: true,
// keep checkJS happy
editorconfig: undefined,
replace: undefined,
tsconfig: undefined,
tsconfigFile: undefined,
tsfmtFile: undefined,
vscode: undefined,
vscodeFile: undefined
}).then(result => {
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. Run the \'Format Document\' command to fix it:', file.relative);
errorCount++;
}
cb(null, file);
}, err => {
cb(err);
});
});
let input;
if (Array.isArray(some) || typeof some === 'string' || !some) {
const options = { base: '.', follow: true, allowEmpty: true };
if (some) {
input = vfs.src(some, options).pipe(filter(all)); // split this up to not unnecessarily filter all a second time
} else {
input = vfs.src(all, options);
}
} else {
input = some;
}
const productJsonFilter = filter('product.json', { restore: true });
const result = input
.pipe(filter(f => !f.stat.isDirectory()))
.pipe(productJsonFilter)
.pipe(process.env['BUILD_SOURCEVERSION'] ? es.through() : productJson)
.pipe(productJsonFilter.restore)
.pipe(filter(indentationFilter))
.pipe(indentation)
.pipe(filter(copyrightFilter))
.pipe(copyrights);
const typescript = result
.pipe(filter(tsHygieneFilter))
.pipe(formatting);
const javascript = result
.pipe(filter(jsHygieneFilter.concat(tsHygieneFilter)))
.pipe(gulpeslint({
configFile: '.eslintrc.json',
rulePaths: ['./build/lib/eslint']
}))
.pipe(gulpeslint.formatEach('compact'))
.pipe(gulpeslint.results(results => {
errorCount += results.warningCount;
errorCount += results.errorCount;
}));
let count = 0;
return es.merge(typescript, javascript)
.pipe(es.through(function (data) {
count++;
if (process.env['TRAVIS'] && count % 10 === 0) {
process.stdout.write('.');
}
this.emit('data', data);
}, function () {
process.stdout.write('\n');
if (errorCount > 0) {
this.emit('error', 'Hygiene failed with ' + errorCount + ' errors. Check \'build/gulpfile.hygiene.js\'.');
} else {
this.emit('end');
}
}));
}
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', task.series(checkPackageJSONTask, () => hygiene()));
// this allows us to run hygiene as a git pre-commit hook
if (require.main === module) {
const cp = require('child_process');
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
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
.split(/\r?\n/)
.filter(l => !!l);
if (some.length > 0) {
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);
});
}
});
}
}
gulp.task(
'hygiene',
task.series(checkPackageJSONTask, () => hygiene())
);

410
build/hygiene.js Normal file
View file

@ -0,0 +1,410 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const filter = require('gulp-filter');
const es = require('event-stream');
const gulpeslint = require('gulp-eslint');
const tsfmt = require('typescript-formatter');
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
* passing them through a sequence of checks. Here are the current subsets,
* named according to the checks performed on them. Each subset contains
* the following one, as described in mathematical notation:
*
* all eol indentation copyright typescript
*/
const all = [
'*',
'build/**/*',
'extensions/**/*',
'scripts/**/*',
'src/**/*',
'test/**/*',
'!test/**/out/**',
'!**/node_modules/**',
];
module.exports.all = all;
const indentationFilter = [
'**',
// except specific files
'!**/ThirdPartyNotices.txt',
'!**/LICENSE.{txt,rtf}',
'!LICENSES.chromium.html',
'!**/LICENSE',
'!src/vs/nls.js',
'!src/vs/nls.build.js',
'!src/vs/css.js',
'!src/vs/css.build.js',
'!src/vs/loader.js',
'!src/vs/base/common/insane/insane.js',
'!src/vs/base/common/marked/marked.js',
'!src/vs/base/node/terminateProcess.sh',
'!src/vs/base/node/cpuUsage.sh',
'!test/unit/assert.js',
// except specific folders
'!test/automation/out/**',
'!test/smoke/out/**',
'!extensions/typescript-language-features/test-workspace/**',
'!extensions/vscode-api-tests/testWorkspace/**',
'!extensions/vscode-api-tests/testWorkspace2/**',
'!build/monaco/**',
'!build/win32/**',
// except multiple specific files
'!**/package.json',
'!**/yarn.lock',
'!**/yarn-error.log',
// except multiple specific folders
'!**/codicon/**',
'!**/fixtures/**',
'!**/lib/**',
'!extensions/**/out/**',
'!extensions/**/snippets/**',
'!extensions/**/syntaxes/**',
'!extensions/**/themes/**',
'!extensions/**/colorize-fixtures/**',
// 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,ico,icns,plist}',
'!build/{lib,download,darwin}/**/*.js',
'!build/**/*.sh',
'!build/azure-pipelines/**/*.js',
'!build/azure-pipelines/**/*.config',
'!**/Dockerfile',
'!**/Dockerfile.*',
'!**/*.Dockerfile',
'!**/*.dockerfile',
'!extensions/markdown-language-features/media/*.js',
];
const copyrightFilter = [
'**',
'!**/*.desktop',
'!**/*.json',
'!**/*.html',
'!**/*.template',
'!**/*.md',
'!**/*.bat',
'!**/*.cmd',
'!**/*.ico',
'!**/*.icns',
'!**/*.xml',
'!**/*.sh',
'!**/*.txt',
'!**/*.xpm',
'!**/*.opts',
'!**/*.disabled',
'!**/*.code-workspace',
'!**/*.js.map',
'!build/**/*.init',
'!resources/linux/snap/snapcraft.yaml',
'!resources/linux/snap/electron-launch',
'!resources/win32/bin/code.js',
'!resources/web/code-web.js',
'!resources/completions/**',
'!extensions/markdown-language-features/media/highlight.css',
'!extensions/html-language-features/server/src/modes/typescript/*',
'!extensions/*/server/bin/*',
'!src/vs/editor/test/node/classification/typescript-test.ts',
];
const jsHygieneFilter = [
'src/**/*.js',
'build/gulpfile.*.js',
'!src/vs/loader.js',
'!src/vs/css.js',
'!src/vs/nls.js',
'!src/vs/css.build.js',
'!src/vs/nls.build.js',
'!src/**/insane.js',
'!src/**/marked.js',
'!**/test/**',
];
module.exports.jsHygieneFilter = jsHygieneFilter;
const tsHygieneFilter = [
'src/**/*.ts',
'test/**/*.ts',
'extensions/**/*.ts',
'!**/fixtures/**',
'!**/typings/**',
'!**/node_modules/**',
'!extensions/typescript-basics/test/colorize-fixtures/**',
'!extensions/vscode-api-tests/testWorkspace/**',
'!extensions/vscode-api-tests/testWorkspace2/**',
'!extensions/**/*.test.ts',
'!extensions/html-language-features/server/lib/jquery.d.ts',
];
module.exports.tsHygieneFilter = tsHygieneFilter;
const copyrightHeaderLines = [
'/*---------------------------------------------------------------------------------------------',
' * Copyright (c) Microsoft Corporation. All rights reserved.',
' * Licensed under the MIT License. See License.txt in the project root for license information.',
' *--------------------------------------------------------------------------------------------*/',
];
function hygiene(some) {
let errorCount = 0;
const productJson = es.through(function (file) {
const product = JSON.parse(file.contents.toString('utf8'));
if (product.extensionsGallery) {
console.error(`product.json: Contains 'extensionsGallery'`);
errorCount++;
}
this.emit('data', file);
});
const indentation = es.through(function (file) {
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
} else if (/^[\t]*[^\s]/.test(line)) {
// good indent
} else if (/^[\t]* \*/.test(line)) {
// block comment using an extra space
} else {
console.error(
file.relative + '(' + (i + 1) + ',1): Bad whitespace indentation'
);
errorCount++;
}
});
this.emit('data', file);
});
const copyrights = es.through(function (file) {
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);
});
const formatting = es.map(function (file, cb) {
tsfmt
.processString(file.path, file.contents.toString('utf8'), {
verify: false,
tsfmt: true,
// verbose: true,
// keep checkJS happy
editorconfig: undefined,
replace: undefined,
tsconfig: undefined,
tsconfigFile: undefined,
tsfmtFile: undefined,
vscode: undefined,
vscodeFile: undefined,
})
.then(
(result) => {
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. Run the 'Format Document' command to fix it:`,
file.relative
);
errorCount++;
}
cb(null, file);
},
(err) => {
cb(err);
}
);
});
let input;
if (Array.isArray(some) || typeof some === 'string' || !some) {
const options = { base: '.', follow: true, allowEmpty: true };
if (some) {
input = vfs.src(some, options).pipe(filter(all)); // split this up to not unnecessarily filter all a second time
} else {
input = vfs.src(all, options);
}
} else {
input = some;
}
const productJsonFilter = filter('product.json', { restore: true });
const result = input
.pipe(filter((f) => !f.stat.isDirectory()))
.pipe(productJsonFilter)
.pipe(process.env['BUILD_SOURCEVERSION'] ? es.through() : productJson)
.pipe(productJsonFilter.restore)
.pipe(filter(indentationFilter))
.pipe(indentation)
.pipe(filter(copyrightFilter))
.pipe(copyrights);
const typescript = result.pipe(filter(tsHygieneFilter)).pipe(formatting);
const javascript = result
.pipe(filter(jsHygieneFilter.concat(tsHygieneFilter)))
.pipe(
gulpeslint({
configFile: '.eslintrc.json',
rulePaths: ['./build/lib/eslint'],
})
)
.pipe(gulpeslint.formatEach('compact'))
.pipe(
gulpeslint.results((results) => {
errorCount += results.warningCount;
errorCount += results.errorCount;
})
);
let count = 0;
return es.merge(typescript, javascript).pipe(
es.through(
function (data) {
count++;
if (process.env['TRAVIS'] && count % 10 === 0) {
process.stdout.write('.');
}
this.emit('data', data);
},
function () {
process.stdout.write('\n');
if (errorCount > 0) {
this.emit(
'error',
'Hygiene failed with ' +
errorCount +
` errors. Check 'build / gulpfile.hygiene.js'.`
);
} else {
this.emit('end');
}
}
)
);
}
module.exports.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));
}
// this allows us to run hygiene as a git pre-commit hook
if (require.main === module) {
const cp = require('child_process');
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
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);
}
const some = out.split(/\r?\n/).filter((l) => !!l);
if (some.length > 0) {
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);
});
}
}
);
}
}

View file

@ -1,120 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.createAsar = void 0;
const path = require("path");
const es = require("event-stream");
const pickle = require('chromium-pickle-js');
const Filesystem = require('asar/lib/filesystem');
const VinylFile = require("vinyl");
const minimatch = require("minimatch");
function createAsar(folderPath, unpackGlobs, destFilename) {
const shouldUnpackFile = (file) => {
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 = [];
// Keep track of pending inserts
let pendingInserts = 0;
let onFileInserted = () => { pendingInserts--; };
// Do not insert twice the same directory
const seenDir = {};
const insertDirectoryRecursive = (dir) => {
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) => {
let lastSlash = file.lastIndexOf('/');
if (lastSlash === -1) {
lastSlash = file.lastIndexOf('\\');
}
if (lastSlash !== -1) {
insertDirectoryRecursive(file.substring(0, lastSlash));
}
};
const insertFile = (relativePath, stat, shouldUnpack) => {
insertDirectoryForFile(relativePath);
pendingInserts++;
// Do not pass `onFileInserted` directly because it gets overwritten below.
// Create a closure capturing `onFileInserted`.
filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}).then(() => onFileInserted(), () => 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();
}
};
}
});
}
exports.createAsar = createAsar;

View file

@ -1,464 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.bundle = void 0;
const fs = require("fs");
const path = require("path");
const vm = require("vm");
/**
* Bundle `entryPoints` given config `config`.
*/
function bundle(entryPoints, config, callback) {
const entryPointsMap = {};
entryPoints.forEach((module) => {
entryPointsMap[module.name] = module;
});
const allMentionedModulesMap = {};
entryPoints.forEach((module) => {
allMentionedModulesMap[module.name] = true;
(module.include || []).forEach(function (includedModule) {
allMentionedModulesMap[includedModule] = true;
});
(module.exclude || []).forEach(function (excludedModule) {
allMentionedModulesMap[excludedModule] = true;
});
});
const code = require('fs').readFileSync(path.join(__dirname, '../../src/vs/loader.js'));
const r = vm.runInThisContext('(function(require, module, exports) { ' + code + '\n});');
const loaderModule = { exports: {} };
r.call({}, require, loaderModule, loaderModule.exports);
const loader = loaderModule.exports;
config.isBuild = true;
config.paths = config.paths || {};
if (!config.paths['vs/nls']) {
config.paths['vs/nls'] = 'out-build/vs/nls.build';
}
if (!config.paths['vs/css']) {
config.paths['vs/css'] = 'out-build/vs/css.build';
}
loader.config(config);
loader(['require'], (localRequire) => {
const resolvePath = (path) => {
const r = localRequire.toUrl(path);
if (!/\.js/.test(r)) {
return r + '.js';
}
return r;
};
for (const moduleId in entryPointsMap) {
const entryPoint = entryPointsMap[moduleId];
if (entryPoint.append) {
entryPoint.append = entryPoint.append.map(resolvePath);
}
if (entryPoint.prepend) {
entryPoint.prepend = entryPoint.prepend.map(resolvePath);
}
}
});
loader(Object.keys(allMentionedModulesMap), () => {
const modules = loader.getBuildInfo();
const partialResult = emitEntryPoints(modules, entryPointsMap);
const cssInlinedResources = loader('vs/css').getInlinedResources();
callback(null, {
files: partialResult.files,
cssInlinedResources: cssInlinedResources,
bundleData: partialResult.bundleData
});
}, (err) => callback(err, null));
}
exports.bundle = bundle;
function emitEntryPoints(modules, entryPoints) {
const modulesMap = {};
modules.forEach((m) => {
modulesMap[m.id] = m;
});
const modulesGraph = {};
modules.forEach((m) => {
modulesGraph[m.id] = m.dependencies;
});
const sortedModules = topologicalSort(modulesGraph);
let result = [];
const usedPlugins = {};
const bundleData = {
graph: modulesGraph,
bundles: {}
};
Object.keys(entryPoints).forEach((moduleToBundle) => {
const info = entryPoints[moduleToBundle];
const rootNodes = [moduleToBundle].concat(info.include || []);
const allDependencies = visit(rootNodes, modulesGraph);
const excludes = ['require', 'exports', 'module'].concat(info.exclude || []);
excludes.forEach((excludeRoot) => {
const allExcludes = visit([excludeRoot], modulesGraph);
Object.keys(allExcludes).forEach((exclude) => {
delete allDependencies[exclude];
});
});
const includedModules = sortedModules.filter((module) => {
return allDependencies[module];
});
bundleData.bundles[moduleToBundle] = includedModules;
const res = emitEntryPoint(modulesMap, modulesGraph, moduleToBundle, includedModules, info.prepend || [], info.append || [], info.dest);
result = result.concat(res.files);
for (const pluginName in res.usedPlugins) {
usedPlugins[pluginName] = usedPlugins[pluginName] || res.usedPlugins[pluginName];
}
});
Object.keys(usedPlugins).forEach((pluginName) => {
const plugin = usedPlugins[pluginName];
if (typeof plugin.finishBuild === 'function') {
const write = (filename, contents) => {
result.push({
dest: filename,
sources: [{
path: null,
contents: contents
}]
});
};
plugin.finishBuild(write);
}
});
return {
// TODO@TS 2.1.2
files: extractStrings(removeDuplicateTSBoilerplate(result)),
bundleData: bundleData
};
}
function extractStrings(destFiles) {
const parseDefineCall = (moduleMatch, depsMatch) => {
const module = moduleMatch.replace(/^"|"$/g, '');
let deps = depsMatch.split(',');
deps = deps.map((dep) => {
dep = dep.trim();
dep = dep.replace(/^"|"$/g, '');
dep = dep.replace(/^'|'$/g, '');
let prefix = null;
let _path = null;
const pieces = dep.split('!');
if (pieces.length > 1) {
prefix = pieces[0] + '!';
_path = pieces[1];
}
else {
prefix = '';
_path = pieces[0];
}
if (/^\.\//.test(_path) || /^\.\.\//.test(_path)) {
const res = path.join(path.dirname(module), _path).replace(/\\/g, '/');
return prefix + res;
}
return prefix + _path;
});
return {
module: module,
deps: deps
};
};
destFiles.forEach((destFile) => {
if (!/\.js$/.test(destFile.dest)) {
return;
}
if (/\.nls\.js$/.test(destFile.dest)) {
return;
}
// Do one pass to record the usage counts for each module id
const useCounts = {};
destFile.sources.forEach((source) => {
const matches = source.contents.match(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/);
if (!matches) {
return;
}
const defineCall = parseDefineCall(matches[1], matches[2]);
useCounts[defineCall.module] = (useCounts[defineCall.module] || 0) + 1;
defineCall.deps.forEach((dep) => {
useCounts[dep] = (useCounts[dep] || 0) + 1;
});
});
const sortedByUseModules = Object.keys(useCounts);
sortedByUseModules.sort((a, b) => {
return useCounts[b] - useCounts[a];
});
const replacementMap = {};
sortedByUseModules.forEach((module, index) => {
replacementMap[module] = index;
});
destFile.sources.forEach((source) => {
source.contents = source.contents.replace(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/, (_, moduleMatch, depsMatch) => {
const defineCall = parseDefineCall(moduleMatch, depsMatch);
return `define(__m[${replacementMap[defineCall.module]}/*${defineCall.module}*/], __M([${defineCall.deps.map(dep => replacementMap[dep] + '/*' + dep + '*/').join(',')}])`;
});
});
destFile.sources.unshift({
path: null,
contents: [
'(function() {',
`var __m = ${JSON.stringify(sortedByUseModules)};`,
`var __M = function(deps) {`,
` var result = [];`,
` for (var i = 0, len = deps.length; i < len; i++) {`,
` result[i] = __m[deps[i]];`,
` }`,
` return result;`,
`};`
].join('\n')
});
destFile.sources.push({
path: null,
contents: '}).call(this);'
});
});
return destFiles;
}
function removeDuplicateTSBoilerplate(destFiles) {
// Taken from typescript compiler => emitFiles
const BOILERPLATE = [
{ start: /^var __extends/, end: /^}\)\(\);$/ },
{ start: /^var __assign/, end: /^};$/ },
{ start: /^var __decorate/, end: /^};$/ },
{ start: /^var __metadata/, end: /^};$/ },
{ start: /^var __param/, end: /^};$/ },
{ start: /^var __awaiter/, end: /^};$/ },
{ start: /^var __generator/, end: /^};$/ },
];
destFiles.forEach((destFile) => {
const SEEN_BOILERPLATE = [];
destFile.sources.forEach((source) => {
const lines = source.contents.split(/\r\n|\n|\r/);
const newLines = [];
let IS_REMOVING_BOILERPLATE = false, END_BOILERPLATE;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (IS_REMOVING_BOILERPLATE) {
newLines.push('');
if (END_BOILERPLATE.test(line)) {
IS_REMOVING_BOILERPLATE = false;
}
}
else {
for (let j = 0; j < BOILERPLATE.length; j++) {
const boilerplate = BOILERPLATE[j];
if (boilerplate.start.test(line)) {
if (SEEN_BOILERPLATE[j]) {
IS_REMOVING_BOILERPLATE = true;
END_BOILERPLATE = boilerplate.end;
}
else {
SEEN_BOILERPLATE[j] = true;
}
}
}
if (IS_REMOVING_BOILERPLATE) {
newLines.push('');
}
else {
newLines.push(line);
}
}
}
source.contents = newLines.join('\n');
});
});
return destFiles;
}
function emitEntryPoint(modulesMap, deps, entryPoint, includedModules, prepend, append, dest) {
if (!dest) {
dest = entryPoint + '.js';
}
const mainResult = {
sources: [],
dest: dest
}, results = [mainResult];
const usedPlugins = {};
const getLoaderPlugin = (pluginName) => {
if (!usedPlugins[pluginName]) {
usedPlugins[pluginName] = modulesMap[pluginName].exports;
}
return usedPlugins[pluginName];
};
includedModules.forEach((c) => {
const bangIndex = c.indexOf('!');
if (bangIndex >= 0) {
const pluginName = c.substr(0, bangIndex);
const plugin = getLoaderPlugin(pluginName);
mainResult.sources.push(emitPlugin(entryPoint, plugin, pluginName, c.substr(bangIndex + 1)));
return;
}
const module = modulesMap[c];
if (module.path === 'empty:') {
return;
}
const contents = readFileAndRemoveBOM(module.path);
if (module.shim) {
mainResult.sources.push(emitShimmedModule(c, deps[c], module.shim, module.path, contents));
}
else {
mainResult.sources.push(emitNamedModule(c, module.defineLocation, module.path, contents));
}
});
Object.keys(usedPlugins).forEach((pluginName) => {
const plugin = usedPlugins[pluginName];
if (typeof plugin.writeFile === 'function') {
const req = (() => {
throw new Error('no-no!');
});
req.toUrl = something => something;
const write = (filename, contents) => {
results.push({
dest: filename,
sources: [{
path: null,
contents: contents
}]
});
};
plugin.writeFile(pluginName, entryPoint, req, write, {});
}
});
const toIFile = (path) => {
const contents = readFileAndRemoveBOM(path);
return {
path: path,
contents: contents
};
};
const toPrepend = (prepend || []).map(toIFile);
const toAppend = (append || []).map(toIFile);
mainResult.sources = toPrepend.concat(mainResult.sources).concat(toAppend);
return {
files: results,
usedPlugins: usedPlugins
};
}
function readFileAndRemoveBOM(path) {
const BOM_CHAR_CODE = 65279;
let contents = fs.readFileSync(path, 'utf8');
// Remove BOM
if (contents.charCodeAt(0) === BOM_CHAR_CODE) {
contents = contents.substring(1);
}
return contents;
}
function emitPlugin(entryPoint, plugin, pluginName, moduleName) {
let result = '';
if (typeof plugin.write === 'function') {
const write = ((what) => {
result += what;
});
write.getEntryPoint = () => {
return entryPoint;
};
write.asModule = (moduleId, code) => {
code = code.replace(/^define\(/, 'define("' + moduleId + '",');
result += code;
};
plugin.write(pluginName, moduleName, write);
}
return {
path: null,
contents: result
};
}
function emitNamedModule(moduleId, defineCallPosition, path, contents) {
// `defineCallPosition` is the position in code: |define()
const defineCallOffset = positionToOffset(contents, defineCallPosition.line, defineCallPosition.col);
// `parensOffset` is the position in code: define|()
const parensOffset = contents.indexOf('(', defineCallOffset);
const insertStr = '"' + moduleId + '", ';
return {
path: path,
contents: contents.substr(0, parensOffset + 1) + insertStr + contents.substr(parensOffset + 1)
};
}
function emitShimmedModule(moduleId, myDeps, factory, path, contents) {
const strDeps = (myDeps.length > 0 ? '"' + myDeps.join('", "') + '"' : '');
const strDefine = 'define("' + moduleId + '", [' + strDeps + '], ' + factory + ');';
return {
path: path,
contents: contents + '\n;\n' + strDefine
};
}
/**
* Convert a position (line:col) to (offset) in string `str`
*/
function positionToOffset(str, desiredLine, desiredCol) {
if (desiredLine === 1) {
return desiredCol - 1;
}
let line = 1;
let lastNewLineOffset = -1;
do {
if (desiredLine === line) {
return lastNewLineOffset + 1 + desiredCol - 1;
}
lastNewLineOffset = str.indexOf('\n', lastNewLineOffset + 1);
line++;
} while (lastNewLineOffset >= 0);
return -1;
}
/**
* Return a set of reachable nodes in `graph` starting from `rootNodes`
*/
function visit(rootNodes, graph) {
const result = {};
const queue = rootNodes;
rootNodes.forEach((node) => {
result[node] = true;
});
while (queue.length > 0) {
const el = queue.shift();
const myEdges = graph[el] || [];
myEdges.forEach((toNode) => {
if (!result[toNode]) {
result[toNode] = true;
queue.push(toNode);
}
});
}
return result;
}
/**
* Perform a topological sort on `graph`
*/
function topologicalSort(graph) {
const allNodes = {}, outgoingEdgeCount = {}, inverseEdges = {};
Object.keys(graph).forEach((fromNode) => {
allNodes[fromNode] = true;
outgoingEdgeCount[fromNode] = graph[fromNode].length;
graph[fromNode].forEach((toNode) => {
allNodes[toNode] = true;
outgoingEdgeCount[toNode] = outgoingEdgeCount[toNode] || 0;
inverseEdges[toNode] = inverseEdges[toNode] || [];
inverseEdges[toNode].push(fromNode);
});
});
// https://en.wikipedia.org/wiki/Topological_sorting
const S = [], L = [];
Object.keys(allNodes).forEach((node) => {
if (outgoingEdgeCount[node] === 0) {
delete outgoingEdgeCount[node];
S.push(node);
}
});
while (S.length > 0) {
// Ensure the exact same order all the time with the same inputs
S.sort();
const n = S.shift();
L.push(n);
const myInverseEdges = inverseEdges[n] || [];
myInverseEdges.forEach((m) => {
outgoingEdgeCount[m]--;
if (outgoingEdgeCount[m] === 0) {
delete outgoingEdgeCount[m];
S.push(m);
}
});
}
if (Object.keys(outgoingEdgeCount).length > 0) {
throw new Error('Cannot do topological sort on cyclic graph, remaining nodes: ' + Object.keys(outgoingEdgeCount));
}
return L;
}

View file

@ -1,174 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.watchTask = exports.compileTask = void 0;
const es = require("event-stream");
const fs = require("fs");
const gulp = require("gulp");
const bom = require("gulp-bom");
const sourcemaps = require("gulp-sourcemaps");
const tsb = require("gulp-tsb");
const path = require("path");
const monacodts = require("../monaco/api");
const nls = require("./nls");
const reporter_1 = require("./reporter");
const util = require("./util");
const fancyLog = require("fancy-log");
const ansiColors = require("ansi-colors");
const os = require("os");
const watch = require('./watch');
const reporter = reporter_1.createReporter();
function getTypeScriptCompilerOptions(src) {
const rootDir = path.join(__dirname, `../../${src}`);
let options = {};
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.baseUrl = rootDir;
options.sourceRoot = util.toFileUri(rootDir);
options.newLine = /\r\n/.test(fs.readFileSync(__filename, 'utf8')) ? 0 : 1;
return options;
}
function createCompile(src, build, emitError) {
const projectPath = path.join(__dirname, '../../', src, 'tsconfig.json');
const overrideOptions = Object.assign(Object.assign({}, getTypeScriptCompilerOptions(src)), { inlineSources: Boolean(build) });
const compilation = tsb.create(projectPath, overrideOptions, false, err => reporter(err));
function pipeline(token) {
const utf8Filter = util.filter(data => /(\/|\\)test(\/|\\).*utf8/.test(data.path));
const tsFilter = util.filter(data => /\.ts$/.test(data.path));
const noDeclarationsFilter = util.filter(data => !(/\.d\.ts$/.test(data.path)));
const input = es.through();
const output = input
.pipe(utf8Filter)
.pipe(bom()) // this is required to preserve BOM in test files that loose it otherwise
.pipe(utf8Filter.restore)
.pipe(tsFilter)
.pipe(util.loadSourcemaps())
.pipe(compilation(token))
.pipe(noDeclarationsFilter)
.pipe(build ? nls() : es.through())
.pipe(noDeclarationsFilter.restore)
.pipe(sourcemaps.write('.', {
addComment: false,
includeContent: !!build,
sourceRoot: overrideOptions.sourceRoot
}))
.pipe(tsFilter.restore)
.pipe(reporter.end(!!emitError));
return es.duplex(input, output);
}
pipeline.tsProjectSrc = () => {
return compilation.src({ base: src });
};
return pipeline;
}
function compileTask(src, out, build) {
return function () {
if (os.totalmem() < 4000000000) {
throw new Error('compilation requires 4GB of RAM');
}
const compile = createCompile(src, build, true);
const srcPipe = gulp.src(`${src}/**`, { base: `${src}` });
let generator = new MonacoGenerator(false);
if (src === 'src') {
generator.execute();
}
return srcPipe
.pipe(generator.stream)
.pipe(compile())
.pipe(gulp.dest(out));
};
}
exports.compileTask = compileTask;
function watchTask(out, build) {
return function () {
const compile = createCompile('src', build);
const src = gulp.src('src/**', { base: 'src' });
const watchSrc = watch('src/**', { base: 'src', readDelay: 200 });
let generator = new MonacoGenerator(true);
generator.execute();
return watchSrc
.pipe(generator.stream)
.pipe(util.incremental(compile, src, true))
.pipe(gulp.dest(out));
};
}
exports.watchTask = watchTask;
const REPO_SRC_FOLDER = path.join(__dirname, '../../src');
class MonacoGenerator {
constructor(isWatch) {
this._executeSoonTimer = null;
this._isWatch = isWatch;
this.stream = es.through();
this._watchedFiles = {};
let onWillReadFile = (moduleId, filePath) => {
if (!this._isWatch) {
return;
}
if (this._watchedFiles[filePath]) {
return;
}
this._watchedFiles[filePath] = true;
fs.watchFile(filePath, () => {
this._declarationResolver.invalidateCache(moduleId);
this._executeSoon();
});
};
this._fsProvider = new class extends monacodts.FSProvider {
readFileSync(moduleId, filePath) {
onWillReadFile(moduleId, filePath);
return super.readFileSync(moduleId, filePath);
}
};
this._declarationResolver = new monacodts.DeclarationResolver(this._fsProvider);
if (this._isWatch) {
fs.watchFile(monacodts.RECIPE_PATH, () => {
this._executeSoon();
});
}
}
_executeSoon() {
if (this._executeSoonTimer !== null) {
clearTimeout(this._executeSoonTimer);
this._executeSoonTimer = null;
}
this._executeSoonTimer = setTimeout(() => {
this._executeSoonTimer = null;
this.execute();
}, 20);
}
_run() {
let r = monacodts.run3(this._declarationResolver);
if (!r && !this._isWatch) {
// The build must always be able to generate the monaco.d.ts
throw new Error(`monaco.d.ts generation error - Cannot continue`);
}
return r;
}
_log(message, ...rest) {
fancyLog(ansiColors.cyan('[monaco.d.ts]'), message, ...rest);
}
execute() {
const startTime = Date.now();
const result = this._run();
if (!result) {
// nothing really changed
return;
}
if (result.isTheSame) {
return;
}
fs.writeFileSync(result.filePath, result.content);
fs.writeFileSync(path.join(REPO_SRC_FOLDER, 'vs/editor/common/standalone/standaloneEnums.ts'), result.enums);
this._log(`monaco.d.ts is changed - total time took ${Date.now() - startTime} ms`);
if (!this._isWatch) {
this.stream.emit('error', 'monaco.d.ts is no longer up to date. Please run gulp watch and commit the new file.');
}
}
}

View file

@ -1,111 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.config = void 0;
const fs = require("fs");
const path = require("path");
const vfs = require("vinyl-fs");
const filter = require("gulp-filter");
const json = require("gulp-json-editor");
const _ = require("underscore");
const util = require("./util");
const electron = require('gulp-atom-electron');
const root = path.dirname(path.dirname(__dirname));
const product = JSON.parse(fs.readFileSync(path.join(root, 'product.json'), 'utf8'));
const commit = util.getVersion(root);
const darwinCreditsTemplate = product.darwinCredits && _.template(fs.readFileSync(path.join(root, product.darwinCredits), 'utf8'));
function darwinBundleDocumentType(extensions, icon) {
return {
name: product.nameLong + ' document',
role: 'Editor',
ostypes: ["TEXT", "utxt", "TUTX", "****"],
extensions: extensions,
iconFile: icon
};
}
exports.config = {
version: util.getElectronVersion(),
productAppName: product.nameLong,
companyName: 'Microsoft Corporation',
copyright: 'Copyright (C) 2019 Microsoft. All rights reserved',
darwinIcon: 'resources/darwin/code.icns',
darwinBundleIdentifier: product.darwinBundleIdentifier,
darwinApplicationCategoryType: 'public.app-category.developer-tools',
darwinHelpBookFolder: 'VS Code HelpBook',
darwinHelpBookName: 'VS Code HelpBook',
darwinBundleDocumentTypes: [
darwinBundleDocumentType(["bat", "cmd"], 'resources/darwin/bat.icns'),
darwinBundleDocumentType(["bowerrc"], 'resources/darwin/bower.icns'),
darwinBundleDocumentType(["c", "h"], 'resources/darwin/c.icns'),
darwinBundleDocumentType(["config", "editorconfig", "gitattributes", "gitconfig", "gitignore", "ini"], 'resources/darwin/config.icns'),
darwinBundleDocumentType(["cc", "cpp", "cxx", "c++", "hh", "hpp", "hxx", "h++"], 'resources/darwin/cpp.icns'),
darwinBundleDocumentType(["cs", "csx"], 'resources/darwin/csharp.icns'),
darwinBundleDocumentType(["css"], 'resources/darwin/css.icns'),
darwinBundleDocumentType(["go"], 'resources/darwin/go.icns'),
darwinBundleDocumentType(["asp", "aspx", "cshtml", "htm", "html", "jshtm", "jsp", "phtml", "shtml"], 'resources/darwin/html.icns'),
darwinBundleDocumentType(["jade"], 'resources/darwin/jade.icns'),
darwinBundleDocumentType(["jav", "java"], 'resources/darwin/java.icns'),
darwinBundleDocumentType(["js", "jscsrc", "jshintrc", "mjs", "cjs"], 'resources/darwin/javascript.icns'),
darwinBundleDocumentType(["json"], 'resources/darwin/json.icns'),
darwinBundleDocumentType(["less"], 'resources/darwin/less.icns'),
darwinBundleDocumentType(["markdown", "md", "mdoc", "mdown", "mdtext", "mdtxt", "mdwn", "mkd", "mkdn"], 'resources/darwin/markdown.icns'),
darwinBundleDocumentType(["php"], 'resources/darwin/php.icns'),
darwinBundleDocumentType(["ps1", "psd1", "psm1"], 'resources/darwin/powershell.icns'),
darwinBundleDocumentType(["py"], 'resources/darwin/python.icns'),
darwinBundleDocumentType(["gemspec", "rb"], 'resources/darwin/ruby.icns'),
darwinBundleDocumentType(["scss"], 'resources/darwin/sass.icns'),
darwinBundleDocumentType(["bash", "bash_login", "bash_logout", "bash_profile", "bashrc", "profile", "rhistory", "rprofile", "sh", "zlogin", "zlogout", "zprofile", "zsh", "zshenv", "zshrc"], 'resources/darwin/shell.icns'),
darwinBundleDocumentType(["sql"], 'resources/darwin/sql.icns'),
darwinBundleDocumentType(["ts"], 'resources/darwin/typescript.icns'),
darwinBundleDocumentType(["tsx", "jsx"], 'resources/darwin/react.icns'),
darwinBundleDocumentType(["vue"], 'resources/darwin/vue.icns'),
darwinBundleDocumentType(["ascx", "csproj", "dtd", "wxi", "wxl", "wxs", "xml", "xaml"], 'resources/darwin/xml.icns'),
darwinBundleDocumentType(["eyaml", "eyml", "yaml", "yml"], 'resources/darwin/yaml.icns'),
darwinBundleDocumentType(["clj", "cljs", "cljx", "clojure", "code-workspace", "coffee", "containerfile", "ctp", "dockerfile", "dot", "edn", "fs", "fsi", "fsscript", "fsx", "handlebars", "hbs", "lua", "m", "makefile", "ml", "mli", "pl", "pl6", "pm", "pm6", "pod", "pp", "properties", "psgi", "pug", "r", "rs", "rt", "svg", "svgz", "t", "txt", "vb", "xcodeproj", "xcworkspace"], 'resources/darwin/default.icns')
],
darwinBundleURLTypes: [{
role: 'Viewer',
name: product.nameLong,
urlSchemes: [product.urlProtocol]
}],
darwinForceDarkModeSupport: true,
darwinCredits: darwinCreditsTemplate ? Buffer.from(darwinCreditsTemplate({ commit: commit, date: new Date().toISOString() })) : undefined,
linuxExecutableName: product.applicationName,
winIcon: 'resources/win32/code.ico',
token: process.env['VSCODE_MIXIN_PASSWORD'] || process.env['GITHUB_TOKEN'] || undefined,
repo: product.electronRepository || undefined
};
function getElectron(arch) {
return () => {
const electronOpts = _.extend({}, exports.config, {
platform: process.platform,
arch: arch === 'armhf' ? 'arm' : arch,
ffmpegChromium: true,
keepDefaultApp: true
});
return vfs.src('package.json')
.pipe(json({ name: product.nameShort }))
.pipe(electron(electronOpts))
.pipe(filter(['**', '!**/app/package.json']))
.pipe(vfs.dest('.build/electron'));
};
}
async function main(arch = process.arch) {
const version = util.getElectronVersion();
const electronPath = path.join(root, '.build', 'electron');
const versionFile = path.join(electronPath, 'version');
const isUpToDate = fs.existsSync(versionFile) && fs.readFileSync(versionFile, 'utf8') === `${version}`;
if (!isUpToDate) {
await util.rimraf(electronPath)();
await util.streamToPromise(getElectron(arch)());
}
}
if (require.main === module) {
main(process.argv[2]).catch(err => {
console.error(err);
process.exit(1);
});
}

View file

@ -1,59 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const path_1 = require("path");
const minimatch = require("minimatch");
const utils_1 = require("./utils");
module.exports = new class {
constructor() {
this.meta = {
messages: {
badImport: 'Imports violates \'{{restrictions}}\' restrictions. See https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
},
docs: {
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
}
};
}
create(context) {
const configs = context.options;
for (const config of configs) {
if (minimatch(context.getFilename(), config.target)) {
return utils_1.createImportRuleListener((node, value) => this._checkImport(context, config, node, value));
}
}
return {};
}
_checkImport(context, config, node, path) {
// resolve relative paths
if (path[0] === '.') {
path = path_1.join(context.getFilename(), path);
}
let restrictions;
if (typeof config.restrictions === 'string') {
restrictions = [config.restrictions];
}
else {
restrictions = config.restrictions;
}
let matched = false;
for (const pattern of restrictions) {
if (minimatch(path, pattern)) {
matched = true;
break;
}
}
if (!matched) {
// None of the restrictions matched
context.report({
loc: node.loc,
messageId: 'badImport',
data: {
restrictions: restrictions.join(' or ')
}
});
}
}
};

View file

@ -1,68 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const path_1 = require("path");
const utils_1 = require("./utils");
module.exports = new class {
constructor() {
this.meta = {
messages: {
layerbreaker: 'Bad layering. You are not allowed to access {{from}} from here, allowed layers are: [{{allowed}}]'
},
docs: {
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
}
};
}
create(context) {
const fileDirname = path_1.dirname(context.getFilename());
const parts = fileDirname.split(/\\|\//);
const ruleArgs = context.options[0];
let config;
for (let i = parts.length - 1; i >= 0; i--) {
if (ruleArgs[parts[i]]) {
config = {
allowed: new Set(ruleArgs[parts[i]]).add(parts[i]),
disallowed: new Set()
};
Object.keys(ruleArgs).forEach(key => {
if (!config.allowed.has(key)) {
config.disallowed.add(key);
}
});
break;
}
}
if (!config) {
// nothing
return {};
}
return utils_1.createImportRuleListener((node, path) => {
if (path[0] === '.') {
path = path_1.join(path_1.dirname(context.getFilename()), path);
}
const parts = path_1.dirname(path).split(/\\|\//);
for (let i = parts.length - 1; i >= 0; i--) {
const part = parts[i];
if (config.allowed.has(part)) {
// GOOD - same layer
break;
}
if (config.disallowed.has(part)) {
// BAD - wrong layer
context.report({
loc: node.loc,
messageId: 'layerbreaker',
data: {
from: part,
allowed: [...config.allowed.keys()].join(', ')
}
});
break;
}
}
});
}
};

View file

@ -1,38 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const path_1 = require("path");
const utils_1 = require("./utils");
module.exports = new class NoNlsInStandaloneEditorRule {
constructor() {
this.meta = {
messages: {
noNls: 'Not allowed to import vs/nls in standalone editor modules. Use standaloneStrings.ts'
}
};
}
create(context) {
const fileName = context.getFilename();
if (/vs(\/|\\)editor(\/|\\)standalone(\/|\\)/.test(fileName)
|| /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone(\/|\\)/.test(fileName)
|| /vs(\/|\\)editor(\/|\\)editor.api/.test(fileName)
|| /vs(\/|\\)editor(\/|\\)editor.main/.test(fileName)
|| /vs(\/|\\)editor(\/|\\)editor.worker/.test(fileName)) {
return utils_1.createImportRuleListener((node, path) => {
// resolve relative paths
if (path[0] === '.') {
path = path_1.join(context.getFilename(), path);
}
if (/vs(\/|\\)nls/.test(path)) {
context.report({
loc: node.loc,
messageId: 'noNls'
});
}
});
}
return {};
}
};

View file

@ -1,41 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const path_1 = require("path");
const utils_1 = require("./utils");
module.exports = new class NoNlsInStandaloneEditorRule {
constructor() {
this.meta = {
messages: {
badImport: 'Not allowed to import standalone editor modules.'
},
docs: {
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
}
};
}
create(context) {
if (/vs(\/|\\)editor/.test(context.getFilename())) {
// the vs/editor folder is allowed to use the standalone editor
return {};
}
return utils_1.createImportRuleListener((node, path) => {
// resolve relative paths
if (path[0] === '.') {
path = path_1.join(context.getFilename(), path);
}
if (/vs(\/|\\)editor(\/|\\)standalone(\/|\\)/.test(path)
|| /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone(\/|\\)/.test(path)
|| /vs(\/|\\)editor(\/|\\)editor.api/.test(path)
|| /vs(\/|\\)editor(\/|\\)editor.main/.test(path)
|| /vs(\/|\\)editor(\/|\\)editor.worker/.test(path)) {
context.report({
loc: node.loc,
messageId: 'badImport'
});
}
});
}
};

View file

@ -1,111 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var _a;
const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
function isStringLiteral(node) {
return !!node && node.type === experimental_utils_1.AST_NODE_TYPES.Literal && typeof node.value === 'string';
}
function isDoubleQuoted(node) {
return node.raw[0] === '"' && node.raw[node.raw.length - 1] === '"';
}
module.exports = new (_a = class NoUnexternalizedStrings {
constructor() {
this.meta = {
messages: {
doubleQuoted: 'Only use double-quoted strings for externalized strings.',
badKey: 'The key \'{{key}}\' doesn\'t conform to a valid localize identifier.',
duplicateKey: 'Duplicate key \'{{key}}\' with different message value.',
badMessage: 'Message argument to \'{{message}}\' must be a string literal.'
}
};
}
create(context) {
const externalizedStringLiterals = new Map();
const doubleQuotedStringLiterals = new Set();
function collectDoubleQuotedStrings(node) {
if (isStringLiteral(node) && isDoubleQuoted(node)) {
doubleQuotedStringLiterals.add(node);
}
}
function visitLocalizeCall(node) {
// localize(key, message)
const [keyNode, messageNode] = node.arguments;
// (1)
// extract key so that it can be checked later
let key;
if (isStringLiteral(keyNode)) {
doubleQuotedStringLiterals.delete(keyNode); //todo@joh reconsider
key = keyNode.value;
}
else if (keyNode.type === experimental_utils_1.AST_NODE_TYPES.ObjectExpression) {
for (let property of keyNode.properties) {
if (property.type === experimental_utils_1.AST_NODE_TYPES.Property && !property.computed) {
if (property.key.type === experimental_utils_1.AST_NODE_TYPES.Identifier && property.key.name === 'key') {
if (isStringLiteral(property.value)) {
doubleQuotedStringLiterals.delete(property.value); //todo@joh reconsider
key = property.value.value;
break;
}
}
}
}
}
if (typeof key === 'string') {
let array = externalizedStringLiterals.get(key);
if (!array) {
array = [];
externalizedStringLiterals.set(key, array);
}
array.push({ call: node, message: messageNode });
}
// (2)
// remove message-argument from doubleQuoted list and make
// sure it is a string-literal
doubleQuotedStringLiterals.delete(messageNode);
if (!isStringLiteral(messageNode)) {
context.report({
loc: messageNode.loc,
messageId: 'badMessage',
data: { message: context.getSourceCode().getText(node) }
});
}
}
function reportBadStringsAndBadKeys() {
// (1)
// report all strings that are in double quotes
for (const node of doubleQuotedStringLiterals) {
context.report({ loc: node.loc, messageId: 'doubleQuoted' });
}
for (const [key, values] of externalizedStringLiterals) {
// (2)
// report all invalid NLS keys
if (!key.match(NoUnexternalizedStrings._rNlsKeys)) {
for (let value of values) {
context.report({ loc: value.call.loc, messageId: 'badKey', data: { key } });
}
}
// (2)
// report all invalid duplicates (same key, different message)
if (values.length > 1) {
for (let i = 1; i < values.length; i++) {
if (context.getSourceCode().getText(values[i - 1].message) !== context.getSourceCode().getText(values[i].message)) {
context.report({ loc: values[i].call.loc, messageId: 'duplicateKey', data: { key } });
}
}
}
}
}
return {
['Literal']: (node) => collectDoubleQuotedStrings(node),
['ExpressionStatement[directive] Literal:exit']: (node) => doubleQuotedStringLiterals.delete(node),
['CallExpression[callee.type="MemberExpression"][callee.object.name="nls"][callee.property.name="localize"]:exit']: (node) => visitLocalizeCall(node),
['CallExpression[callee.name="localize"][arguments.length>=2]:exit']: (node) => visitLocalizeCall(node),
['Program:exit']: reportBadStringsAndBadKeys,
};
}
},
_a._rNlsKeys = /^[_a-zA-Z0-9][ .\-_a-zA-Z0-9]*$/,
_a);

View file

@ -1,57 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var _a;
const fs_1 = require("fs");
const utils_1 = require("./utils");
module.exports = new (_a = class TranslationRemind {
constructor() {
this.meta = {
messages: {
missing: 'Please add \'{{resource}}\' to ./build/lib/i18n.resources.json file to use translations here.'
}
};
}
create(context) {
return utils_1.createImportRuleListener((node, path) => this._checkImport(context, node, path));
}
_checkImport(context, node, path) {
if (path !== TranslationRemind.NLS_MODULE) {
return;
}
const currentFile = context.getFilename();
const matchService = currentFile.match(/vs\/workbench\/services\/\w+/);
const matchPart = currentFile.match(/vs\/workbench\/contrib\/\w+/);
if (!matchService && !matchPart) {
return;
}
const resource = matchService ? matchService[0] : matchPart[0];
let resourceDefined = false;
let json;
try {
json = fs_1.readFileSync('./build/lib/i18n.resources.json', 'utf8');
}
catch (e) {
console.error('[translation-remind rule]: File with resources to pull from Transifex was not found. Aborting translation resource check for newly defined workbench part/service.');
return;
}
const workbenchResources = JSON.parse(json).workbench;
workbenchResources.forEach((existingResource) => {
if (existingResource.name === resource) {
resourceDefined = true;
return;
}
});
if (!resourceDefined) {
context.report({
loc: node.loc,
messageId: 'missing',
data: { resource }
});
}
}
},
_a.NLS_MODULE = 'vs/nls',
_a);

View file

@ -1,37 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.createImportRuleListener = void 0;
function createImportRuleListener(validateImport) {
function _checkImport(node) {
if (node && node.type === 'Literal' && typeof node.value === 'string') {
validateImport(node, node.value);
}
}
return {
// import ??? from 'module'
ImportDeclaration: (node) => {
_checkImport(node.source);
},
// import('module').then(...) OR await import('module')
['CallExpression[callee.type="Import"][arguments.length=1] > Literal']: (node) => {
_checkImport(node);
},
// import foo = ...
['TSImportEqualsDeclaration > TSExternalModuleReference > Literal']: (node) => {
_checkImport(node);
},
// export ?? from 'module'
ExportAllDeclaration: (node) => {
_checkImport(node.source);
},
// export {foo} from 'module'
ExportNamedDeclaration: (node) => {
_checkImport(node.source);
},
};
}
exports.createImportRuleListener = createImportRuleListener;

View file

@ -1,35 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
module.exports = new class ApiLiteralOrTypes {
constructor() {
this.meta = {
docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#creating-objects' },
messages: { sync: '`createXYZ`-functions are constructor-replacements and therefore must return sync', }
};
}
create(context) {
return {
['TSDeclareFunction Identifier[name=/create.*/]']: (node) => {
var _a;
const decl = node.parent;
if (((_a = decl.returnType) === null || _a === void 0 ? void 0 : _a.typeAnnotation.type) !== experimental_utils_1.AST_NODE_TYPES.TSTypeReference) {
return;
}
if (decl.returnType.typeAnnotation.typeName.type !== experimental_utils_1.AST_NODE_TYPES.Identifier) {
return;
}
const ident = decl.returnType.typeAnnotation.typeName.name;
if (ident === 'Promise' || ident === 'Thenable') {
context.report({
node,
messageId: 'sync'
});
}
}
};
}
};

View file

@ -1,87 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var _a;
const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
module.exports = new (_a = class ApiEventNaming {
constructor() {
this.meta = {
docs: {
url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#event-naming'
},
messages: {
naming: 'Event names must follow this patten: `on[Did|Will]<Verb><Subject>`',
verb: 'Unknown verb \'{{verb}}\' - is this really a verb? Iff so, then add this verb to the configuration',
subject: 'Unknown subject \'{{subject}}\' - This subject has not been used before but it should refer to something in the API',
unknown: 'UNKNOWN event declaration, lint-rule needs tweaking'
}
};
}
create(context) {
const config = context.options[0];
const allowed = new Set(config.allowed);
const verbs = new Set(config.verbs);
return {
['TSTypeAnnotation TSTypeReference Identifier[name="Event"]']: (node) => {
var _a, _b;
const def = (_b = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.parent;
const ident = this.getIdent(def);
if (!ident) {
// event on unknown structure...
return context.report({
node,
message: 'unknown'
});
}
if (allowed.has(ident.name)) {
// configured exception
return;
}
const match = ApiEventNaming._nameRegExp.exec(ident.name);
if (!match) {
context.report({
node: ident,
messageId: 'naming'
});
return;
}
// check that <verb> is spelled out (configured) as verb
if (!verbs.has(match[2].toLowerCase())) {
context.report({
node: ident,
messageId: 'verb',
data: { verb: match[2] }
});
}
// check that a subject (if present) has occurred
if (match[3]) {
const regex = new RegExp(match[3], 'ig');
const parts = context.getSourceCode().getText().split(regex);
if (parts.length < 3) {
context.report({
node: ident,
messageId: 'subject',
data: { subject: match[3] }
});
}
}
}
};
}
getIdent(def) {
if (!def) {
return;
}
if (def.type === experimental_utils_1.AST_NODE_TYPES.Identifier) {
return def;
}
else if ((def.type === experimental_utils_1.AST_NODE_TYPES.TSPropertySignature || def.type === experimental_utils_1.AST_NODE_TYPES.ClassProperty) && def.key.type === experimental_utils_1.AST_NODE_TYPES.Identifier) {
return def.key;
}
return this.getIdent(def.parent);
}
},
_a._nameRegExp = /on(Did|Will)([A-Z][a-z]+)([A-Z][a-z]+)?/,
_a);

View file

@ -1,30 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
var _a;
module.exports = new (_a = class ApiInterfaceNaming {
constructor() {
this.meta = {
messages: {
naming: 'Interfaces must not be prefixed with uppercase `I`',
}
};
}
create(context) {
return {
['TSInterfaceDeclaration Identifier']: (node) => {
const name = node.name;
if (ApiInterfaceNaming._nameRegExp.test(name)) {
context.report({
node,
messageId: 'naming'
});
}
}
};
}
},
_a._nameRegExp = /I[A-Z]/,
_a);

View file

@ -1,27 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
module.exports = new class ApiLiteralOrTypes {
constructor() {
this.meta = {
docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#enums' },
messages: { useEnum: 'Use enums, not literal-or-types', }
};
}
create(context) {
return {
['TSTypeAnnotation TSUnionType TSLiteralType']: (node) => {
var _a;
if (((_a = node.literal) === null || _a === void 0 ? void 0 : _a.type) === 'TSNullKeyword') {
return;
}
context.report({
node: node,
messageId: 'useEnum'
});
}
};
}
};

View file

@ -1,325 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.translatePackageJSON = exports.scanBuiltinExtensions = exports.packageMarketplaceExtensionsStream = exports.packageLocalExtensionsStream = exports.fromMarketplace = void 0;
const es = require("event-stream");
const fs = require("fs");
const glob = require("glob");
const gulp = require("gulp");
const path = require("path");
const File = require("vinyl");
const vsce = require("vsce");
const stats_1 = require("./stats");
const util2 = require("./util");
const remote = require("gulp-remote-retry-src");
const vzip = require('gulp-vinyl-zip');
const filter = require("gulp-filter");
const rename = require("gulp-rename");
const fancyLog = require("fancy-log");
const ansiColors = require("ansi-colors");
const buffer = require('gulp-buffer');
const json = require("gulp-json-editor");
const jsoncParser = require("jsonc-parser");
const webpack = require('webpack');
const webpackGulp = require('webpack-stream');
const util = require('./util');
const root = path.dirname(path.dirname(__dirname));
const commit = util.getVersion(root);
const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`;
function minifyExtensionResources(input) {
const jsonFilter = filter(['**/*.json', '**/*.code-snippets'], { restore: true });
return input
.pipe(jsonFilter)
.pipe(buffer())
.pipe(es.mapSync((f) => {
const errors = [];
const value = jsoncParser.parse(f.contents.toString('utf8'), errors);
if (errors.length === 0) {
// file parsed OK => just stringify to drop whitespace and comments
f.contents = Buffer.from(JSON.stringify(value));
}
return f;
}))
.pipe(jsonFilter.restore);
}
function updateExtensionPackageJSON(input, update) {
const packageJsonFilter = filter('extensions/*/package.json', { restore: true });
return input
.pipe(packageJsonFilter)
.pipe(buffer())
.pipe(es.mapSync((f) => {
const data = JSON.parse(f.contents.toString('utf8'));
f.contents = Buffer.from(JSON.stringify(update(data)));
return f;
}))
.pipe(packageJsonFilter.restore);
}
function fromLocal(extensionPath, forWeb) {
const webpackConfigFileName = forWeb ? 'extension-browser.webpack.config.js' : 'extension.webpack.config.js';
const isWebPacked = fs.existsSync(path.join(extensionPath, webpackConfigFileName));
let input = isWebPacked
? fromLocalWebpack(extensionPath, webpackConfigFileName)
: fromLocalNormal(extensionPath);
if (isWebPacked) {
input = updateExtensionPackageJSON(input, (data) => {
delete data.scripts;
delete data.dependencies;
delete data.devDependencies;
if (data.main) {
data.main = data.main.replace('/out/', /dist/);
}
return data;
});
}
return input;
}
function fromLocalWebpack(extensionPath, webpackConfigFileName) {
const result = es.through();
const packagedDependencies = [];
const packageJsonConfig = require(path.join(extensionPath, 'package.json'));
if (packageJsonConfig.dependencies) {
const webpackRootConfig = require(path.join(extensionPath, webpackConfigFileName));
for (const key in webpackRootConfig.externals) {
if (key in packageJsonConfig.dependencies) {
packagedDependencies.push(key);
}
}
}
vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Yarn, packagedDependencies }).then(fileNames => {
const files = fileNames
.map(fileName => path.join(extensionPath, fileName))
.map(filePath => new File({
path: filePath,
stat: fs.statSync(filePath),
base: extensionPath,
contents: fs.createReadStream(filePath)
}));
// check for a webpack configuration files, then invoke webpack
// and merge its output with the files stream.
const webpackConfigLocations = glob.sync(path.join(extensionPath, '**', webpackConfigFileName), { ignore: ['**/node_modules'] });
const webpackStreams = webpackConfigLocations.map(webpackConfigPath => {
const webpackDone = (err, stats) => {
fancyLog(`Bundled extension: ${ansiColors.yellow(path.join(path.basename(extensionPath), path.relative(extensionPath, webpackConfigPath)))}...`);
if (err) {
result.emit('error', err);
}
const { compilation } = stats;
if (compilation.errors.length > 0) {
result.emit('error', compilation.errors.join('\n'));
}
if (compilation.warnings.length > 0) {
result.emit('error', compilation.warnings.join('\n'));
}
};
const webpackConfig = Object.assign(Object.assign({}, require(webpackConfigPath)), { mode: 'production' });
const relativeOutputPath = path.relative(extensionPath, webpackConfig.output.path);
return webpackGulp(webpackConfig, webpack, webpackDone)
.pipe(es.through(function (data) {
data.stat = data.stat || {};
data.base = extensionPath;
this.emit('data', data);
}))
.pipe(es.through(function (data) {
// source map handling:
// * rewrite sourceMappingURL
// * save to disk so that upload-task picks this up
const contents = data.contents.toString('utf8');
data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, function (_m, g1) {
return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`;
}), 'utf8');
this.emit('data', data);
}));
});
es.merge(...webpackStreams, es.readArray(files))
// .pipe(es.through(function (data) {
// // debug
// console.log('out', data.path, data.contents.length);
// this.emit('data', data);
// }))
.pipe(result);
}).catch(err => {
console.error(extensionPath);
console.error(packagedDependencies);
result.emit('error', err);
});
return result.pipe(stats_1.createStatsStream(path.basename(extensionPath)));
}
function fromLocalNormal(extensionPath) {
const result = es.through();
vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Yarn })
.then(fileNames => {
const files = fileNames
.map(fileName => path.join(extensionPath, fileName))
.map(filePath => new File({
path: filePath,
stat: fs.statSync(filePath),
base: extensionPath,
contents: fs.createReadStream(filePath)
}));
es.readArray(files).pipe(result);
})
.catch(err => result.emit('error', err));
return result.pipe(stats_1.createStatsStream(path.basename(extensionPath)));
}
const baseHeaders = {
'X-Market-Client-Id': 'VSCode Build',
'User-Agent': 'VSCode Build',
'X-Market-User-Id': '291C1CD0-051A-4123-9B4B-30D60EF52EE2',
};
function fromMarketplace(extensionName, version, metadata) {
const [publisher, name] = extensionName.split('.');
const url = `https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${publisher}/vsextensions/${name}/${version}/vspackage`;
fancyLog('Downloading extension:', ansiColors.yellow(`${extensionName}@${version}`), '...');
const options = {
base: url,
requestOptions: {
gzip: true,
headers: baseHeaders
}
};
const packageJsonFilter = filter('package.json', { restore: true });
return remote('', options)
.pipe(vzip.src())
.pipe(filter('extension/**'))
.pipe(rename(p => p.dirname = p.dirname.replace(/^extension\/?/, '')))
.pipe(packageJsonFilter)
.pipe(buffer())
.pipe(json({ __metadata: metadata }))
.pipe(packageJsonFilter.restore);
}
exports.fromMarketplace = fromMarketplace;
const excludedExtensions = [
'vscode-api-tests',
'vscode-colorize-tests',
'vscode-test-resolver',
'ms-vscode.node-debug',
'ms-vscode.node-debug2',
'vscode-notebook-tests',
'vscode-custom-editor-tests',
];
const marketplaceWebExtensions = [
'ms-vscode.references-view'
];
const productJson = JSON.parse(fs.readFileSync(path.join(__dirname, '../../product.json'), 'utf8'));
const builtInExtensions = productJson.builtInExtensions || [];
const webBuiltInExtensions = productJson.webBuiltInExtensions || [];
/**
* Loosely based on `getExtensionKind` from `src/vs/workbench/services/extensions/common/extensionsUtil.ts`
*/
function isWebExtension(manifest) {
if (typeof manifest.extensionKind !== 'undefined') {
const extensionKind = Array.isArray(manifest.extensionKind) ? manifest.extensionKind : [manifest.extensionKind];
return (extensionKind.indexOf('web') >= 0);
}
return (!Boolean(manifest.main) || Boolean(manifest.browser));
}
function packageLocalExtensionsStream(forWeb) {
const localExtensionsDescriptions = (glob.sync('extensions/*/package.json')
.map(manifestPath => {
const absoluteManifestPath = path.join(root, manifestPath);
const extensionPath = path.dirname(path.join(root, manifestPath));
const extensionName = path.basename(extensionPath);
return { name: extensionName, path: extensionPath, manifestPath: absoluteManifestPath };
})
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
.filter(({ manifestPath }) => (forWeb ? isWebExtension(require(manifestPath)) : true)));
const localExtensionsStream = minifyExtensionResources(es.merge(...localExtensionsDescriptions.map(extension => {
return fromLocal(extension.path, forWeb)
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
})));
let result;
if (forWeb) {
result = localExtensionsStream;
}
else {
// also include shared node modules
result = es.merge(localExtensionsStream, gulp.src('extensions/node_modules/**', { base: '.' }));
}
return (result
.pipe(util2.setExecutableBit(['**/*.sh'])));
}
exports.packageLocalExtensionsStream = packageLocalExtensionsStream;
function packageMarketplaceExtensionsStream(forWeb) {
const marketplaceExtensionsDescriptions = [
...builtInExtensions.filter(({ name }) => (forWeb ? marketplaceWebExtensions.indexOf(name) >= 0 : true)),
...(forWeb ? webBuiltInExtensions : [])
];
const marketplaceExtensionsStream = minifyExtensionResources(es.merge(...marketplaceExtensionsDescriptions
.map(extension => {
const input = fromMarketplace(extension.name, extension.version, extension.metadata)
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
return updateExtensionPackageJSON(input, (data) => {
delete data.scripts;
delete data.dependencies;
delete data.devDependencies;
return data;
});
})));
return (marketplaceExtensionsStream
.pipe(util2.setExecutableBit(['**/*.sh'])));
}
exports.packageMarketplaceExtensionsStream = packageMarketplaceExtensionsStream;
function scanBuiltinExtensions(extensionsRoot, exclude = []) {
const scannedExtensions = [];
try {
const extensionsFolders = fs.readdirSync(extensionsRoot);
for (const extensionFolder of extensionsFolders) {
if (exclude.indexOf(extensionFolder) >= 0) {
continue;
}
const packageJSONPath = path.join(extensionsRoot, extensionFolder, 'package.json');
if (!fs.existsSync(packageJSONPath)) {
continue;
}
let packageJSON = JSON.parse(fs.readFileSync(packageJSONPath).toString('utf8'));
if (!isWebExtension(packageJSON)) {
continue;
}
const children = fs.readdirSync(path.join(extensionsRoot, extensionFolder));
const packageNLSPath = children.filter(child => child === 'package.nls.json')[0];
const packageNLS = packageNLSPath ? JSON.parse(fs.readFileSync(path.join(extensionsRoot, extensionFolder, packageNLSPath)).toString()) : undefined;
const readme = children.filter(child => /^readme(\.txt|\.md|)$/i.test(child))[0];
const changelog = children.filter(child => /^changelog(\.txt|\.md|)$/i.test(child))[0];
scannedExtensions.push({
extensionPath: extensionFolder,
packageJSON,
packageNLS,
readmePath: readme ? path.join(extensionFolder, readme) : undefined,
changelogPath: changelog ? path.join(extensionFolder, changelog) : undefined,
});
}
return scannedExtensions;
}
catch (ex) {
return scannedExtensions;
}
}
exports.scanBuiltinExtensions = scanBuiltinExtensions;
function translatePackageJSON(packageJSON, packageNLSPath) {
const CharCode_PC = '%'.charCodeAt(0);
const packageNls = JSON.parse(fs.readFileSync(packageNLSPath).toString());
const translate = (obj) => {
for (let key in obj) {
const val = obj[key];
if (Array.isArray(val)) {
val.forEach(translate);
}
else if (val && typeof val === 'object') {
translate(val);
}
else if (typeof val === 'string' && val.charCodeAt(0) === CharCode_PC && val.charCodeAt(val.length - 1) === CharCode_PC) {
const translated = packageNls[val.substr(1, val.length - 2)];
if (translated) {
obj[key] = translated;
}
}
}
};
translate(packageJSON);
return packageJSON;
}
exports.translatePackageJSON = translatePackageJSON;

View file

@ -1,54 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.getVersion = void 0;
const path = require("path");
const fs = require("fs");
/**
* Returns the sha1 commit version of a repository or undefined in case of failure.
*/
function getVersion(repo) {
const git = path.join(repo, '.git');
const headPath = path.join(git, 'HEAD');
let head;
try {
head = fs.readFileSync(headPath, 'utf8').trim();
}
catch (e) {
return undefined;
}
if (/^[0-9a-f]{40}$/i.test(head)) {
return head;
}
const refMatch = /^ref: (.*)$/.exec(head);
if (!refMatch) {
return undefined;
}
const ref = refMatch[1];
const refPath = path.join(git, ref);
try {
return fs.readFileSync(refPath, 'utf8').trim();
}
catch (e) {
// noop
}
const packedRefsPath = path.join(git, 'packed-refs');
let refsRaw;
try {
refsRaw = fs.readFileSync(packedRefsPath, 'utf8').trim();
}
catch (e) {
return undefined;
}
const refsRegex = /^([0-9a-f]{40})\s+(.+)$/gm;
let refsMatch;
let refs = {};
while (refsMatch = refsRegex.exec(refsRaw)) {
refs[refsMatch[2]] = refsMatch[1];
}
return refs[ref];
}
exports.getVersion = getVersion;

File diff suppressed because it is too large Load diff

View file

@ -1,285 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
const ts = require("typescript");
const fs_1 = require("fs");
const path_1 = require("path");
const minimatch_1 = require("minimatch");
//
// #############################################################################################
//
// A custom typescript checker for the specific task of detecting the use of certain types in a
// layer that does not allow such use. For example:
// - using DOM globals in common/node/electron-main layer (e.g. HTMLElement)
// - using node.js globals in common/browser layer (e.g. process)
//
// Make changes to below RULES to lift certain files from these checks only if absolutely needed
//
// #############################################################################################
//
// Types we assume are present in all implementations of JS VMs (node.js, browsers)
// Feel free to add more core types as you see needed if present in node.js and browsers
const CORE_TYPES = [
'require',
'atob',
'btoa',
'setTimeout',
'clearTimeout',
'setInterval',
'clearInterval',
'console',
'log',
'info',
'warn',
'error',
'group',
'groupEnd',
'table',
'assert',
'Error',
'String',
'throws',
'stack',
'captureStackTrace',
'stackTraceLimit',
'TextDecoder',
'TextEncoder',
'encode',
'decode',
'self',
'trimLeft',
'trimRight'
];
// Types that are defined in a common layer but are known to be only
// available in native environments should not be allowed in browser
const NATIVE_TYPES = [
'NativeParsedArgs',
'INativeEnvironmentService',
'INativeWindowConfiguration',
'ICommonNativeHostService'
];
const RULES = [
// Tests: skip
{
target: '**/vs/**/test/**',
skip: true // -> skip all test files
},
// Common: vs/base/common/platform.ts
{
target: '**/vs/base/common/platform.ts',
allowedTypes: [
...CORE_TYPES,
// Safe access to postMessage() and friends
'MessageEvent',
'data'
],
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts',
'@types/node' // no node.js
]
},
// Common: vs/platform/environment/common/argv.ts
{
target: '**/vs/platform/environment/common/argv.ts',
disallowedTypes: [ /* Ignore native types that are defined from here */],
allowedTypes: CORE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts',
'@types/node' // no node.js
]
},
// Common: vs/platform/environment/common/environment.ts
{
target: '**/vs/platform/environment/common/environment.ts',
disallowedTypes: [ /* Ignore native types that are defined from here */],
allowedTypes: CORE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts',
'@types/node' // no node.js
]
},
// Common: vs/platform/windows/common/windows.ts
{
target: '**/vs/platform/windows/common/windows.ts',
disallowedTypes: [ /* Ignore native types that are defined from here */],
allowedTypes: CORE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts',
'@types/node' // no node.js
]
},
// Common: vs/platform/native/common/native.ts
{
target: '**/vs/platform/native/common/native.ts',
disallowedTypes: [ /* Ignore native types that are defined from here */],
allowedTypes: CORE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts',
'@types/node' // no node.js
]
},
// Common: vs/workbench/api/common/extHostExtensionService.ts
{
target: '**/vs/workbench/api/common/extHostExtensionService.ts',
allowedTypes: [
...CORE_TYPES,
// Safe access to global
'global'
],
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts',
'@types/node' // no node.js
]
},
// Common
{
target: '**/vs/**/common/**',
allowedTypes: CORE_TYPES,
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'lib.dom.d.ts',
'@types/node' // no node.js
]
},
// Browser
{
target: '**/vs/**/browser/**',
allowedTypes: CORE_TYPES,
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'@types/node' // no node.js
]
},
// Browser (editor contrib)
{
target: '**/src/vs/editor/contrib/**',
allowedTypes: CORE_TYPES,
disallowedTypes: NATIVE_TYPES,
disallowedDefinitions: [
'@types/node' // no node.js
]
},
// node.js
{
target: '**/vs/**/node/**',
allowedTypes: [
...CORE_TYPES,
// --> types from node.d.ts that duplicate from lib.dom.d.ts
'URL',
'protocol',
'hostname',
'port',
'pathname',
'search',
'username',
'password'
],
disallowedDefinitions: [
'lib.dom.d.ts' // no DOM
]
},
// Electron (sandbox)
{
target: '**/vs/**/electron-sandbox/**',
allowedTypes: CORE_TYPES,
disallowedDefinitions: [
'@types/node' // no node.js
]
},
// Electron (renderer): skip
{
target: '**/vs/**/electron-browser/**',
skip: true // -> supports all types
},
// Electron (main)
{
target: '**/vs/**/electron-main/**',
allowedTypes: [
...CORE_TYPES,
// --> types from electron.d.ts that duplicate from lib.dom.d.ts
'Event',
'Request'
],
disallowedDefinitions: [
'lib.dom.d.ts' // no DOM
]
}
];
const TS_CONFIG_PATH = path_1.join(__dirname, '../../', 'src', 'tsconfig.json');
let hasErrors = false;
function checkFile(program, sourceFile, rule) {
checkNode(sourceFile);
function checkNode(node) {
var _a, _b;
if (node.kind !== ts.SyntaxKind.Identifier) {
return ts.forEachChild(node, checkNode); // recurse down
}
const text = node.getText(sourceFile);
if ((_a = rule.allowedTypes) === null || _a === void 0 ? void 0 : _a.some(allowed => allowed === text)) {
return; // override
}
if ((_b = rule.disallowedTypes) === null || _b === void 0 ? void 0 : _b.some(disallowed => disallowed === text)) {
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
console.log(`[build/lib/layersChecker.ts]: Reference to '${text}' violates layer '${rule.target}' (${sourceFile.fileName} (${line + 1},${character + 1})`);
hasErrors = true;
return;
}
const checker = program.getTypeChecker();
const symbol = checker.getSymbolAtLocation(node);
if (symbol) {
const declarations = symbol.declarations;
if (Array.isArray(declarations)) {
for (const declaration of declarations) {
if (declaration) {
const parent = declaration.parent;
if (parent) {
const parentSourceFile = parent.getSourceFile();
if (parentSourceFile) {
const definitionFileName = parentSourceFile.fileName;
if (rule.disallowedDefinitions) {
for (const disallowedDefinition of rule.disallowedDefinitions) {
if (definitionFileName.indexOf(disallowedDefinition) >= 0) {
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
console.log(`[build/lib/layersChecker.ts]: Reference to '${text}' from '${disallowedDefinition}' violates layer '${rule.target}' (${sourceFile.fileName} (${line + 1},${character + 1})`);
hasErrors = true;
return;
}
}
}
}
}
}
}
}
}
}
}
function createProgram(tsconfigPath) {
const tsConfig = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
const configHostParser = { fileExists: fs_1.existsSync, readDirectory: ts.sys.readDirectory, readFile: file => fs_1.readFileSync(file, 'utf8'), useCaseSensitiveFileNames: process.platform === 'linux' };
const tsConfigParsed = ts.parseJsonConfigFileContent(tsConfig.config, configHostParser, path_1.resolve(path_1.dirname(tsconfigPath)), { noEmit: true });
const compilerHost = ts.createCompilerHost(tsConfigParsed.options, true);
return ts.createProgram(tsConfigParsed.fileNames, tsConfigParsed.options, compilerHost);
}
//
// Create program and start checking
//
const program = createProgram(TS_CONFIG_PATH);
for (const sourceFile of program.getSourceFiles()) {
for (const rule of RULES) {
if (minimatch_1.match([sourceFile.fileName], rule.target).length > 0) {
if (!rule.skip) {
checkFile(program, sourceFile, rule);
}
break;
}
}
}
if (hasErrors) {
process.exit(1);
}

View file

@ -1,354 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
const ts = require("typescript");
const lazy = require("lazy.js");
const event_stream_1 = require("event-stream");
const File = require("vinyl");
const sm = require("source-map");
const path = require("path");
var CollectStepResult;
(function (CollectStepResult) {
CollectStepResult[CollectStepResult["Yes"] = 0] = "Yes";
CollectStepResult[CollectStepResult["YesAndRecurse"] = 1] = "YesAndRecurse";
CollectStepResult[CollectStepResult["No"] = 2] = "No";
CollectStepResult[CollectStepResult["NoAndRecurse"] = 3] = "NoAndRecurse";
})(CollectStepResult || (CollectStepResult = {}));
function collect(node, fn) {
const result = [];
function loop(node) {
const stepResult = fn(node);
if (stepResult === CollectStepResult.Yes || stepResult === CollectStepResult.YesAndRecurse) {
result.push(node);
}
if (stepResult === CollectStepResult.YesAndRecurse || stepResult === CollectStepResult.NoAndRecurse) {
ts.forEachChild(node, loop);
}
}
loop(node);
return result;
}
function clone(object) {
const result = {};
for (const id in object) {
result[id] = object[id];
}
return result;
}
function template(lines) {
let indent = '', wrap = '';
if (lines.length > 1) {
indent = '\t';
wrap = '\n';
}
return `/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/
define([], [${wrap + lines.map(l => indent + l).join(',\n') + wrap}]);`;
}
/**
* Returns a stream containing the patched JavaScript and source maps.
*/
function nls() {
const input = event_stream_1.through();
const output = input.pipe(event_stream_1.through(function (f) {
if (!f.sourceMap) {
return this.emit('error', new Error(`File ${f.relative} does not have sourcemaps.`));
}
let source = f.sourceMap.sources[0];
if (!source) {
return this.emit('error', new Error(`File ${f.relative} does not have a source in the source map.`));
}
const root = f.sourceMap.sourceRoot;
if (root) {
source = path.join(root, source);
}
const typescript = f.sourceMap.sourcesContent[0];
if (!typescript) {
return this.emit('error', new Error(`File ${f.relative} does not have the original content in the source map.`));
}
nls.patchFiles(f, typescript).forEach(f => this.emit('data', f));
}));
return event_stream_1.duplex(input, output);
}
function isImportNode(node) {
return node.kind === ts.SyntaxKind.ImportDeclaration || node.kind === ts.SyntaxKind.ImportEqualsDeclaration;
}
(function (nls_1) {
function fileFrom(file, contents, path = file.path) {
return new File({
contents: Buffer.from(contents),
base: file.base,
cwd: file.cwd,
path: path
});
}
nls_1.fileFrom = fileFrom;
function mappedPositionFrom(source, lc) {
return { source, line: lc.line + 1, column: lc.character };
}
nls_1.mappedPositionFrom = mappedPositionFrom;
function lcFrom(position) {
return { line: position.line - 1, character: position.column };
}
nls_1.lcFrom = lcFrom;
class SingleFileServiceHost {
constructor(options, filename, contents) {
this.options = options;
this.filename = filename;
this.getCompilationSettings = () => this.options;
this.getScriptFileNames = () => [this.filename];
this.getScriptVersion = () => '1';
this.getScriptSnapshot = (name) => name === this.filename ? this.file : this.lib;
this.getCurrentDirectory = () => '';
this.getDefaultLibFileName = () => 'lib.d.ts';
this.file = ts.ScriptSnapshot.fromString(contents);
this.lib = ts.ScriptSnapshot.fromString('');
}
}
nls_1.SingleFileServiceHost = SingleFileServiceHost;
function isCallExpressionWithinTextSpanCollectStep(textSpan, node) {
if (!ts.textSpanContainsTextSpan({ start: node.pos, length: node.end - node.pos }, textSpan)) {
return CollectStepResult.No;
}
return node.kind === ts.SyntaxKind.CallExpression ? CollectStepResult.YesAndRecurse : CollectStepResult.NoAndRecurse;
}
function analyze(contents, options = {}) {
const filename = 'file.ts';
const serviceHost = new SingleFileServiceHost(Object.assign(clone(options), { noResolve: true }), filename, contents);
const service = ts.createLanguageService(serviceHost);
const sourceFile = ts.createSourceFile(filename, contents, ts.ScriptTarget.ES5, true);
// all imports
const imports = lazy(collect(sourceFile, n => isImportNode(n) ? CollectStepResult.YesAndRecurse : CollectStepResult.NoAndRecurse));
// import nls = require('vs/nls');
const importEqualsDeclarations = imports
.filter(n => n.kind === ts.SyntaxKind.ImportEqualsDeclaration)
.map(n => n)
.filter(d => d.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference)
.filter(d => d.moduleReference.expression.getText() === '\'vs/nls\'');
// import ... from 'vs/nls';
const importDeclarations = imports
.filter(n => n.kind === ts.SyntaxKind.ImportDeclaration)
.map(n => n)
.filter(d => d.moduleSpecifier.kind === ts.SyntaxKind.StringLiteral)
.filter(d => d.moduleSpecifier.getText() === '\'vs/nls\'')
.filter(d => !!d.importClause && !!d.importClause.namedBindings);
const nlsExpressions = importEqualsDeclarations
.map(d => d.moduleReference.expression)
.concat(importDeclarations.map(d => d.moduleSpecifier))
.map(d => ({
start: ts.getLineAndCharacterOfPosition(sourceFile, d.getStart()),
end: ts.getLineAndCharacterOfPosition(sourceFile, d.getEnd())
}));
// `nls.localize(...)` calls
const nlsLocalizeCallExpressions = importDeclarations
.filter(d => !!(d.importClause && d.importClause.namedBindings && d.importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport))
.map(d => d.importClause.namedBindings.name)
.concat(importEqualsDeclarations.map(d => d.name))
// find read-only references to `nls`
.map(n => service.getReferencesAtPosition(filename, n.pos + 1))
.flatten()
.filter(r => !r.isWriteAccess)
// find the deepest call expressions AST nodes that contain those references
.map(r => collect(sourceFile, n => isCallExpressionWithinTextSpanCollectStep(r.textSpan, n)))
.map(a => lazy(a).last())
.filter(n => !!n)
.map(n => n)
// only `localize` calls
.filter(n => n.expression.kind === ts.SyntaxKind.PropertyAccessExpression && n.expression.name.getText() === 'localize');
// `localize` named imports
const allLocalizeImportDeclarations = importDeclarations
.filter(d => !!(d.importClause && d.importClause.namedBindings && d.importClause.namedBindings.kind === ts.SyntaxKind.NamedImports))
.map(d => [].concat(d.importClause.namedBindings.elements))
.flatten();
// `localize` read-only references
const localizeReferences = allLocalizeImportDeclarations
.filter(d => d.name.getText() === 'localize')
.map(n => service.getReferencesAtPosition(filename, n.pos + 1))
.flatten()
.filter(r => !r.isWriteAccess);
// custom named `localize` read-only references
const namedLocalizeReferences = allLocalizeImportDeclarations
.filter(d => d.propertyName && d.propertyName.getText() === 'localize')
.map(n => service.getReferencesAtPosition(filename, n.name.pos + 1))
.flatten()
.filter(r => !r.isWriteAccess);
// find the deepest call expressions AST nodes that contain those references
const localizeCallExpressions = localizeReferences
.concat(namedLocalizeReferences)
.map(r => collect(sourceFile, n => isCallExpressionWithinTextSpanCollectStep(r.textSpan, n)))
.map(a => lazy(a).last())
.filter(n => !!n)
.map(n => n);
// collect everything
const localizeCalls = nlsLocalizeCallExpressions
.concat(localizeCallExpressions)
.map(e => e.arguments)
.filter(a => a.length > 1)
.sort((a, b) => a[0].getStart() - b[0].getStart())
.map(a => ({
keySpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getStart()), end: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getEnd()) },
key: a[0].getText(),
valueSpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getStart()), end: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getEnd()) },
value: a[1].getText()
}));
return {
localizeCalls: localizeCalls.toArray(),
nlsExpressions: nlsExpressions.toArray()
};
}
nls_1.analyze = analyze;
class TextModel {
constructor(contents) {
const regex = /\r\n|\r|\n/g;
let index = 0;
let match;
this.lines = [];
this.lineEndings = [];
while (match = regex.exec(contents)) {
this.lines.push(contents.substring(index, match.index));
this.lineEndings.push(match[0]);
index = regex.lastIndex;
}
if (contents.length > 0) {
this.lines.push(contents.substring(index, contents.length));
this.lineEndings.push('');
}
}
get(index) {
return this.lines[index];
}
set(index, line) {
this.lines[index] = line;
}
get lineCount() {
return this.lines.length;
}
/**
* Applies patch(es) to the model.
* Multiple patches must be ordered.
* Does not support patches spanning multiple lines.
*/
apply(patch) {
const startLineNumber = patch.span.start.line;
const endLineNumber = patch.span.end.line;
const startLine = this.lines[startLineNumber] || '';
const endLine = this.lines[endLineNumber] || '';
this.lines[startLineNumber] = [
startLine.substring(0, patch.span.start.character),
patch.content,
endLine.substring(patch.span.end.character)
].join('');
for (let i = startLineNumber + 1; i <= endLineNumber; i++) {
this.lines[i] = '';
}
}
toString() {
return lazy(this.lines).zip(this.lineEndings)
.flatten().toArray().join('');
}
}
nls_1.TextModel = TextModel;
function patchJavascript(patches, contents, moduleId) {
const model = new nls.TextModel(contents);
// patch the localize calls
lazy(patches).reverse().each(p => model.apply(p));
// patch the 'vs/nls' imports
const firstLine = model.get(0);
const patchedFirstLine = firstLine.replace(/(['"])vs\/nls\1/g, `$1vs/nls!${moduleId}$1`);
model.set(0, patchedFirstLine);
return model.toString();
}
nls_1.patchJavascript = patchJavascript;
function patchSourcemap(patches, rsm, smc) {
const smg = new sm.SourceMapGenerator({
file: rsm.file,
sourceRoot: rsm.sourceRoot
});
patches = patches.reverse();
let currentLine = -1;
let currentLineDiff = 0;
let source = null;
smc.eachMapping(m => {
const patch = patches[patches.length - 1];
const original = { line: m.originalLine, column: m.originalColumn };
const generated = { line: m.generatedLine, column: m.generatedColumn };
if (currentLine !== generated.line) {
currentLineDiff = 0;
}
currentLine = generated.line;
generated.column += currentLineDiff;
if (patch && m.generatedLine - 1 === patch.span.end.line && m.generatedColumn === patch.span.end.character) {
const originalLength = patch.span.end.character - patch.span.start.character;
const modifiedLength = patch.content.length;
const lengthDiff = modifiedLength - originalLength;
currentLineDiff += lengthDiff;
generated.column += lengthDiff;
patches.pop();
}
source = rsm.sourceRoot ? path.relative(rsm.sourceRoot, m.source) : m.source;
source = source.replace(/\\/g, '/');
smg.addMapping({ source, name: m.name, original, generated });
}, null, sm.SourceMapConsumer.GENERATED_ORDER);
if (source) {
smg.setSourceContent(source, smc.sourceContentFor(source));
}
return JSON.parse(smg.toString());
}
nls_1.patchSourcemap = patchSourcemap;
function patch(moduleId, typescript, javascript, sourcemap) {
const { localizeCalls, nlsExpressions } = analyze(typescript);
if (localizeCalls.length === 0) {
return { javascript, sourcemap };
}
const nlsKeys = template(localizeCalls.map(lc => lc.key));
const nls = template(localizeCalls.map(lc => lc.value));
const smc = new sm.SourceMapConsumer(sourcemap);
const positionFrom = mappedPositionFrom.bind(null, sourcemap.sources[0]);
let i = 0;
// build patches
const patches = lazy(localizeCalls)
.map(lc => ([
{ range: lc.keySpan, content: '' + (i++) },
{ range: lc.valueSpan, content: 'null' }
]))
.flatten()
.map(c => {
const start = lcFrom(smc.generatedPositionFor(positionFrom(c.range.start)));
const end = lcFrom(smc.generatedPositionFor(positionFrom(c.range.end)));
return { span: { start, end }, content: c.content };
})
.toArray();
javascript = patchJavascript(patches, javascript, moduleId);
// since imports are not within the sourcemap information,
// we must do this MacGyver style
if (nlsExpressions.length) {
javascript = javascript.replace(/^define\(.*$/m, line => {
return line.replace(/(['"])vs\/nls\1/g, `$1vs/nls!${moduleId}$1`);
});
}
sourcemap = patchSourcemap(patches, sourcemap, smc);
return { javascript, sourcemap, nlsKeys, nls };
}
nls_1.patch = patch;
function patchFiles(javascriptFile, typescript) {
// hack?
const moduleId = javascriptFile.relative
.replace(/\.js$/, '')
.replace(/\\/g, '/');
const { javascript, sourcemap, nlsKeys, nls } = patch(moduleId, typescript, javascriptFile.contents.toString(), javascriptFile.sourceMap);
const result = [fileFrom(javascriptFile, javascript)];
result[0].sourceMap = sourcemap;
if (nlsKeys) {
result.push(fileFrom(javascriptFile, nlsKeys, javascriptFile.path.replace(/\.js$/, '.nls.keys.js')));
}
if (nls) {
result.push(fileFrom(javascriptFile, nls, javascriptFile.path.replace(/\.js$/, '.nls.js')));
}
return result;
}
nls_1.patchFiles = patchFiles;
})(nls || (nls = {}));
module.exports = nls;

View file

@ -1,15 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const fs = require("fs");
const root = path.dirname(path.dirname(__dirname));
const yarnrcPath = path.join(root, 'remote', '.yarnrc');
const yarnrc = fs.readFileSync(yarnrcPath, 'utf8');
const version = /^target\s+"([^"]+)"$/m.exec(yarnrc)[1];
const node = process.platform === 'win32' ? 'node.exe' : 'node';
const nodePath = path.join(root, '.build', 'node', `v${version}`, `${process.platform}-${process.arch}`, node);
console.log(nodePath);

View file

@ -1,235 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.minifyTask = exports.optimizeTask = exports.loaderConfig = void 0;
const es = require("event-stream");
const gulp = require("gulp");
const concat = require("gulp-concat");
const minifyCSS = require("gulp-cssnano");
const filter = require("gulp-filter");
const flatmap = require("gulp-flatmap");
const sourcemaps = require("gulp-sourcemaps");
const uglify = require("gulp-uglify");
const composer = require("gulp-uglify/composer");
const fancyLog = require("fancy-log");
const ansiColors = require("ansi-colors");
const path = require("path");
const pump = require("pump");
const terser = require("terser");
const VinylFile = require("vinyl");
const bundle = require("./bundle");
const i18n_1 = require("./i18n");
const stats_1 = require("./stats");
const util = require("./util");
const REPO_ROOT_PATH = path.join(__dirname, '../..');
function log(prefix, message) {
fancyLog(ansiColors.cyan('[' + prefix + ']'), message);
}
function loaderConfig() {
const result = {
paths: {
'vs': 'out-build/vs',
'vscode': 'empty:'
},
amdModulesPattern: /^vs\//
};
result['vs/css'] = { inlineResources: true };
return result;
}
exports.loaderConfig = loaderConfig;
const IS_OUR_COPYRIGHT_REGEXP = /Copyright \(C\) Microsoft Corporation/i;
function loader(src, bundledFileHeader, bundleLoader) {
let sources = [
`${src}/vs/loader.js`
];
if (bundleLoader) {
sources = sources.concat([
`${src}/vs/css.js`,
`${src}/vs/nls.js`
]);
}
let isFirst = true;
return (gulp
.src(sources, { base: `${src}` })
.pipe(es.through(function (data) {
if (isFirst) {
isFirst = false;
this.emit('data', new VinylFile({
path: 'fake',
base: '',
contents: Buffer.from(bundledFileHeader)
}));
this.emit('data', data);
}
else {
this.emit('data', data);
}
}))
.pipe(concat('vs/loader.js')));
}
function toConcatStream(src, bundledFileHeader, sources, dest, fileContentMapper) {
const useSourcemaps = /\.js$/.test(dest) && !/\.nls\.js$/.test(dest);
// If a bundle ends up including in any of the sources our copyright, then
// insert a fake source at the beginning of each bundle with our copyright
let containsOurCopyright = false;
for (let i = 0, len = sources.length; i < len; i++) {
const fileContents = sources[i].contents;
if (IS_OUR_COPYRIGHT_REGEXP.test(fileContents)) {
containsOurCopyright = true;
break;
}
}
if (containsOurCopyright) {
sources.unshift({
path: null,
contents: bundledFileHeader
});
}
const treatedSources = sources.map(function (source) {
const root = source.path ? REPO_ROOT_PATH.replace(/\\/g, '/') : '';
const base = source.path ? root + `/${src}` : '';
const path = source.path ? root + '/' + source.path.replace(/\\/g, '/') : 'fake';
const contents = source.path ? fileContentMapper(source.contents, path) : source.contents;
return new VinylFile({
path: path,
base: base,
contents: Buffer.from(contents)
});
});
return es.readArray(treatedSources)
.pipe(useSourcemaps ? util.loadSourcemaps() : es.through())
.pipe(concat(dest))
.pipe(stats_1.createStatsStream(dest));
}
function toBundleStream(src, bundledFileHeader, bundles, fileContentMapper) {
return es.merge(bundles.map(function (bundle) {
return toConcatStream(src, bundledFileHeader, bundle.sources, bundle.dest, fileContentMapper);
}));
}
const DEFAULT_FILE_HEADER = [
'/*!--------------------------------------------------------',
' * Copyright (C) Microsoft Corporation. All rights reserved.',
' *--------------------------------------------------------*/'
].join('\n');
function optimizeTask(opts) {
const src = opts.src;
const entryPoints = opts.entryPoints;
const resources = opts.resources;
const loaderConfig = opts.loaderConfig;
const bundledFileHeader = opts.header || DEFAULT_FILE_HEADER;
const bundleLoader = (typeof opts.bundleLoader === 'undefined' ? true : opts.bundleLoader);
const out = opts.out;
const fileContentMapper = opts.fileContentMapper || ((contents, _path) => contents);
return function () {
const bundlesStream = es.through(); // this stream will contain the bundled files
const resourcesStream = es.through(); // this stream will contain the resources
const bundleInfoStream = es.through(); // this stream will contain bundleInfo.json
bundle.bundle(entryPoints, loaderConfig, function (err, result) {
if (err || !result) {
return bundlesStream.emit('error', JSON.stringify(err));
}
toBundleStream(src, bundledFileHeader, result.files, fileContentMapper).pipe(bundlesStream);
// Remove css inlined resources
const filteredResources = resources.slice();
result.cssInlinedResources.forEach(function (resource) {
if (process.env['VSCODE_BUILD_VERBOSE']) {
log('optimizer', 'excluding inlined: ' + resource);
}
filteredResources.push('!' + resource);
});
gulp.src(filteredResources, { base: `${src}`, allowEmpty: true }).pipe(resourcesStream);
const bundleInfoArray = [];
if (opts.bundleInfo) {
bundleInfoArray.push(new VinylFile({
path: 'bundleInfo.json',
base: '.',
contents: Buffer.from(JSON.stringify(result.bundleData, null, '\t'))
}));
}
es.readArray(bundleInfoArray).pipe(bundleInfoStream);
});
const result = es.merge(loader(src, bundledFileHeader, bundleLoader), bundlesStream, resourcesStream, bundleInfoStream);
return result
.pipe(sourcemaps.write('./', {
sourceRoot: undefined,
addComment: true,
includeContent: true
}))
.pipe(opts.languages && opts.languages.length ? i18n_1.processNlsFiles({
fileHeader: bundledFileHeader,
languages: opts.languages
}) : es.through())
.pipe(gulp.dest(out));
};
}
exports.optimizeTask = optimizeTask;
/**
* Wrap around uglify and allow the preserveComments function
* to have a file "context" to include our copyright only once per file.
*/
function uglifyWithCopyrights() {
const preserveComments = (f) => {
return (_node, comment) => {
const text = comment.value;
const type = comment.type;
if (/@minifier_do_not_preserve/.test(text)) {
return false;
}
const isOurCopyright = IS_OUR_COPYRIGHT_REGEXP.test(text);
if (isOurCopyright) {
if (f.__hasOurCopyright) {
return false;
}
f.__hasOurCopyright = true;
return true;
}
if ('comment2' === type) {
// check for /*!. Note that text doesn't contain leading /*
return (text.length > 0 && text[0] === '!') || /@preserve|license|@cc_on|copyright/i.test(text);
}
else if ('comment1' === type) {
return /license|copyright/i.test(text);
}
return false;
};
};
const minify = composer(terser);
const input = es.through();
const output = input
.pipe(flatmap((stream, f) => {
return stream.pipe(minify({
output: {
comments: preserveComments(f),
max_line_len: 1024
}
}));
}));
return es.duplex(input, output);
}
function minifyTask(src, sourceMapBaseUrl) {
const sourceMappingURL = sourceMapBaseUrl ? ((f) => `${sourceMapBaseUrl}/${f.relative}.map`) : undefined;
return cb => {
const jsFilter = filter('**/*.js', { restore: true });
const cssFilter = filter('**/*.css', { restore: true });
pump(gulp.src([src + '/**', '!' + src + '/**/*.map']), jsFilter, sourcemaps.init({ loadMaps: true }), uglifyWithCopyrights(), jsFilter.restore, cssFilter, minifyCSS({ reduceIdents: false }), cssFilter.restore, sourcemaps.mapSources((sourcePath) => {
if (sourcePath === 'bootstrap-fork.js') {
return 'bootstrap-fork.orig.js';
}
return sourcePath;
}), sourcemaps.write('./', {
sourceMappingURL,
sourceRoot: undefined,
includeContent: true,
addComment: true
}), gulp.dest(src + '-min'), (err) => {
if (err instanceof uglify.GulpUglifyError) {
console.error(`Uglify error in '${err.cause && err.cause.filename}'`);
}
cb(err);
});
};
}
exports.minifyTask = minifyTask;

View file

@ -1,55 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
// @ts-check
const path = require("path");
const child_process_1 = require("child_process");
const fs_1 = require("fs");
const yarn = process.platform === 'win32' ? 'yarn.cmd' : 'yarn';
const rootDir = path.resolve(__dirname, '..', '..');
function runProcess(command, args = []) {
return new Promise((resolve, reject) => {
const child = child_process_1.spawn(command, args, { cwd: rootDir, stdio: 'inherit', env: process.env });
child.on('exit', err => !err ? resolve() : process.exit(err !== null && err !== void 0 ? err : 1));
child.on('error', reject);
});
}
async function exists(subdir) {
try {
await fs_1.promises.stat(path.join(rootDir, subdir));
return true;
}
catch (_a) {
return false;
}
}
async function ensureNodeModules() {
if (!(await exists('node_modules'))) {
await runProcess(yarn);
}
}
async function getElectron() {
await runProcess(yarn, ['electron']);
}
async function ensureCompiled() {
if (!(await exists('out'))) {
await runProcess(yarn, ['compile']);
}
}
async function main() {
await ensureNodeModules();
await getElectron();
await ensureCompiled();
// Can't require this until after dependencies are installed
const { getBuiltInExtensions } = require('./builtInExtensions');
await getBuiltInExtensions();
}
if (require.main === module) {
main().catch(err => {
console.error(err);
process.exit(1);
});
}

View file

@ -1,86 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.createReporter = void 0;
const es = require("event-stream");
const _ = require("underscore");
const fancyLog = require("fancy-log");
const ansiColors = require("ansi-colors");
const fs = require("fs");
const path = require("path");
const allErrors = [];
let startTime = null;
let count = 0;
function onStart() {
if (count++ > 0) {
return;
}
startTime = new Date().getTime();
fancyLog(`Starting ${ansiColors.green('compilation')}...`);
}
function onEnd() {
if (--count > 0) {
return;
}
log();
}
const buildLogPath = path.join(path.dirname(path.dirname(__dirname)), '.build', 'log');
try {
fs.mkdirSync(path.dirname(buildLogPath));
}
catch (err) {
// ignore
}
function log() {
const errors = _.flatten(allErrors);
const seen = new Set();
errors.map(err => {
if (!seen.has(err)) {
seen.add(err);
fancyLog(`${ansiColors.red('Error')}: ${err}`);
}
});
const regex = /^([^(]+)\((\d+),(\d+)\): (.*)$/;
const messages = errors
.map(err => regex.exec(err))
.filter(match => !!match)
.map(x => x)
.map(([, path, line, column, message]) => ({ path, line: parseInt(line), column: parseInt(column), message }));
try {
fs.writeFileSync(buildLogPath, JSON.stringify(messages));
}
catch (err) {
//noop
}
fancyLog(`Finished ${ansiColors.green('compilation')} with ${errors.length} errors after ${ansiColors.magenta((new Date().getTime() - startTime) + ' ms')}`);
}
function createReporter() {
const errors = [];
allErrors.push(errors);
const result = (err) => errors.push(err);
result.hasErrors = () => errors.length > 0;
result.end = (emitError) => {
errors.length = 0;
onStart();
return es.through(undefined, function () {
onEnd();
if (emitError && errors.length > 0) {
if (!errors.__logged__) {
log();
}
errors.__logged__ = true;
const err = new Error(`Found ${errors.length} errors`);
err.__reporter__ = true;
this.emit('error', err);
}
else {
this.emit('end');
}
});
};
return result;
}
exports.createReporter = createReporter;

View file

@ -1,55 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
var snaps;
(function (snaps) {
const fs = require('fs');
const path = require('path');
const os = require('os');
const cp = require('child_process');
const mksnapshot = path.join(__dirname, `../../node_modules/.bin/${process.platform === 'win32' ? 'mksnapshot.cmd' : 'mksnapshot'}`);
const product = require('../../product.json');
const arch = (process.argv.join('').match(/--arch=(.*)/) || [])[1];
//
let loaderFilepath;
let startupBlobFilepath;
switch (process.platform) {
case 'darwin':
loaderFilepath = `VSCode-darwin/${product.nameLong}.app/Contents/Resources/app/out/vs/loader.js`;
startupBlobFilepath = `VSCode-darwin/${product.nameLong}.app/Contents/Frameworks/Electron Framework.framework/Resources/snapshot_blob.bin`;
break;
case 'win32':
case 'linux':
loaderFilepath = `VSCode-${process.platform}-${arch}/resources/app/out/vs/loader.js`;
startupBlobFilepath = `VSCode-${process.platform}-${arch}/snapshot_blob.bin`;
break;
default:
throw new Error('Unknown platform');
}
loaderFilepath = path.join(__dirname, '../../../', loaderFilepath);
startupBlobFilepath = path.join(__dirname, '../../../', startupBlobFilepath);
snapshotLoader(loaderFilepath, startupBlobFilepath);
function snapshotLoader(loaderFilepath, startupBlobFilepath) {
const inputFile = fs.readFileSync(loaderFilepath);
const wrappedInputFile = `
var Monaco_Loader_Init;
(function() {
var doNotInitLoader = true;
${inputFile.toString()};
Monaco_Loader_Init = function() {
AMDLoader.init();
CSSLoaderPlugin.init();
NLSLoaderPlugin.init();
return { define, require };
}
})();
`;
const wrappedInputFilepath = path.join(os.tmpdir(), 'wrapped-loader.js');
console.log(wrappedInputFilepath);
fs.writeFileSync(wrappedInputFilepath, wrappedInputFile);
cp.execFileSync(mksnapshot, [wrappedInputFilepath, `--startup_blob`, startupBlobFilepath]);
}
})(snaps || (snaps = {}));

View file

@ -1,314 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.createESMSourcesAndResources2 = exports.extractEditor = void 0;
const ts = require("typescript");
const fs = require("fs");
const path = require("path");
const tss = require("./treeshaking");
const REPO_ROOT = path.join(__dirname, '../../');
const SRC_DIR = path.join(REPO_ROOT, 'src');
let dirCache = {};
function writeFile(filePath, contents) {
function ensureDirs(dirPath) {
if (dirCache[dirPath]) {
return;
}
dirCache[dirPath] = true;
ensureDirs(path.dirname(dirPath));
if (fs.existsSync(dirPath)) {
return;
}
fs.mkdirSync(dirPath);
}
ensureDirs(path.dirname(filePath));
fs.writeFileSync(filePath, contents);
}
function extractEditor(options) {
const tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.monaco.json')).toString());
let compilerOptions;
if (tsConfig.extends) {
compilerOptions = Object.assign({}, require(path.join(options.sourcesRoot, tsConfig.extends)).compilerOptions, tsConfig.compilerOptions);
delete tsConfig.extends;
}
else {
compilerOptions = tsConfig.compilerOptions;
}
tsConfig.compilerOptions = compilerOptions;
compilerOptions.noEmit = false;
compilerOptions.noUnusedLocals = false;
compilerOptions.preserveConstEnums = false;
compilerOptions.declaration = false;
compilerOptions.moduleResolution = ts.ModuleResolutionKind.Classic;
options.compilerOptions = compilerOptions;
console.log(`Running tree shaker with shakeLevel ${tss.toStringShakeLevel(options.shakeLevel)}`);
// Take the extra included .d.ts files from `tsconfig.monaco.json`
options.typings = tsConfig.include.filter(includedFile => /\.d\.ts$/.test(includedFile));
let result = tss.shake(options);
for (let fileName in result) {
if (result.hasOwnProperty(fileName)) {
writeFile(path.join(options.destRoot, fileName), result[fileName]);
}
}
let copied = {};
const copyFile = (fileName) => {
if (copied[fileName]) {
return;
}
copied[fileName] = true;
const srcPath = path.join(options.sourcesRoot, fileName);
const dstPath = path.join(options.destRoot, fileName);
writeFile(dstPath, fs.readFileSync(srcPath));
};
const writeOutputFile = (fileName, contents) => {
writeFile(path.join(options.destRoot, fileName), contents);
};
for (let fileName in result) {
if (result.hasOwnProperty(fileName)) {
const fileContents = result[fileName];
const info = ts.preProcessFile(fileContents);
for (let i = info.importedFiles.length - 1; i >= 0; i--) {
const importedFileName = info.importedFiles[i].fileName;
let importedFilePath;
if (/^vs\/css!/.test(importedFileName)) {
importedFilePath = importedFileName.substr('vs/css!'.length) + '.css';
}
else {
importedFilePath = importedFileName;
}
if (/(^\.\/)|(^\.\.\/)/.test(importedFilePath)) {
importedFilePath = path.join(path.dirname(fileName), importedFilePath);
}
if (/\.css$/.test(importedFilePath)) {
transportCSS(importedFilePath, copyFile, writeOutputFile);
}
else {
if (fs.existsSync(path.join(options.sourcesRoot, importedFilePath + '.js'))) {
copyFile(importedFilePath + '.js');
}
}
}
}
}
delete tsConfig.compilerOptions.moduleResolution;
writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t'));
[
'vs/css.build.js',
'vs/css.d.ts',
'vs/css.js',
'vs/loader.js',
'vs/nls.build.js',
'vs/nls.d.ts',
'vs/nls.js',
'vs/nls.mock.ts',
].forEach(copyFile);
}
exports.extractEditor = extractEditor;
function createESMSourcesAndResources2(options) {
const SRC_FOLDER = path.join(REPO_ROOT, options.srcFolder);
const OUT_FOLDER = path.join(REPO_ROOT, options.outFolder);
const OUT_RESOURCES_FOLDER = path.join(REPO_ROOT, options.outResourcesFolder);
const getDestAbsoluteFilePath = (file) => {
let dest = options.renames[file.replace(/\\/g, '/')] || file;
if (dest === 'tsconfig.json') {
return path.join(OUT_FOLDER, `tsconfig.json`);
}
if (/\.ts$/.test(dest)) {
return path.join(OUT_FOLDER, dest);
}
return path.join(OUT_RESOURCES_FOLDER, dest);
};
const allFiles = walkDirRecursive(SRC_FOLDER);
for (const file of allFiles) {
if (options.ignores.indexOf(file.replace(/\\/g, '/')) >= 0) {
continue;
}
if (file === 'tsconfig.json') {
const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString());
tsConfig.compilerOptions.module = 'es6';
tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs').replace(/\\/g, '/');
write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t'));
continue;
}
if (/\.d\.ts$/.test(file) || /\.css$/.test(file) || /\.js$/.test(file) || /\.ttf$/.test(file)) {
// Transport the files directly
write(getDestAbsoluteFilePath(file), fs.readFileSync(path.join(SRC_FOLDER, file)));
continue;
}
if (/\.ts$/.test(file)) {
// Transform the .ts file
let fileContents = fs.readFileSync(path.join(SRC_FOLDER, file)).toString();
const info = ts.preProcessFile(fileContents);
for (let i = info.importedFiles.length - 1; i >= 0; i--) {
const importedFilename = info.importedFiles[i].fileName;
const pos = info.importedFiles[i].pos;
const end = info.importedFiles[i].end;
let importedFilepath;
if (/^vs\/css!/.test(importedFilename)) {
importedFilepath = importedFilename.substr('vs/css!'.length) + '.css';
}
else {
importedFilepath = importedFilename;
}
if (/(^\.\/)|(^\.\.\/)/.test(importedFilepath)) {
importedFilepath = path.join(path.dirname(file), importedFilepath);
}
let relativePath;
if (importedFilepath === path.dirname(file).replace(/\\/g, '/')) {
relativePath = '../' + path.basename(path.dirname(file));
}
else if (importedFilepath === path.dirname(path.dirname(file)).replace(/\\/g, '/')) {
relativePath = '../../' + path.basename(path.dirname(path.dirname(file)));
}
else {
relativePath = path.relative(path.dirname(file), importedFilepath);
}
relativePath = relativePath.replace(/\\/g, '/');
if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) {
relativePath = './' + relativePath;
}
fileContents = (fileContents.substring(0, pos + 1)
+ relativePath
+ fileContents.substring(end + 1));
}
fileContents = fileContents.replace(/import ([a-zA-z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) {
return `import * as ${m1} from ${m2};`;
});
write(getDestAbsoluteFilePath(file), fileContents);
continue;
}
console.log(`UNKNOWN FILE: ${file}`);
}
function walkDirRecursive(dir) {
if (dir.charAt(dir.length - 1) !== '/' || dir.charAt(dir.length - 1) !== '\\') {
dir += '/';
}
let result = [];
_walkDirRecursive(dir, result, dir.length);
return result;
}
function _walkDirRecursive(dir, result, trimPos) {
const files = fs.readdirSync(dir);
for (let i = 0; i < files.length; i++) {
const file = path.join(dir, files[i]);
if (fs.statSync(file).isDirectory()) {
_walkDirRecursive(file, result, trimPos);
}
else {
result.push(file.substr(trimPos));
}
}
}
function write(absoluteFilePath, contents) {
if (/(\.ts$)|(\.js$)/.test(absoluteFilePath)) {
contents = toggleComments(contents.toString());
}
writeFile(absoluteFilePath, contents);
function toggleComments(fileContents) {
let lines = fileContents.split(/\r\n|\r|\n/);
let mode = 0;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (mode === 0) {
if (/\/\/ ESM-comment-begin/.test(line)) {
mode = 1;
continue;
}
if (/\/\/ ESM-uncomment-begin/.test(line)) {
mode = 2;
continue;
}
continue;
}
if (mode === 1) {
if (/\/\/ ESM-comment-end/.test(line)) {
mode = 0;
continue;
}
lines[i] = '// ' + line;
continue;
}
if (mode === 2) {
if (/\/\/ ESM-uncomment-end/.test(line)) {
mode = 0;
continue;
}
lines[i] = line.replace(/^(\s*)\/\/ ?/, function (_, indent) {
return indent;
});
}
}
return lines.join('\n');
}
}
}
exports.createESMSourcesAndResources2 = createESMSourcesAndResources2;
function transportCSS(module, enqueue, write) {
if (!/\.css/.test(module)) {
return false;
}
const filename = path.join(SRC_DIR, module);
const fileContents = fs.readFileSync(filename).toString();
const inlineResources = 'base64'; // see https://github.com/microsoft/monaco-editor/issues/148
const newContents = _rewriteOrInlineUrls(fileContents, inlineResources === 'base64');
write(module, newContents);
return true;
function _rewriteOrInlineUrls(contents, forceBase64) {
return _replaceURL(contents, (url) => {
const fontMatch = url.match(/^(.*).ttf\?(.*)$/);
if (fontMatch) {
const relativeFontPath = `${fontMatch[1]}.ttf`; // trim the query parameter
const fontPath = path.join(path.dirname(module), relativeFontPath);
enqueue(fontPath);
return relativeFontPath;
}
const imagePath = path.join(path.dirname(module), url);
const fileContents = fs.readFileSync(path.join(SRC_DIR, imagePath));
const MIME = /\.svg$/.test(url) ? 'image/svg+xml' : 'image/png';
let DATA = ';base64,' + fileContents.toString('base64');
if (!forceBase64 && /\.svg$/.test(url)) {
// .svg => url encode as explained at https://codepen.io/tigt/post/optimizing-svgs-in-data-uris
let newText = fileContents.toString()
.replace(/"/g, '\'')
.replace(/</g, '%3C')
.replace(/>/g, '%3E')
.replace(/&/g, '%26')
.replace(/#/g, '%23')
.replace(/\s+/g, ' ');
let encodedData = ',' + newText;
if (encodedData.length < DATA.length) {
DATA = encodedData;
}
}
return '"data:' + MIME + DATA + '"';
});
}
function _replaceURL(contents, replacer) {
// Use ")" as the terminator as quotes are oftentimes not used at all
return contents.replace(/url\(\s*([^\)]+)\s*\)?/g, (_, ...matches) => {
let url = matches[0];
// Eliminate starting quotes (the initial whitespace is not captured)
if (url.charAt(0) === '"' || url.charAt(0) === '\'') {
url = url.substring(1);
}
// The ending whitespace is captured
while (url.length > 0 && (url.charAt(url.length - 1) === ' ' || url.charAt(url.length - 1) === '\t')) {
url = url.substring(0, url.length - 1);
}
// Eliminate ending quotes
if (url.charAt(url.length - 1) === '"' || url.charAt(url.length - 1) === '\'') {
url = url.substring(0, url.length - 1);
}
if (!_startsWith(url, 'data:') && !_startsWith(url, 'http://') && !_startsWith(url, 'https://')) {
url = replacer(url);
}
return 'url(' + url + ')';
});
}
function _startsWith(haystack, needle) {
return haystack.length >= needle.length && haystack.substr(0, needle.length) === needle;
}
}

View file

@ -1,137 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.submitAllStats = exports.createStatsStream = void 0;
const es = require("event-stream");
const fancyLog = require("fancy-log");
const ansiColors = require("ansi-colors");
const appInsights = require("applicationinsights");
class Entry {
constructor(name, totalCount, totalSize) {
this.name = name;
this.totalCount = totalCount;
this.totalSize = totalSize;
}
toString(pretty) {
if (!pretty) {
if (this.totalCount === 1) {
return `${this.name}: ${this.totalSize} bytes`;
}
else {
return `${this.name}: ${this.totalCount} files with ${this.totalSize} bytes`;
}
}
else {
if (this.totalCount === 1) {
return `Stats for '${ansiColors.grey(this.name)}': ${Math.round(this.totalSize / 1204)}KB`;
}
else {
const count = this.totalCount < 100
? ansiColors.green(this.totalCount.toString())
: ansiColors.red(this.totalCount.toString());
return `Stats for '${ansiColors.grey(this.name)}': ${count} files, ${Math.round(this.totalSize / 1204)}KB`;
}
}
}
}
const _entries = new Map();
function createStatsStream(group, log) {
const entry = new Entry(group, 0, 0);
_entries.set(entry.name, entry);
return es.through(function (data) {
const file = data;
if (typeof file.path === 'string') {
entry.totalCount += 1;
if (Buffer.isBuffer(file.contents)) {
entry.totalSize += file.contents.length;
}
else if (file.stat && typeof file.stat.size === 'number') {
entry.totalSize += file.stat.size;
}
else {
// funky file...
}
}
this.emit('data', data);
}, function () {
if (log) {
if (entry.totalCount === 1) {
fancyLog(`Stats for '${ansiColors.grey(entry.name)}': ${Math.round(entry.totalSize / 1204)}KB`);
}
else {
const count = entry.totalCount < 100
? ansiColors.green(entry.totalCount.toString())
: ansiColors.red(entry.totalCount.toString());
fancyLog(`Stats for '${ansiColors.grey(entry.name)}': ${count} files, ${Math.round(entry.totalSize / 1204)}KB`);
}
}
this.emit('end');
});
}
exports.createStatsStream = createStatsStream;
function submitAllStats(productJson, commit) {
const sorted = [];
// move entries for single files to the front
_entries.forEach(value => {
if (value.totalCount === 1) {
sorted.unshift(value);
}
else {
sorted.push(value);
}
});
// print to console
for (const entry of sorted) {
console.log(entry.toString(true));
}
// send data as telementry event when the
// product is configured to send telemetry
if (!productJson || !productJson.aiConfig || typeof productJson.aiConfig.asimovKey !== 'string') {
return Promise.resolve(false);
}
return new Promise(resolve => {
try {
const sizes = {};
const counts = {};
for (const entry of sorted) {
sizes[entry.name] = entry.totalSize;
counts[entry.name] = entry.totalCount;
}
appInsights.setup(productJson.aiConfig.asimovKey)
.setAutoCollectConsole(false)
.setAutoCollectExceptions(false)
.setAutoCollectPerformance(false)
.setAutoCollectRequests(false)
.setAutoCollectDependencies(false)
.setAutoDependencyCorrelation(false)
.start();
appInsights.defaultClient.config.endpointUrl = 'https://vortex.data.microsoft.com/collect/v1';
/* __GDPR__
"monacoworkbench/packagemetrics" : {
"commit" : {"classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
"size" : {"classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
"count" : {"classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
}
*/
appInsights.defaultClient.trackEvent({
name: 'monacoworkbench/packagemetrics',
properties: { commit, size: JSON.stringify(sizes), count: JSON.stringify(counts) }
});
appInsights.defaultClient.flush({
callback: () => {
appInsights.dispose();
resolve(true);
}
});
}
catch (err) {
console.error('ERROR sending build stats as telemetry event!');
console.error(err);
resolve(false);
}
});
}
exports.submitAllStats = submitAllStats;

View file

@ -1,97 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.define = exports.parallel = exports.series = void 0;
const fancyLog = require("fancy-log");
const ansiColors = require("ansi-colors");
function _isPromise(p) {
if (typeof p.then === 'function') {
return true;
}
return false;
}
function _renderTime(time) {
return `${Math.round(time)} ms`;
}
async function _execute(task) {
const name = task.taskName || task.displayName || `<anonymous>`;
if (!task._tasks) {
fancyLog('Starting', ansiColors.cyan(name), '...');
}
const startTime = process.hrtime();
await _doExecute(task);
const elapsedArr = process.hrtime(startTime);
const elapsedNanoseconds = (elapsedArr[0] * 1e9 + elapsedArr[1]);
if (!task._tasks) {
fancyLog(`Finished`, ansiColors.cyan(name), 'after', ansiColors.magenta(_renderTime(elapsedNanoseconds / 1e6)));
}
}
async function _doExecute(task) {
// Always invoke as if it were a callback task
return new Promise((resolve, reject) => {
if (task.length === 1) {
// this is a callback task
task((err) => {
if (err) {
return reject(err);
}
resolve();
});
return;
}
const taskResult = task();
if (typeof taskResult === 'undefined') {
// this is a sync task
resolve();
return;
}
if (_isPromise(taskResult)) {
// this is a promise returning task
taskResult.then(resolve, reject);
return;
}
// this is a stream returning task
taskResult.on('end', _ => resolve());
taskResult.on('error', err => reject(err));
});
}
function series(...tasks) {
const result = async () => {
for (let i = 0; i < tasks.length; i++) {
await _execute(tasks[i]);
}
};
result._tasks = tasks;
return result;
}
exports.series = series;
function parallel(...tasks) {
const result = async () => {
await Promise.all(tasks.map(t => _execute(t)));
};
result._tasks = tasks;
return result;
}
exports.parallel = parallel;
function define(name, task) {
if (task._tasks) {
// This is a composite task
const lastTask = task._tasks[task._tasks.length - 1];
if (lastTask._tasks || lastTask.taskName) {
// This is a composite task without a real task function
// => generate a fake task function
return define(name, series(task, () => Promise.resolve()));
}
lastTask.taskName = name;
task.displayName = name;
return task;
}
// This is a simple task
task.taskName = name;
task.displayName = name;
return task;
}
exports.define = define;

View file

@ -1,40 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
const assert = require("assert");
const i18n = require("../i18n");
suite('XLF Parser Tests', () => {
const sampleXlf = '<?xml version="1.0" encoding="utf-8"?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"><file original="vs/base/common/keybinding" source-language="en" datatype="plaintext"><body><trans-unit id="key1"><source xml:lang="en">Key #1</source></trans-unit><trans-unit id="key2"><source xml:lang="en">Key #2 &amp;</source></trans-unit></body></file></xliff>';
const sampleTranslatedXlf = '<?xml version="1.0" encoding="utf-8"?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"><file original="vs/base/common/keybinding" source-language="en" target-language="ru" datatype="plaintext"><body><trans-unit id="key1"><source xml:lang="en">Key #1</source><target>Кнопка #1</target></trans-unit><trans-unit id="key2"><source xml:lang="en">Key #2 &amp;</source><target>Кнопка #2 &amp;</target></trans-unit></body></file></xliff>';
const originalFilePath = 'vs/base/common/keybinding';
const keys = ['key1', 'key2'];
const messages = ['Key #1', 'Key #2 &'];
const translatedMessages = { key1: 'Кнопка #1', key2: 'Кнопка #2 &' };
test('Keys & messages to XLF conversion', () => {
const xlf = new i18n.XLF('vscode-workbench');
xlf.addFile(originalFilePath, keys, messages);
const xlfString = xlf.toString();
assert.strictEqual(xlfString.replace(/\s{2,}/g, ''), sampleXlf);
});
test('XLF to keys & messages conversion', () => {
i18n.XLF.parse(sampleTranslatedXlf).then(function (resolvedFiles) {
assert.deepEqual(resolvedFiles[0].messages, translatedMessages);
assert.strictEqual(resolvedFiles[0].originalFilePath, originalFilePath);
});
});
test('JSON file source path to Transifex resource match', () => {
const editorProject = 'vscode-editor', workbenchProject = 'vscode-workbench';
const platform = { name: 'vs/platform', project: editorProject }, editorContrib = { name: 'vs/editor/contrib', project: editorProject }, editor = { name: 'vs/editor', project: editorProject }, base = { name: 'vs/base', project: editorProject }, code = { name: 'vs/code', project: workbenchProject }, workbenchParts = { name: 'vs/workbench/contrib/html', project: workbenchProject }, workbenchServices = { name: 'vs/workbench/services/textfile', project: workbenchProject }, workbench = { name: 'vs/workbench', project: workbenchProject };
assert.deepEqual(i18n.getResource('vs/platform/actions/browser/menusExtensionPoint'), platform);
assert.deepEqual(i18n.getResource('vs/editor/contrib/clipboard/browser/clipboard'), editorContrib);
assert.deepEqual(i18n.getResource('vs/editor/common/modes/modesRegistry'), editor);
assert.deepEqual(i18n.getResource('vs/base/common/errorMessage'), base);
assert.deepEqual(i18n.getResource('vs/code/electron-main/window'), code);
assert.deepEqual(i18n.getResource('vs/workbench/contrib/html/browser/webview'), workbenchParts);
assert.deepEqual(i18n.getResource('vs/workbench/services/textfile/node/testFileService'), workbenchServices);
assert.deepEqual(i18n.getResource('vs/workbench/browser/parts/panel/panelActions'), workbench);
});
});

View file

@ -1,779 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.shake = exports.toStringShakeLevel = exports.ShakeLevel = void 0;
const fs = require("fs");
const path = require("path");
const ts = require("typescript");
const TYPESCRIPT_LIB_FOLDER = path.dirname(require.resolve('typescript/lib/lib.d.ts'));
var ShakeLevel;
(function (ShakeLevel) {
ShakeLevel[ShakeLevel["Files"] = 0] = "Files";
ShakeLevel[ShakeLevel["InnerFile"] = 1] = "InnerFile";
ShakeLevel[ShakeLevel["ClassMembers"] = 2] = "ClassMembers";
})(ShakeLevel = exports.ShakeLevel || (exports.ShakeLevel = {}));
function toStringShakeLevel(shakeLevel) {
switch (shakeLevel) {
case 0 /* Files */:
return 'Files (0)';
case 1 /* InnerFile */:
return 'InnerFile (1)';
case 2 /* ClassMembers */:
return 'ClassMembers (2)';
}
}
exports.toStringShakeLevel = toStringShakeLevel;
function printDiagnostics(options, diagnostics) {
for (const diag of diagnostics) {
let result = '';
if (diag.file) {
result += `${path.join(options.sourcesRoot, diag.file.fileName)}`;
}
if (diag.file && diag.start) {
let location = diag.file.getLineAndCharacterOfPosition(diag.start);
result += `:${location.line + 1}:${location.character}`;
}
result += ` - ` + JSON.stringify(diag.messageText);
console.log(result);
}
}
function shake(options) {
const languageService = createTypeScriptLanguageService(options);
const program = languageService.getProgram();
const globalDiagnostics = program.getGlobalDiagnostics();
if (globalDiagnostics.length > 0) {
printDiagnostics(options, globalDiagnostics);
throw new Error(`Compilation Errors encountered.`);
}
const syntacticDiagnostics = program.getSyntacticDiagnostics();
if (syntacticDiagnostics.length > 0) {
printDiagnostics(options, syntacticDiagnostics);
throw new Error(`Compilation Errors encountered.`);
}
const semanticDiagnostics = program.getSemanticDiagnostics();
if (semanticDiagnostics.length > 0) {
printDiagnostics(options, semanticDiagnostics);
throw new Error(`Compilation Errors encountered.`);
}
markNodes(languageService, options);
return generateResult(languageService, options.shakeLevel);
}
exports.shake = shake;
//#region Discovery, LanguageService & Setup
function createTypeScriptLanguageService(options) {
// Discover referenced files
const FILES = discoverAndReadFiles(options);
// Add fake usage files
options.inlineEntryPoints.forEach((inlineEntryPoint, index) => {
FILES[`inlineEntryPoint.${index}.ts`] = inlineEntryPoint;
});
// Add additional typings
options.typings.forEach((typing) => {
const filePath = path.join(options.sourcesRoot, typing);
FILES[typing] = fs.readFileSync(filePath).toString();
});
// Resolve libs
const RESOLVED_LIBS = processLibFiles(options);
const compilerOptions = ts.convertCompilerOptionsFromJson(options.compilerOptions, options.sourcesRoot).options;
const host = new TypeScriptLanguageServiceHost(RESOLVED_LIBS, FILES, compilerOptions);
return ts.createLanguageService(host);
}
/**
* Read imports and follow them until all files have been handled
*/
function discoverAndReadFiles(options) {
const FILES = {};
const in_queue = Object.create(null);
const queue = [];
const enqueue = (moduleId) => {
if (in_queue[moduleId]) {
return;
}
in_queue[moduleId] = true;
queue.push(moduleId);
};
options.entryPoints.forEach((entryPoint) => enqueue(entryPoint));
while (queue.length > 0) {
const moduleId = queue.shift();
const dts_filename = path.join(options.sourcesRoot, moduleId + '.d.ts');
if (fs.existsSync(dts_filename)) {
const dts_filecontents = fs.readFileSync(dts_filename).toString();
FILES[`${moduleId}.d.ts`] = dts_filecontents;
continue;
}
const js_filename = path.join(options.sourcesRoot, moduleId + '.js');
if (fs.existsSync(js_filename)) {
// This is an import for a .js file, so ignore it...
continue;
}
let ts_filename;
if (options.redirects[moduleId]) {
ts_filename = path.join(options.sourcesRoot, options.redirects[moduleId] + '.ts');
}
else {
ts_filename = path.join(options.sourcesRoot, moduleId + '.ts');
}
const ts_filecontents = fs.readFileSync(ts_filename).toString();
const info = ts.preProcessFile(ts_filecontents);
for (let i = info.importedFiles.length - 1; i >= 0; i--) {
const importedFileName = info.importedFiles[i].fileName;
if (options.importIgnorePattern.test(importedFileName)) {
// Ignore vs/css! imports
continue;
}
let importedModuleId = importedFileName;
if (/(^\.\/)|(^\.\.\/)/.test(importedModuleId)) {
importedModuleId = path.join(path.dirname(moduleId), importedModuleId);
}
enqueue(importedModuleId);
}
FILES[`${moduleId}.ts`] = ts_filecontents;
}
return FILES;
}
/**
* Read lib files and follow lib references
*/
function processLibFiles(options) {
const stack = [...options.compilerOptions.lib];
const result = {};
while (stack.length > 0) {
const filename = `lib.${stack.shift().toLowerCase()}.d.ts`;
const key = `defaultLib:${filename}`;
if (!result[key]) {
// add this file
const filepath = path.join(TYPESCRIPT_LIB_FOLDER, filename);
const sourceText = fs.readFileSync(filepath).toString();
result[key] = sourceText;
// precess dependencies and "recurse"
const info = ts.preProcessFile(sourceText);
for (let ref of info.libReferenceDirectives) {
stack.push(ref.fileName);
}
}
}
return result;
}
/**
* A TypeScript language service host
*/
class TypeScriptLanguageServiceHost {
constructor(libs, files, compilerOptions) {
this._libs = libs;
this._files = files;
this._compilerOptions = compilerOptions;
}
// --- language service host ---------------
getCompilationSettings() {
return this._compilerOptions;
}
getScriptFileNames() {
return ([]
.concat(Object.keys(this._libs))
.concat(Object.keys(this._files)));
}
getScriptVersion(_fileName) {
return '1';
}
getProjectVersion() {
return '1';
}
getScriptSnapshot(fileName) {
if (this._files.hasOwnProperty(fileName)) {
return ts.ScriptSnapshot.fromString(this._files[fileName]);
}
else if (this._libs.hasOwnProperty(fileName)) {
return ts.ScriptSnapshot.fromString(this._libs[fileName]);
}
else {
return ts.ScriptSnapshot.fromString('');
}
}
getScriptKind(_fileName) {
return ts.ScriptKind.TS;
}
getCurrentDirectory() {
return '';
}
getDefaultLibFileName(_options) {
return 'defaultLib:lib.d.ts';
}
isDefaultLibFileName(fileName) {
return fileName === this.getDefaultLibFileName(this._compilerOptions);
}
}
//#endregion
//#region Tree Shaking
var NodeColor;
(function (NodeColor) {
NodeColor[NodeColor["White"] = 0] = "White";
NodeColor[NodeColor["Gray"] = 1] = "Gray";
NodeColor[NodeColor["Black"] = 2] = "Black";
})(NodeColor || (NodeColor = {}));
function getColor(node) {
return node.$$$color || 0 /* White */;
}
function setColor(node, color) {
node.$$$color = color;
}
function nodeOrParentIsBlack(node) {
while (node) {
const color = getColor(node);
if (color === 2 /* Black */) {
return true;
}
node = node.parent;
}
return false;
}
function nodeOrChildIsBlack(node) {
if (getColor(node) === 2 /* Black */) {
return true;
}
for (const child of node.getChildren()) {
if (nodeOrChildIsBlack(child)) {
return true;
}
}
return false;
}
function markNodes(languageService, options) {
const program = languageService.getProgram();
if (!program) {
throw new Error('Could not get program from language service');
}
if (options.shakeLevel === 0 /* Files */) {
// Mark all source files Black
program.getSourceFiles().forEach((sourceFile) => {
setColor(sourceFile, 2 /* Black */);
});
return;
}
const black_queue = [];
const gray_queue = [];
const export_import_queue = [];
const sourceFilesLoaded = {};
function enqueueTopLevelModuleStatements(sourceFile) {
sourceFile.forEachChild((node) => {
if (ts.isImportDeclaration(node)) {
if (!node.importClause && ts.isStringLiteral(node.moduleSpecifier)) {
setColor(node, 2 /* Black */);
enqueueImport(node, node.moduleSpecifier.text);
}
return;
}
if (ts.isExportDeclaration(node)) {
if (!node.exportClause && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
// export * from "foo";
setColor(node, 2 /* Black */);
enqueueImport(node, node.moduleSpecifier.text);
}
if (node.exportClause && ts.isNamedExports(node.exportClause)) {
for (const exportSpecifier of node.exportClause.elements) {
export_import_queue.push(exportSpecifier);
}
}
return;
}
if (ts.isExpressionStatement(node)
|| ts.isIfStatement(node)
|| ts.isIterationStatement(node, true)
|| ts.isExportAssignment(node)) {
enqueue_black(node);
}
if (ts.isImportEqualsDeclaration(node)) {
if (/export/.test(node.getFullText(sourceFile))) {
// e.g. "export import Severity = BaseSeverity;"
enqueue_black(node);
}
}
});
}
function enqueue_gray(node) {
if (nodeOrParentIsBlack(node) || getColor(node) === 1 /* Gray */) {
return;
}
setColor(node, 1 /* Gray */);
gray_queue.push(node);
}
function enqueue_black(node) {
const previousColor = getColor(node);
if (previousColor === 2 /* Black */) {
return;
}
if (previousColor === 1 /* Gray */) {
// remove from gray queue
gray_queue.splice(gray_queue.indexOf(node), 1);
setColor(node, 0 /* White */);
// add to black queue
enqueue_black(node);
// // move from one queue to the other
// black_queue.push(node);
// setColor(node, NodeColor.Black);
return;
}
if (nodeOrParentIsBlack(node)) {
return;
}
const fileName = node.getSourceFile().fileName;
if (/^defaultLib:/.test(fileName) || /\.d\.ts$/.test(fileName)) {
setColor(node, 2 /* Black */);
return;
}
const sourceFile = node.getSourceFile();
if (!sourceFilesLoaded[sourceFile.fileName]) {
sourceFilesLoaded[sourceFile.fileName] = true;
enqueueTopLevelModuleStatements(sourceFile);
}
if (ts.isSourceFile(node)) {
return;
}
setColor(node, 2 /* Black */);
black_queue.push(node);
if (options.shakeLevel === 2 /* ClassMembers */ && (ts.isMethodDeclaration(node) || ts.isMethodSignature(node) || ts.isPropertySignature(node) || ts.isPropertyDeclaration(node) || ts.isGetAccessor(node) || ts.isSetAccessor(node))) {
const references = languageService.getReferencesAtPosition(node.getSourceFile().fileName, node.name.pos + node.name.getLeadingTriviaWidth());
if (references) {
for (let i = 0, len = references.length; i < len; i++) {
const reference = references[i];
const referenceSourceFile = program.getSourceFile(reference.fileName);
if (!referenceSourceFile) {
continue;
}
const referenceNode = getTokenAtPosition(referenceSourceFile, reference.textSpan.start, false, false);
if (ts.isMethodDeclaration(referenceNode.parent)
|| ts.isPropertyDeclaration(referenceNode.parent)
|| ts.isGetAccessor(referenceNode.parent)
|| ts.isSetAccessor(referenceNode.parent)) {
enqueue_gray(referenceNode.parent);
}
}
}
}
}
function enqueueFile(filename) {
const sourceFile = program.getSourceFile(filename);
if (!sourceFile) {
console.warn(`Cannot find source file ${filename}`);
return;
}
enqueue_black(sourceFile);
}
function enqueueImport(node, importText) {
if (options.importIgnorePattern.test(importText)) {
// this import should be ignored
return;
}
const nodeSourceFile = node.getSourceFile();
let fullPath;
if (/(^\.\/)|(^\.\.\/)/.test(importText)) {
fullPath = path.join(path.dirname(nodeSourceFile.fileName), importText) + '.ts';
}
else {
fullPath = importText + '.ts';
}
enqueueFile(fullPath);
}
options.entryPoints.forEach(moduleId => enqueueFile(moduleId + '.ts'));
// Add fake usage files
options.inlineEntryPoints.forEach((_, index) => enqueueFile(`inlineEntryPoint.${index}.ts`));
let step = 0;
const checker = program.getTypeChecker();
while (black_queue.length > 0 || gray_queue.length > 0) {
++step;
let node;
if (step % 100 === 0) {
console.log(`Treeshaking - ${Math.floor(100 * step / (step + black_queue.length + gray_queue.length))}% - ${step}/${step + black_queue.length + gray_queue.length} (${black_queue.length}, ${gray_queue.length})`);
}
if (black_queue.length === 0) {
for (let i = 0; i < gray_queue.length; i++) {
const node = gray_queue[i];
const nodeParent = node.parent;
if ((ts.isClassDeclaration(nodeParent) || ts.isInterfaceDeclaration(nodeParent)) && nodeOrChildIsBlack(nodeParent)) {
gray_queue.splice(i, 1);
black_queue.push(node);
setColor(node, 2 /* Black */);
i--;
}
}
}
if (black_queue.length > 0) {
node = black_queue.shift();
}
else {
// only gray nodes remaining...
break;
}
const nodeSourceFile = node.getSourceFile();
const loop = (node) => {
const [symbol, symbolImportNode] = getRealNodeSymbol(checker, node);
if (symbolImportNode) {
setColor(symbolImportNode, 2 /* Black */);
}
if (symbol && !nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol)) {
for (let i = 0, len = symbol.declarations.length; i < len; i++) {
const declaration = symbol.declarations[i];
if (ts.isSourceFile(declaration)) {
// Do not enqueue full source files
// (they can be the declaration of a module import)
continue;
}
if (options.shakeLevel === 2 /* ClassMembers */ && (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration)) && !isLocalCodeExtendingOrInheritingFromDefaultLibSymbol(program, checker, declaration)) {
enqueue_black(declaration.name);
for (let j = 0; j < declaration.members.length; j++) {
const member = declaration.members[j];
const memberName = member.name ? member.name.getText() : null;
if (ts.isConstructorDeclaration(member)
|| ts.isConstructSignatureDeclaration(member)
|| ts.isIndexSignatureDeclaration(member)
|| ts.isCallSignatureDeclaration(member)
|| memberName === '[Symbol.iterator]'
|| memberName === '[Symbol.toStringTag]'
|| memberName === 'toJSON'
|| memberName === 'toString'
|| memberName === 'dispose' // TODO: keeping all `dispose` methods
|| /^_(.*)Brand$/.test(memberName || '') // TODO: keeping all members ending with `Brand`...
) {
enqueue_black(member);
}
}
// queue the heritage clauses
if (declaration.heritageClauses) {
for (let heritageClause of declaration.heritageClauses) {
enqueue_black(heritageClause);
}
}
}
else {
enqueue_black(declaration);
}
}
}
node.forEachChild(loop);
};
node.forEachChild(loop);
}
while (export_import_queue.length > 0) {
const node = export_import_queue.shift();
if (nodeOrParentIsBlack(node)) {
continue;
}
const symbol = node.symbol;
if (!symbol) {
continue;
}
const aliased = checker.getAliasedSymbol(symbol);
if (aliased.declarations && aliased.declarations.length > 0) {
if (nodeOrParentIsBlack(aliased.declarations[0]) || nodeOrChildIsBlack(aliased.declarations[0])) {
setColor(node, 2 /* Black */);
}
}
}
}
function nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol) {
for (let i = 0, len = symbol.declarations.length; i < len; i++) {
const declaration = symbol.declarations[i];
const declarationSourceFile = declaration.getSourceFile();
if (nodeSourceFile === declarationSourceFile) {
if (declaration.pos <= node.pos && node.end <= declaration.end) {
return true;
}
}
}
return false;
}
function generateResult(languageService, shakeLevel) {
const program = languageService.getProgram();
if (!program) {
throw new Error('Could not get program from language service');
}
let result = {};
const writeFile = (filePath, contents) => {
result[filePath] = contents;
};
program.getSourceFiles().forEach((sourceFile) => {
const fileName = sourceFile.fileName;
if (/^defaultLib:/.test(fileName)) {
return;
}
const destination = fileName;
if (/\.d\.ts$/.test(fileName)) {
if (nodeOrChildIsBlack(sourceFile)) {
writeFile(destination, sourceFile.text);
}
return;
}
let text = sourceFile.text;
let result = '';
function keep(node) {
result += text.substring(node.pos, node.end);
}
function write(data) {
result += data;
}
function writeMarkedNodes(node) {
if (getColor(node) === 2 /* Black */) {
return keep(node);
}
// Always keep certain top-level statements
if (ts.isSourceFile(node.parent)) {
if (ts.isExpressionStatement(node) && ts.isStringLiteral(node.expression) && node.expression.text === 'use strict') {
return keep(node);
}
if (ts.isVariableStatement(node) && nodeOrChildIsBlack(node)) {
return keep(node);
}
}
// Keep the entire import in import * as X cases
if (ts.isImportDeclaration(node)) {
if (node.importClause && node.importClause.namedBindings) {
if (ts.isNamespaceImport(node.importClause.namedBindings)) {
if (getColor(node.importClause.namedBindings) === 2 /* Black */) {
return keep(node);
}
}
else {
let survivingImports = [];
for (const importNode of node.importClause.namedBindings.elements) {
if (getColor(importNode) === 2 /* Black */) {
survivingImports.push(importNode.getFullText(sourceFile));
}
}
const leadingTriviaWidth = node.getLeadingTriviaWidth();
const leadingTrivia = sourceFile.text.substr(node.pos, leadingTriviaWidth);
if (survivingImports.length > 0) {
if (node.importClause && node.importClause.name && getColor(node.importClause) === 2 /* Black */) {
return write(`${leadingTrivia}import ${node.importClause.name.text}, {${survivingImports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`);
}
return write(`${leadingTrivia}import {${survivingImports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`);
}
else {
if (node.importClause && node.importClause.name && getColor(node.importClause) === 2 /* Black */) {
return write(`${leadingTrivia}import ${node.importClause.name.text} from${node.moduleSpecifier.getFullText(sourceFile)};`);
}
}
}
}
else {
if (node.importClause && getColor(node.importClause) === 2 /* Black */) {
return keep(node);
}
}
}
if (ts.isExportDeclaration(node)) {
if (node.exportClause && node.moduleSpecifier && ts.isNamedExports(node.exportClause)) {
let survivingExports = [];
for (const exportSpecifier of node.exportClause.elements) {
if (getColor(exportSpecifier) === 2 /* Black */) {
survivingExports.push(exportSpecifier.getFullText(sourceFile));
}
}
const leadingTriviaWidth = node.getLeadingTriviaWidth();
const leadingTrivia = sourceFile.text.substr(node.pos, leadingTriviaWidth);
if (survivingExports.length > 0) {
return write(`${leadingTrivia}export {${survivingExports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`);
}
}
}
if (shakeLevel === 2 /* ClassMembers */ && (ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) && nodeOrChildIsBlack(node)) {
let toWrite = node.getFullText();
for (let i = node.members.length - 1; i >= 0; i--) {
const member = node.members[i];
if (getColor(member) === 2 /* Black */ || !member.name) {
// keep method
continue;
}
let pos = member.pos - node.pos;
let end = member.end - node.pos;
toWrite = toWrite.substring(0, pos) + toWrite.substring(end);
}
return write(toWrite);
}
if (ts.isFunctionDeclaration(node)) {
// Do not go inside functions if they haven't been marked
return;
}
node.forEachChild(writeMarkedNodes);
}
if (getColor(sourceFile) !== 2 /* Black */) {
if (!nodeOrChildIsBlack(sourceFile)) {
// none of the elements are reachable => don't write this file at all!
return;
}
sourceFile.forEachChild(writeMarkedNodes);
result += sourceFile.endOfFileToken.getFullText(sourceFile);
}
else {
result = text;
}
writeFile(destination, result);
});
return result;
}
//#endregion
//#region Utils
function isLocalCodeExtendingOrInheritingFromDefaultLibSymbol(program, checker, declaration) {
if (!program.isSourceFileDefaultLibrary(declaration.getSourceFile()) && declaration.heritageClauses) {
for (const heritageClause of declaration.heritageClauses) {
for (const type of heritageClause.types) {
const symbol = findSymbolFromHeritageType(checker, type);
if (symbol) {
const decl = symbol.valueDeclaration || (symbol.declarations && symbol.declarations[0]);
if (decl && program.isSourceFileDefaultLibrary(decl.getSourceFile())) {
return true;
}
}
}
}
}
return false;
}
function findSymbolFromHeritageType(checker, type) {
if (ts.isExpressionWithTypeArguments(type)) {
return findSymbolFromHeritageType(checker, type.expression);
}
if (ts.isIdentifier(type)) {
return getRealNodeSymbol(checker, type)[0];
}
if (ts.isPropertyAccessExpression(type)) {
return findSymbolFromHeritageType(checker, type.name);
}
return null;
}
/**
* Returns the node's symbol and the `import` node (if the symbol resolved from a different module)
*/
function getRealNodeSymbol(checker, node) {
const getPropertySymbolsFromContextualType = ts.getPropertySymbolsFromContextualType;
const getContainingObjectLiteralElement = ts.getContainingObjectLiteralElement;
const getNameFromPropertyName = ts.getNameFromPropertyName;
// Go to the original declaration for cases:
//
// (1) when the aliased symbol was declared in the location(parent).
// (2) when the aliased symbol is originating from an import.
//
function shouldSkipAlias(node, declaration) {
if (!ts.isShorthandPropertyAssignment(node) && node.kind !== ts.SyntaxKind.Identifier) {
return false;
}
if (node.parent === declaration) {
return true;
}
switch (declaration.kind) {
case ts.SyntaxKind.ImportClause:
case ts.SyntaxKind.ImportEqualsDeclaration:
return true;
case ts.SyntaxKind.ImportSpecifier:
return declaration.parent.kind === ts.SyntaxKind.NamedImports;
default:
return false;
}
}
if (!ts.isShorthandPropertyAssignment(node)) {
if (node.getChildCount() !== 0) {
return [null, null];
}
}
const { parent } = node;
let symbol = (ts.isShorthandPropertyAssignment(node)
? checker.getShorthandAssignmentValueSymbol(node)
: checker.getSymbolAtLocation(node));
let importNode = null;
// If this is an alias, and the request came at the declaration location
// get the aliased symbol instead. This allows for goto def on an import e.g.
// import {A, B} from "mod";
// to jump to the implementation directly.
if (symbol && symbol.flags & ts.SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) {
const aliased = checker.getAliasedSymbol(symbol);
if (aliased.declarations) {
// We should mark the import as visited
importNode = symbol.declarations[0];
symbol = aliased;
}
}
if (symbol) {
// Because name in short-hand property assignment has two different meanings: property name and property value,
// using go-to-definition at such position should go to the variable declaration of the property value rather than
// go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition
// is performed at the location of property access, we would like to go to definition of the property in the short-hand
// assignment. This case and others are handled by the following code.
if (node.parent.kind === ts.SyntaxKind.ShorthandPropertyAssignment) {
symbol = checker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration);
}
// If the node is the name of a BindingElement within an ObjectBindingPattern instead of just returning the
// declaration the symbol (which is itself), we should try to get to the original type of the ObjectBindingPattern
// and return the property declaration for the referenced property.
// For example:
// import('./foo').then(({ b/*goto*/ar }) => undefined); => should get use to the declaration in file "./foo"
//
// function bar<T>(onfulfilled: (value: T) => void) { //....}
// interface Test {
// pr/*destination*/op1: number
// }
// bar<Test>(({pr/*goto*/op1})=>{});
if (ts.isPropertyName(node) && ts.isBindingElement(parent) && ts.isObjectBindingPattern(parent.parent) &&
(node === (parent.propertyName || parent.name))) {
const name = getNameFromPropertyName(node);
const type = checker.getTypeAtLocation(parent.parent);
if (name && type) {
if (type.isUnion()) {
const prop = type.types[0].getProperty(name);
if (prop) {
symbol = prop;
}
}
else {
const prop = type.getProperty(name);
if (prop) {
symbol = prop;
}
}
}
}
// If the current location we want to find its definition is in an object literal, try to get the contextual type for the
// object literal, lookup the property symbol in the contextual type, and use this for goto-definition.
// For example
// interface Props{
// /*first*/prop1: number
// prop2: boolean
// }
// function Foo(arg: Props) {}
// Foo( { pr/*1*/op1: 10, prop2: false })
const element = getContainingObjectLiteralElement(node);
if (element) {
const contextualType = element && checker.getContextualType(element.parent);
if (contextualType) {
const propertySymbols = getPropertySymbolsFromContextualType(element, checker, contextualType, /*unionSymbolOk*/ false);
if (propertySymbols) {
symbol = propertySymbols[0];
}
}
}
}
if (symbol && symbol.declarations) {
return [symbol, importNode];
}
return [null, null];
}
/** Get the token whose text contains the position */
function getTokenAtPosition(sourceFile, position, allowPositionInLeadingTrivia, includeEndPosition) {
let current = sourceFile;
outer: while (true) {
// find the child that contains 'position'
for (const child of current.getChildren()) {
const start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile, /*includeJsDoc*/ true);
if (start > position) {
// If this child begins after position, then all subsequent children will as well.
break;
}
const end = child.getEnd();
if (position < end || (position === end && (child.kind === ts.SyntaxKind.EndOfFileToken || includeEndPosition))) {
current = child;
continue outer;
}
}
return current;
}
}

View file

@ -1,264 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.getElectronVersion = exports.streamToPromise = exports.versionStringToNumber = exports.filter = exports.rebase = exports.getVersion = exports.ensureDir = exports.rreddir = exports.rimraf = exports.stripSourceMappingURL = exports.loadSourcemaps = exports.cleanNodeModules = exports.skipDirectories = exports.toFileUri = exports.setExecutableBit = exports.fixWin32DirectoryPermissions = exports.incremental = void 0;
const es = require("event-stream");
const debounce = require("debounce");
const _filter = require("gulp-filter");
const rename = require("gulp-rename");
const path = require("path");
const fs = require("fs");
const _rimraf = require("rimraf");
const git = require("./git");
const VinylFile = require("vinyl");
const root = path.dirname(path.dirname(__dirname));
const NoCancellationToken = { isCancellationRequested: () => false };
function incremental(streamProvider, initial, supportsCancellation) {
const input = es.through();
const output = es.through();
let state = 'idle';
let buffer = Object.create(null);
const token = !supportsCancellation ? undefined : { isCancellationRequested: () => Object.keys(buffer).length > 0 };
const run = (input, isCancellable) => {
state = 'running';
const stream = !supportsCancellation ? streamProvider() : streamProvider(isCancellable ? token : NoCancellationToken);
input
.pipe(stream)
.pipe(es.through(undefined, () => {
state = 'idle';
eventuallyRun();
}))
.pipe(output);
};
if (initial) {
run(initial, false);
}
const eventuallyRun = debounce(() => {
const paths = Object.keys(buffer);
if (paths.length === 0) {
return;
}
const data = paths.map(path => buffer[path]);
buffer = Object.create(null);
run(es.readArray(data), true);
}, 500);
input.on('data', (f) => {
buffer[f.path] = f;
if (state === 'idle') {
eventuallyRun();
}
});
return es.duplex(input, output);
}
exports.incremental = incremental;
function fixWin32DirectoryPermissions() {
if (!/win32/.test(process.platform)) {
return es.through();
}
return es.mapSync(f => {
if (f.stat && f.stat.isDirectory && f.stat.isDirectory()) {
f.stat.mode = 16877;
}
return f;
});
}
exports.fixWin32DirectoryPermissions = fixWin32DirectoryPermissions;
function setExecutableBit(pattern) {
const setBit = es.mapSync(f => {
if (!f.stat) {
f.stat = { isFile() { return true; } };
}
f.stat.mode = /* 100755 */ 33261;
return f;
});
if (!pattern) {
return setBit;
}
const input = es.through();
const filter = _filter(pattern, { restore: true });
const output = input
.pipe(filter)
.pipe(setBit)
.pipe(filter.restore);
return es.duplex(input, output);
}
exports.setExecutableBit = setExecutableBit;
function toFileUri(filePath) {
const match = filePath.match(/^([a-z])\:(.*)$/i);
if (match) {
filePath = '/' + match[1].toUpperCase() + ':' + match[2];
}
return 'file://' + filePath.replace(/\\/g, '/');
}
exports.toFileUri = toFileUri;
function skipDirectories() {
return es.mapSync(f => {
if (!f.isDirectory()) {
return f;
}
});
}
exports.skipDirectories = skipDirectories;
function cleanNodeModules(rulePath) {
const rules = fs.readFileSync(rulePath, 'utf8')
.split(/\r?\n/g)
.map(line => line.trim())
.filter(line => line && !/^#/.test(line));
const excludes = rules.filter(line => !/^!/.test(line)).map(line => `!**/node_modules/${line}`);
const includes = rules.filter(line => /^!/.test(line)).map(line => `**/node_modules/${line.substr(1)}`);
const input = es.through();
const output = es.merge(input.pipe(_filter(['**', ...excludes])), input.pipe(_filter(includes)));
return es.duplex(input, output);
}
exports.cleanNodeModules = cleanNodeModules;
function loadSourcemaps() {
const input = es.through();
const output = input
.pipe(es.map((f, cb) => {
if (f.sourceMap) {
cb(undefined, f);
return;
}
if (!f.contents) {
cb(undefined, f);
return;
}
const contents = f.contents.toString('utf8');
const reg = /\/\/# sourceMappingURL=(.*)$/g;
let lastMatch = null;
let match = null;
while (match = reg.exec(contents)) {
lastMatch = match;
}
if (!lastMatch) {
f.sourceMap = {
version: '3',
names: [],
mappings: '',
sources: [f.relative],
sourcesContent: [contents]
};
cb(undefined, f);
return;
}
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);
}
f.sourceMap = JSON.parse(contents);
cb(undefined, f);
});
}));
return es.duplex(input, output);
}
exports.loadSourcemaps = loadSourcemaps;
function stripSourceMappingURL() {
const input = es.through();
const output = input
.pipe(es.mapSync(f => {
const contents = f.contents.toString('utf8');
f.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, ''), 'utf8');
return f;
}));
return es.duplex(input, output);
}
exports.stripSourceMappingURL = stripSourceMappingURL;
function rimraf(dir) {
const result = () => new Promise((c, e) => {
let retries = 0;
const retry = () => {
_rimraf(dir, { maxBusyTries: 1 }, (err) => {
if (!err) {
return c();
}
if (err.code === 'ENOTEMPTY' && ++retries < 5) {
return setTimeout(() => retry(), 10);
}
return e(err);
});
};
retry();
});
result.taskName = `clean-${path.basename(dir).toLowerCase()}`;
return result;
}
exports.rimraf = rimraf;
function _rreaddir(dirPath, prepend, result) {
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
for (const entry of entries) {
if (entry.isDirectory()) {
_rreaddir(path.join(dirPath, entry.name), `${prepend}/${entry.name}`, result);
}
else {
result.push(`${prepend}/${entry.name}`);
}
}
}
function rreddir(dirPath) {
let result = [];
_rreaddir(dirPath, '', result);
return result;
}
exports.rreddir = rreddir;
function ensureDir(dirPath) {
if (fs.existsSync(dirPath)) {
return;
}
ensureDir(path.dirname(dirPath));
fs.mkdirSync(dirPath);
}
exports.ensureDir = ensureDir;
function getVersion(root) {
let version = process.env['BUILD_SOURCEVERSION'];
if (!version || !/^[0-9a-f]{40}$/i.test(version)) {
version = git.getVersion(root);
}
return version;
}
exports.getVersion = getVersion;
function rebase(count) {
return rename(f => {
const parts = f.dirname ? f.dirname.split(/[\/\\]/) : [];
f.dirname = parts.slice(count).join(path.sep);
});
}
exports.rebase = rebase;
function filter(fn) {
const result = es.through(function (data) {
if (fn(data)) {
this.emit('data', data);
}
else {
result.restore.push(data);
}
});
result.restore = es.through();
return result;
}
exports.filter = filter;
function versionStringToNumber(versionStr) {
const semverRegex = /(\d+)\.(\d+)\.(\d+)/;
const match = versionStr.match(semverRegex);
if (!match) {
throw new Error('Version string is not properly formatted: ' + versionStr);
}
return parseInt(match[1], 10) * 1e4 + parseInt(match[2], 10) * 1e2 + parseInt(match[3], 10);
}
exports.versionStringToNumber = versionStringToNumber;
function streamToPromise(stream) {
return new Promise((c, e) => {
stream.on('error', err => e(err));
stream.on('end', () => c());
});
}
exports.streamToPromise = streamToPromise;
function getElectronVersion() {
const yarnrc = fs.readFileSync(path.join(root, '.yarnrc'), 'utf8');
const target = /^target "(.*)"$/m.exec(yarnrc)[1];
return target;
}
exports.getElectronVersion = getElectronVersion;

View file

@ -1,627 +0,0 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.execute = exports.run3 = exports.DeclarationResolver = exports.FSProvider = exports.RECIPE_PATH = void 0;
const fs = require("fs");
const ts = require("typescript");
const path = require("path");
const fancyLog = require("fancy-log");
const ansiColors = require("ansi-colors");
const dtsv = '3';
const tsfmt = require('../../tsfmt.json');
const SRC = path.join(__dirname, '../../src');
exports.RECIPE_PATH = path.join(__dirname, './monaco.d.ts.recipe');
const DECLARATION_PATH = path.join(__dirname, '../../src/vs/monaco.d.ts');
function logErr(message, ...rest) {
fancyLog(ansiColors.yellow(`[monaco.d.ts]`), message, ...rest);
}
function isDeclaration(a) {
return (a.kind === ts.SyntaxKind.InterfaceDeclaration
|| a.kind === ts.SyntaxKind.EnumDeclaration
|| a.kind === ts.SyntaxKind.ClassDeclaration
|| a.kind === ts.SyntaxKind.TypeAliasDeclaration
|| a.kind === ts.SyntaxKind.FunctionDeclaration
|| a.kind === ts.SyntaxKind.ModuleDeclaration);
}
function visitTopLevelDeclarations(sourceFile, visitor) {
let stop = false;
let visit = (node) => {
if (stop) {
return;
}
switch (node.kind) {
case ts.SyntaxKind.InterfaceDeclaration:
case ts.SyntaxKind.EnumDeclaration:
case ts.SyntaxKind.ClassDeclaration:
case ts.SyntaxKind.VariableStatement:
case ts.SyntaxKind.TypeAliasDeclaration:
case ts.SyntaxKind.FunctionDeclaration:
case ts.SyntaxKind.ModuleDeclaration:
stop = visitor(node);
}
if (stop) {
return;
}
ts.forEachChild(node, visit);
};
visit(sourceFile);
}
function getAllTopLevelDeclarations(sourceFile) {
let all = [];
visitTopLevelDeclarations(sourceFile, (node) => {
if (node.kind === ts.SyntaxKind.InterfaceDeclaration || node.kind === ts.SyntaxKind.ClassDeclaration || node.kind === ts.SyntaxKind.ModuleDeclaration) {
let interfaceDeclaration = node;
let triviaStart = interfaceDeclaration.pos;
let triviaEnd = interfaceDeclaration.name.pos;
let triviaText = getNodeText(sourceFile, { pos: triviaStart, end: triviaEnd });
if (triviaText.indexOf('@internal') === -1) {
all.push(node);
}
}
else {
let nodeText = getNodeText(sourceFile, node);
if (nodeText.indexOf('@internal') === -1) {
all.push(node);
}
}
return false /*continue*/;
});
return all;
}
function getTopLevelDeclaration(sourceFile, typeName) {
let result = null;
visitTopLevelDeclarations(sourceFile, (node) => {
if (isDeclaration(node) && node.name) {
if (node.name.text === typeName) {
result = node;
return true /*stop*/;
}
return false /*continue*/;
}
// node is ts.VariableStatement
if (getNodeText(sourceFile, node).indexOf(typeName) >= 0) {
result = node;
return true /*stop*/;
}
return false /*continue*/;
});
return result;
}
function getNodeText(sourceFile, node) {
return sourceFile.getFullText().substring(node.pos, node.end);
}
function hasModifier(modifiers, kind) {
if (modifiers) {
for (let i = 0; i < modifiers.length; i++) {
let mod = modifiers[i];
if (mod.kind === kind) {
return true;
}
}
}
return false;
}
function isStatic(member) {
return hasModifier(member.modifiers, ts.SyntaxKind.StaticKeyword);
}
function isDefaultExport(declaration) {
return (hasModifier(declaration.modifiers, ts.SyntaxKind.DefaultKeyword)
&& hasModifier(declaration.modifiers, ts.SyntaxKind.ExportKeyword));
}
function getMassagedTopLevelDeclarationText(sourceFile, declaration, importName, usage, enums) {
let result = getNodeText(sourceFile, declaration);
if (declaration.kind === ts.SyntaxKind.InterfaceDeclaration || declaration.kind === ts.SyntaxKind.ClassDeclaration) {
let interfaceDeclaration = declaration;
const staticTypeName = (isDefaultExport(interfaceDeclaration)
? `${importName}.default`
: `${importName}.${declaration.name.text}`);
let instanceTypeName = staticTypeName;
const typeParametersCnt = (interfaceDeclaration.typeParameters ? interfaceDeclaration.typeParameters.length : 0);
if (typeParametersCnt > 0) {
let arr = [];
for (let i = 0; i < typeParametersCnt; i++) {
arr.push('any');
}
instanceTypeName = `${instanceTypeName}<${arr.join(',')}>`;
}
const members = interfaceDeclaration.members;
members.forEach((member) => {
try {
let memberText = getNodeText(sourceFile, member);
if (memberText.indexOf('@internal') >= 0 || memberText.indexOf('private') >= 0) {
result = result.replace(memberText, '');
}
else {
const memberName = member.name.text;
const memberAccess = (memberName.indexOf('.') >= 0 ? `['${memberName}']` : `.${memberName}`);
if (isStatic(member)) {
usage.push(`a = ${staticTypeName}${memberAccess};`);
}
else {
usage.push(`a = (<${instanceTypeName}>b)${memberAccess};`);
}
}
}
catch (err) {
// life..
}
});
}
else if (declaration.kind === ts.SyntaxKind.VariableStatement) {
const jsDoc = result.substr(0, declaration.getLeadingTriviaWidth(sourceFile));
if (jsDoc.indexOf('@monacodtsreplace') >= 0) {
const jsDocLines = jsDoc.split(/\r\n|\r|\n/);
let directives = [];
for (const jsDocLine of jsDocLines) {
const m = jsDocLine.match(/^\s*\* \/([^/]+)\/([^/]+)\/$/);
if (m) {
directives.push([new RegExp(m[1], 'g'), m[2]]);
}
}
// remove the jsdoc
result = result.substr(jsDoc.length);
if (directives.length > 0) {
// apply replace directives
const replacer = createReplacerFromDirectives(directives);
result = replacer(result);
}
}
}
result = result.replace(/export default /g, 'export ');
result = result.replace(/export declare /g, 'export ');
result = result.replace(/declare /g, '');
let lines = result.split(/\r\n|\r|\n/);
for (let i = 0; i < lines.length; i++) {
if (/\s*\*/.test(lines[i])) {
// very likely a comment
continue;
}
lines[i] = lines[i].replace(/"/g, '\'');
}
result = lines.join('\n');
if (declaration.kind === ts.SyntaxKind.EnumDeclaration) {
result = result.replace(/const enum/, 'enum');
enums.push({
enumName: declaration.name.getText(sourceFile),
text: result
});
}
return result;
}
function format(text, endl) {
const REALLY_FORMAT = false;
text = preformat(text, endl);
if (!REALLY_FORMAT) {
return text;
}
// Parse the source text
let sourceFile = ts.createSourceFile('file.ts', text, ts.ScriptTarget.Latest, /*setParentPointers*/ true);
// Get the formatting edits on the input sources
let edits = ts.formatting.formatDocument(sourceFile, getRuleProvider(tsfmt), tsfmt);
// Apply the edits on the input code
return applyEdits(text, edits);
function countParensCurly(text) {
let cnt = 0;
for (let i = 0; i < text.length; i++) {
if (text.charAt(i) === '(' || text.charAt(i) === '{') {
cnt++;
}
if (text.charAt(i) === ')' || text.charAt(i) === '}') {
cnt--;
}
}
return cnt;
}
function repeatStr(s, cnt) {
let r = '';
for (let i = 0; i < cnt; i++) {
r += s;
}
return r;
}
function preformat(text, endl) {
let lines = text.split(endl);
let inComment = false;
let inCommentDeltaIndent = 0;
let indent = 0;
for (let i = 0; i < lines.length; i++) {
let line = lines[i].replace(/\s$/, '');
let repeat = false;
let lineIndent = 0;
do {
repeat = false;
if (line.substring(0, 4) === ' ') {
line = line.substring(4);
lineIndent++;
repeat = true;
}
if (line.charAt(0) === '\t') {
line = line.substring(1);
lineIndent++;
repeat = true;
}
} while (repeat);
if (line.length === 0) {
continue;
}
if (inComment) {
if (/\*\//.test(line)) {
inComment = false;
}
lines[i] = repeatStr('\t', lineIndent + inCommentDeltaIndent) + line;
continue;
}
if (/\/\*/.test(line)) {
inComment = true;
inCommentDeltaIndent = indent - lineIndent;
lines[i] = repeatStr('\t', indent) + line;
continue;
}
const cnt = countParensCurly(line);
let shouldUnindentAfter = false;
let shouldUnindentBefore = false;
if (cnt < 0) {
if (/[({]/.test(line)) {
shouldUnindentAfter = true;
}
else {
shouldUnindentBefore = true;
}
}
else if (cnt === 0) {
shouldUnindentBefore = /^\}/.test(line);
}
let shouldIndentAfter = false;
if (cnt > 0) {
shouldIndentAfter = true;
}
else if (cnt === 0) {
shouldIndentAfter = /{$/.test(line);
}
if (shouldUnindentBefore) {
indent--;
}
lines[i] = repeatStr('\t', indent) + line;
if (shouldUnindentAfter) {
indent--;
}
if (shouldIndentAfter) {
indent++;
}
}
return lines.join(endl);
}
function getRuleProvider(options) {
// Share this between multiple formatters using the same options.
// This represents the bulk of the space the formatter uses.
return ts.formatting.getFormatContext(options);
}
function applyEdits(text, edits) {
// Apply edits in reverse on the existing text
let result = text;
for (let i = edits.length - 1; i >= 0; i--) {
let change = edits[i];
let head = result.slice(0, change.span.start);
let tail = result.slice(change.span.start + change.span.length);
result = head + change.newText + tail;
}
return result;
}
}
function createReplacerFromDirectives(directives) {
return (str) => {
for (let i = 0; i < directives.length; i++) {
str = str.replace(directives[i][0], directives[i][1]);
}
return str;
};
}
function createReplacer(data) {
data = data || '';
let rawDirectives = data.split(';');
let directives = [];
rawDirectives.forEach((rawDirective) => {
if (rawDirective.length === 0) {
return;
}
let pieces = rawDirective.split('=>');
let findStr = pieces[0];
let replaceStr = pieces[1];
findStr = findStr.replace(/[\-\\\{\}\*\+\?\|\^\$\.\,\[\]\(\)\#\s]/g, '\\$&');
findStr = '\\b' + findStr + '\\b';
directives.push([new RegExp(findStr, 'g'), replaceStr]);
});
return createReplacerFromDirectives(directives);
}
function generateDeclarationFile(recipe, sourceFileGetter) {
const endl = /\r\n/.test(recipe) ? '\r\n' : '\n';
let lines = recipe.split(endl);
let result = [];
let usageCounter = 0;
let usageImports = [];
let usage = [];
let failed = false;
usage.push(`var a: any;`);
usage.push(`var b: any;`);
const generateUsageImport = (moduleId) => {
let importName = 'm' + (++usageCounter);
usageImports.push(`import * as ${importName} from './${moduleId.replace(/\.d\.ts$/, '')}';`);
return importName;
};
let enums = [];
let version = null;
lines.forEach(line => {
if (failed) {
return;
}
let m0 = line.match(/^\/\/dtsv=(\d+)$/);
if (m0) {
version = m0[1];
}
let m1 = line.match(/^\s*#include\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
if (m1) {
let moduleId = m1[1];
const sourceFile = sourceFileGetter(moduleId);
if (!sourceFile) {
logErr(`While handling ${line}`);
logErr(`Cannot find ${moduleId}`);
failed = true;
return;
}
const importName = generateUsageImport(moduleId);
let replacer = createReplacer(m1[2]);
let typeNames = m1[3].split(/,/);
typeNames.forEach((typeName) => {
typeName = typeName.trim();
if (typeName.length === 0) {
return;
}
let declaration = getTopLevelDeclaration(sourceFile, typeName);
if (!declaration) {
logErr(`While handling ${line}`);
logErr(`Cannot find ${typeName}`);
failed = true;
return;
}
result.push(replacer(getMassagedTopLevelDeclarationText(sourceFile, declaration, importName, usage, enums)));
});
return;
}
let m2 = line.match(/^\s*#includeAll\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
if (m2) {
let moduleId = m2[1];
const sourceFile = sourceFileGetter(moduleId);
if (!sourceFile) {
logErr(`While handling ${line}`);
logErr(`Cannot find ${moduleId}`);
failed = true;
return;
}
const importName = generateUsageImport(moduleId);
let replacer = createReplacer(m2[2]);
let typeNames = m2[3].split(/,/);
let typesToExcludeMap = {};
let typesToExcludeArr = [];
typeNames.forEach((typeName) => {
typeName = typeName.trim();
if (typeName.length === 0) {
return;
}
typesToExcludeMap[typeName] = true;
typesToExcludeArr.push(typeName);
});
getAllTopLevelDeclarations(sourceFile).forEach((declaration) => {
if (isDeclaration(declaration) && declaration.name) {
if (typesToExcludeMap[declaration.name.text]) {
return;
}
}
else {
// node is ts.VariableStatement
let nodeText = getNodeText(sourceFile, declaration);
for (let i = 0; i < typesToExcludeArr.length; i++) {
if (nodeText.indexOf(typesToExcludeArr[i]) >= 0) {
return;
}
}
}
result.push(replacer(getMassagedTopLevelDeclarationText(sourceFile, declaration, importName, usage, enums)));
});
return;
}
result.push(line);
});
if (failed) {
return null;
}
if (version !== dtsv) {
if (!version) {
logErr(`gulp watch restart required. 'monaco.d.ts.recipe' is written before versioning was introduced.`);
}
else {
logErr(`gulp watch restart required. 'monaco.d.ts.recipe' v${version} does not match runtime v${dtsv}.`);
}
return null;
}
let resultTxt = result.join(endl);
resultTxt = resultTxt.replace(/\bURI\b/g, 'Uri');
resultTxt = resultTxt.replace(/\bEvent</g, 'IEvent<');
resultTxt = resultTxt.split(/\r\n|\n|\r/).join(endl);
resultTxt = format(resultTxt, endl);
resultTxt = resultTxt.split(/\r\n|\n|\r/).join(endl);
enums.sort((e1, e2) => {
if (e1.enumName < e2.enumName) {
return -1;
}
if (e1.enumName > e2.enumName) {
return 1;
}
return 0;
});
let resultEnums = [
'/*---------------------------------------------------------------------------------------------',
' * Copyright (c) Microsoft Corporation. All rights reserved.',
' * Licensed under the MIT License. See License.txt in the project root for license information.',
' *--------------------------------------------------------------------------------------------*/',
'',
'// THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY.',
''
].concat(enums.map(e => e.text)).join(endl);
resultEnums = resultEnums.split(/\r\n|\n|\r/).join(endl);
resultEnums = format(resultEnums, endl);
resultEnums = resultEnums.split(/\r\n|\n|\r/).join(endl);
return {
result: resultTxt,
usageContent: `${usageImports.join('\n')}\n\n${usage.join('\n')}`,
enums: resultEnums
};
}
function _run(sourceFileGetter) {
const recipe = fs.readFileSync(exports.RECIPE_PATH).toString();
const t = generateDeclarationFile(recipe, sourceFileGetter);
if (!t) {
return null;
}
const result = t.result;
const usageContent = t.usageContent;
const enums = t.enums;
const currentContent = fs.readFileSync(DECLARATION_PATH).toString();
const one = currentContent.replace(/\r\n/gm, '\n');
const other = result.replace(/\r\n/gm, '\n');
const isTheSame = (one === other);
return {
content: result,
usageContent: usageContent,
enums: enums,
filePath: DECLARATION_PATH,
isTheSame
};
}
class FSProvider {
existsSync(filePath) {
return fs.existsSync(filePath);
}
statSync(filePath) {
return fs.statSync(filePath);
}
readFileSync(_moduleId, filePath) {
return fs.readFileSync(filePath);
}
}
exports.FSProvider = FSProvider;
class CacheEntry {
constructor(sourceFile, mtime) {
this.sourceFile = sourceFile;
this.mtime = mtime;
}
}
class DeclarationResolver {
constructor(_fsProvider) {
this._fsProvider = _fsProvider;
this._sourceFileCache = Object.create(null);
}
invalidateCache(moduleId) {
this._sourceFileCache[moduleId] = null;
}
getDeclarationSourceFile(moduleId) {
if (this._sourceFileCache[moduleId]) {
// Since we cannot trust file watching to invalidate the cache, check also the mtime
const fileName = this._getFileName(moduleId);
const mtime = this._fsProvider.statSync(fileName).mtime.getTime();
if (this._sourceFileCache[moduleId].mtime !== mtime) {
this._sourceFileCache[moduleId] = null;
}
}
if (!this._sourceFileCache[moduleId]) {
this._sourceFileCache[moduleId] = this._getDeclarationSourceFile(moduleId);
}
return this._sourceFileCache[moduleId] ? this._sourceFileCache[moduleId].sourceFile : null;
}
_getFileName(moduleId) {
if (/\.d\.ts$/.test(moduleId)) {
return path.join(SRC, moduleId);
}
return path.join(SRC, `${moduleId}.ts`);
}
_getDeclarationSourceFile(moduleId) {
const fileName = this._getFileName(moduleId);
if (!this._fsProvider.existsSync(fileName)) {
return null;
}
const mtime = this._fsProvider.statSync(fileName).mtime.getTime();
if (/\.d\.ts$/.test(moduleId)) {
// const mtime = this._fsProvider.statFileSync()
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
return new CacheEntry(ts.createSourceFile(fileName, fileContents, ts.ScriptTarget.ES5), mtime);
}
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
const fileMap = {
'file.ts': fileContents
};
const service = ts.createLanguageService(new TypeScriptLanguageServiceHost({}, fileMap, {}));
const text = service.getEmitOutput('file.ts', true, true).outputFiles[0].text;
return new CacheEntry(ts.createSourceFile(fileName, text, ts.ScriptTarget.ES5), mtime);
}
}
exports.DeclarationResolver = DeclarationResolver;
function run3(resolver) {
const sourceFileGetter = (moduleId) => resolver.getDeclarationSourceFile(moduleId);
return _run(sourceFileGetter);
}
exports.run3 = run3;
class TypeScriptLanguageServiceHost {
constructor(libs, files, compilerOptions) {
this._libs = libs;
this._files = files;
this._compilerOptions = compilerOptions;
}
// --- language service host ---------------
getCompilationSettings() {
return this._compilerOptions;
}
getScriptFileNames() {
return ([]
.concat(Object.keys(this._libs))
.concat(Object.keys(this._files)));
}
getScriptVersion(_fileName) {
return '1';
}
getProjectVersion() {
return '1';
}
getScriptSnapshot(fileName) {
if (this._files.hasOwnProperty(fileName)) {
return ts.ScriptSnapshot.fromString(this._files[fileName]);
}
else if (this._libs.hasOwnProperty(fileName)) {
return ts.ScriptSnapshot.fromString(this._libs[fileName]);
}
else {
return ts.ScriptSnapshot.fromString('');
}
}
getScriptKind(_fileName) {
return ts.ScriptKind.TS;
}
getCurrentDirectory() {
return '';
}
getDefaultLibFileName(_options) {
return 'defaultLib:es5';
}
isDefaultLibFileName(fileName) {
return fileName === this.getDefaultLibFileName(this._compilerOptions);
}
}
function execute() {
let r = run3(new DeclarationResolver(new FSProvider()));
if (!r) {
throw new Error(`monaco.d.ts generation error - Cannot continue`);
}
return r;
}
exports.execute = execute;

View file

@ -121,9 +121,16 @@ export function activate(context: vscode.ExtensionContext) {
function relativePathToUri(path: string, resultsUri: vscode.Uri): vscode.Uri | undefined {
if (pathUtils.isAbsolute(path)) { return vscode.Uri.file(path); }
if (pathUtils.isAbsolute(path)) {
return vscode.Uri
.file(path)
.with({ scheme: process.env.HOME ? 'file' : 'vscode-userdata' });
}
if (path.indexOf('~/') === 0) {
return vscode.Uri.file(pathUtils.join(process.env.HOME!, path.slice(2)));
return vscode.Uri
.file(pathUtils.join(process.env.HOME ?? '', path.slice(2)))
.with({ scheme: process.env.HOME ? 'file' : 'vscode-userdata' });
}
const uriFromFolderWithPath = (folder: vscode.WorkspaceFolder, path: string): vscode.Uri =>

View file

@ -12,8 +12,6 @@
"activityBarBadge.background": "#007ACC",
"sideBarTitle.foreground": "#BBBBBB",
"input.placeholderForeground": "#A6A6A6",
"settings.textInputBackground": "#292929",
"settings.numberInputBackground": "#292929",
"menu.background": "#252526",
"menu.foreground": "#CCCCCC",
"statusBarItem.remoteForeground": "#FFF",

View file

@ -11,8 +11,6 @@
"list.activeSelectionBackground": "#75715E",
"list.focusBackground": "#414339",
"dropdown.listBackground": "#1e1f1c",
"settings.textInputBackground": "#32342d",
"settings.numberInputBackground": "#32342d",
"list.inactiveSelectionBackground": "#414339",
"list.hoverBackground": "#3e3d32",
"list.dropBackground": "#414339",
@ -46,6 +44,7 @@
"panelTitle.activeBorder": "#75715E",
"panelTitle.inactiveForeground": "#75715E",
"panel.border": "#414339",
"settings.focusedRowBackground": "#4143395A",
"titleBar.activeBackground": "#1e1f1c",
"statusBar.background": "#414339",
"statusBar.noFolderBackground": "#414339",

View file

@ -456,7 +456,7 @@ suite('Notebook API tests', () => {
});
test('edit API (replaceMetadata)', async function () {
this.skip();
assertInitalState();
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
@ -475,7 +475,7 @@ suite('Notebook API tests', () => {
});
test('edit API (replaceMetadata, event)', async function () {
this.skip();
assertInitalState();
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
@ -624,7 +624,6 @@ suite('Notebook API tests', () => {
});
test('edit API batch edits', async function () {
this.skip();
assertInitalState();
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');
@ -644,7 +643,6 @@ suite('Notebook API tests', () => {
});
test('edit API batch edits undo/redo', async function () {
this.skip();
assertInitalState();
const resource = await createRandomFile('', undefined, 'first', '.vsctestnb');
await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest');

View file

@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.50.0",
"distro": "e1ab83d5a229ad32d7b0af96380fdf36ec203b2f",
"distro": "20bcc93e22ceef0a6c4464ae78363429f59be797",
"author": {
"name": "Microsoft Corporation"
},
@ -28,7 +28,7 @@
"watch-extensionsd": "deemon yarn watch-extensions",
"kill-watch-extensionsd": "deemon --kill yarn watch-extensions",
"mocha": "mocha test/unit/node/all.js --delay",
"precommit": "node build/gulpfile.hygiene.js",
"precommit": "node build/hygiene.js",
"gulp": "gulp --max_old_space_size=8192",
"electron": "node build/lib/electron",
"7z": "7z",
@ -63,7 +63,7 @@
"semver-umd": "^5.5.7",
"spdlog": "^0.11.1",
"sudo-prompt": "9.1.1",
"tas-client-umd": "^0.1.1",
"tas-client-umd": "0.1.2",
"v8-inspect-profiler": "^0.0.20",
"vscode-nsfw": "1.2.8",
"vscode-oniguruma": "1.3.1",

View file

@ -31,7 +31,7 @@
"builtInExtensions": [
{
"name": "ms-vscode.node-debug",
"version": "1.44.11",
"version": "1.44.14",
"repo": "https://github.com/microsoft/vscode-node-debug",
"metadata": {
"id": "b6ded8fb-a0a0-4c1c-acbd-ab2a3bc995a6",

View file

@ -5,7 +5,7 @@
"iconv-lite-umd": "0.6.8",
"jschardet": "2.2.1",
"semver-umd": "^5.5.7",
"tas-client-umd": "^0.1.1",
"tas-client-umd": "0.1.2",
"vscode-oniguruma": "1.3.1",
"vscode-textmate": "5.2.0",
"xterm": "4.10.0-beta.4",

View file

@ -17,10 +17,10 @@ semver-umd@^5.5.7:
resolved "https://registry.yarnpkg.com/semver-umd/-/semver-umd-5.5.7.tgz#966beb5e96c7da6fbf09c3da14c2872d6836c528"
integrity sha512-XgjPNlD0J6aIc8xoTN6GQGwWc2Xg0kq8NzrqMVuKG/4Arl6ab1F8+Am5Y/XKKCR+FceFr2yN/Uv5ZJBhRyRqKg==
tas-client-umd@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/tas-client-umd/-/tas-client-umd-0.1.1.tgz#a858ced3d3af5989a505f5b6bc961e4ff33ab1a4"
integrity sha512-vWp7WNBL+tMifW3k1HJb9fmmJhvbu+zIYtvQbx5w04hCl8KXuhfc59fu//Cx31WZiKcfTaIw/WPB47hzYGuh8A==
tas-client-umd@0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/tas-client-umd/-/tas-client-umd-0.1.2.tgz#fe93ae085f65424292ac79feff4f1add3e50e624"
integrity sha512-rT9BdDCejckqOTQL2ShX67QtTiAUGbmPm5ZTC8giXobBvZC6JuvBVy5G32hoGZ3Q0dpTvMfgpf3iVFNN2F7wzg==
vscode-oniguruma@1.3.1:
version "1.3.1"

View file

@ -695,13 +695,13 @@ export function isAncestor(testChild: Node | null, testAncestor: Node | null): b
export function findParentWithClass(node: HTMLElement, clazz: string, stopAtClazzOrNode?: string | HTMLElement): HTMLElement | null {
while (node && node.nodeType === node.ELEMENT_NODE) {
if (hasClass(node, clazz)) {
if (node.classList.contains(clazz)) {
return node;
}
if (stopAtClazzOrNode) {
if (typeof stopAtClazzOrNode === 'string') {
if (hasClass(node, stopAtClazzOrNode)) {
if (node.classList.contains(stopAtClazzOrNode)) {
return null;
}
} else {

View file

@ -336,7 +336,7 @@ export class BreadcrumbsWidget {
item.render(container);
container.tabIndex = -1;
container.setAttribute('role', 'listitem');
dom.addClasses(container, 'monaco-breadcrumb-item');
container.classList.add('monaco-breadcrumb-item');
const iconContainer = dom.$(breadcrumbSeparatorIcon.cssSelector);
container.appendChild(iconContainer);
}

View file

@ -188,7 +188,7 @@ class Label {
if (typeof label === 'string') {
if (!this.singleLabel) {
this.container.innerText = '';
dom.removeClass(this.container, 'multiple');
this.container.classList.remove('multiple');
this.singleLabel = dom.append(this.container, dom.$('a.label-name', { id: options?.domId }));
}
@ -251,7 +251,7 @@ class LabelWithHighlights {
if (typeof label === 'string') {
if (!this.singleLabel) {
this.container.innerText = '';
dom.removeClass(this.container, 'multiple');
this.container.classList.remove('multiple');
this.singleLabel = new HighlightedLabel(dom.append(this.container, dom.$('a.label-name', { id: options?.domId })), this.supportCodicons);
}

View file

@ -15,13 +15,18 @@
/** Actions */
.monaco-workbench .monaco-action-bar .action-item.select-container {
.monaco-action-bar .action-item.select-container {
cursor: default;
}
.monaco-workbench .monaco-action-bar .action-item .monaco-select-box {
.monaco-action-bar .action-item .monaco-select-box {
font-size: 11px;
cursor: pointer;
min-width: 110px;
min-height: 18px;
padding: 2px 23px 2px 8px;
}
.mac .monaco-action-bar .action-item .monaco-select-box {
border-radius: 5px;
}

View file

@ -135,7 +135,7 @@
transition-property: width;
}
#monaco-workbench-pane-drop-overlay {
#monaco-pane-drop-overlay {
position: absolute;
z-index: 10000;
width: 100%;
@ -144,7 +144,7 @@
box-sizing: border-box;
}
#monaco-workbench-pane-drop-overlay > .pane-overlay-indicator {
#monaco-pane-drop-overlay > .pane-overlay-indicator {
position: absolute;
width: 100%;
height: 100%;
@ -155,6 +155,6 @@
transition: opacity 150ms ease-out;
}
#monaco-workbench-pane-drop-overlay > .pane-overlay-indicator.overlay-move-transition {
#monaco-pane-drop-overlay > .pane-overlay-indicator.overlay-move-transition {
transition: top 70ms ease-out, left 70ms ease-out, width 70ms ease-out, height 70ms ease-out, opacity 150ms ease-out;
}

View file

@ -480,6 +480,8 @@ export namespace Codicon {
export const exportIcon = new Codicon('export', { character: '\\ebac' });
export const graphLeft = new Codicon('graph-left', { character: '\\ebad' });
export const magnet = new Codicon('magnet', { character: '\\ebae' });
export const notebook = new Codicon('notebook', { character: '\\ebaf' });
export const redo = new Codicon('redo', { character: '\\ebb0' });
}

View file

@ -144,41 +144,6 @@ export function stripWildcards(pattern: string): string {
return pattern.replace(/\*/g, '');
}
/**
* @deprecated ES6: use `String.startsWith`
*/
export function startsWith(haystack: string, needle: string): boolean {
if (haystack.length < needle.length) {
return false;
}
if (haystack === needle) {
return true;
}
for (let i = 0; i < needle.length; i++) {
if (haystack[i] !== needle[i]) {
return false;
}
}
return true;
}
/**
* @deprecated ES6: use `String.endsWith`
*/
export function endsWith(haystack: string, needle: string): boolean {
const diff = haystack.length - needle.length;
if (diff > 0) {
return haystack.indexOf(needle, diff) === diff;
} else if (diff === 0) {
return haystack === needle;
} else {
return false;
}
}
export interface RegExpOptions {
matchCase?: boolean;
wholeWord?: boolean;

View file

@ -7,7 +7,6 @@ import { dirname, basename, distinctParents, joinPath, normalizePath, isAbsolute
import { URI } from 'vs/base/common/uri';
import { isWindows } from 'vs/base/common/platform';
import { toSlashes } from 'vs/base/common/extpath';
import { startsWith } from 'vs/base/common/strings';
import { win32, posix } from 'vs/base/common/path';
@ -304,7 +303,7 @@ suite('Resources', () => {
const p = path.indexOf('/') !== -1 ? posix : win32;
if (!p.isAbsolute(path)) {
let expectedPath = isWindows ? toSlashes(path) : path;
expectedPath = startsWith(expectedPath, './') ? expectedPath.substr(2) : expectedPath;
expectedPath = expectedPath.startsWith('./') ? expectedPath.substr(2) : expectedPath;
assert.equal(relativePath(u1, actual), expectedPath, `relativePath (${u1.toString()}) on actual (${actual.toString()}) should be to path (${expectedPath})`);
}
}

View file

@ -140,28 +140,6 @@ suite('Strings', () => {
assert.strictEqual(strings.escape('<foo>Hello</foo>'), '&lt;foo&gt;Hello&lt;/foo&gt;');
});
test('startsWith', () => {
assert(strings.startsWith('foo', 'f'));
assert(strings.startsWith('foo', 'fo'));
assert(strings.startsWith('foo', 'foo'));
assert(!strings.startsWith('foo', 'o'));
assert(!strings.startsWith('', 'f'));
assert(strings.startsWith('foo', ''));
assert(strings.startsWith('', ''));
});
test('endsWith', () => {
assert(strings.endsWith('foo', 'o'));
assert(strings.endsWith('foo', 'oo'));
assert(strings.endsWith('foo', 'foo'));
assert(strings.endsWith('foo bar foo', 'foo'));
assert(!strings.endsWith('foo', 'f'));
assert(!strings.endsWith('', 'f'));
assert(strings.endsWith('foo', ''));
assert(strings.endsWith('', ''));
assert(strings.endsWith('/', '/'));
});
test('ltrim', () => {
assert.strictEqual(strings.ltrim('foo', 'f'), 'oo');
assert.strictEqual(strings.ltrim('foo', 'o'), 'foo');

View file

@ -55,8 +55,6 @@ import { UserDataSyncChannel, UserDataSyncUtilServiceClient, UserDataAutoSyncCha
import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
import { LoggerService } from 'vs/platform/log/node/loggerService';
import { UserDataSyncLogService } from 'vs/platform/userDataSync/common/userDataSyncLog';
import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
import { KeytarCredentialsService } from 'vs/platform/credentials/node/credentialsService';
import { UserDataAutoSyncService } from 'vs/platform/userDataSync/electron-sandbox/userDataAutoSyncService';
import { NativeStorageService } from 'vs/platform/storage/node/storageService';
import { GlobalStorageDatabaseChannelClient } from 'vs/platform/storage/node/storageIpc';
@ -198,7 +196,6 @@ async function main(server: Server, initData: ISharedProcessInitData, configurat
services.set(IDiagnosticsService, new SyncDescriptor(DiagnosticsService));
services.set(IExtensionTipsService, new SyncDescriptor(ExtensionTipsService));
services.set(ICredentialsService, new SyncDescriptor(KeytarCredentialsService));
services.set(IUserDataSyncAccountService, new SyncDescriptor(UserDataSyncAccountService));
services.set(IUserDataSyncLogService, new SyncDescriptor(UserDataSyncLogService));
services.set(IUserDataSyncUtilService, new UserDataSyncUtilServiceClient(server.getChannel('userDataSyncUtil', client => client.ctx !== 'main')));

View file

@ -689,8 +689,8 @@ export class CodeApplication extends Disposable {
});
}
// new window if "-n" or "--remote" was used without paths
if ((args['new-window'] || args.remote) && !hasCliArgs && !hasFolderURIs && !hasFileURIs) {
// new window if "-n"
if (args['new-window'] && !hasCliArgs && !hasFolderURIs && !hasFileURIs) {
return windowsMainService.open({
context,
cli: args,

View file

@ -9,7 +9,7 @@ import { INativeHostService } from 'vs/platform/native/electron-sandbox/native';
import { NativeHostService } from 'vs/platform/native/electron-sandbox/nativeHostService';
import { ipcRenderer, process } from 'vs/base/parts/sandbox/electron-sandbox/globals';
import { applyZoom, zoomIn, zoomOut } from 'vs/platform/windows/electron-sandbox/window';
import { $, reset, windowOpenNoOpener, addClass } from 'vs/base/browser/dom';
import { $, reset, windowOpenNoOpener } from 'vs/base/browser/dom';
import { Button } from 'vs/base/browser/ui/button/button';
import { CodiconLabel } from 'vs/base/browser/ui/codicons/codiconLabel';
import * as collections from 'vs/base/common/collections';
@ -56,7 +56,7 @@ export interface IssueReporterConfiguration extends IWindowConfiguration {
export function startup(configuration: IssueReporterConfiguration) {
const platformClass = platform.isWindows ? 'windows' : platform.isLinux ? 'linux' : 'mac';
addClass(document.body, platformClass); // used by our fonts
document.body.classList.add(platformClass); // used by our fonts
document.body.innerHTML = BaseHtml();
const issueReporter = new IssueReporter(configuration);

View file

@ -14,7 +14,7 @@ import { applyZoom, zoomIn, zoomOut } from 'vs/platform/windows/electron-sandbox
import { IContextMenuItem } from 'vs/base/parts/contextmenu/common/contextmenu';
import { popup } from 'vs/base/parts/contextmenu/electron-sandbox/contextmenu';
import { ProcessItem } from 'vs/base/common/processes';
import { addDisposableListener, addClass, $ } from 'vs/base/browser/dom';
import { addDisposableListener, $ } from 'vs/base/browser/dom';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { isRemoteDiagnosticError, IRemoteDiagnosticError } from 'vs/platform/diagnostics/common/diagnostics';
import { MainProcessService } from 'vs/platform/ipc/electron-sandbox/mainProcessService';
@ -417,7 +417,7 @@ class ProcessExplorer {
export function startup(windowId: number, data: ProcessExplorerData): void {
const platformClass = data.platform === 'win32' ? 'windows' : data.platform === 'linux' ? 'linux' : 'mac';
addClass(document.body, platformClass); // used by our fonts
document.body.classList.add(platformClass); // used by our fonts
applyZoom(data.zoomLevel);
const processExplorer = new ProcessExplorer(windowId, data);

View file

@ -55,14 +55,6 @@ const autoCloseAlways = () => true;
const autoCloseNever = () => false;
const autoCloseBeforeWhitespace = (chr: string) => (chr === ' ' || chr === '\t');
function appendEntry<K, V>(target: Map<K, V[]>, key: K, value: V): void {
if (target.has(key)) {
target.get(key)!.push(value);
} else {
target.set(key, [value]);
}
}
export class CursorConfiguration {
_cursorMoveConfigurationBrand: void;
@ -136,8 +128,6 @@ export class CursorConfiguration {
this.autoSurround = options.get(EditorOption.autoSurround);
this.autoIndent = options.get(EditorOption.autoIndent);
this.autoClosingPairsOpen2 = new Map<string, StandardAutoClosingPairConditional[]>();
this.autoClosingPairsClose2 = new Map<string, StandardAutoClosingPairConditional[]>();
this.surroundingPairs = {};
this._electricChars = null;
@ -146,15 +136,9 @@ export class CursorConfiguration {
bracket: CursorConfiguration._getShouldAutoClose(languageIdentifier, this.autoClosingBrackets)
};
let autoClosingPairs = CursorConfiguration._getAutoClosingPairs(languageIdentifier);
if (autoClosingPairs) {
for (const pair of autoClosingPairs) {
appendEntry(this.autoClosingPairsOpen2, pair.open.charAt(pair.open.length - 1), pair);
if (pair.close.length === 1) {
appendEntry(this.autoClosingPairsClose2, pair.close, pair);
}
}
}
const autoClosingPairs = LanguageConfigurationRegistry.getAutoClosingPairs(languageIdentifier.id);
this.autoClosingPairsOpen2 = autoClosingPairs.autoClosingPairsOpen;
this.autoClosingPairsClose2 = autoClosingPairs.autoClosingPairsClose;
let surroundingPairs = CursorConfiguration._getSurroundingPairs(languageIdentifier);
if (surroundingPairs) {
@ -190,15 +174,6 @@ export class CursorConfiguration {
}
}
private static _getAutoClosingPairs(languageIdentifier: LanguageIdentifier): StandardAutoClosingPairConditional[] | null {
try {
return LanguageConfigurationRegistry.getAutoClosingPairs(languageIdentifier.id);
} catch (e) {
onUnexpectedError(e);
return null;
}
}
private static _getShouldAutoClose(languageIdentifier: LanguageIdentifier, autoCloseConfig: EditorAutoClosingStrategy): (ch: string) => boolean {
switch (autoCloseConfig) {
case 'beforeWhitespace':

View file

@ -5,11 +5,13 @@
import * as strings from 'vs/base/common/strings';
import { ReplaceCommand } from 'vs/editor/common/commands/replaceCommand';
import { EditorAutoClosingStrategy } from 'vs/editor/common/config/editorOptions';
import { CursorColumns, CursorConfiguration, EditOperationResult, EditOperationType, ICursorSimpleModel, isQuote } from 'vs/editor/common/controller/cursorCommon';
import { MoveOperations } from 'vs/editor/common/controller/cursorMoveOperations';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { ICommand } from 'vs/editor/common/editorCommon';
import { StandardAutoClosingPairConditional } from 'vs/editor/common/modes/languageConfiguration';
export class DeleteOperations {
@ -47,8 +49,14 @@ export class DeleteOperations {
return [shouldPushStackElementBefore, commands];
}
private static _isAutoClosingPairDelete(config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[]): boolean {
if (config.autoClosingBrackets === 'never' && config.autoClosingQuotes === 'never') {
public static isAutoClosingPairDelete(
autoClosingBrackets: EditorAutoClosingStrategy,
autoClosingQuotes: EditorAutoClosingStrategy,
autoClosingPairsOpen: Map<string, StandardAutoClosingPairConditional[]>,
model: ICursorSimpleModel,
selections: Selection[]
): boolean {
if (autoClosingBrackets === 'never' && autoClosingQuotes === 'never') {
return false;
}
@ -61,24 +69,27 @@ export class DeleteOperations {
}
const lineText = model.getLineContent(position.lineNumber);
const character = lineText[position.column - 2];
if (position.column < 2 || position.column >= lineText.length + 1) {
return false;
}
const character = lineText.charAt(position.column - 2);
const autoClosingPairCandidates = config.autoClosingPairsOpen2.get(character);
const autoClosingPairCandidates = autoClosingPairsOpen.get(character);
if (!autoClosingPairCandidates) {
return false;
}
if (isQuote(character)) {
if (config.autoClosingQuotes === 'never') {
if (autoClosingQuotes === 'never') {
return false;
}
} else {
if (config.autoClosingBrackets === 'never') {
if (autoClosingBrackets === 'never') {
return false;
}
}
const afterCharacter = lineText[position.column - 1];
const afterCharacter = lineText.charAt(position.column - 1);
let foundAutoClosingPair = false;
for (const autoClosingPairCandidate of autoClosingPairCandidates) {
@ -111,7 +122,7 @@ export class DeleteOperations {
public static deleteLeft(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[]): [boolean, Array<ICommand | null>] {
if (this._isAutoClosingPairDelete(config, model, selections)) {
if (this.isAutoClosingPairDelete(config.autoClosingBrackets, config.autoClosingQuotes, config.autoClosingPairsOpen2, model, selections)) {
return this._runAutoClosingPairDelete(config, model, selections);
}

View file

@ -5,12 +5,15 @@
import { CharCode } from 'vs/base/common/charCode';
import * as strings from 'vs/base/common/strings';
import { EditorAutoClosingStrategy } from 'vs/editor/common/config/editorOptions';
import { CursorConfiguration, ICursorSimpleModel, SingleCursorState } from 'vs/editor/common/controller/cursorCommon';
import { DeleteOperations } from 'vs/editor/common/controller/cursorDeleteOperations';
import { WordCharacterClass, WordCharacterClassifier, getMapForWordSeparators } from 'vs/editor/common/controller/wordCharacterClassifier';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { ITextModel, IWordAtPosition } from 'vs/editor/common/model';
import { AutoClosingPairs } from 'vs/editor/common/modes/languageConfiguration';
interface IFindWordResult {
/**
@ -44,6 +47,16 @@ export const enum WordNavigationType {
WordAccessibility = 3 // Respect chrome defintion of a word
}
export interface DeleteWordContext {
wordSeparators: WordCharacterClassifier;
model: ITextModel;
selection: Selection;
whitespaceHeuristics: boolean;
autoClosingBrackets: EditorAutoClosingStrategy;
autoClosingQuotes: EditorAutoClosingStrategy;
autoClosingPairs: AutoClosingPairs;
}
export class WordOperations {
private static _createWord(lineContent: string, wordType: WordType, nextCharClass: WordCharacterClass, start: number, end: number): IFindWordResult {
@ -361,11 +374,21 @@ export class WordOperations {
return null;
}
public static deleteWordLeft(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range | null {
public static deleteWordLeft(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range | null {
const wordSeparators = ctx.wordSeparators;
const model = ctx.model;
const selection = ctx.selection;
const whitespaceHeuristics = ctx.whitespaceHeuristics;
if (!selection.isEmpty()) {
return selection;
}
if (DeleteOperations.isAutoClosingPairDelete(ctx.autoClosingBrackets, ctx.autoClosingQuotes, ctx.autoClosingPairs.autoClosingPairsOpen, ctx.model, [ctx.selection])) {
const position = ctx.selection.getPosition();
return new Range(position.lineNumber, position.column - 1, position.lineNumber, position.column + 1);
}
const position = new Position(selection.positionLineNumber, selection.positionColumn);
let lineNumber = position.lineNumber;
@ -447,7 +470,12 @@ export class WordOperations {
return null;
}
public static deleteWordRight(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range | null {
public static deleteWordRight(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range | null {
const wordSeparators = ctx.wordSeparators;
const model = ctx.model;
const selection = ctx.selection;
const whitespaceHeuristics = ctx.whitespaceHeuristics;
if (!selection.isEmpty()) {
return selection;
}
@ -621,21 +649,21 @@ export class WordOperations {
}
export class WordPartOperations extends WordOperations {
public static deleteWordPartLeft(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, selection: Selection, whitespaceHeuristics: boolean): Range {
public static deleteWordPartLeft(ctx: DeleteWordContext): Range {
const candidates = enforceDefined([
WordOperations.deleteWordLeft(wordSeparators, model, selection, whitespaceHeuristics, WordNavigationType.WordStart),
WordOperations.deleteWordLeft(wordSeparators, model, selection, whitespaceHeuristics, WordNavigationType.WordEnd),
WordOperations._deleteWordPartLeft(model, selection)
WordOperations.deleteWordLeft(ctx, WordNavigationType.WordStart),
WordOperations.deleteWordLeft(ctx, WordNavigationType.WordEnd),
WordOperations._deleteWordPartLeft(ctx.model, ctx.selection)
]);
candidates.sort(Range.compareRangesUsingEnds);
return candidates[2];
}
public static deleteWordPartRight(wordSeparators: WordCharacterClassifier, model: ICursorSimpleModel, selection: Selection, whitespaceHeuristics: boolean): Range {
public static deleteWordPartRight(ctx: DeleteWordContext): Range {
const candidates = enforceDefined([
WordOperations.deleteWordRight(wordSeparators, model, selection, whitespaceHeuristics, WordNavigationType.WordStart),
WordOperations.deleteWordRight(wordSeparators, model, selection, whitespaceHeuristics, WordNavigationType.WordEnd),
WordOperations._deleteWordPartRight(model, selection)
WordOperations.deleteWordRight(ctx, WordNavigationType.WordStart),
WordOperations.deleteWordRight(ctx, WordNavigationType.WordEnd),
WordOperations._deleteWordPartRight(ctx.model, ctx.selection)
]);
candidates.sort(Range.compareRangesUsingStarts);
return candidates[0];

View file

@ -13,6 +13,7 @@ import { URI } from 'vs/base/common/uri';
import { TextChange, compressConsecutiveTextChanges } from 'vs/editor/common/model/textChange';
import * as buffer from 'vs/base/common/buffer';
import { IDisposable } from 'vs/base/common/lifecycle';
import { basename } from 'vs/base/common/resources';
function uriGetComparisonKey(resource: URI): string {
return resource.toString();
@ -340,6 +341,14 @@ export class MultiModelEditStackElement implements IWorkspaceUndoRedoElement {
public split(): IResourceUndoRedoElement[] {
return this._editStackElementsArr;
}
public toString(): string {
let result: string[] = [];
for (const editStackElement of this._editStackElementsArr) {
result.push(`${basename(editStackElement.resource)}: ${editStackElement}`);
}
return `{${result.join(', ')}}`;
}
}
export type EditStackElement = SingleModelEditStackElement | MultiModelEditStackElement;

View file

@ -6,6 +6,14 @@
import * as buffer from 'vs/base/common/buffer';
import { decodeUTF16LE } from 'vs/editor/common/core/stringBuilder';
function escapeNewLine(str: string): string {
return (
str
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r')
);
}
export class TextChange {
public get oldLength(): number {
@ -33,12 +41,12 @@ export class TextChange {
public toString(): string {
if (this.oldText.length === 0) {
return `(insert@${this.oldPosition} "${this.newText}")`;
return `(insert@${this.oldPosition} "${escapeNewLine(this.newText)}")`;
}
if (this.newText.length === 0) {
return `(delete@${this.oldPosition} "${this.oldText}")`;
return `(delete@${this.oldPosition} "${escapeNewLine(this.oldText)}")`;
}
return `(replace@${this.oldPosition} "${this.oldText}" with "${this.newText}")`;
return `(replace@${this.oldPosition} "${escapeNewLine(this.oldText)}" with "${escapeNewLine(this.newText)}")`;
}
private static _writeStringSize(str: string): number {

View file

@ -358,7 +358,7 @@ export const completionKindToCssClass = (function () {
data[CompletionItemKind.User] = 'account';
data[CompletionItemKind.Issue] = 'issues';
return function (kind: CompletionItemKind) {
return function (kind: CompletionItemKind): string {
const name = data[kind];
let codicon = name && iconRegistry.get(name);
if (!codicon) {

View file

@ -289,3 +289,31 @@ export class StandardAutoClosingPairConditional {
return (this._standardTokenMask & <number>standardToken) === 0;
}
}
/**
* @internal
*/
export class AutoClosingPairs {
public readonly autoClosingPairsOpen: Map<string, StandardAutoClosingPairConditional[]>;
public readonly autoClosingPairsClose: Map<string, StandardAutoClosingPairConditional[]>;
constructor(autoClosingPairs: StandardAutoClosingPairConditional[]) {
this.autoClosingPairsOpen = new Map<string, StandardAutoClosingPairConditional[]>();
this.autoClosingPairsClose = new Map<string, StandardAutoClosingPairConditional[]>();
for (const pair of autoClosingPairs) {
appendEntry(this.autoClosingPairsOpen, pair.open.charAt(pair.open.length - 1), pair);
if (pair.close.length === 1) {
appendEntry(this.autoClosingPairsClose, pair.close, pair);
}
}
}
}
function appendEntry<K, V>(target: Map<K, V[]>, key: K, value: V): void {
if (target.has(key)) {
target.get(key)!.push(value);
} else {
target.set(key, [value]);
}
}

View file

@ -11,7 +11,7 @@ import { Range } from 'vs/editor/common/core/range';
import { ITextModel } from 'vs/editor/common/model';
import { DEFAULT_WORD_REGEXP, ensureValidWordDefinition } from 'vs/editor/common/model/wordHelper';
import { LanguageId, LanguageIdentifier } from 'vs/editor/common/modes';
import { EnterAction, FoldingRules, IAutoClosingPair, IndentAction, IndentationRule, LanguageConfiguration, StandardAutoClosingPairConditional, CompleteEnterAction } from 'vs/editor/common/modes/languageConfiguration';
import { EnterAction, FoldingRules, IAutoClosingPair, IndentAction, IndentationRule, LanguageConfiguration, StandardAutoClosingPairConditional, CompleteEnterAction, AutoClosingPairs } from 'vs/editor/common/modes/languageConfiguration';
import { createScopedLineTokens, ScopedLineTokens } from 'vs/editor/common/modes/supports';
import { CharacterPairSupport } from 'vs/editor/common/modes/supports/characterPair';
import { BracketElectricCharacterSupport, IElectricAction } from 'vs/editor/common/modes/supports/electricCharacter';
@ -235,12 +235,9 @@ export class LanguageConfigurationRegistryImpl {
return value.characterPair || null;
}
public getAutoClosingPairs(languageId: LanguageId): StandardAutoClosingPairConditional[] {
let characterPairSupport = this._getCharacterPairSupport(languageId);
if (!characterPairSupport) {
return [];
}
return characterPairSupport.getAutoClosingPairs();
public getAutoClosingPairs(languageId: LanguageId): AutoClosingPairs {
const characterPairSupport = this._getCharacterPairSupport(languageId);
return new AutoClosingPairs(characterPairSupport ? characterPairSupport.getAutoClosingPairs() : []);
}
public getAutoCloseBeforeSet(languageId: LanguageId): string {

View file

@ -24,9 +24,9 @@ import { RunOnceScheduler } from 'vs/base/common/async';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { ILogService } from 'vs/platform/log/common/log';
import { IUndoRedoService, IUndoRedoElement, IPastFutureElements, ResourceEditStackSnapshot } from 'vs/platform/undoRedo/common/undoRedo';
import { IUndoRedoService, ResourceEditStackSnapshot } from 'vs/platform/undoRedo/common/undoRedo';
import { StringSHA1 } from 'vs/base/common/hash';
import { SingleModelEditStackElement, MultiModelEditStackElement, EditStackElement, isEditStackElement } from 'vs/editor/common/model/editStack';
import { EditStackElement, isEditStackElement } from 'vs/editor/common/model/editStack';
import { Schemas } from 'vs/base/common/network';
import { SemanticTokensProviderStyling, toMultilineTokens2 } from 'vs/editor/common/services/semanticTokensProviderStyling';
@ -118,23 +118,6 @@ export interface EditStackPastFutureElements {
future: EditStackElement[];
}
export function isEditStackPastFutureElements(undoElements: IPastFutureElements): undoElements is EditStackPastFutureElements {
return (isEditStackElements(undoElements.past) && isEditStackElements(undoElements.future));
}
function isEditStackElements(elements: IUndoRedoElement[]): elements is EditStackElement[] {
for (const element of elements) {
if (element instanceof SingleModelEditStackElement) {
continue;
}
if (element instanceof MultiModelEditStackElement) {
continue;
}
return false;
}
return true;
}
class DisposedModelInfo {
constructor(
public readonly uri: URI,

View file

@ -6,8 +6,7 @@
import { IModelService } from 'vs/editor/common/services/modelService';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IUndoRedoService, UndoRedoElementType } from 'vs/platform/undoRedo/common/undoRedo';
import { isEditStackPastFutureElements } from 'vs/editor/common/services/modelServiceImpl';
import { IUndoRedoService } from 'vs/platform/undoRedo/common/undoRedo';
import { IUndoRedoDelegate, MultiModelEditStackElement } from 'vs/editor/common/model/editStack';
export class ModelUndoRedoParticipant extends Disposable implements IUndoRedoDelegate {
@ -23,16 +22,13 @@ export class ModelUndoRedoParticipant extends Disposable implements IUndoRedoDel
if (elements.past.length === 0 && elements.future.length === 0) {
return;
}
if (!isEditStackPastFutureElements(elements)) {
return;
}
for (const element of elements.past) {
if (element.type === UndoRedoElementType.Workspace) {
if (element instanceof MultiModelEditStackElement) {
element.setDelegate(this);
}
}
for (const element of elements.future) {
if (element.type === UndoRedoElementType.Workspace) {
if (element instanceof MultiModelEditStackElement) {
element.setDelegate(this);
}
}

View file

@ -3,7 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { startsWith } from 'vs/base/common/strings';
import { CodeAction, CodeActionTriggerType } from 'vs/editor/common/modes';
import { Position } from 'vs/editor/common/core/position';
@ -27,7 +26,7 @@ export class CodeActionKind {
}
public contains(other: CodeActionKind): boolean {
return this.equals(other) || this.value === '' || startsWith(other.value, this.value + CodeActionKind.sep);
return this.equals(other) || this.value === '' || other.value.startsWith(this.value + CodeActionKind.sep);
}
public intersects(other: CodeActionKind): boolean {

View file

@ -149,7 +149,7 @@ export class OutlineElementRenderer implements ITreeRenderer<OutlineElement, Fuz
if (this._configurationService.getValue(OutlineConfigKeys.icons)) {
// add styles for the icons
template.iconClass.className = '';
dom.addClasses(template.iconClass, `outline-element-icon ${SymbolKinds.toCssClassName(element.symbol.kind, true)}`);
template.iconClass.classList.add(`outline-element-icon`, ...SymbolKinds.toCssClassName(element.symbol.kind, true).split(' '));
}
if (element.symbol.tags.indexOf(SymbolTag.Deprecated) >= 0) {
options.extraClasses.push(`deprecated`);

View file

@ -13,7 +13,7 @@ import * as strings from 'vs/base/common/strings';
import { Event, Emitter } from 'vs/base/common/event';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IDisposable, dispose, toDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
import { append, $, hide, show, getDomNodePagePosition, addDisposableListener, addStandardDisposableListener, addClasses } from 'vs/base/browser/dom';
import { append, $, hide, show, getDomNodePagePosition, addDisposableListener, addStandardDisposableListener } from 'vs/base/browser/dom';
import { IListVirtualDelegate, IListEvent, IListRenderer, IListMouseEvent, IListGestureEvent } from 'vs/base/browser/ui/list/list';
import { List } from 'vs/base/browser/ui/list/listWidget';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
@ -233,7 +233,7 @@ class ItemRenderer implements IListRenderer<CompletionItem, ISuggestionTemplateD
// normal icon
data.icon.className = 'icon hide';
data.iconContainer.className = '';
addClasses(data.iconContainer, `suggest-icon ${completionKindToCssClass(suggestion.kind)}`);
data.iconContainer.classList.add('suggest-icon', ...completionKindToCssClass(suggestion.kind).split(' '));
}
if (suggestion.tags && suggestion.tags.indexOf(CompletionItemTag.Deprecated) >= 0) {

View file

@ -13,6 +13,10 @@ import { CursorWordEndLeft, CursorWordEndLeftSelect, CursorWordEndRight, CursorW
import { withTestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
import { CoreEditingCommands } from 'vs/editor/browser/controller/coreCommands';
import { ViewModel } from 'vs/editor/common/viewModel/viewModelImpl';
import { LanguageIdentifier } from 'vs/editor/common/modes';
import { MockMode } from 'vs/editor/test/common/mocks/mockMode';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
suite('WordOperations', () => {
@ -721,4 +725,29 @@ suite('WordOperations', () => {
deleteWordLeft(editor); assert.equal(model.getLineContent(1), 'A line with text. And another one', '001');
});
});
test('deleteWordLeft - issue #91855: Matching (quote, bracket, paren) doesn\'t get deleted when hitting Ctrl+Backspace', () => {
const languageId = new LanguageIdentifier('myTestMode', 5);
class TestMode extends MockMode {
constructor() {
super(languageId);
this._register(LanguageConfigurationRegistry.register(this.getLanguageIdentifier(), {
autoClosingPairs: [
{ open: '\"', close: '\"' }
]
}));
}
}
const mode = new TestMode();
const model = createTextModel('a ""', undefined, languageId);
withTestCodeEditor(null, { model }, (editor, _) => {
editor.setPosition(new Position(1, 4));
deleteWordLeft(editor); assert.equal(model.getLineContent(1), 'a ');
});
model.dispose();
mode.dispose();
});
});

View file

@ -9,7 +9,7 @@ import { EditorCommand, ICommandOptions, ServicesAccessor, registerEditorCommand
import { ReplaceCommand } from 'vs/editor/common/commands/replaceCommand';
import { CursorState } from 'vs/editor/common/controller/cursorCommon';
import { CursorChangeReason } from 'vs/editor/common/controller/cursorEvents';
import { WordNavigationType, WordOperations } from 'vs/editor/common/controller/cursorWordOperations';
import { DeleteWordContext, WordNavigationType, WordOperations } from 'vs/editor/common/controller/cursorWordOperations';
import { WordCharacterClassifier, getMapForWordSeparators } from 'vs/editor/common/controller/wordCharacterClassifier';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
@ -21,6 +21,7 @@ import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegis
import { CONTEXT_ACCESSIBILITY_MODE_ENABLED } from 'vs/platform/accessibility/common/accessibility';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { EditorOption, EditorOptions } from 'vs/editor/common/config/editorOptions';
import { LanguageConfigurationRegistry } from 'vs/editor/common/modes/languageConfigurationRegistry';
export interface MoveWordOptions extends ICommandOptions {
inSelectionMode: boolean;
@ -354,9 +355,20 @@ export abstract class DeleteWordCommand extends EditorCommand {
const wordSeparators = getMapForWordSeparators(editor.getOption(EditorOption.wordSeparators));
const model = editor.getModel();
const selections = editor.getSelections();
const autoClosingBrackets = editor.getOption(EditorOption.autoClosingBrackets);
const autoClosingQuotes = editor.getOption(EditorOption.autoClosingQuotes);
const autoClosingPairs = LanguageConfigurationRegistry.getAutoClosingPairs(model.getLanguageIdentifier().id);
const commands = selections.map((sel) => {
const deleteRange = this._delete(wordSeparators, model, sel, this._whitespaceHeuristics, this._wordNavigationType);
const deleteRange = this._delete({
wordSeparators,
model,
selection: sel,
whitespaceHeuristics: this._whitespaceHeuristics,
autoClosingBrackets,
autoClosingQuotes,
autoClosingPairs,
}, this._wordNavigationType);
return new ReplaceCommand(deleteRange, '');
});
@ -365,12 +377,12 @@ export abstract class DeleteWordCommand extends EditorCommand {
editor.pushUndoStop();
}
protected abstract _delete(wordSeparators: WordCharacterClassifier, model: ITextModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range;
protected abstract _delete(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range;
}
export class DeleteWordLeftCommand extends DeleteWordCommand {
protected _delete(wordSeparators: WordCharacterClassifier, model: ITextModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range {
let r = WordOperations.deleteWordLeft(wordSeparators, model, selection, whitespaceHeuristics, wordNavigationType);
protected _delete(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range {
let r = WordOperations.deleteWordLeft(ctx, wordNavigationType);
if (r) {
return r;
}
@ -379,13 +391,13 @@ export class DeleteWordLeftCommand extends DeleteWordCommand {
}
export class DeleteWordRightCommand extends DeleteWordCommand {
protected _delete(wordSeparators: WordCharacterClassifier, model: ITextModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range {
let r = WordOperations.deleteWordRight(wordSeparators, model, selection, whitespaceHeuristics, wordNavigationType);
protected _delete(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range {
let r = WordOperations.deleteWordRight(ctx, wordNavigationType);
if (r) {
return r;
}
const lineCount = model.getLineCount();
const maxColumn = model.getLineMaxColumn(lineCount);
const lineCount = ctx.model.getLineCount();
const maxColumn = ctx.model.getLineMaxColumn(lineCount);
return new Range(lineCount, maxColumn, lineCount, maxColumn);
}
}

View file

@ -5,11 +5,10 @@
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { registerEditorCommand } from 'vs/editor/browser/editorExtensions';
import { WordNavigationType, WordPartOperations } from 'vs/editor/common/controller/cursorWordOperations';
import { DeleteWordContext, WordNavigationType, WordPartOperations } from 'vs/editor/common/controller/cursorWordOperations';
import { WordCharacterClassifier } from 'vs/editor/common/controller/wordCharacterClassifier';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ITextModel } from 'vs/editor/common/model';
import { DeleteWordCommand, MoveWordCommand } from 'vs/editor/contrib/wordOperations/wordOperations';
@ -32,8 +31,8 @@ export class DeleteWordPartLeft extends DeleteWordCommand {
});
}
protected _delete(wordSeparators: WordCharacterClassifier, model: ITextModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range {
let r = WordPartOperations.deleteWordPartLeft(wordSeparators, model, selection, whitespaceHeuristics);
protected _delete(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range {
let r = WordPartOperations.deleteWordPartLeft(ctx);
if (r) {
return r;
}
@ -57,13 +56,13 @@ export class DeleteWordPartRight extends DeleteWordCommand {
});
}
protected _delete(wordSeparators: WordCharacterClassifier, model: ITextModel, selection: Selection, whitespaceHeuristics: boolean, wordNavigationType: WordNavigationType): Range {
let r = WordPartOperations.deleteWordPartRight(wordSeparators, model, selection, whitespaceHeuristics);
protected _delete(ctx: DeleteWordContext, wordNavigationType: WordNavigationType): Range {
let r = WordPartOperations.deleteWordPartRight(ctx);
if (r) {
return r;
}
const lineCount = model.getLineCount();
const maxColumn = model.getLineMaxColumn(lineCount);
const lineCount = ctx.model.getLineCount();
const maxColumn = ctx.model.getLineMaxColumn(lineCount);
return new Range(lineCount, maxColumn, lineCount, maxColumn);
}
}

View file

@ -1,20 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export interface ICredentialsProvider {
getPassword(service: string, account: string): Promise<string | null>;
setPassword(service: string, account: string, password: string): Promise<void>;
deletePassword(service: string, account: string): Promise<boolean>;
findPassword(service: string): Promise<string | null>;
findCredentials(service: string): Promise<Array<{ account: string, password: string }>>;
}
export const ICredentialsService = createDecorator<ICredentialsService>('ICredentialsService');
export interface ICredentialsService extends ICredentialsProvider {
readonly _serviceBrand: undefined;
}

View file

@ -1,40 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import type * as keytar from 'keytar';
import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
import { IdleValue } from 'vs/base/common/async';
export class KeytarCredentialsService implements ICredentialsService {
declare readonly _serviceBrand: undefined;
private readonly _keytar = new IdleValue<Promise<typeof keytar>>(() => import('keytar'));
async getPassword(service: string, account: string): Promise<string | null> {
const keytar = await this._keytar.value;
return keytar.getPassword(service, account);
}
async setPassword(service: string, account: string, password: string): Promise<void> {
const keytar = await this._keytar.value;
return keytar.setPassword(service, account, password);
}
async deletePassword(service: string, account: string): Promise<boolean> {
const keytar = await this._keytar.value;
return keytar.deletePassword(service, account);
}
async findPassword(service: string): Promise<string | null> {
const keytar = await this._keytar.value;
return keytar.findPassword(service);
}
async findCredentials(service: string): Promise<Array<{ account: string, password: string }>> {
const keytar = await this._keytar.value;
return keytar.findCredentials(service);
}
}

View file

@ -10,7 +10,6 @@ import { join, basename } from 'vs/base/common/path';
import { parse, ParseError, getNodeType } from 'vs/base/common/json';
import { listProcesses } from 'vs/base/node/ps';
import product from 'vs/platform/product/common/product';
import { repeat, pad } from 'vs/base/common/strings';
import { isWindows, isLinux } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { ProcessItem } from 'vs/base/common/processes';
@ -435,7 +434,7 @@ export class DiagnosticsService implements IDiagnosticsService {
private expandGPUFeatures(gpuFeatures: any): string {
const longestFeatureName = Math.max(...Object.keys(gpuFeatures).map(feature => feature.length));
// Make columns aligned by adding spaces after feature name
return Object.keys(gpuFeatures).map(feature => `${feature}: ${repeat(' ', longestFeatureName - feature.length)} ${gpuFeatures[feature]}`).join('\n ');
return Object.keys(gpuFeatures).map(feature => `${feature}: ${' '.repeat(longestFeatureName - feature.length)} ${gpuFeatures[feature]}`).join('\n ');
}
private formatWorkspaceMetadata(info: IMainProcessInfo): Promise<string> {
@ -500,14 +499,15 @@ export class DiagnosticsService implements IDiagnosticsService {
if (isRoot) {
name = item.pid === mainPid ? `${product.applicationName} main` : 'remote agent';
} else {
name = `${repeat(' ', indent)} ${item.name}`;
name = `${' '.repeat(indent)} ${item.name}`;
if (item.name === 'window') {
name = `${name} (${mapPidToWindowTitle.get(item.pid)})`;
}
}
const memory = process.platform === 'win32' ? item.mem : (osLib.totalmem() * (item.mem / 100));
output.push(`${pad(Number(item.load.toFixed(0)), 5, ' ')}\t${pad(Number((memory / MB).toFixed(0)), 6, ' ')}\t${pad(Number((item.pid).toFixed(0)), 6, ' ')}\t${name}`);
output.push(`${item.load.toFixed(0).padStart(5, ' ')}\t${(memory / MB).toFixed(0).padStart(6, ' ')}\t${item.pid.toFixed(0).padStart(6, ' ')}\t${name}`);
// Recurse into children if any
if (Array.isArray(item.children)) {

View file

@ -262,5 +262,7 @@ export interface IExtensionTipsService {
export const DefaultIconPath = require.toUrl('./media/defaultIcon.png');
export const ExtensionsLabel = localize('extensions', "Extensions");
export const ExtensionsLocalizedLabel = { value: ExtensionsLabel, original: 'Extensions' };
export const ExtensionsChannelId = 'extensions';
export const PreferencesLabel = localize('preferences', "Preferences");
export const PreferencesLocalizedLabel = { value: PreferencesLabel, original: 'Preferences' };

View file

@ -183,9 +183,15 @@ export class InstantiationService implements IInstantiationService {
}
for (const { data } of roots) {
// create instance and overwrite the service collections
const instance = this._createServiceInstanceWithOwner(data.id, data.desc.ctor, data.desc.staticArguments, data.desc.supportsDelayedInstantiation, data._trace);
this._setServiceInstance(data.id, instance);
// Repeat the check for this still being a service sync descriptor. That's because
// instantiating a dependency might have side-effect and recursively trigger instantiation
// so that some dependencies are now fullfilled already.
const instanceOrDesc = this._getServiceInstanceOrDescriptor(data.id);
if (instanceOrDesc instanceof SyncDescriptor) {
// create instance and overwrite the service collections
const instance = this._createServiceInstanceWithOwner(data.id, data.desc.ctor, data.desc.staticArguments, data.desc.supportsDelayedInstantiation, data._trace);
this._setServiceInstance(data.id, instance);
}
graph.removeNode(data);
}
}

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { createDecorator, optional, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { createDecorator, IInstantiationService, optional, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { InstantiationService } from 'vs/platform/instantiation/common/instantiationService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
@ -392,4 +392,36 @@ suite('Instantiation Service', () => {
assert.equal(serviceInstanceCount, 1);
});
test('Remote window / integration tests is broken #105562', function () {
const Service1 = createDecorator<any>('service1');
class Service1Impl {
constructor(@IInstantiationService insta: IInstantiationService) {
const c = insta.invokeFunction(accessor => accessor.get(Service2)); // THIS is the recursive call
assert.ok(c);
}
}
const Service2 = createDecorator<any>('service2');
class Service2Impl {
constructor() { }
}
// This service depends on Service1 and Service2 BUT creating Service1 creates Service2 (via recursive invocation)
// and then Servce2 should not be created a second time
const Service21 = createDecorator<any>('service21');
class Service21Impl {
constructor(@Service2 readonly service2: Service2Impl, @Service1 readonly service1: Service1Impl) { }
}
const insta = new InstantiationService(new ServiceCollection(
[Service1, new SyncDescriptor(Service1Impl)],
[Service2, new SyncDescriptor(Service2Impl)],
[Service21, new SyncDescriptor(Service21Impl)],
));
const obj = insta.invokeFunction(accessor => accessor.get(Service21));
assert.ok(obj);
});
});

View file

@ -3,24 +3,24 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { endsWith, rtrim } from 'vs/base/common/strings';
import { rtrim } from 'vs/base/common/strings';
export function normalizeGitHubUrl(url: string): string {
// If the url has a .git suffix, remove it
if (endsWith(url, '.git')) {
if (url.endsWith('.git')) {
url = url.substr(0, url.length - 4);
}
// Remove trailing slash
url = rtrim(url, '/');
if (endsWith(url, '/new')) {
if (url.endsWith('/new')) {
url = rtrim(url, '/new');
}
if (endsWith(url, '/issues')) {
if (url.endsWith('/issues')) {
url = rtrim(url, '/issues');
}
return url;
}
}

View file

@ -141,4 +141,11 @@ export interface ICommonNativeHostService {
// Registry (windows only)
windowsGetStringRegKey(hive: 'HKEY_CURRENT_USER' | 'HKEY_LOCAL_MACHINE' | 'HKEY_CLASSES_ROOT' | 'HKEY_USERS' | 'HKEY_CURRENT_CONFIG', path: string, name: string): Promise<string | undefined>;
// Credentials
getPassword(service: string, account: string): Promise<string | null>;
setPassword(service: string, account: string, password: string): Promise<void>;
deletePassword(service: string, account: string): Promise<boolean>;
findPassword(service: string): Promise<string | null>;
findCredentials(service: string): Promise<Array<{ account: string, password: string }>>
}

View file

@ -610,6 +610,42 @@ export class NativeHostMainService implements INativeHostMainService {
}
}
//#endregion
//#region Credentials
async getPassword(windowId: number | undefined, service: string, account: string): Promise<string | null> {
const keytar = await import('keytar');
return keytar.getPassword(service, account);
}
async setPassword(windowId: number | undefined, service: string, account: string, password: string): Promise<void> {
const keytar = await import('keytar');
return keytar.setPassword(service, account, password);
}
async deletePassword(windowId: number | undefined, service: string, account: string): Promise<boolean> {
const keytar = await import('keytar');
return keytar.deletePassword(service, account);
}
async findPassword(windowId: number | undefined, service: string): Promise<string | null> {
const keytar = await import('keytar');
return keytar.findPassword(service);
}
async findCredentials(windowId: number | undefined, service: string): Promise<Array<{ account: string, password: string }>> {
const keytar = await import('keytar');
return keytar.findCredentials(service);
}
//#endregion
private windowById(windowId: number | undefined): ICodeWindow | undefined {
if (typeof windowId !== 'number') {
return undefined;

View file

@ -443,6 +443,18 @@ export const problemsErrorIconForeground = registerColor('problemsErrorIcon.fore
export const problemsWarningIconForeground = registerColor('problemsWarningIcon.foreground', { dark: editorWarningForeground, light: editorWarningForeground, hc: editorWarningForeground }, nls.localize('problemsWarningIconForeground', "The color used for the problems warning icon."));
export const problemsInfoIconForeground = registerColor('problemsInfoIcon.foreground', { dark: editorInfoForeground, light: editorInfoForeground, hc: editorInfoForeground }, nls.localize('problemsInfoIconForeground', "The color used for the problems info icon."));
/**
* Chart colors
*/
export const chartsForeground = registerColor('charts.foreground', { dark: foreground, light: foreground, hc: foreground }, nls.localize('chartsForeground', "The foreground color used in charts."));
export const chartsLines = registerColor('charts.lines', { dark: transparent(foreground, .5), light: transparent(foreground, .5), hc: transparent(foreground, .5) }, nls.localize('chartsLines', "The color used for horizontal lines in charts."));
export const chartsRed = registerColor('charts.red', { dark: editorErrorForeground, light: editorErrorForeground, hc: editorErrorForeground }, nls.localize('chartsRed', "The red color used charts."));
export const chartsBlue = registerColor('charts.blue', { dark: editorInfoForeground, light: editorInfoForeground, hc: editorInfoForeground }, nls.localize('chartsBlue', "The blue color used charts."));
export const chartsYellow = registerColor('charts.yellow', { dark: editorWarningForeground, light: editorWarningForeground, hc: editorWarningForeground }, nls.localize('chartsYellow', "The yellow color used charts."));
export const chartsOrange = registerColor('charts.orange', { dark: minimapFindMatch, light: minimapFindMatch, hc: minimapFindMatch }, nls.localize('chartsOrange', "The orange color used charts."));
export const chartsGreen = registerColor('charts.green', { dark: '#89D185', light: '#388A34', hc: '#89D185' }, nls.localize('chartsGreen', "The green color used charts."));
export const chartsPurple = registerColor('charts.purple', { dark: '#B180D7', light: '#652D90', hc: '#B180D7' }, nls.localize('chartsPurple', "The purple color used charts."));
// ----- color functions
export function darken(colorValue: ColorValue, factor: number): ColorFunction {

View file

@ -60,6 +60,27 @@ export class ResourceEditStackSnapshot {
) { }
}
export class UndoRedoGroup {
private static _ID = 0;
public readonly id: number;
private order: number;
constructor() {
this.id = UndoRedoGroup._ID++;
this.order = 1;
}
public nextOrder(): number {
if (this.id === 0) {
return 0;
}
return this.order++;
}
public static None = new UndoRedoGroup();
}
export interface IUndoRedoService {
readonly _serviceBrand: undefined;
@ -79,7 +100,7 @@ export interface IUndoRedoService {
* Add a new element to the `undo` stack.
* This will destroy the `redo` stack.
*/
pushElement(element: IUndoRedoElement): void;
pushElement(element: IUndoRedoElement, group?: UndoRedoGroup): void;
/**
* Get the last pushed element for a resource.

View file

@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as nls from 'vs/nls';
import { IUndoRedoService, IWorkspaceUndoRedoElement, UndoRedoElementType, IUndoRedoElement, IPastFutureElements, ResourceEditStackSnapshot, UriComparisonKeyComputer, IResourceUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo';
import { IUndoRedoService, IWorkspaceUndoRedoElement, UndoRedoElementType, IUndoRedoElement, IPastFutureElements, ResourceEditStackSnapshot, UriComparisonKeyComputer, IResourceUndoRedoElement, UndoRedoGroup } from 'vs/platform/undoRedo/common/undoRedo';
import { URI } from 'vs/base/common/uri';
import { onUnexpectedError } from 'vs/base/common/errors';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
@ -32,15 +32,19 @@ class ResourceStackElement {
public readonly strResource: string;
public readonly resourceLabels: string[];
public readonly strResources: string[];
public readonly groupId: number;
public readonly groupOrder: number;
public isValid: boolean;
constructor(actual: IUndoRedoElement, resourceLabel: string, strResource: string) {
constructor(actual: IUndoRedoElement, resourceLabel: string, strResource: string, groupId: number, groupOrder: number) {
this.actual = actual;
this.label = actual.label;
this.resourceLabel = resourceLabel;
this.strResource = strResource;
this.resourceLabels = [this.resourceLabel];
this.strResources = [this.strResource];
this.groupId = groupId;
this.groupOrder = groupOrder;
this.isValid = true;
}
@ -49,7 +53,7 @@ class ResourceStackElement {
}
public toString(): string {
return `[${this.id}] [${this.isValid ? 'VALID' : 'INVALID'}] ${this.actual}`;
return `[id:${this.id}] [group:${this.groupId}] [${this.isValid ? 'VALID' : 'INVALID'}] ${this.actual}`;
}
}
@ -124,14 +128,18 @@ class WorkspaceStackElement {
public readonly resourceLabels: string[];
public readonly strResources: string[];
public readonly groupId: number;
public readonly groupOrder: number;
public removedResources: RemovedResources | null;
public invalidatedResources: RemovedResources | null;
constructor(actual: IWorkspaceUndoRedoElement, resourceLabels: string[], strResources: string[]) {
constructor(actual: IWorkspaceUndoRedoElement, resourceLabels: string[], strResources: string[], groupId: number, groupOrder: number) {
this.actual = actual;
this.label = actual.label;
this.resourceLabels = resourceLabels;
this.strResources = strResources;
this.groupId = groupId;
this.groupOrder = groupOrder;
this.removedResources = null;
this.invalidatedResources = null;
}
@ -168,7 +176,7 @@ class WorkspaceStackElement {
}
public toString(): string {
return `[${this.id}] [${this.invalidatedResources ? 'INVALID' : 'VALID'}] ${this.actual}`;
return `[id:${this.id}] [group:${this.groupId}] [${this.invalidatedResources ? 'INVALID' : 'VALID'}] ${this.actual}`;
}
}
@ -349,6 +357,13 @@ class ResourceEditStack {
return this._past[this._past.length - 1];
}
public getSecondClosestPastElement(): StackElement | null {
if (this._past.length < 2) {
return null;
}
return this._past[this._past.length - 2];
}
public getClosestFutureElement(): StackElement | null {
if (this._future.length === 0) {
return null;
@ -482,11 +497,11 @@ export class UndoRedoService implements IUndoRedoService {
console.log(str.join('\n'));
}
public pushElement(element: IUndoRedoElement): void {
public pushElement(element: IUndoRedoElement, group: UndoRedoGroup = UndoRedoGroup.None): void {
if (element.type === UndoRedoElementType.Resource) {
const resourceLabel = getResourceLabel(element.resource);
const strResource = this.getUriComparisonKey(element.resource);
this._pushElement(new ResourceStackElement(element, resourceLabel, strResource));
this._pushElement(new ResourceStackElement(element, resourceLabel, strResource, group.id, group.nextOrder()));
} else {
const seen = new Set<string>();
const resourceLabels: string[] = [];
@ -504,9 +519,9 @@ export class UndoRedoService implements IUndoRedoService {
}
if (resourceLabels.length === 1) {
this._pushElement(new ResourceStackElement(element, resourceLabels[0], strResources[0]));
this._pushElement(new ResourceStackElement(element, resourceLabels[0], strResources[0], group.id, group.nextOrder()));
} else {
this._pushElement(new WorkspaceStackElement(element, resourceLabels, strResources));
this._pushElement(new WorkspaceStackElement(element, resourceLabels, strResources, group.id, group.nextOrder()));
}
}
if (DEBUG) {
@ -550,7 +565,7 @@ export class UndoRedoService implements IUndoRedoService {
for (const _element of individualArr) {
const resourceLabel = getResourceLabel(_element.resource);
const strResource = this.getUriComparisonKey(_element.resource);
const element = new ResourceStackElement(_element, resourceLabel, strResource);
const element = new ResourceStackElement(_element, resourceLabel, strResource, 0, 0);
individualMap.set(element.strResource, element);
}
@ -569,7 +584,7 @@ export class UndoRedoService implements IUndoRedoService {
for (const _element of individualArr) {
const resourceLabel = getResourceLabel(_element.resource);
const strResource = this.getUriComparisonKey(_element.resource);
const element = new ResourceStackElement(_element, resourceLabel, strResource);
const element = new ResourceStackElement(_element, resourceLabel, strResource, 0, 0);
individualMap.set(element.strResource, element);
}
@ -688,7 +703,7 @@ export class UndoRedoService implements IUndoRedoService {
};
}
private _safeInvokeWithLocks(element: StackElement, invoke: () => Promise<void> | void, editStackSnapshot: EditStackSnapshot, cleanup: IDisposable = Disposable.None): Promise<void> | void {
private _safeInvokeWithLocks(element: StackElement, invoke: () => Promise<void> | void, editStackSnapshot: EditStackSnapshot, cleanup: IDisposable, continuation: () => Promise<void> | void): Promise<void> | void {
const releaseLocks = this._acquireLocks(editStackSnapshot);
let result: Promise<void> | void;
@ -706,6 +721,7 @@ export class UndoRedoService implements IUndoRedoService {
() => {
releaseLocks();
cleanup.dispose();
return continuation();
},
(err) => {
releaseLocks();
@ -717,6 +733,7 @@ export class UndoRedoService implements IUndoRedoService {
// result is void
releaseLocks();
cleanup.dispose();
return continuation();
}
}
@ -864,9 +881,34 @@ export class UndoRedoService implements IUndoRedoService {
return this._confirmAndExecuteWorkspaceUndo(strResource, element, affectedEditStacks);
}
private _isPartOfUndoGroup(element: WorkspaceStackElement): boolean {
if (!element.groupId) {
return false;
}
// check that there is at least another element with the same groupId ready to be undone
for (const [, editStack] of this._editStacks) {
const pastElement = editStack.getClosestPastElement();
if (!pastElement) {
continue;
}
if (pastElement === element) {
const secondPastElement = editStack.getSecondClosestPastElement();
if (secondPastElement && secondPastElement.groupId === element.groupId) {
// there is another element with the same group id in the same stack!
return true;
}
}
if (pastElement.groupId === element.groupId) {
// there is another element with the same group id in another stack!
return true;
}
}
return false;
}
private async _confirmAndExecuteWorkspaceUndo(strResource: string, element: WorkspaceStackElement, editStackSnapshot: EditStackSnapshot): Promise<void> {
if (element.canSplit()) {
if (element.canSplit() && !this._isPartOfUndoGroup(element)) {
// this element can be split
const result = await this._dialogService.show(
@ -920,7 +962,7 @@ export class UndoRedoService implements IUndoRedoService {
for (const editStack of editStackSnapshot.editStacks) {
editStack.moveBackward(element);
}
return this._safeInvokeWithLocks(element, () => element.actual.undo(), editStackSnapshot, cleanup);
return this._safeInvokeWithLocks(element, () => element.actual.undo(), editStackSnapshot, cleanup, () => this._continueUndoInGroup(element.groupId));
}
private _resourceUndo(editStack: ResourceEditStack, element: ResourceStackElement): Promise<void> | void {
@ -939,10 +981,46 @@ export class UndoRedoService implements IUndoRedoService {
}
return this._invokeResourcePrepare(element, (cleanup) => {
editStack.moveBackward(element);
return this._safeInvokeWithLocks(element, () => element.actual.undo(), new EditStackSnapshot([editStack]), cleanup);
return this._safeInvokeWithLocks(element, () => element.actual.undo(), new EditStackSnapshot([editStack]), cleanup, () => this._continueUndoInGroup(element.groupId));
});
}
private _findClosestUndoElementInGroup(groupId: number): [StackElement | null, string | null] {
if (!groupId) {
return [null, null];
}
// find another element with the same groupId and with the highest groupOrder ready to be undone
let matchedElement: StackElement | null = null;
let matchedStrResource: string | null = null;
for (const [strResource, editStack] of this._editStacks) {
const candidate = editStack.getClosestPastElement();
if (!candidate) {
continue;
}
if (candidate.groupId === groupId) {
if (!matchedElement || candidate.groupOrder > matchedElement.groupOrder) {
matchedElement = candidate;
matchedStrResource = strResource;
}
}
}
return [matchedElement, matchedStrResource];
}
private _continueUndoInGroup(groupId: number): Promise<void> | void {
if (!groupId) {
return;
}
const [, matchedStrResource] = this._findClosestUndoElementInGroup(groupId);
if (matchedStrResource) {
return this.undo(matchedStrResource);
}
}
public undo(resource: URI | string): Promise<void> | void {
const strResource = typeof resource === 'string' ? resource : this.getUriComparisonKey(resource);
if (!this._editStacks.has(strResource)) {
@ -955,6 +1033,15 @@ export class UndoRedoService implements IUndoRedoService {
return;
}
if (element.groupId) {
// this element is a part of a group, we need to make sure undoing in a group is in order
const [matchedElement, matchedStrResource] = this._findClosestUndoElementInGroup(element.groupId);
if (element !== matchedElement && matchedStrResource) {
// there is an element in the same group that should be undone before this one
return this.undo(matchedStrResource);
}
}
try {
if (element.type === UndoRedoElementType.Workspace) {
return this._workspaceUndo(strResource, element);
@ -1097,7 +1184,7 @@ export class UndoRedoService implements IUndoRedoService {
for (const editStack of editStackSnapshot.editStacks) {
editStack.moveForward(element);
}
return this._safeInvokeWithLocks(element, () => element.actual.redo(), editStackSnapshot, cleanup);
return this._safeInvokeWithLocks(element, () => element.actual.redo(), editStackSnapshot, cleanup, () => this._continueRedoInGroup(element.groupId));
}
private _resourceRedo(editStack: ResourceEditStack, element: ResourceStackElement): Promise<void> | void {
@ -1117,10 +1204,46 @@ export class UndoRedoService implements IUndoRedoService {
return this._invokeResourcePrepare(element, (cleanup) => {
editStack.moveForward(element);
return this._safeInvokeWithLocks(element, () => element.actual.redo(), new EditStackSnapshot([editStack]), cleanup);
return this._safeInvokeWithLocks(element, () => element.actual.redo(), new EditStackSnapshot([editStack]), cleanup, () => this._continueRedoInGroup(element.groupId));
});
}
private _findClosestRedoElementInGroup(groupId: number): [StackElement | null, string | null] {
if (!groupId) {
return [null, null];
}
// find another element with the same groupId and with the lowest groupOrder ready to be redone
let matchedElement: StackElement | null = null;
let matchedStrResource: string | null = null;
for (const [strResource, editStack] of this._editStacks) {
const candidate = editStack.getClosestFutureElement();
if (!candidate) {
continue;
}
if (candidate.groupId === groupId) {
if (!matchedElement || candidate.groupOrder < matchedElement.groupOrder) {
matchedElement = candidate;
matchedStrResource = strResource;
}
}
}
return [matchedElement, matchedStrResource];
}
private _continueRedoInGroup(groupId: number): Promise<void> | void {
if (!groupId) {
return;
}
const [, matchedStrResource] = this._findClosestRedoElementInGroup(groupId);
if (matchedStrResource) {
return this.redo(matchedStrResource);
}
}
public redo(resource: URI | string): Promise<void> | void {
const strResource = typeof resource === 'string' ? resource : this.getUriComparisonKey(resource);
if (!this._editStacks.has(strResource)) {
@ -1133,6 +1256,15 @@ export class UndoRedoService implements IUndoRedoService {
return;
}
if (element.groupId) {
// this element is a part of a group, we need to make sure redoing in a group is in order
const [matchedElement, matchedStrResource] = this._findClosestRedoElementInGroup(element.groupId);
if (element !== matchedElement && matchedStrResource) {
// there is an element in the same group that should be redone before this one
return this.redo(matchedStrResource);
}
}
try {
if (element.type === UndoRedoElementType.Workspace) {
return this._workspaceRedo(strResource, element);

View file

@ -7,7 +7,7 @@ import * as assert from 'assert';
import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService';
import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService';
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
import { UndoRedoElementType, IUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo';
import { UndoRedoElementType, IUndoRedoElement, UndoRedoGroup } from 'vs/platform/undoRedo/common/undoRedo';
import { URI } from 'vs/base/common/uri';
import { mock } from 'vs/base/test/common/mock';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
@ -208,4 +208,11 @@ suite('UndoRedoService', () => {
assert.ok(service.getLastElement(resource2) === element1);
});
test('UndoRedoGroup.None uses id 0', () => {
assert.equal(UndoRedoGroup.None.id, 0);
assert.equal(UndoRedoGroup.None.nextOrder(), 0);
assert.equal(UndoRedoGroup.None.nextOrder(), 0);
});
});

6
src/vs/vscode.d.ts vendored
View file

@ -8599,6 +8599,12 @@ declare module 'vscode' {
*/
title?: string;
/**
* An optional human-readable description which is rendered less prominently in the title of the view.
* Setting the title description to null, undefined, or empty string will remove the description from the view.
*/
description?: string;
/**
* Reveals the given element in the tree view.
* If the tree view is not visible then the tree view is shown and element is revealed.

View file

@ -744,7 +744,9 @@ declare module 'vscode' {
// TODO@jrieken FileDecoration, FileDecorationProvider etc.
// TODO@jrieken Add selector notion to limit decorations to a view.
// TODO@jrieken Rename `Decoration.letter` to `short` so that it could be used for coverage et al.
// TODO@jrieken priority -> DecorationSeverity.INFO,WARN,ERROR
// TODO@jrieken title -> tooltip
// TODO@jrieken bubble -> propagte
export class Decoration {
/**
@ -2132,7 +2134,7 @@ declare module 'vscode' {
}
//#endregion
//#region
//#region https://github.com/microsoft/vscode/issues/91697
export interface FileSystem {
/**
@ -2154,24 +2156,20 @@ declare module 'vscode' {
//#endregion
//#region https://github.com/microsoft/vscode/issues/105667
export interface TreeView<T> {
/**
* An optional human-readable description that will be rendered in the title of the view.
* Setting the title description to null, undefined, or empty string will remove the title description from the view.
*/
description?: string | undefined;
}
//#endregion
//#region https://github.com/microsoft/vscode/issues/103120 @alexr00
export class ThemeIcon2 extends ThemeIcon {
/**
* Returns a new `ThemeIcon` that will use the specified `ThemeColor`
* @param color The `ThemeColor` to use for the icon.
* The id of the icon. The available icons are listed in https://microsoft.github.io/vscode-codicons/dist/codicon.html.
*/
with(color: ThemeColor): ThemeIcon2;
public readonly id: string;
/**
* Creates a reference to a theme icon.
* @param id id of the icon. The available icons are listed in https://microsoft.github.io/vscode-codicons/dist/codicon.html.
* @param color optional `ThemeColor` for the icon.
*/
constructor(id: string, color?: ThemeColor);
}
//#endregion
}

View file

@ -18,7 +18,7 @@ import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
import { fromNow } from 'vs/base/common/date';
import { ActivationKind, IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { Platform, platform } from 'vs/base/common/platform';
import { isWeb } from 'vs/base/common/platform';
const VSO_ALLOWED_EXTENSIONS = ['github.vscode-pull-request-github', 'github.vscode-pull-request-github-insiders', 'vscode.git', 'ms-vsonline.vsonline', 'vscode.github-browser', 'ms-vscode.github-browser'];
@ -405,7 +405,7 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu
const remoteConnection = this.remoteAgentService.getConnection();
const isVSO = remoteConnection !== null
? remoteConnection.remoteAuthority.startsWith('vsonline')
: platform === Platform.Web;
: isWeb;
if (isVSO && VSO_ALLOWED_EXTENSIONS.includes(extensionId)) {
addAccountUsage(this.storageService, providerId, accountName, extensionId, extensionName);

View file

@ -5,7 +5,7 @@
import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers';
import { MainContext, MainThreadKeytarShape, IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
import { ICredentialsService } from 'vs/workbench/services/credentials/common/credentials';
@extHostNamedCustomer(MainContext.MainThreadKeytar)
export class MainThreadKeytar implements MainThreadKeytarShape {

View file

@ -26,7 +26,7 @@ import { ViewletRegistry, Extensions as ViewletExtensions, ShowViewletAction } f
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions, CATEGORIES } from 'vs/workbench/common/actions';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
@ -408,7 +408,7 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
registry.registerWorkbenchAction(
SyncActionDescriptor.create(OpenCustomViewletAction, id, localize('showViewlet', "Show {0}", title)),
`View: Show ${title}`,
localize('view', "View")
CATEGORIES.View.value
);
}

View file

@ -16,7 +16,7 @@ import { IWorkspacesService, hasWorkspaceFileExtension, IRecent } from 'vs/platf
import { Schemas } from 'vs/base/common/network';
import { ILogService } from 'vs/platform/log/common/log';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IViewDescriptorService, IViewsService } from 'vs/workbench/common/views';
import { IViewDescriptorService, IViewsService, ViewVisibilityState } from 'vs/workbench/common/views';
// -----------------------------------------------------------------
// The following commands are registered on both sides separately.
@ -279,7 +279,7 @@ CommandsRegistry.registerCommand('_workbench.action.moveViews', async function (
for (const viewId of options.viewIds) {
const viewDescriptor = viewDescriptorService.getViewDescriptorById(viewId);
if (viewDescriptor?.canMoveView) {
viewDescriptorService.moveViewsToContainer([viewDescriptor], destination);
viewDescriptorService.moveViewsToContainer([viewDescriptor], destination, ViewVisibilityState.Default);
}
}

View file

@ -102,11 +102,9 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape {
treeView.title = title;
},
get description() {
checkProposedApiEnabled(extension);
return treeView.description;
},
set description(description: string | undefined) {
checkProposedApiEnabled(extension);
treeView.description = description;
},
reveal: (element: T, options?: IRevealOptions): Promise<void> => {

View file

@ -9,7 +9,6 @@ import { illegalArgument } from 'vs/base/common/errors';
import { IRelativePattern } from 'vs/base/common/glob';
import { isMarkdownString } from 'vs/base/common/htmlContent';
import { ResourceMap } from 'vs/base/common/map';
import { startsWith } from 'vs/base/common/strings';
import { isStringArray } from 'vs/base/common/types';
import { URI } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
@ -782,7 +781,7 @@ export class SnippetString {
}
appendChoice(values: string[], number: number = this._tabstop++): SnippetString {
const value = SnippetString._escape(values.toString());
const value = values.map(s => s.replace(/\$|}|\\|,/g, '\\$&')).join(',');
this.value += '${';
this.value += number;
@ -1171,7 +1170,7 @@ export class CodeActionKind {
}
public contains(other: CodeActionKind): boolean {
return this.value === other.value || startsWith(other.value, this.value + CodeActionKind.sep);
return this.value === other.value || other.value.startsWith(this.value + CodeActionKind.sep);
}
}
CodeActionKind.Empty = new CodeActionKind('');
@ -2178,10 +2177,6 @@ export class ThemeIcon {
this.id = id;
this.themeColor = color;
}
with(color: ThemeColor): ThemeIcon {
return new ThemeIcon(this.id, color);
}
}
ThemeIcon.File = new ThemeIcon('file');
ThemeIcon.Folder = new ThemeIcon('folder');

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