mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-08 07:44:33 +01:00
Merge branch 'main' into suggest-notify
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { TSESTree } from '@typescript-eslint/experimental-utils';
|
||||
import * as eslint from 'eslint';
|
||||
|
||||
function isCallExpression(node: TSESTree.Node): node is TSESTree.CallExpression {
|
||||
return node.type === 'CallExpression';
|
||||
}
|
||||
|
||||
function isFunctionExpression(node: TSESTree.Node): node is TSESTree.FunctionExpression {
|
||||
return node.type.includes('FunctionExpression');
|
||||
}
|
||||
|
||||
export = new class NoAsyncSuite implements eslint.Rule.RuleModule {
|
||||
|
||||
create(context: eslint.Rule.RuleContext): eslint.Rule.RuleListener {
|
||||
function hasAsyncSuite(node: any) {
|
||||
if (isCallExpression(node) && node.arguments.length >= 2 && isFunctionExpression(node.arguments[1]) && node.arguments[1].async) {
|
||||
return context.report({
|
||||
node: node as any,
|
||||
message: 'suite factory function should never be async'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
['CallExpression[callee.name=/suite$/][arguments]']: hasAsyncSuite,
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -120,6 +120,7 @@
|
||||
],
|
||||
"rules": {
|
||||
"local/code-no-test-only": "error",
|
||||
"local/code-no-test-async-suite": "warn",
|
||||
"local/code-no-unexternalized-strings": "off"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -281,7 +281,6 @@
|
||||
"workbench-editor-resolver": {"assign": ["lramos15"]},
|
||||
"workbench-editors": {"assign": ["bpasero"]},
|
||||
"workbench-electron": {"assign": ["deepak1556"]},
|
||||
"workbench-feedback": {"assign": ["bpasero"]},
|
||||
"workbench-fonts": {"assign": []},
|
||||
"workbench-history": {"assign": ["bpasero"]},
|
||||
"workbench-hot-exit": {"assign": ["bpasero"]},
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -231,15 +231,14 @@ async function main(): Promise<void> {
|
||||
|
||||
if (rejectedPromiseResults.length === 0) {
|
||||
console.log('All blobs successfully uploaded.');
|
||||
} else if (rejectedPromiseResults[0].reason?.message?.includes('already exists')) {
|
||||
} else if (rejectedPromiseResults[0]?.reason?.message?.includes('already exists')) {
|
||||
console.warn(rejectedPromiseResults[0].reason.message);
|
||||
console.log('Some blobs successfully uploaded.');
|
||||
} else {
|
||||
throw rejectedPromiseResults[0].reason;
|
||||
// eslint-disable-next-line no-throw-literal
|
||||
throw rejectedPromiseResults[0]?.reason;
|
||||
}
|
||||
|
||||
console.log('All blobs successfully uploaded.');
|
||||
|
||||
const assetUrl = `${process.env['AZURE_CDN_URL']}/${quality}/${blobName}`;
|
||||
const blobPath = new URL(assetUrl).pathname;
|
||||
const mooncakeUrl = `${process.env['MOONCAKE_CDN_URL']}${blobPath}`;
|
||||
|
||||
@@ -46,11 +46,12 @@ async function main(force) {
|
||||
await (0, retry_1.retry)(() => scripts.storedProcedure('releaseBuild').execute('', [commit]));
|
||||
}
|
||||
const [, , force] = process.argv;
|
||||
main(force === 'true').then(() => {
|
||||
console.log(process.argv);
|
||||
main(/^true$/i.test(force)).then(() => {
|
||||
console.log('Build successfully released');
|
||||
process.exit(0);
|
||||
}, err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVsZWFzZUJ1aWxkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicmVsZWFzZUJ1aWxkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7QUFFaEcsOENBQXlEO0FBQ3pELDBDQUE2QztBQUM3QyxtQ0FBZ0M7QUFFaEMsU0FBUyxNQUFNLENBQUMsSUFBWTtJQUMzQixNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRWpDLElBQUksT0FBTyxNQUFNLEtBQUssV0FBVyxFQUFFO1FBQ2xDLE1BQU0sSUFBSSxLQUFLLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxDQUFDO0tBQ3hDO0lBRUQsT0FBTyxNQUFNLENBQUM7QUFDZixDQUFDO0FBT0QsU0FBUyxtQkFBbUIsQ0FBQyxPQUFlO0lBQzNDLE9BQU87UUFDTixFQUFFLEVBQUUsT0FBTztRQUNYLE1BQU0sRUFBRSxLQUFLO0tBQ2IsQ0FBQztBQUNILENBQUM7QUFFRCxLQUFLLFVBQVUsU0FBUyxDQUFDLE1BQW9CLEVBQUUsT0FBZTtJQUM3RCxNQUFNLEtBQUssR0FBRyx1Q0FBdUMsT0FBTyxHQUFHLENBQUM7SUFFaEUsTUFBTSxHQUFHLEdBQUcsTUFBTSxNQUFNLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBRTlGLElBQUksR0FBRyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQy9CLE9BQU8sbUJBQW1CLENBQUMsT0FBTyxDQUFDLENBQUM7S0FDcEM7SUFFRCxPQUFPLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFXLENBQUM7QUFDbkMsQ0FBQztBQUVELEtBQUssVUFBVSxJQUFJLENBQUMsS0FBYztJQUNqQyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMscUJBQXFCLENBQUMsQ0FBQztJQUM3QyxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUV6QyxNQUFNLGNBQWMsR0FBRyxJQUFJLGlDQUFzQixDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBRSxDQUFDLENBQUM7SUFDekosTUFBTSxNQUFNLEdBQUcsSUFBSSxxQkFBWSxDQUFDLEVBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLENBQUUsRUFBRSxjQUFjLEVBQUUsQ0FBQyxDQUFDO0lBRXpHLElBQUksQ0FBQyxLQUFLLEVBQUU7UUFDWCxNQUFNLE1BQU0sR0FBRyxNQUFNLFNBQVMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFaEQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUV2QyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUU7WUFDbEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQ0FBb0MsT0FBTyxhQUFhLENBQUMsQ0FBQztZQUN0RSxPQUFPO1NBQ1A7S0FDRDtJQUVELE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLE1BQU0sS0FBSyxDQUFDLENBQUM7SUFFNUMsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxDQUFDO0lBQ3JFLE1BQU0sSUFBQSxhQUFLLEVBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxjQUFjLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2xGLENBQUM7QUFFRCxNQUFNLENBQUMsRUFBRSxBQUFELEVBQUcsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztBQUVqQyxJQUFJLENBQUMsS0FBSyxLQUFLLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7SUFDaEMsT0FBTyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0lBQzNDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDakIsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxFQUFFO0lBQ1IsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuQixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2pCLENBQUMsQ0FBQyxDQUFDIn0=
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVsZWFzZUJ1aWxkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicmVsZWFzZUJ1aWxkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7QUFFaEcsOENBQXlEO0FBQ3pELDBDQUE2QztBQUM3QyxtQ0FBZ0M7QUFFaEMsU0FBUyxNQUFNLENBQUMsSUFBWTtJQUMzQixNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBRWpDLElBQUksT0FBTyxNQUFNLEtBQUssV0FBVyxFQUFFO1FBQ2xDLE1BQU0sSUFBSSxLQUFLLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxDQUFDO0tBQ3hDO0lBRUQsT0FBTyxNQUFNLENBQUM7QUFDZixDQUFDO0FBT0QsU0FBUyxtQkFBbUIsQ0FBQyxPQUFlO0lBQzNDLE9BQU87UUFDTixFQUFFLEVBQUUsT0FBTztRQUNYLE1BQU0sRUFBRSxLQUFLO0tBQ2IsQ0FBQztBQUNILENBQUM7QUFFRCxLQUFLLFVBQVUsU0FBUyxDQUFDLE1BQW9CLEVBQUUsT0FBZTtJQUM3RCxNQUFNLEtBQUssR0FBRyx1Q0FBdUMsT0FBTyxHQUFHLENBQUM7SUFFaEUsTUFBTSxHQUFHLEdBQUcsTUFBTSxNQUFNLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBRTlGLElBQUksR0FBRyxDQUFDLFNBQVMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQy9CLE9BQU8sbUJBQW1CLENBQUMsT0FBTyxDQUFDLENBQUM7S0FDcEM7SUFFRCxPQUFPLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFXLENBQUM7QUFDbkMsQ0FBQztBQUVELEtBQUssVUFBVSxJQUFJLENBQUMsS0FBYztJQUNqQyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMscUJBQXFCLENBQUMsQ0FBQztJQUM3QyxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztJQUV6QyxNQUFNLGNBQWMsR0FBRyxJQUFJLGlDQUFzQixDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUUsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFFLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBRSxDQUFDLENBQUM7SUFDekosTUFBTSxNQUFNLEdBQUcsSUFBSSxxQkFBWSxDQUFDLEVBQUUsUUFBUSxFQUFFLE9BQU8sQ0FBQyxHQUFHLENBQUMsMkJBQTJCLENBQUUsRUFBRSxjQUFjLEVBQUUsQ0FBQyxDQUFDO0lBRXpHLElBQUksQ0FBQyxLQUFLLEVBQUU7UUFDWCxNQUFNLE1BQU0sR0FBRyxNQUFNLFNBQVMsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUM7UUFFaEQsT0FBTyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxNQUFNLENBQUMsQ0FBQztRQUV2QyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEVBQUU7WUFDbEIsT0FBTyxDQUFDLEdBQUcsQ0FBQyxvQ0FBb0MsT0FBTyxhQUFhLENBQUMsQ0FBQztZQUN0RSxPQUFPO1NBQ1A7S0FDRDtJQUVELE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLE1BQU0sS0FBSyxDQUFDLENBQUM7SUFFNUMsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxDQUFDO0lBQ3JFLE1BQU0sSUFBQSxhQUFLLEVBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxjQUFjLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2xGLENBQUM7QUFFRCxNQUFNLENBQUMsRUFBRSxBQUFELEVBQUcsS0FBSyxDQUFDLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztBQUVqQyxPQUFPLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUUxQixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7SUFDckMsT0FBTyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFDO0lBQzNDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDakIsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxFQUFFO0lBQ1IsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNuQixPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2pCLENBQUMsQ0FBQyxDQUFDIn0=
|
||||
@@ -67,7 +67,9 @@ async function main(force: boolean): Promise<void> {
|
||||
|
||||
const [, , force] = process.argv;
|
||||
|
||||
main(force === 'true').then(() => {
|
||||
console.log(process.argv);
|
||||
|
||||
main(/^true$/i.test(force)).then(() => {
|
||||
console.log('Build successfully released');
|
||||
process.exit(0);
|
||||
}, err => {
|
||||
|
||||
@@ -86,10 +86,6 @@
|
||||
"name": "vs/workbench/contrib/externalTerminal",
|
||||
"project": "vscode-workbench"
|
||||
},
|
||||
{
|
||||
"name": "vs/workbench/contrib/feedback",
|
||||
"project": "vscode-workbench"
|
||||
},
|
||||
{
|
||||
"name": "vs/workbench/contrib/files",
|
||||
"project": "vscode-workbench"
|
||||
|
||||
@@ -71,10 +71,18 @@ function calculatePackageDeps(binaryPath, arch, sysroot) {
|
||||
// on the newer package, this hack skips the dep. This is safe because
|
||||
// libgcc-s1 is a dependency of libc6. This hack can be removed once
|
||||
// support for Debian Buster and Ubuntu Bionic are dropped.
|
||||
//
|
||||
// Remove kerberos native module related dependencies as the versions
|
||||
// computed from sysroot will not satisfy the minimum supported distros
|
||||
// Refs https://github.com/microsoft/vscode/issues/188881.
|
||||
// TODO(deepak1556): remove this workaround in favor of computing the
|
||||
// versions from build container for native modules.
|
||||
const filteredDeps = depsStr.split(', ').filter(dependency => {
|
||||
return !dependency.startsWith('libgcc-s1');
|
||||
return !dependency.startsWith('libgcc-s1') &&
|
||||
!dependency.startsWith('libgssapi-krb5-2') &&
|
||||
!dependency.startsWith('libkrb5-3');
|
||||
}).sort();
|
||||
const requires = new Set(filteredDeps);
|
||||
return requires;
|
||||
}
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsY3VsYXRlLWRlcHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjYWxjdWxhdGUtZGVwcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztnR0FHZ0c7OztBQUVoRyxpREFBMEM7QUFDMUMsMkJBQXlDO0FBQ3pDLDJCQUE0QjtBQUM1Qiw2QkFBOEI7QUFDOUIsc0RBQXNEO0FBQ3RELDJDQUE2QztBQUc3QyxTQUFnQixtQkFBbUIsQ0FBQyxLQUFlLEVBQUUsSUFBc0IsRUFBRSxPQUFlO0lBQzNGLE1BQU0sWUFBWSxHQUFrQixLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsb0JBQW9CLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQ2pHLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxHQUFHLENBQUMsMEJBQWMsQ0FBQyxDQUFDO0lBQ2xELFlBQVksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUNyQyxPQUFPLFlBQVksQ0FBQztBQUNyQixDQUFDO0FBTEQsa0RBS0M7QUFFRCw2SEFBNkg7QUFDN0gsU0FBUyxvQkFBb0IsQ0FBQyxVQUFrQixFQUFFLElBQXNCLEVBQUUsT0FBZTtJQUN4RixJQUFJO1FBQ0gsSUFBSSxDQUFDLENBQUMsSUFBQSxhQUFRLEVBQUMsVUFBVSxDQUFDLENBQUMsSUFBSSxHQUFHLGNBQVMsQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUNyRCxNQUFNLElBQUksS0FBSyxDQUFDLFVBQVUsVUFBVSx1Q0FBdUMsQ0FBQyxDQUFDO1NBQzdFO0tBQ0Q7SUFBQyxPQUFPLENBQUMsRUFBRTtRQUNYLDhEQUE4RDtRQUM5RCxPQUFPLENBQUMsS0FBSyxDQUFDLGdCQUFnQixHQUFHLFVBQVUsR0FBRyxjQUFjLENBQUMsQ0FBQztLQUM5RDtJQUVELHdDQUF3QztJQUN4QyxNQUFNLGdCQUFnQixHQUFHLFNBQVMsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxFQUFFO1FBQ3RFLE9BQU8sWUFBWSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEtBQUssS0FBSyxJQUFJLFlBQVksQ0FBQyxTQUFTLENBQUMsR0FBSSxDQUFDLElBQUksS0FBSyxVQUFVLENBQUM7SUFDakcsQ0FBQyxDQUFDLENBQUM7SUFDSCxNQUFNLGdCQUFnQixHQUFHLHVEQUF1RCxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLCtDQUErQyxDQUFDO0lBQzNKLE1BQU0sMkJBQTJCLEdBQUcsR0FBRyxJQUFBLFdBQU0sR0FBRSxvQkFBb0IsQ0FBQztJQUNwRSxNQUFNLE1BQU0sR0FBRyxJQUFBLHlCQUFTLEVBQUMsTUFBTSxFQUFFLENBQUMsZ0JBQWdCLEVBQUUsSUFBSSxFQUFFLDJCQUEyQixDQUFDLENBQUMsQ0FBQztJQUN4RixJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQ3hCLE1BQU0sSUFBSSxLQUFLLENBQUMsMkNBQTJDLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0tBQzdFO0lBQ0QsTUFBTSxHQUFHLEdBQUcsQ0FBQywyQkFBMkIsRUFBRSx5QkFBeUIsQ0FBQyxDQUFDO0lBQ3JFLFFBQVEsSUFBSSxFQUFFO1FBQ2IsS0FBSyxPQUFPO1lBQ1gsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLE9BQU8sMkJBQTJCLEVBQy9DLEtBQUssT0FBTyx1QkFBdUIsQ0FBQyxDQUFDO1lBQ3RDLE1BQU07UUFDUCxLQUFLLE9BQU87WUFDWCxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssT0FBTyw4QkFBOEIsRUFDbEQsS0FBSyxPQUFPLDBCQUEwQixDQUFDLENBQUM7WUFDekMsTUFBTTtRQUNQLEtBQUssT0FBTztZQUNYLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxPQUFPLDRCQUE0QixFQUNoRCxLQUFLLE9BQU8sd0JBQXdCLENBQUMsQ0FBQztZQUN2QyxNQUFNO0tBQ1A7SUFDRCxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssT0FBTyxVQUFVLENBQUMsQ0FBQztJQUNqQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBRS9DLE1BQU0sbUJBQW1CLEdBQUcsSUFBQSx5QkFBUyxFQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUNyRSxJQUFJLG1CQUFtQixDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDckMsTUFBTSxJQUFJLEtBQUssQ0FBQyx3Q0FBd0MsbUJBQW1CLENBQUMsTUFBTSxjQUFjLG1CQUFtQixDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7S0FDL0g7SUFFRCxNQUFNLG1CQUFtQixHQUFHLGlCQUFpQixDQUFDO0lBQzlDLE1BQU0sWUFBWSxHQUFHLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hGLElBQUksT0FBTyxHQUFHLEVBQUUsQ0FBQztJQUNqQixLQUFLLE1BQU0sSUFBSSxJQUFJLFlBQVksRUFBRTtRQUNoQyxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsbUJBQW1CLENBQUMsRUFBRTtZQUN6QyxPQUFPLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztTQUNyRDtLQUNEO0lBQ0QseUVBQXlFO0lBQ3pFLDBFQUEwRTtJQUMxRSx5RUFBeUU7SUFDekUsdUVBQXVFO0lBQ3ZFLHFFQUFxRTtJQUNyRSwyREFBMkQ7SUFDM0QsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFDNUQsT0FBTyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDNUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDVixNQUFNLFFBQVEsR0FBRyxJQUFJLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUN2QyxPQUFPLFFBQVEsQ0FBQztBQUNqQixDQUFDIn0=
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsY3VsYXRlLWRlcHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjYWxjdWxhdGUtZGVwcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7OztnR0FHZ0c7OztBQUVoRyxpREFBMEM7QUFDMUMsMkJBQXlDO0FBQ3pDLDJCQUE0QjtBQUM1Qiw2QkFBOEI7QUFDOUIsc0RBQXNEO0FBQ3RELDJDQUE2QztBQUc3QyxTQUFnQixtQkFBbUIsQ0FBQyxLQUFlLEVBQUUsSUFBc0IsRUFBRSxPQUFlO0lBQzNGLE1BQU0sWUFBWSxHQUFrQixLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsb0JBQW9CLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQ2pHLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxHQUFHLENBQUMsMEJBQWMsQ0FBQyxDQUFDO0lBQ2xELFlBQVksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUNyQyxPQUFPLFlBQVksQ0FBQztBQUNyQixDQUFDO0FBTEQsa0RBS0M7QUFFRCw2SEFBNkg7QUFDN0gsU0FBUyxvQkFBb0IsQ0FBQyxVQUFrQixFQUFFLElBQXNCLEVBQUUsT0FBZTtJQUN4RixJQUFJO1FBQ0gsSUFBSSxDQUFDLENBQUMsSUFBQSxhQUFRLEVBQUMsVUFBVSxDQUFDLENBQUMsSUFBSSxHQUFHLGNBQVMsQ0FBQyxPQUFPLENBQUMsRUFBRTtZQUNyRCxNQUFNLElBQUksS0FBSyxDQUFDLFVBQVUsVUFBVSx1Q0FBdUMsQ0FBQyxDQUFDO1NBQzdFO0tBQ0Q7SUFBQyxPQUFPLENBQUMsRUFBRTtRQUNYLDhEQUE4RDtRQUM5RCxPQUFPLENBQUMsS0FBSyxDQUFDLGdCQUFnQixHQUFHLFVBQVUsR0FBRyxjQUFjLENBQUMsQ0FBQztLQUM5RDtJQUVELHdDQUF3QztJQUN4QyxNQUFNLGdCQUFnQixHQUFHLFNBQVMsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxFQUFFO1FBQ3RFLE9BQU8sWUFBWSxDQUFDLFNBQVMsQ0FBQyxJQUFJLEtBQUssS0FBSyxJQUFJLFlBQVksQ0FBQyxTQUFTLENBQUMsR0FBSSxDQUFDLElBQUksS0FBSyxVQUFVLENBQUM7SUFDakcsQ0FBQyxDQUFDLENBQUM7SUFDSCxNQUFNLGdCQUFnQixHQUFHLHVEQUF1RCxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLCtDQUErQyxDQUFDO0lBQzNKLE1BQU0sMkJBQTJCLEdBQUcsR0FBRyxJQUFBLFdBQU0sR0FBRSxvQkFBb0IsQ0FBQztJQUNwRSxNQUFNLE1BQU0sR0FBRyxJQUFBLHlCQUFTLEVBQUMsTUFBTSxFQUFFLENBQUMsZ0JBQWdCLEVBQUUsSUFBSSxFQUFFLDJCQUEyQixDQUFDLENBQUMsQ0FBQztJQUN4RixJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQ3hCLE1BQU0sSUFBSSxLQUFLLENBQUMsMkNBQTJDLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0tBQzdFO0lBQ0QsTUFBTSxHQUFHLEdBQUcsQ0FBQywyQkFBMkIsRUFBRSx5QkFBeUIsQ0FBQyxDQUFDO0lBQ3JFLFFBQVEsSUFBSSxFQUFFO1FBQ2IsS0FBSyxPQUFPO1lBQ1gsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLE9BQU8sMkJBQTJCLEVBQy9DLEtBQUssT0FBTyx1QkFBdUIsQ0FBQyxDQUFDO1lBQ3RDLE1BQU07UUFDUCxLQUFLLE9BQU87WUFDWCxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssT0FBTyw4QkFBOEIsRUFDbEQsS0FBSyxPQUFPLDBCQUEwQixDQUFDLENBQUM7WUFDekMsTUFBTTtRQUNQLEtBQUssT0FBTztZQUNYLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxPQUFPLDRCQUE0QixFQUNoRCxLQUFLLE9BQU8sd0JBQXdCLENBQUMsQ0FBQztZQUN2QyxNQUFNO0tBQ1A7SUFDRCxHQUFHLENBQUMsSUFBSSxDQUFDLEtBQUssT0FBTyxVQUFVLENBQUMsQ0FBQztJQUNqQyxHQUFHLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0lBRS9DLE1BQU0sbUJBQW1CLEdBQUcsSUFBQSx5QkFBUyxFQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsRUFBRSxHQUFHLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUNyRSxJQUFJLG1CQUFtQixDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7UUFDckMsTUFBTSxJQUFJLEtBQUssQ0FBQyx3Q0FBd0MsbUJBQW1CLENBQUMsTUFBTSxjQUFjLG1CQUFtQixDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7S0FDL0g7SUFFRCxNQUFNLG1CQUFtQixHQUFHLGlCQUFpQixDQUFDO0lBQzlDLE1BQU0sWUFBWSxHQUFHLG1CQUFtQixDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3hGLElBQUksT0FBTyxHQUFHLEVBQUUsQ0FBQztJQUNqQixLQUFLLE1BQU0sSUFBSSxJQUFJLFlBQVksRUFBRTtRQUNoQyxJQUFJLElBQUksQ0FBQyxVQUFVLENBQUMsbUJBQW1CLENBQUMsRUFBRTtZQUN6QyxPQUFPLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxtQkFBbUIsQ0FBQyxNQUFNLENBQUMsQ0FBQztTQUNyRDtLQUNEO0lBQ0QseUVBQXlFO0lBQ3pFLDBFQUEwRTtJQUMxRSx5RUFBeUU7SUFDekUsdUVBQXVFO0lBQ3ZFLHFFQUFxRTtJQUNyRSwyREFBMkQ7SUFDM0QsRUFBRTtJQUNGLHFFQUFxRTtJQUNyRSx1RUFBdUU7SUFDdkUsMERBQTBEO0lBQzFELHFFQUFxRTtJQUNyRSxvREFBb0Q7SUFDcEQsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLEVBQUU7UUFDNUQsT0FBTyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDO1lBQ3pDLENBQUMsVUFBVSxDQUFDLFVBQVUsQ0FBQyxrQkFBa0IsQ0FBQztZQUMxQyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDdEMsQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDVixNQUFNLFFBQVEsR0FBRyxJQUFJLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUN2QyxPQUFPLFFBQVEsQ0FBQztBQUNqQixDQUFDIn0=
|
||||
@@ -76,8 +76,16 @@ function calculatePackageDeps(binaryPath: string, arch: DebianArchString, sysroo
|
||||
// on the newer package, this hack skips the dep. This is safe because
|
||||
// libgcc-s1 is a dependency of libc6. This hack can be removed once
|
||||
// support for Debian Buster and Ubuntu Bionic are dropped.
|
||||
//
|
||||
// Remove kerberos native module related dependencies as the versions
|
||||
// computed from sysroot will not satisfy the minimum supported distros
|
||||
// Refs https://github.com/microsoft/vscode/issues/188881.
|
||||
// TODO(deepak1556): remove this workaround in favor of computing the
|
||||
// versions from build container for native modules.
|
||||
const filteredDeps = depsStr.split(', ').filter(dependency => {
|
||||
return !dependency.startsWith('libgcc-s1');
|
||||
return !dependency.startsWith('libgcc-s1') &&
|
||||
!dependency.startsWith('libgssapi-krb5-2') &&
|
||||
!dependency.startsWith('libkrb5-3');
|
||||
}).sort();
|
||||
const requires = new Set(filteredDeps);
|
||||
return requires;
|
||||
|
||||
@@ -12,7 +12,9 @@ exports.additionalDeps = [
|
||||
'libgtk-3-0 (>= 3.9.10) | libgtk-4-1',
|
||||
'libnss3 (>= 3.26)',
|
||||
'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3',
|
||||
'xdg-utils (>= 1.0.2)' // OS integration
|
||||
'xdg-utils (>= 1.0.2)',
|
||||
'libgssapi-krb5-2',
|
||||
'libkrb5-3',
|
||||
];
|
||||
// Based on https://source.chromium.org/chromium/chromium/src/+/main:chrome/installer/linux/debian/manual_recommends
|
||||
// Dependencies that we can only recommend
|
||||
@@ -38,10 +40,10 @@ exports.referenceGeneratedDepsByArch = {
|
||||
'libgbm1 (>= 17.1.0~rc2)',
|
||||
'libglib2.0-0 (>= 2.16.0)',
|
||||
'libglib2.0-0 (>= 2.39.4)',
|
||||
'libgssapi-krb5-2 (>= 1.17)',
|
||||
'libgssapi-krb5-2',
|
||||
'libgtk-3-0 (>= 3.9.10)',
|
||||
'libgtk-3-0 (>= 3.9.10) | libgtk-4-1',
|
||||
'libkrb5-3 (>= 1.6.dfsg.2)',
|
||||
'libkrb5-3',
|
||||
'libnspr4 (>= 2:4.9-2~)',
|
||||
'libnss3 (>= 2:3.22)',
|
||||
'libnss3 (>= 3.26)',
|
||||
@@ -78,10 +80,10 @@ exports.referenceGeneratedDepsByArch = {
|
||||
'libgbm1 (>= 17.1.0~rc2)',
|
||||
'libglib2.0-0 (>= 2.12.0)',
|
||||
'libglib2.0-0 (>= 2.39.4)',
|
||||
'libgssapi-krb5-2 (>= 1.17)',
|
||||
'libgssapi-krb5-2',
|
||||
'libgtk-3-0 (>= 3.9.10)',
|
||||
'libgtk-3-0 (>= 3.9.10) | libgtk-4-1',
|
||||
'libkrb5-3 (>= 1.6.dfsg.2)',
|
||||
'libkrb5-3',
|
||||
'libnspr4 (>= 2:4.9-2~)',
|
||||
'libnss3 (>= 2:3.22)',
|
||||
'libnss3 (>= 3.26)',
|
||||
@@ -117,10 +119,10 @@ exports.referenceGeneratedDepsByArch = {
|
||||
'libgbm1 (>= 17.1.0~rc2)',
|
||||
'libglib2.0-0 (>= 2.12.0)',
|
||||
'libglib2.0-0 (>= 2.39.4)',
|
||||
'libgssapi-krb5-2 (>= 1.17)',
|
||||
'libgssapi-krb5-2',
|
||||
'libgtk-3-0 (>= 3.9.10)',
|
||||
'libgtk-3-0 (>= 3.9.10) | libgtk-4-1',
|
||||
'libkrb5-3 (>= 1.6.dfsg.2)',
|
||||
'libkrb5-3',
|
||||
'libnspr4 (>= 2:4.9-2~)',
|
||||
'libnss3 (>= 2:3.22)',
|
||||
'libnss3 (>= 3.26)',
|
||||
@@ -142,4 +144,4 @@ exports.referenceGeneratedDepsByArch = {
|
||||
'xdg-utils (>= 1.0.2)'
|
||||
]
|
||||
};
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwLWxpc3RzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZGVwLWxpc3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7O0FBRWhHLGtIQUFrSDtBQUNsSCw0REFBNEQ7QUFDL0MsUUFBQSxjQUFjLEdBQUc7SUFDN0IsaUJBQWlCO0lBQ2pCLHFDQUFxQztJQUNyQyxtQkFBbUI7SUFDbkIsc0RBQXNEO0lBQ3RELHNCQUFzQixDQUFDLGlCQUFpQjtDQUN4QyxDQUFDO0FBRUYsb0hBQW9IO0FBQ3BILDBDQUEwQztBQUMxQyw4REFBOEQ7QUFDakQsUUFBQSxlQUFlLEdBQUc7SUFDOUIsWUFBWSxDQUFDLHlFQUF5RTtDQUN0RixDQUFDO0FBRVcsUUFBQSw0QkFBNEIsR0FBRztJQUMzQyxPQUFPLEVBQUU7UUFDUixpQkFBaUI7UUFDakIsd0JBQXdCO1FBQ3hCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsMkJBQTJCO1FBQzNCLGlCQUFpQjtRQUNqQixpQkFBaUI7UUFDakIsa0JBQWtCO1FBQ2xCLHNCQUFzQjtRQUN0QixzREFBc0Q7UUFDdEQseUJBQXlCO1FBQ3pCLHFCQUFxQjtRQUNyQixzQkFBc0I7UUFDdEIseUJBQXlCO1FBQ3pCLDBCQUEwQjtRQUMxQiwwQkFBMEI7UUFDMUIsNEJBQTRCO1FBQzVCLHdCQUF3QjtRQUN4QixxQ0FBcUM7UUFDckMsMkJBQTJCO1FBQzNCLHdCQUF3QjtRQUN4QixxQkFBcUI7UUFDckIsbUJBQW1CO1FBQ25CLDRCQUE0QjtRQUM1Qix5QkFBeUI7UUFDekIsVUFBVTtRQUNWLDBCQUEwQjtRQUMxQixvQkFBb0I7UUFDcEIsK0JBQStCO1FBQy9CLHdCQUF3QjtRQUN4QixVQUFVO1FBQ1YsWUFBWTtRQUNaLDBCQUEwQjtRQUMxQixhQUFhO1FBQ2IsWUFBWTtRQUNaLHNCQUFzQjtLQUN0QjtJQUNELE9BQU8sRUFBRTtRQUNSLGlCQUFpQjtRQUNqQix3QkFBd0I7UUFDeEIsK0JBQStCO1FBQy9CLHdCQUF3QjtRQUN4QiwyQkFBMkI7UUFDM0IsaUJBQWlCO1FBQ2pCLGlCQUFpQjtRQUNqQixnQkFBZ0I7UUFDaEIsZ0JBQWdCO1FBQ2hCLGdCQUFnQjtRQUNoQixzQkFBc0I7UUFDdEIsc0RBQXNEO1FBQ3RELHlCQUF5QjtRQUN6QixxQkFBcUI7UUFDckIsc0JBQXNCO1FBQ3RCLHlCQUF5QjtRQUN6QiwwQkFBMEI7UUFDMUIsMEJBQTBCO1FBQzFCLDRCQUE0QjtRQUM1Qix3QkFBd0I7UUFDeEIscUNBQXFDO1FBQ3JDLDJCQUEyQjtRQUMzQix3QkFBd0I7UUFDeEIscUJBQXFCO1FBQ3JCLG1CQUFtQjtRQUNuQiw0QkFBNEI7UUFDNUIseUJBQXlCO1FBQ3pCLG1CQUFtQjtRQUNuQixxQkFBcUI7UUFDckIsbUJBQW1CO1FBQ25CLFVBQVU7UUFDViwwQkFBMEI7UUFDMUIsb0JBQW9CO1FBQ3BCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsVUFBVTtRQUNWLFlBQVk7UUFDWiwwQkFBMEI7UUFDMUIsYUFBYTtRQUNiLFlBQVk7UUFDWixzQkFBc0I7S0FDdEI7SUFDRCxPQUFPLEVBQUU7UUFDUixpQkFBaUI7UUFDakIsd0JBQXdCO1FBQ3hCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsMkJBQTJCO1FBQzNCLGlCQUFpQjtRQUNqQixzQkFBc0I7UUFDdEIsc0RBQXNEO1FBQ3RELHdCQUF3QjtRQUN4QixxQkFBcUI7UUFDckIsc0JBQXNCO1FBQ3RCLHlCQUF5QjtRQUN6QiwwQkFBMEI7UUFDMUIsMEJBQTBCO1FBQzFCLDRCQUE0QjtRQUM1Qix3QkFBd0I7UUFDeEIscUNBQXFDO1FBQ3JDLDJCQUEyQjtRQUMzQix3QkFBd0I7UUFDeEIscUJBQXFCO1FBQ3JCLG1CQUFtQjtRQUNuQiw0QkFBNEI7UUFDNUIseUJBQXlCO1FBQ3pCLG1CQUFtQjtRQUNuQixxQkFBcUI7UUFDckIsbUJBQW1CO1FBQ25CLFVBQVU7UUFDViwwQkFBMEI7UUFDMUIsb0JBQW9CO1FBQ3BCLCtCQUErQjtRQUMvQix3QkFBd0I7UUFDeEIsVUFBVTtRQUNWLFlBQVk7UUFDWiwwQkFBMEI7UUFDMUIsYUFBYTtRQUNiLFlBQVk7UUFDWixzQkFBc0I7S0FDdEI7Q0FDRCxDQUFDIn0=
|
||||
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVwLWxpc3RzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZGVwLWxpc3RzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7O2dHQUdnRzs7O0FBRWhHLGtIQUFrSDtBQUNsSCw0REFBNEQ7QUFDL0MsUUFBQSxjQUFjLEdBQUc7SUFDN0IsaUJBQWlCO0lBQ2pCLHFDQUFxQztJQUNyQyxtQkFBbUI7SUFDbkIsc0RBQXNEO0lBQ3RELHNCQUFzQjtJQUN0QixrQkFBa0I7SUFDbEIsV0FBVztDQUNYLENBQUM7QUFFRixvSEFBb0g7QUFDcEgsMENBQTBDO0FBQzFDLDhEQUE4RDtBQUNqRCxRQUFBLGVBQWUsR0FBRztJQUM5QixZQUFZLENBQUMseUVBQXlFO0NBQ3RGLENBQUM7QUFFVyxRQUFBLDRCQUE0QixHQUFHO0lBQzNDLE9BQU8sRUFBRTtRQUNSLGlCQUFpQjtRQUNqQix3QkFBd0I7UUFDeEIsK0JBQStCO1FBQy9CLHdCQUF3QjtRQUN4QiwyQkFBMkI7UUFDM0IsaUJBQWlCO1FBQ2pCLGlCQUFpQjtRQUNqQixrQkFBa0I7UUFDbEIsc0JBQXNCO1FBQ3RCLHNEQUFzRDtRQUN0RCx5QkFBeUI7UUFDekIscUJBQXFCO1FBQ3JCLHNCQUFzQjtRQUN0Qix5QkFBeUI7UUFDekIsMEJBQTBCO1FBQzFCLDBCQUEwQjtRQUMxQixrQkFBa0I7UUFDbEIsd0JBQXdCO1FBQ3hCLHFDQUFxQztRQUNyQyxXQUFXO1FBQ1gsd0JBQXdCO1FBQ3hCLHFCQUFxQjtRQUNyQixtQkFBbUI7UUFDbkIsNEJBQTRCO1FBQzVCLHlCQUF5QjtRQUN6QixVQUFVO1FBQ1YsMEJBQTBCO1FBQzFCLG9CQUFvQjtRQUNwQiwrQkFBK0I7UUFDL0Isd0JBQXdCO1FBQ3hCLFVBQVU7UUFDVixZQUFZO1FBQ1osMEJBQTBCO1FBQzFCLGFBQWE7UUFDYixZQUFZO1FBQ1osc0JBQXNCO0tBQ3RCO0lBQ0QsT0FBTyxFQUFFO1FBQ1IsaUJBQWlCO1FBQ2pCLHdCQUF3QjtRQUN4QiwrQkFBK0I7UUFDL0Isd0JBQXdCO1FBQ3hCLDJCQUEyQjtRQUMzQixpQkFBaUI7UUFDakIsaUJBQWlCO1FBQ2pCLGdCQUFnQjtRQUNoQixnQkFBZ0I7UUFDaEIsZ0JBQWdCO1FBQ2hCLHNCQUFzQjtRQUN0QixzREFBc0Q7UUFDdEQseUJBQXlCO1FBQ3pCLHFCQUFxQjtRQUNyQixzQkFBc0I7UUFDdEIseUJBQXlCO1FBQ3pCLDBCQUEwQjtRQUMxQiwwQkFBMEI7UUFDMUIsa0JBQWtCO1FBQ2xCLHdCQUF3QjtRQUN4QixxQ0FBcUM7UUFDckMsV0FBVztRQUNYLHdCQUF3QjtRQUN4QixxQkFBcUI7UUFDckIsbUJBQW1CO1FBQ25CLDRCQUE0QjtRQUM1Qix5QkFBeUI7UUFDekIsbUJBQW1CO1FBQ25CLHFCQUFxQjtRQUNyQixtQkFBbUI7UUFDbkIsVUFBVTtRQUNWLDBCQUEwQjtRQUMxQixvQkFBb0I7UUFDcEIsK0JBQStCO1FBQy9CLHdCQUF3QjtRQUN4QixVQUFVO1FBQ1YsWUFBWTtRQUNaLDBCQUEwQjtRQUMxQixhQUFhO1FBQ2IsWUFBWTtRQUNaLHNCQUFzQjtLQUN0QjtJQUNELE9BQU8sRUFBRTtRQUNSLGlCQUFpQjtRQUNqQix3QkFBd0I7UUFDeEIsK0JBQStCO1FBQy9CLHdCQUF3QjtRQUN4QiwyQkFBMkI7UUFDM0IsaUJBQWlCO1FBQ2pCLHNCQUFzQjtRQUN0QixzREFBc0Q7UUFDdEQsd0JBQXdCO1FBQ3hCLHFCQUFxQjtRQUNyQixzQkFBc0I7UUFDdEIseUJBQXlCO1FBQ3pCLDBCQUEwQjtRQUMxQiwwQkFBMEI7UUFDMUIsa0JBQWtCO1FBQ2xCLHdCQUF3QjtRQUN4QixxQ0FBcUM7UUFDckMsV0FBVztRQUNYLHdCQUF3QjtRQUN4QixxQkFBcUI7UUFDckIsbUJBQW1CO1FBQ25CLDRCQUE0QjtRQUM1Qix5QkFBeUI7UUFDekIsbUJBQW1CO1FBQ25CLHFCQUFxQjtRQUNyQixtQkFBbUI7UUFDbkIsVUFBVTtRQUNWLDBCQUEwQjtRQUMxQixvQkFBb0I7UUFDcEIsK0JBQStCO1FBQy9CLHdCQUF3QjtRQUN4QixVQUFVO1FBQ1YsWUFBWTtRQUNaLDBCQUEwQjtRQUMxQixhQUFhO1FBQ2IsWUFBWTtRQUNaLHNCQUFzQjtLQUN0QjtDQUNELENBQUMifQ==
|
||||
@@ -10,7 +10,9 @@ export const additionalDeps = [
|
||||
'libgtk-3-0 (>= 3.9.10) | libgtk-4-1',
|
||||
'libnss3 (>= 3.26)',
|
||||
'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3', // For Breakpad crash reports.
|
||||
'xdg-utils (>= 1.0.2)' // OS integration
|
||||
'xdg-utils (>= 1.0.2)', // OS integration
|
||||
'libgssapi-krb5-2',
|
||||
'libkrb5-3',
|
||||
];
|
||||
|
||||
// Based on https://source.chromium.org/chromium/chromium/src/+/main:chrome/installer/linux/debian/manual_recommends
|
||||
@@ -38,10 +40,10 @@ export const referenceGeneratedDepsByArch = {
|
||||
'libgbm1 (>= 17.1.0~rc2)',
|
||||
'libglib2.0-0 (>= 2.16.0)',
|
||||
'libglib2.0-0 (>= 2.39.4)',
|
||||
'libgssapi-krb5-2 (>= 1.17)',
|
||||
'libgssapi-krb5-2',
|
||||
'libgtk-3-0 (>= 3.9.10)',
|
||||
'libgtk-3-0 (>= 3.9.10) | libgtk-4-1',
|
||||
'libkrb5-3 (>= 1.6.dfsg.2)',
|
||||
'libkrb5-3',
|
||||
'libnspr4 (>= 2:4.9-2~)',
|
||||
'libnss3 (>= 2:3.22)',
|
||||
'libnss3 (>= 3.26)',
|
||||
@@ -78,10 +80,10 @@ export const referenceGeneratedDepsByArch = {
|
||||
'libgbm1 (>= 17.1.0~rc2)',
|
||||
'libglib2.0-0 (>= 2.12.0)',
|
||||
'libglib2.0-0 (>= 2.39.4)',
|
||||
'libgssapi-krb5-2 (>= 1.17)',
|
||||
'libgssapi-krb5-2',
|
||||
'libgtk-3-0 (>= 3.9.10)',
|
||||
'libgtk-3-0 (>= 3.9.10) | libgtk-4-1',
|
||||
'libkrb5-3 (>= 1.6.dfsg.2)',
|
||||
'libkrb5-3',
|
||||
'libnspr4 (>= 2:4.9-2~)',
|
||||
'libnss3 (>= 2:3.22)',
|
||||
'libnss3 (>= 3.26)',
|
||||
@@ -117,10 +119,10 @@ export const referenceGeneratedDepsByArch = {
|
||||
'libgbm1 (>= 17.1.0~rc2)',
|
||||
'libglib2.0-0 (>= 2.12.0)',
|
||||
'libglib2.0-0 (>= 2.39.4)',
|
||||
'libgssapi-krb5-2 (>= 1.17)',
|
||||
'libgssapi-krb5-2',
|
||||
'libgtk-3-0 (>= 3.9.10)',
|
||||
'libgtk-3-0 (>= 3.9.10) | libgtk-4-1',
|
||||
'libkrb5-3 (>= 1.6.dfsg.2)',
|
||||
'libkrb5-3',
|
||||
'libnspr4 (>= 2:4.9-2~)',
|
||||
'libnss3 (>= 2:3.22)',
|
||||
'libnss3 (>= 3.26)',
|
||||
|
||||
@@ -41,8 +41,7 @@
|
||||
".code-workspace",
|
||||
"language-configuration.json",
|
||||
"icon-theme.json",
|
||||
"color-theme.json",
|
||||
".code-snippets"
|
||||
"color-theme.json"
|
||||
],
|
||||
"filenames": [
|
||||
"settings.json",
|
||||
@@ -54,10 +53,6 @@
|
||||
"profiles.json",
|
||||
"devcontainer.json",
|
||||
".devcontainer.json"
|
||||
],
|
||||
"filenamePatterns": [
|
||||
"**/User/snippets/*.json",
|
||||
"**/User/profiles/*/snippets/*.json"
|
||||
]
|
||||
}, {
|
||||
"id": "json",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"git": {
|
||||
"name": "dotnet/csharp-tmLanguage",
|
||||
"repositoryUrl": "https://github.com/dotnet/csharp-tmLanguage",
|
||||
"commitHash": "878aefe73f942ac68dc4a46a0f154661bcb9eff4"
|
||||
"commitHash": "772323937fedd65c6dc1c8ce6ea41d97415ed7d1"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/dotnet/csharp-tmLanguage/commit/878aefe73f942ac68dc4a46a0f154661bcb9eff4",
|
||||
"version": "https://github.com/dotnet/csharp-tmLanguage/commit/772323937fedd65c6dc1c8ce6ea41d97415ed7d1",
|
||||
"name": "C#",
|
||||
"scopeName": "source.cs",
|
||||
"patterns": [
|
||||
@@ -286,6 +286,9 @@
|
||||
{
|
||||
"include": "#nameof-expression"
|
||||
},
|
||||
{
|
||||
"include": "#default-literal-expression"
|
||||
},
|
||||
{
|
||||
"include": "#throw-expression"
|
||||
},
|
||||
@@ -298,6 +301,9 @@
|
||||
{
|
||||
"include": "#verbatim-interpolated-string"
|
||||
},
|
||||
{
|
||||
"include": "#type-builtin"
|
||||
},
|
||||
{
|
||||
"include": "#this-or-base-expression"
|
||||
},
|
||||
@@ -2733,6 +2739,14 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"default-literal-expression": {
|
||||
"match": "(?<!\\.)\\b(default)\\b",
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "keyword.other.default.cs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"throw-expression": {
|
||||
"match": "(?<!\\.)\\b(throw)\\b",
|
||||
"captures": {
|
||||
@@ -3673,7 +3687,7 @@
|
||||
]
|
||||
},
|
||||
"object-creation-expression-with-parameters": {
|
||||
"begin": "(?x)\n(new)\\s+\n(?<type_name>\n (?:\n (?:\n (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (?<name_and_type_args> # identifier + type arguments (if any)\n \\g<identifier>\\s*\n (?<type_args>\\s*<(?:[^<>]|\\g<type_args>)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g<name_and_type_args>)* | # Are there any more names being dotted into?\n (?<tuple>\\s*\\((?:[^\\(\\)]|\\g<tuple>)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n)\\s*\n(?=\\()",
|
||||
"begin": "(?x)\n(new)(?:\\s+\n(?<type_name>\n (?:\n (?:\n (?:(?<identifier>@?[_[:alpha:]][_[:alnum:]]*)\\s*\\:\\:\\s*)? # alias-qualification\n (?<name_and_type_args> # identifier + type arguments (if any)\n \\g<identifier>\\s*\n (?<type_args>\\s*<(?:[^<>]|\\g<type_args>)+>\\s*)?\n )\n (?:\\s*\\.\\s*\\g<name_and_type_args>)* | # Are there any more names being dotted into?\n (?<tuple>\\s*\\((?:[^\\(\\)]|\\g<tuple>)+\\))\n )\n (?:\\s*\\?\\s*)? # nullable suffix?\n (?:\\s* # array suffix?\n \\[\n (?:\\s*,\\s*)* # commata for multi-dimensional arrays\n \\]\n \\s*\n (?:\\?)? # arrays can be nullable reference types\n \\s*\n )*\n )\n))?\\s*\n(?=\\()",
|
||||
"beginCaptures": {
|
||||
"1": {
|
||||
"name": "keyword.other.new.cs"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"git": {
|
||||
"name": "ionide/ionide-fsgrammar",
|
||||
"repositoryUrl": "https://github.com/ionide/ionide-fsgrammar",
|
||||
"commitHash": "71b1ead8c99715f6c994115ebab7ee4a14cf0c59"
|
||||
"commitHash": "8740e610a367c5e3f15be716acc7207655ced4cf"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/ionide/ionide-fsgrammar/commit/71b1ead8c99715f6c994115ebab7ee4a14cf0c59",
|
||||
"version": "https://github.com/ionide/ionide-fsgrammar/commit/8740e610a367c5e3f15be716acc7207655ced4cf",
|
||||
"name": "fsharp",
|
||||
"scopeName": "source.fsharp",
|
||||
"patterns": [
|
||||
@@ -314,7 +314,7 @@
|
||||
},
|
||||
{
|
||||
"match": "(?!when|and|or\\b)\\b([\\w0-9'`^._]+)",
|
||||
"comments": "Here we need the \\w modifier in order to check that the words isn't blacklisted",
|
||||
"comments": "Here we need the \\w modifier in order to check that the words are allowed",
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "entity.name.type.fsharp"
|
||||
@@ -1832,4 +1832,4 @@
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
"git": {
|
||||
"name": "redhat-developer/vscode-java",
|
||||
"repositoryUrl": "https://github.com/redhat-developer/vscode-java",
|
||||
"commitHash": "7a770ab6750b4b09173d98de14eb9792e3432b36"
|
||||
"commitHash": "5fb57e8e1c5d776b21be13cd7227b25b87edf4a6"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
@@ -48,4 +48,4 @@
|
||||
}
|
||||
],
|
||||
"version": 1
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/redhat-developer/vscode-java/commit/7a770ab6750b4b09173d98de14eb9792e3432b36",
|
||||
"version": "https://github.com/redhat-developer/vscode-java/commit/5fb57e8e1c5d776b21be13cd7227b25b87edf4a6",
|
||||
"name": "Java",
|
||||
"scopeName": "source.java",
|
||||
"patterns": [
|
||||
@@ -1378,6 +1378,17 @@
|
||||
},
|
||||
"properties": {
|
||||
"patterns": [
|
||||
{
|
||||
"match": "(\\.)\\s*(new)",
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "punctuation.separator.period.java"
|
||||
},
|
||||
"2": {
|
||||
"name": "keyword.control.new.java"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": "(\\.)\\s*([a-zA-Z_$][\\w$]*)(?=\\s*\\.\\s*[a-zA-Z_$][\\w$]*)",
|
||||
"captures": {
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
|
||||
var updateGrammar = require('vscode-grammar-updater');
|
||||
|
||||
function adaptJSON(grammar, name, replacementScope) {
|
||||
function adaptJSON(grammar, name, replacementScope, replaceeScope = 'json') {
|
||||
grammar.name = name;
|
||||
grammar.scopeName = `source${replacementScope}`;
|
||||
|
||||
const regex = new RegExp(`\.${replaceeScope}`, 'g');
|
||||
var fixScopeNames = function (rule) {
|
||||
if (typeof rule.name === 'string') {
|
||||
rule.name = rule.name.replace(/\.json/g, replacementScope);
|
||||
rule.name = rule.name.replace(regex, replacementScope);
|
||||
}
|
||||
if (typeof rule.contentName === 'string') {
|
||||
rule.contentName = rule.contentName.replace(/\.json/g, replacementScope);
|
||||
rule.contentName = rule.contentName.replace(regex, replacementScope);
|
||||
}
|
||||
for (var property in rule) {
|
||||
var value = rule[property];
|
||||
@@ -35,3 +35,5 @@ var tsGrammarRepo = 'microsoft/vscode-JSON.tmLanguage';
|
||||
updateGrammar.update(tsGrammarRepo, 'JSON.tmLanguage', './syntaxes/JSON.tmLanguage.json');
|
||||
updateGrammar.update(tsGrammarRepo, 'JSON.tmLanguage', './syntaxes/JSONC.tmLanguage.json', grammar => adaptJSON(grammar, 'JSON with Comments', '.json.comments'));
|
||||
updateGrammar.update(tsGrammarRepo, 'JSON.tmLanguage', './syntaxes/JSONL.tmLanguage.json', grammar => adaptJSON(grammar, 'JSON Lines', '.json.lines'));
|
||||
|
||||
updateGrammar.update('jeff-hykin/better-snippet-syntax', 'autogenerated/jsonc.tmLanguage.json', './syntaxes/snippets.tmLanguage.json', grammar => adaptJSON(grammar, 'Snippets', '.json.comments.snippets', 'json.comments'));
|
||||
|
||||
@@ -11,6 +11,18 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"version": "0.0.0"
|
||||
},
|
||||
{
|
||||
"component": {
|
||||
"type": "git",
|
||||
"git": {
|
||||
"name": "jeff-hykin/better-snippet-syntax",
|
||||
"repositoryUrl": "https://github.com/jeff-hykin/better-snippet-syntax",
|
||||
"commitHash": "2b1bb124cb2b9c75c3c80eae1b8f3a043841d654"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
"version": "1.0.2"
|
||||
}
|
||||
],
|
||||
"version": 1
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
".jslintrc",
|
||||
".jsonld",
|
||||
".geojson",
|
||||
".ipynb",
|
||||
".ipynb",
|
||||
".vuerc"
|
||||
],
|
||||
"filenames": [
|
||||
@@ -77,6 +77,20 @@
|
||||
],
|
||||
"filenames": [],
|
||||
"configuration": "./language-configuration.json"
|
||||
},
|
||||
{
|
||||
"id": "snippets",
|
||||
"aliases": [
|
||||
"Code Snippets"
|
||||
],
|
||||
"extensions": [
|
||||
".code-snippets"
|
||||
],
|
||||
"filenamePatterns": [
|
||||
"**/User/snippets/*.json",
|
||||
"**/User/profiles/*/snippets/*.json"
|
||||
],
|
||||
"configuration": "./language-configuration.json"
|
||||
}
|
||||
],
|
||||
"grammars": [
|
||||
@@ -94,6 +108,11 @@
|
||||
"language": "jsonl",
|
||||
"scopeName": "source.json.lines",
|
||||
"path": "./syntaxes/JSONL.tmLanguage.json"
|
||||
},
|
||||
{
|
||||
"language": "snippets",
|
||||
"scopeName": "source.json.comments.snippets",
|
||||
"path": "./syntaxes/snippets.tmLanguage.json"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -6,7 +6,7 @@
|
||||
"git": {
|
||||
"name": "jlelong/vscode-latex-basics",
|
||||
"repositoryUrl": "https://github.com/jlelong/vscode-latex-basics",
|
||||
"commitHash": "30adbfae9dcb0a6477584247ac477f13845d1f5f"
|
||||
"commitHash": "30d04562e592305b6f6d41a539b3ccf326888aaf"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
|
||||
"Once accepted there, we are happy to receive an update request."
|
||||
],
|
||||
"version": "https://github.com/jlelong/vscode-latex-basics/commit/30adbfae9dcb0a6477584247ac477f13845d1f5f",
|
||||
"version": "https://github.com/jlelong/vscode-latex-basics/commit/30d04562e592305b6f6d41a539b3ccf326888aaf",
|
||||
"name": "LaTeX",
|
||||
"scopeName": "text.tex.latex",
|
||||
"patterns": [
|
||||
@@ -1337,7 +1337,7 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"begin": "(\\s*\\\\begin\\{(tabular[xy*]?|xltabular|longtable|(?:long)?tabu|(?:long|tall)?tblr|NiceTabular[X*]?)\\}(\\s*\\n)?)",
|
||||
"begin": "(\\s*\\\\begin\\{(tabular[xy*]?|xltabular|longtable|(?:long)?tabu|(?:long|tall)?tblr|NiceTabular[X*]?|booktabs)\\}(\\s*\\n)?)",
|
||||
"captures": {
|
||||
"1": {
|
||||
"patterns": [
|
||||
|
||||
@@ -502,7 +502,7 @@
|
||||
"type": "string",
|
||||
"scope": "resource",
|
||||
"markdownDescription": "%configuration.markdown.editor.pasteUrlAsFormattedLink.enabled%",
|
||||
"default":"smart",
|
||||
"default":"never",
|
||||
"enum": [
|
||||
"always",
|
||||
"smart",
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ class PasteLinkEditProvider implements vscode.DocumentPasteEditProvider {
|
||||
return;
|
||||
}
|
||||
|
||||
uriEdit.label = pasteEdit.label;
|
||||
uriEdit.label = pasteUrlSetting === PasteUrlAsFormattedLink.Smart ? vscode.l10n.t('Smartly Insert Link') : pasteEdit.label;
|
||||
uriEdit.additionalEdit = pasteEdit.additionalEdits;
|
||||
return uriEdit;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"git": {
|
||||
"name": "microsoft/vscode-mssql",
|
||||
"repositoryUrl": "https://github.com/microsoft/vscode-mssql",
|
||||
"commitHash": "cb5940297a8cef76daaf4a6b63c4968c9a12d17a"
|
||||
"commitHash": "9cb3529a978ddf599bf5bdd228f21bbcfe2914f5"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,40 @@
|
||||
{
|
||||
// Each snippet is defined under a snippet name and has a scope, prefix, body and
|
||||
// description. The scope defines in watch languages the snippet is applicable. The prefix is what is
|
||||
// used to trigger the snippet and the body will be expanded and inserted.Possible variables are:
|
||||
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
|
||||
// Placeholders with the same ids are connected.
|
||||
// Example:
|
||||
"MSFT Copyright Header": {
|
||||
"scope": "javascript,typescript,css",
|
||||
"prefix": [
|
||||
"header",
|
||||
"stub",
|
||||
"copyright"
|
||||
],
|
||||
"body": [
|
||||
"/*---------------------------------------------------------------------------------------------",
|
||||
" * Copyright (c) Microsoft Corporation. All rights reserved.",
|
||||
" * Licensed under the MIT License. See License.txt in the project root for license information.",
|
||||
" *--------------------------------------------------------------------------------------------*/",
|
||||
"",
|
||||
"$0"
|
||||
],
|
||||
"description": "Insert Copyright Statement"
|
||||
},
|
||||
"TS -> Inject Service": {
|
||||
"scope": "typescript",
|
||||
"description": "Constructor Injection Pattern",
|
||||
"prefix": "@inject",
|
||||
"body": "@$1 private readonly _$2: ${1},$0"
|
||||
},
|
||||
"TS -> Event & Emitter": {
|
||||
"scope": "typescript",
|
||||
"prefix": "emitter",
|
||||
"description": "Add emitter and event properties",
|
||||
"body": [
|
||||
"private readonly _onDid$1 = new Emitter<$2>();",
|
||||
"readonly onDid$1: Event<$2> = this._onDid$1.event;"
|
||||
],
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "code-oss-dev",
|
||||
"version": "1.81.0",
|
||||
"distro": "4522c9eb8ccecb983f40d135de4b91df6f8e0312",
|
||||
"version": "1.82.0",
|
||||
"distro": "3278b6d258cb23d8d52820288c40fdba5e61ddd4",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
},
|
||||
|
||||
Vendored
+5
-4
@@ -23,6 +23,7 @@
|
||||
const Module = typeof require === 'function' ? require('module') : undefined;
|
||||
const path = typeof require === 'function' ? require('path') : undefined;
|
||||
const fs = typeof require === 'function' ? require('fs') : undefined;
|
||||
const util = typeof require === 'function' ? require('util') : undefined;
|
||||
|
||||
//#region global bootstrapping
|
||||
|
||||
@@ -222,8 +223,8 @@
|
||||
return ipcRenderer.invoke('vscode:readNlsFile', ...pathSegments);
|
||||
}
|
||||
|
||||
if (fs && path) {
|
||||
return (await fs.promises.readFile(path.join(...pathSegments))).toString();
|
||||
if (fs && path && util) {
|
||||
return (await util.promisify(fs.readFile)(path.join(...pathSegments))).toString();
|
||||
}
|
||||
|
||||
throw new Error('Unsupported operation (read NLS files)');
|
||||
@@ -240,8 +241,8 @@
|
||||
return ipcRenderer.invoke('vscode:writeNlsFile', path, content);
|
||||
}
|
||||
|
||||
if (fs) {
|
||||
return fs.promises.writeFile(path, content);
|
||||
if (fs && util) {
|
||||
return util.promisify(fs.writeFile)(path, content);
|
||||
}
|
||||
|
||||
throw new Error('Unsupported operation (write NLS files)');
|
||||
|
||||
@@ -391,7 +391,13 @@ export abstract class AbstractScrollableElement extends Widget {
|
||||
let deltaX = e.deltaX * this._options.mouseWheelScrollSensitivity;
|
||||
|
||||
if (this._options.scrollPredominantAxis) {
|
||||
if (Math.abs(deltaY) >= Math.abs(deltaX)) {
|
||||
if (this._options.scrollYToX && deltaX + deltaY === 0) {
|
||||
// when configured to map Y to X and we both see
|
||||
// no dominant axis and X and Y are competing with
|
||||
// identical values into opposite directions, we
|
||||
// ignore the delta as we cannot make a decision then
|
||||
deltaX = deltaY = 0;
|
||||
} else if (Math.abs(deltaY) >= Math.abs(deltaX)) {
|
||||
deltaX = 0;
|
||||
} else {
|
||||
deltaY = 0;
|
||||
|
||||
@@ -118,7 +118,7 @@ export class AutorunObserver<TChangeSummary = any> implements IObserver, IReader
|
||||
}
|
||||
|
||||
private _runIfNeeded() {
|
||||
if (this.state === AutorunState.upToDate || this.disposed) {
|
||||
if (this.state === AutorunState.upToDate) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -128,12 +128,13 @@ export class AutorunObserver<TChangeSummary = any> implements IObserver, IReader
|
||||
|
||||
this.state = AutorunState.upToDate;
|
||||
|
||||
getLogger()?.handleAutorunTriggered(this);
|
||||
|
||||
try {
|
||||
const changeSummary = this.changeSummary!;
|
||||
this.changeSummary = this.createChangeSummary?.();
|
||||
this.runFn(this, changeSummary);
|
||||
if (!this.disposed) {
|
||||
getLogger()?.handleAutorunTriggered(this);
|
||||
const changeSummary = this.changeSummary!;
|
||||
this.changeSummary = this.createChangeSummary?.();
|
||||
this.runFn(this, changeSummary);
|
||||
}
|
||||
} finally {
|
||||
// We don't want our observed observables to think that they are (not even temporarily) not being observed.
|
||||
// Thus, we only unsubscribe from observables that are definitely not read anymore.
|
||||
|
||||
@@ -130,11 +130,6 @@ export interface IProductConfiguration {
|
||||
readonly ariaKey: string;
|
||||
};
|
||||
|
||||
readonly sendASmile?: {
|
||||
readonly reportIssueUrl: string;
|
||||
readonly requestFeatureUrl: string;
|
||||
};
|
||||
|
||||
readonly documentationUrl?: string;
|
||||
readonly serverDocumentationUrl?: string;
|
||||
readonly releaseNotesUrl?: string;
|
||||
@@ -144,7 +139,7 @@ export interface IProductConfiguration {
|
||||
readonly introductoryVideosUrl?: string;
|
||||
readonly tipsAndTricksUrl?: string;
|
||||
readonly newsletterSignupUrl?: string;
|
||||
readonly twitterUrl?: string;
|
||||
readonly youTubeUrl?: string;
|
||||
readonly requestFeatureUrl?: string;
|
||||
readonly reportIssueUrl?: string;
|
||||
readonly reportMarketplaceIssueUrl?: string;
|
||||
|
||||
+51
-6
@@ -6,7 +6,7 @@
|
||||
import * as fs from 'fs';
|
||||
import { tmpdir } from 'os';
|
||||
import { promisify } from 'util';
|
||||
import { ResourceQueue } from 'vs/base/common/async';
|
||||
import { ResourceQueue, timeout } from 'vs/base/common/async';
|
||||
import { isEqualOrParent, isRootOrDriveLetter, randomPath } from 'vs/base/common/extpath';
|
||||
import { normalizeNFC } from 'vs/base/common/normalization';
|
||||
import { join } from 'vs/base/common/path';
|
||||
@@ -491,16 +491,24 @@ function ensureWriteOptions(options?: IWriteFileOptions): IEnsuredWriteFileOptio
|
||||
/**
|
||||
* A drop-in replacement for `fs.rename` that:
|
||||
* - allows to move across multiple disks
|
||||
* - attempts to retry the operation for certain error codes on Windows
|
||||
*/
|
||||
async function move(source: string, target: string): Promise<void> {
|
||||
async function rename(source: string, target: string, windowsRetryTimeout: number | false = 60000 /* matches graceful-fs */): Promise<void> {
|
||||
if (source === target) {
|
||||
return; // simulate node.js behaviour here and do a no-op if paths match
|
||||
}
|
||||
|
||||
try {
|
||||
await Promises.rename(source, target);
|
||||
if (isWindows && typeof windowsRetryTimeout === 'number') {
|
||||
// On Windows, a rename can fail when either source or target
|
||||
// is locked by AV software. We do leverage graceful-fs to iron
|
||||
// out these issues, however in case the target file exists,
|
||||
// graceful-fs will immediately return without retry for fs.rename().
|
||||
await renameWithRetry(source, target, Date.now(), windowsRetryTimeout);
|
||||
} else {
|
||||
await promisify(fs.rename)(source, target);
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
// In two cases we fallback to classic copy and delete:
|
||||
//
|
||||
// 1.) The EXDEV error indicates that source and target are on different devices
|
||||
@@ -518,6 +526,44 @@ async function move(source: string, target: string): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
async function renameWithRetry(source: string, target: string, startTime: number, retryTimeout: number, attempt = 0): Promise<void> {
|
||||
try {
|
||||
return await promisify(fs.rename)(source, target);
|
||||
} catch (error) {
|
||||
if (error.code !== 'EACCES' && error.code !== 'EPERM' && error.code !== 'EBUSY') {
|
||||
throw error; // only for errors we think are temporary
|
||||
}
|
||||
|
||||
if (Date.now() - startTime >= retryTimeout) {
|
||||
console.error(`[node.js fs] rename failed after ${attempt} retries with error: ${error}`);
|
||||
|
||||
throw error; // give up after configurable timeout
|
||||
}
|
||||
|
||||
if (attempt === 0) {
|
||||
let abortRetry = false;
|
||||
try {
|
||||
const { stat } = await SymlinkSupport.stat(target);
|
||||
if (!stat.isFile()) {
|
||||
abortRetry = true; // if target is not a file, EPERM error may be raised and we should not attempt to retry
|
||||
}
|
||||
} catch (error) {
|
||||
// Ignore
|
||||
}
|
||||
|
||||
if (abortRetry) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Delay with incremental backoff up to 100ms
|
||||
await timeout(Math.min(100, attempt * 10));
|
||||
|
||||
// Attempt again
|
||||
return renameWithRetry(source, target, startTime, retryTimeout, attempt + 1);
|
||||
}
|
||||
}
|
||||
|
||||
interface ICopyPayload {
|
||||
readonly root: { source: string; target: string };
|
||||
readonly options: { preserveSymlinks: boolean };
|
||||
@@ -694,7 +740,6 @@ export const Promises = new class {
|
||||
get fdatasync() { return promisify(fs.fdatasync); }
|
||||
get truncate() { return promisify(fs.truncate); }
|
||||
|
||||
get rename() { return promisify(fs.rename); }
|
||||
get copyFile() { return promisify(fs.copyFile); }
|
||||
|
||||
get open() { return promisify(fs.open); }
|
||||
@@ -733,7 +778,7 @@ export const Promises = new class {
|
||||
|
||||
get rm() { return rimraf; }
|
||||
|
||||
get move() { return move; }
|
||||
get rename() { return rename; }
|
||||
get copy() { return copy; }
|
||||
|
||||
//#endregion
|
||||
|
||||
@@ -274,7 +274,7 @@ export class SQLiteStorageDatabase implements IStorageDatabase {
|
||||
try {
|
||||
await Promises.unlink(path);
|
||||
try {
|
||||
await Promises.rename(this.toBackupPath(path), path);
|
||||
await Promises.rename(this.toBackupPath(path), path, false /* no retry */);
|
||||
} catch (error) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
@@ -992,6 +992,29 @@ suite('observables', () => {
|
||||
'event fired',
|
||||
]);
|
||||
});
|
||||
|
||||
test('dont run autorun after dispose', () => {
|
||||
const log = new Log();
|
||||
const myObservable = new LoggingObservableValue('myObservable', 0, log);
|
||||
|
||||
const d = autorun('update', reader => {
|
||||
const v = myObservable.read(reader);
|
||||
log.log('autorun, myObservable:' + v);
|
||||
});
|
||||
|
||||
transaction(tx => {
|
||||
myObservable.set(1, tx);
|
||||
d.dispose();
|
||||
});
|
||||
|
||||
assert.deepStrictEqual(log.getAndClearEntries(), [
|
||||
'myObservable.firstObserverAdded',
|
||||
'myObservable.get',
|
||||
'autorun, myObservable:0',
|
||||
'myObservable.set (value 1)',
|
||||
'myObservable.lastObserverRemoved',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
export class LoggingObserver implements IObserver {
|
||||
|
||||
@@ -173,7 +173,7 @@ flakySuite('PFS', function () {
|
||||
assert.ok(!fs.existsSync(testDir));
|
||||
});
|
||||
|
||||
test('copy, move and delete', async () => {
|
||||
test('copy, rename and delete', async () => {
|
||||
const sourceDir = FileAccess.asFileUri('vs/base/test/node/pfs/fixtures').fsPath;
|
||||
const parentDir = join(tmpdir(), 'vsctests', 'pfs');
|
||||
const targetDir = randomPath(parentDir);
|
||||
@@ -188,7 +188,7 @@ flakySuite('PFS', function () {
|
||||
assert.ok(fs.statSync(join(targetDir, 'examples')).isDirectory());
|
||||
assert.ok(fs.existsSync(join(targetDir, 'examples', 'small.jxs')));
|
||||
|
||||
await Promises.move(targetDir, targetDir2);
|
||||
await Promises.rename(targetDir, targetDir2);
|
||||
|
||||
assert.ok(!fs.existsSync(targetDir));
|
||||
assert.ok(fs.existsSync(targetDir2));
|
||||
@@ -198,7 +198,34 @@ flakySuite('PFS', function () {
|
||||
assert.ok(fs.statSync(join(targetDir2, 'examples')).isDirectory());
|
||||
assert.ok(fs.existsSync(join(targetDir2, 'examples', 'small.jxs')));
|
||||
|
||||
await Promises.move(join(targetDir2, 'index.html'), join(targetDir2, 'index_moved.html'));
|
||||
await Promises.rename(join(targetDir2, 'index.html'), join(targetDir2, 'index_moved.html'));
|
||||
|
||||
assert.ok(!fs.existsSync(join(targetDir2, 'index.html')));
|
||||
assert.ok(fs.existsSync(join(targetDir2, 'index_moved.html')));
|
||||
|
||||
await Promises.rm(parentDir);
|
||||
|
||||
assert.ok(!fs.existsSync(parentDir));
|
||||
});
|
||||
|
||||
test('rename without retry', async () => {
|
||||
const sourceDir = FileAccess.asFileUri('vs/base/test/node/pfs/fixtures').fsPath;
|
||||
const parentDir = join(tmpdir(), 'vsctests', 'pfs');
|
||||
const targetDir = randomPath(parentDir);
|
||||
const targetDir2 = randomPath(parentDir);
|
||||
|
||||
await Promises.copy(sourceDir, targetDir, { preserveSymlinks: true });
|
||||
await Promises.rename(targetDir, targetDir2, false);
|
||||
|
||||
assert.ok(!fs.existsSync(targetDir));
|
||||
assert.ok(fs.existsSync(targetDir2));
|
||||
assert.ok(fs.existsSync(join(targetDir2, 'index.html')));
|
||||
assert.ok(fs.existsSync(join(targetDir2, 'site.css')));
|
||||
assert.ok(fs.existsSync(join(targetDir2, 'examples')));
|
||||
assert.ok(fs.statSync(join(targetDir2, 'examples')).isDirectory());
|
||||
assert.ok(fs.existsSync(join(targetDir2, 'examples', 'small.jxs')));
|
||||
|
||||
await Promises.rename(join(targetDir2, 'index.html'), join(targetDir2, 'index_moved.html'), false);
|
||||
|
||||
assert.ok(!fs.existsSync(join(targetDir2, 'index.html')));
|
||||
assert.ok(fs.existsSync(join(targetDir2, 'index_moved.html')));
|
||||
|
||||
@@ -90,9 +90,30 @@ export function findFocusedDiffEditor(accessor: ServicesAccessor): IDiffEditor |
|
||||
return diffEditor;
|
||||
}
|
||||
}
|
||||
|
||||
if (document.activeElement) {
|
||||
for (const d of diffEditors) {
|
||||
const container = d.getContainerDomNode();
|
||||
if (isElementOrParentOf(container, document.activeElement)) {
|
||||
return d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function isElementOrParentOf(elementOrParent: Element, element: Element): boolean {
|
||||
let e: Element | null = element;
|
||||
while (e) {
|
||||
if (e === elementOrParent) {
|
||||
return true;
|
||||
}
|
||||
e = e.parentElement;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
CommandsRegistry.registerCommandAlias('editor.action.diffReview.next', AccessibleDiffViewerNext.id);
|
||||
registerAction2(AccessibleDiffViewerNext);
|
||||
|
||||
|
||||
@@ -63,14 +63,14 @@ function executeAction(instantiationService: IInstantiationService, editor: ICod
|
||||
});
|
||||
}
|
||||
|
||||
suite('FindController', async () => {
|
||||
suite('FindController', () => {
|
||||
const queryState: { [key: string]: any } = {};
|
||||
let clipboardState = '';
|
||||
const serviceCollection = new ServiceCollection();
|
||||
serviceCollection.set(IStorageService, {
|
||||
_serviceBrand: undefined,
|
||||
onDidChangeTarget: Event.None,
|
||||
onDidChangeValue: Event.None,
|
||||
onDidChangeValue: () => Event.None,
|
||||
onWillSaveState: Event.None,
|
||||
get: (key: string) => queryState[key],
|
||||
getBoolean: (key: string) => !!queryState[key],
|
||||
@@ -495,7 +495,7 @@ suite('FindController', async () => {
|
||||
});
|
||||
});
|
||||
|
||||
suite('FindController query options persistence', async () => {
|
||||
suite('FindController query options persistence', () => {
|
||||
let queryState: { [key: string]: any } = {};
|
||||
queryState['editor.isRegex'] = false;
|
||||
queryState['editor.matchCase'] = false;
|
||||
@@ -504,7 +504,7 @@ suite('FindController query options persistence', async () => {
|
||||
serviceCollection.set(IStorageService, {
|
||||
_serviceBrand: undefined,
|
||||
onDidChangeTarget: Event.None,
|
||||
onDidChangeValue: Event.None,
|
||||
onDidChangeValue: () => Event.None,
|
||||
onWillSaveState: Event.None,
|
||||
get: (key: string) => queryState[key],
|
||||
getBoolean: (key: string) => !!queryState[key],
|
||||
|
||||
@@ -86,7 +86,8 @@ suite('Multicursor selection', () => {
|
||||
const serviceCollection = new ServiceCollection();
|
||||
serviceCollection.set(IStorageService, {
|
||||
_serviceBrand: undefined,
|
||||
onDidChangeValue: Event.None,
|
||||
onDidChangeValue: () => { throw new Error(); },
|
||||
onDidChangeValue2: Event.None,
|
||||
onDidChangeTarget: Event.None,
|
||||
onWillSaveState: Event.None,
|
||||
get: (key: string) => queryState[key],
|
||||
|
||||
@@ -58,10 +58,7 @@ class PersistedMenuHideState {
|
||||
this._data = Object.create(null);
|
||||
}
|
||||
|
||||
this._disposables.add(_storageService.onDidChangeValue(e => {
|
||||
if (e.key !== PersistedMenuHideState._key) {
|
||||
return;
|
||||
}
|
||||
this._disposables.add(_storageService.onDidChangeValue(StorageScope.PROFILE, PersistedMenuHideState._key, this._disposables)(() => {
|
||||
if (!this._ignoreChangeEvent) {
|
||||
try {
|
||||
const raw = _storageService.get(PersistedMenuHideState._key, StorageScope.PROFILE, '{}');
|
||||
|
||||
@@ -130,7 +130,7 @@ export class BackupMainService implements IBackupMainService {
|
||||
// When we have data to migrate from, move it over to the target location
|
||||
if (await Promises.exists(moveFromPath)) {
|
||||
try {
|
||||
await Promises.rename(moveFromPath, backupPath);
|
||||
await Promises.rename(moveFromPath, backupPath, false /* no retry */);
|
||||
} catch (error) {
|
||||
this.logService.error(`Backup: Could not move backup folder to new location: ${error.toString()}`);
|
||||
}
|
||||
@@ -285,7 +285,7 @@ export class BackupMainService implements IBackupMainService {
|
||||
// Rename backupPath to new empty window backup path
|
||||
const newEmptyWindowBackupPath = join(this.backupHome, newEmptyWindowBackupInfo.backupFolder);
|
||||
try {
|
||||
await Promises.rename(backupPath, newEmptyWindowBackupPath);
|
||||
await Promises.rename(backupPath, newEmptyWindowBackupPath, false /* no retry */);
|
||||
} catch (error) {
|
||||
this.logService.error(`Backup: Could not rename backup folder: ${error.toString()}`);
|
||||
return false;
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
import { DISABLED_EXTENSIONS_STORAGE_PATH, IExtensionIdentifier, IExtensionManagementService, IGlobalExtensionEnablementService, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { IStorageService, IStorageValueChangeEvent, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { IProfileStorageValueChangeEvent, IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
|
||||
export class GlobalExtensionEnablementService extends Disposable implements IGlobalExtensionEnablementService {
|
||||
|
||||
@@ -102,7 +102,7 @@ export class StorageManager extends Disposable {
|
||||
|
||||
constructor(private storageService: IStorageService) {
|
||||
super();
|
||||
this._register(storageService.onDidChangeValue(e => this.onDidStorageChange(e)));
|
||||
this._register(storageService.onDidChangeValue(StorageScope.PROFILE, undefined, this._register(new DisposableStore()))(e => this.onDidStorageChange(e)));
|
||||
}
|
||||
|
||||
get(key: string, scope: StorageScope): IExtensionIdentifier[] {
|
||||
@@ -133,19 +133,17 @@ export class StorageManager extends Disposable {
|
||||
}
|
||||
}
|
||||
|
||||
private onDidStorageChange(storageChangeEvent: IStorageValueChangeEvent): void {
|
||||
if (storageChangeEvent.scope === StorageScope.PROFILE) {
|
||||
if (!isUndefinedOrNull(this.storage[storageChangeEvent.key])) {
|
||||
const newValue = this._get(storageChangeEvent.key, storageChangeEvent.scope);
|
||||
if (newValue !== this.storage[storageChangeEvent.key]) {
|
||||
const oldValues = this.get(storageChangeEvent.key, storageChangeEvent.scope);
|
||||
delete this.storage[storageChangeEvent.key];
|
||||
const newValues = this.get(storageChangeEvent.key, storageChangeEvent.scope);
|
||||
const added = oldValues.filter(oldValue => !newValues.some(newValue => areSameExtensions(oldValue, newValue)));
|
||||
const removed = newValues.filter(newValue => !oldValues.some(oldValue => areSameExtensions(oldValue, newValue)));
|
||||
if (added.length || removed.length) {
|
||||
this._onDidChange.fire([...added, ...removed]);
|
||||
}
|
||||
private onDidStorageChange(storageChangeEvent: IProfileStorageValueChangeEvent): void {
|
||||
if (!isUndefinedOrNull(this.storage[storageChangeEvent.key])) {
|
||||
const newValue = this._get(storageChangeEvent.key, storageChangeEvent.scope);
|
||||
if (newValue !== this.storage[storageChangeEvent.key]) {
|
||||
const oldValues = this.get(storageChangeEvent.key, storageChangeEvent.scope);
|
||||
delete this.storage[storageChangeEvent.key];
|
||||
const newValues = this.get(storageChangeEvent.key, storageChangeEvent.scope);
|
||||
const added = oldValues.filter(oldValue => !newValues.some(newValue => areSameExtensions(oldValue, newValue)));
|
||||
const removed = newValues.filter(newValue => !oldValues.some(oldValue => areSameExtensions(oldValue, newValue)));
|
||||
if (added.length || removed.length) {
|
||||
this._onDidChange.fire([...added, ...removed]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IStorageService, IStorageValueChangeEvent, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IProfileStorageValueChangeEvent, IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { adoptToGalleryExtensionId, areSameExtensions, getExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { distinct } from 'vs/base/common/arrays';
|
||||
@@ -103,13 +103,10 @@ export class ExtensionStorageService extends Disposable implements IExtensionSto
|
||||
) {
|
||||
super();
|
||||
this.extensionsWithKeysForSync = ExtensionStorageService.readAllExtensionsWithKeysForSync(storageService);
|
||||
this._register(this.storageService.onDidChangeValue(e => this.onDidChangeStorageValue(e)));
|
||||
this._register(this.storageService.onDidChangeValue(StorageScope.PROFILE, undefined, this._register(new DisposableStore()))(e => this.onDidChangeStorageValue(e)));
|
||||
}
|
||||
|
||||
private onDidChangeStorageValue(e: IStorageValueChangeEvent): void {
|
||||
if (e.scope !== StorageScope.PROFILE) {
|
||||
return;
|
||||
}
|
||||
private onDidChangeStorageValue(e: IProfileStorageValueChangeEvent): void {
|
||||
|
||||
// State of extension with keys for sync has changed
|
||||
if (this.extensionsWithKeysForSync.has(e.key.toLowerCase())) {
|
||||
|
||||
@@ -7,7 +7,6 @@ import { Promises } from 'vs/base/common/async';
|
||||
import { getErrorMessage } from 'vs/base/common/errors';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
import { joinPath } from 'vs/base/common/resources';
|
||||
import * as semver from 'vs/base/common/semver/semver';
|
||||
import { isBoolean } from 'vs/base/common/types';
|
||||
@@ -129,7 +128,7 @@ export class ExtensionsDownloader extends Disposable {
|
||||
|
||||
try {
|
||||
// Rename temp location to original
|
||||
await this.rename(tempLocation, location, Date.now() + (2 * 60 * 1000) /* Retry for 2 minutes */);
|
||||
await FSPromises.rename(tempLocation.fsPath, location.fsPath, 2 * 60 * 1000 /* Retry for 2 minutes */);
|
||||
} catch (error) {
|
||||
try {
|
||||
await this.fileService.del(tempLocation);
|
||||
@@ -148,18 +147,6 @@ export class ExtensionsDownloader extends Disposable {
|
||||
await this.fileService.del(location);
|
||||
}
|
||||
|
||||
private async rename(from: URI, to: URI, retryUntil: number): Promise<void> {
|
||||
try {
|
||||
await FSPromises.rename(from.fsPath, to.fsPath);
|
||||
} catch (error) {
|
||||
if (isWindows && error && error.code === 'EPERM' && Date.now() < retryUntil) {
|
||||
this.logService.info(`Failed renaming ${from} to ${to} with 'EPERM' error. Trying again...`);
|
||||
return this.rename(from, to, retryUntil);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
private async cleanUp(): Promise<void> {
|
||||
try {
|
||||
if (!(await this.fileService.exists(this.extensionsDownloadDir))) {
|
||||
|
||||
@@ -15,7 +15,6 @@ import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ResourceSet } from 'vs/base/common/map';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import * as path from 'vs/base/common/path';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
import { joinPath } from 'vs/base/common/resources';
|
||||
import * as semver from 'vs/base/common/semver/semver';
|
||||
import { isBoolean, isUndefined } from 'vs/base/common/types';
|
||||
@@ -508,7 +507,7 @@ export class ExtensionsScanner extends Disposable {
|
||||
// Rename
|
||||
try {
|
||||
this.logService.trace(`Started renaming the extension from ${tempLocation.fsPath} to ${extensionLocation.fsPath}`);
|
||||
await this.rename(extensionKey, tempLocation.fsPath, extensionLocation.fsPath, Date.now() + (2 * 60 * 1000) /* Retry for 2 minutes */);
|
||||
await this.rename(tempLocation.fsPath, extensionLocation.fsPath);
|
||||
this.logService.info('Renamed to', extensionLocation.fsPath);
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOTEMPTY') {
|
||||
@@ -606,7 +605,7 @@ export class ExtensionsScanner extends Disposable {
|
||||
private async deleteExtensionFromLocation(id: string, location: URI, type: string): Promise<void> {
|
||||
this.logService.trace(`Deleting ${type} extension from disk`, id, location.fsPath);
|
||||
const renamedLocation = this.uriIdentityService.extUri.joinPath(this.uriIdentityService.extUri.dirname(location), `${this.uriIdentityService.extUri.basename(location)}.${hash(generateUuid()).toString(16)}${DELETED_FOLDER_POSTFIX}`);
|
||||
await this.rename({ id }, location.fsPath, renamedLocation.fsPath, Date.now() + (2 * 60 * 1000) /* Retry for 2 minutes */);
|
||||
await this.rename(location.fsPath, renamedLocation.fsPath);
|
||||
await this.fileService.del(renamedLocation, { recursive: true });
|
||||
this.logService.info(`Deleted ${type} extension from disk`, id, location.fsPath);
|
||||
}
|
||||
@@ -643,14 +642,10 @@ export class ExtensionsScanner extends Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
private async rename(identifier: IExtensionIdentifier, extractPath: string, renamePath: string, retryUntil: number): Promise<void> {
|
||||
private async rename(extractPath: string, renamePath: string): Promise<void> {
|
||||
try {
|
||||
await pfs.Promises.rename(extractPath, renamePath);
|
||||
await pfs.Promises.rename(extractPath, renamePath, 2 * 60 * 1000 /* Retry for 2 minutes */);
|
||||
} catch (error) {
|
||||
if (isWindows && error && error.code === 'EPERM' && Date.now() < retryUntil) {
|
||||
this.logService.info(`Failed renaming ${extractPath} to ${renamePath} with 'EPERM' error. Trying again...`, identifier.id);
|
||||
return this.rename(identifier, extractPath, renamePath, retryUntil);
|
||||
}
|
||||
throw new ExtensionManagementError(error.message || nls.localize('renameError', "Unknown error while renaming {0} to {1}", extractPath, renamePath), error.code || ExtensionManagementErrorCode.Rename);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -640,8 +640,8 @@ export class DiskFileSystemProvider extends AbstractDiskFileSystemProvider imple
|
||||
// Validate the move operation can perform
|
||||
await this.validateMoveCopy(from, to, 'move', opts.overwrite);
|
||||
|
||||
// Move
|
||||
await Promises.move(fromFilePath, toFilePath);
|
||||
// Rename
|
||||
await Promises.rename(fromFilePath, toFilePath);
|
||||
} catch (error) {
|
||||
|
||||
// Rewrite some typical errors that can happen especially around symlinks
|
||||
|
||||
@@ -252,7 +252,7 @@ import { FileAccess } from 'vs/base/common/network';
|
||||
|
||||
// Move file
|
||||
changeFuture = awaitEvent(watcher, filePath, FileChangeType.DELETED);
|
||||
await Promises.move(filePath, `${filePath}-moved`);
|
||||
await Promises.rename(filePath, `${filePath}-moved`);
|
||||
await changeFuture;
|
||||
});
|
||||
|
||||
|
||||
@@ -125,9 +125,9 @@ export class Menubar {
|
||||
this.fallbackMenuHandlers['workbench.action.clearRecentFiles'] = () => this.workspacesHistoryMainService.clearRecentlyOpened();
|
||||
|
||||
// Help Menu Items
|
||||
const twitterUrl = this.productService.twitterUrl;
|
||||
if (twitterUrl) {
|
||||
this.fallbackMenuHandlers['workbench.action.openTwitterUrl'] = () => this.openUrl(twitterUrl, 'openTwitterUrl');
|
||||
const youTubeUrl = this.productService.youTubeUrl;
|
||||
if (youTubeUrl) {
|
||||
this.fallbackMenuHandlers['workbench.action.openYouTubeUrl'] = () => this.openUrl(youTubeUrl, 'openYouTubeUrl');
|
||||
}
|
||||
|
||||
const requestFeatureUrl = this.productService.requestFeatureUrl;
|
||||
|
||||
@@ -58,7 +58,7 @@ else {
|
||||
// Running out of sources
|
||||
if (Object.keys(product).length === 0) {
|
||||
Object.assign(product, {
|
||||
version: '1.80.0-dev',
|
||||
version: '1.82.0-dev',
|
||||
nameShort: 'Code - OSS Dev',
|
||||
nameLong: 'Code - OSS Dev',
|
||||
applicationName: 'code-oss',
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as os from 'os';
|
||||
import * as cp from 'child_process';
|
||||
import { promises as fs } from 'fs';
|
||||
import { Promises } from 'vs/base/node/pfs';
|
||||
import * as path from 'path';
|
||||
|
||||
let hasWSLFeaturePromise: Promise<boolean> | undefined;
|
||||
@@ -33,7 +33,7 @@ async function testWSLFeatureInstalled(): Promise<boolean> {
|
||||
const dllPath = getLxssManagerDllPath();
|
||||
if (dllPath) {
|
||||
try {
|
||||
if ((await fs.stat(dllPath)).isFile()) {
|
||||
if ((await Promises.stat(dllPath)).isFile()) {
|
||||
return true;
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'
|
||||
import { IStorageService, InMemoryStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
|
||||
export const ISecretStorageService = createDecorator<ISecretStorageService>('secretStorageService');
|
||||
|
||||
@@ -38,7 +38,7 @@ export abstract class BaseSecretStorageService implements ISecretStorageService
|
||||
|
||||
private _type: 'in-memory' | 'persisted' | 'unknown' = 'unknown';
|
||||
|
||||
private _onDidChangeValueDisposable: IDisposable | undefined;
|
||||
private readonly _onDidChangeValueDisposable = new DisposableStore();
|
||||
|
||||
constructor(
|
||||
@IStorageService private _storageService: IStorageService,
|
||||
@@ -127,15 +127,10 @@ export abstract class BaseSecretStorageService implements ISecretStorageService
|
||||
storageService = new InMemoryStorageService();
|
||||
}
|
||||
|
||||
this._onDidChangeValueDisposable?.dispose();
|
||||
this._onDidChangeValueDisposable = storageService.onDidChangeValue(e => {
|
||||
// We only care about changes to the application scope since SecretStorage
|
||||
// only stores secrets in the application scope but this seems to fire
|
||||
// 2 events. Once for APP scope and once for PROFILE scope. ref #188460
|
||||
if (e.scope === StorageScope.APPLICATION) {
|
||||
this.onDidChangeValue(e.key);
|
||||
}
|
||||
});
|
||||
this._onDidChangeValueDisposable.clear();
|
||||
this._onDidChangeValueDisposable.add(storageService.onDidChangeValue(StorageScope.APPLICATION, undefined, this._onDidChangeValueDisposable)(e => {
|
||||
this.onDidChangeValue(e.key);
|
||||
}));
|
||||
return storageService;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { Promises, RunOnceScheduler, runWhenIdle } from 'vs/base/common/async';
|
||||
import { Emitter, Event, PauseableEmitter } from 'vs/base/common/event';
|
||||
import { Disposable, dispose, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore, dispose, MutableDisposable } from 'vs/base/common/lifecycle';
|
||||
import { mark } from 'vs/base/common/performance';
|
||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||
import { InMemoryStorageDatabase, IStorage, IStorageChangeEvent, Storage, StorageHint, StorageValue } from 'vs/base/parts/storage/common/storage';
|
||||
@@ -42,14 +42,34 @@ export interface IStorageEntry {
|
||||
readonly target: StorageTarget;
|
||||
}
|
||||
|
||||
export interface IWorkspaceStorageValueChangeEvent extends IStorageValueChangeEvent {
|
||||
readonly scope: StorageScope.WORKSPACE;
|
||||
}
|
||||
|
||||
export interface IProfileStorageValueChangeEvent extends IStorageValueChangeEvent {
|
||||
readonly scope: StorageScope.PROFILE;
|
||||
}
|
||||
|
||||
export interface IApplicationStorageValueChangeEvent extends IStorageValueChangeEvent {
|
||||
readonly scope: StorageScope.APPLICATION;
|
||||
}
|
||||
|
||||
export interface IStorageService {
|
||||
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
/**
|
||||
* Emitted whenever data is updated or deleted.
|
||||
* Emitted whenever data is updated or deleted on the given
|
||||
* scope and optional key.
|
||||
*
|
||||
* @param scope the `StorageScope` to listen to changes
|
||||
* @param key the optional key to filter for or all keys of
|
||||
* the scope if `undefined`
|
||||
*/
|
||||
readonly onDidChangeValue: Event<IStorageValueChangeEvent>;
|
||||
onDidChangeValue(scope: StorageScope.WORKSPACE, key: string | undefined, disposable: DisposableStore): Event<IWorkspaceStorageValueChangeEvent>;
|
||||
onDidChangeValue(scope: StorageScope.PROFILE, key: string | undefined, disposable: DisposableStore): Event<IProfileStorageValueChangeEvent>;
|
||||
onDidChangeValue(scope: StorageScope.APPLICATION, key: string | undefined, disposable: DisposableStore): Event<IApplicationStorageValueChangeEvent>;
|
||||
onDidChangeValue(scope: StorageScope, key: string | undefined, disposable: DisposableStore): Event<IStorageValueChangeEvent>;
|
||||
|
||||
/**
|
||||
* Emitted whenever target of a storage entry changes.
|
||||
@@ -294,7 +314,6 @@ export abstract class AbstractStorageService extends Disposable implements IStor
|
||||
private static DEFAULT_FLUSH_INTERVAL = 60 * 1000; // every minute
|
||||
|
||||
private readonly _onDidChangeValue = this._register(new PauseableEmitter<IStorageValueChangeEvent>());
|
||||
readonly onDidChangeValue = this._onDidChangeValue.event;
|
||||
|
||||
private readonly _onDidChangeTarget = this._register(new PauseableEmitter<IStorageTargetChangeEvent>());
|
||||
readonly onDidChangeTarget = this._onDidChangeTarget.event;
|
||||
@@ -311,6 +330,13 @@ export abstract class AbstractStorageService extends Disposable implements IStor
|
||||
super();
|
||||
}
|
||||
|
||||
onDidChangeValue(scope: StorageScope.WORKSPACE, key: string | undefined, disposable: DisposableStore): Event<IWorkspaceStorageValueChangeEvent>;
|
||||
onDidChangeValue(scope: StorageScope.PROFILE, key: string | undefined, disposable: DisposableStore): Event<IProfileStorageValueChangeEvent>;
|
||||
onDidChangeValue(scope: StorageScope.APPLICATION, key: string | undefined, disposable: DisposableStore): Event<IApplicationStorageValueChangeEvent>;
|
||||
onDidChangeValue(scope: StorageScope, key: string | undefined, disposable: DisposableStore): Event<IStorageValueChangeEvent> {
|
||||
return Event.filter(this._onDidChangeValue.event, e => e.scope === scope && (key === undefined || e.key === key), disposable);
|
||||
}
|
||||
|
||||
private doFlushWhenIdle(): void {
|
||||
this.runFlushWhenIdle.value = runWhenIdle(() => {
|
||||
if (this.shouldFlushWhenIdle()) {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { deepStrictEqual, ok, strictEqual } from 'assert';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { InMemoryStorageService, IStorageService, IStorageTargetChangeEvent, IStorageValueChangeEvent, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
|
||||
export function createSuite<T extends IStorageService>(params: { setup: () => Promise<T>; teardown: (service: T) => Promise<void> }): void {
|
||||
@@ -32,7 +33,7 @@ export function createSuite<T extends IStorageService>(params: { setup: () => Pr
|
||||
|
||||
test('Storage change source', () => {
|
||||
const storageValueChangeEvents: IStorageValueChangeEvent[] = [];
|
||||
storageService.onDidChangeValue(e => storageValueChangeEvents.push(e));
|
||||
storageService.onDidChangeValue(StorageScope.WORKSPACE, undefined, new DisposableStore())(e => storageValueChangeEvents.push(e));
|
||||
|
||||
// Explicit external source
|
||||
storageService.storeAll([{ key: 'testExternalChange', value: 'foobar', scope: StorageScope.WORKSPACE, target: StorageTarget.MACHINE }], true);
|
||||
@@ -49,9 +50,34 @@ export function createSuite<T extends IStorageService>(params: { setup: () => Pr
|
||||
strictEqual(storageValueChangeEvent?.external, false);
|
||||
});
|
||||
|
||||
test('Storage change event scope (all keys)', () => {
|
||||
const storageValueChangeEvents: IStorageValueChangeEvent[] = [];
|
||||
storageService.onDidChangeValue(StorageScope.WORKSPACE, undefined, new DisposableStore())(e => storageValueChangeEvents.push(e));
|
||||
|
||||
storageService.store('testChange', 'foobar', StorageScope.WORKSPACE, StorageTarget.MACHINE);
|
||||
storageService.store('testChange2', 'foobar', StorageScope.WORKSPACE, StorageTarget.MACHINE);
|
||||
storageService.store('testChange', 'foobar', StorageScope.APPLICATION, StorageTarget.MACHINE);
|
||||
storageService.store('testChange', 'foobar', StorageScope.PROFILE, StorageTarget.MACHINE);
|
||||
storageService.store('testChange2', 'foobar', StorageScope.PROFILE, StorageTarget.MACHINE);
|
||||
strictEqual(storageValueChangeEvents.length, 2);
|
||||
});
|
||||
|
||||
test('Storage change event scope (specific key)', () => {
|
||||
const storageValueChangeEvents: IStorageValueChangeEvent[] = [];
|
||||
storageService.onDidChangeValue(StorageScope.WORKSPACE, 'testChange', new DisposableStore())(e => storageValueChangeEvents.push(e));
|
||||
|
||||
storageService.store('testChange', 'foobar', StorageScope.WORKSPACE, StorageTarget.MACHINE);
|
||||
storageService.store('testChange', 'foobar', StorageScope.PROFILE, StorageTarget.USER);
|
||||
storageService.store('testChange', 'foobar', StorageScope.APPLICATION, StorageTarget.MACHINE);
|
||||
storageService.store('testChange2', 'foobar', StorageScope.WORKSPACE, StorageTarget.MACHINE);
|
||||
const storageValueChangeEvent = storageValueChangeEvents.find(e => e.key === 'testChange');
|
||||
ok(storageValueChangeEvent);
|
||||
strictEqual(storageValueChangeEvents.length, 1);
|
||||
});
|
||||
|
||||
function storeData(scope: StorageScope): void {
|
||||
let storageValueChangeEvents: IStorageValueChangeEvent[] = [];
|
||||
storageService.onDidChangeValue(e => storageValueChangeEvents.push(e));
|
||||
storageService.onDidChangeValue(scope, undefined, new DisposableStore())(e => storageValueChangeEvents.push(e));
|
||||
|
||||
strictEqual(storageService.get('test.get', scope, 'foobar'), 'foobar');
|
||||
strictEqual(storageService.get('test.get', scope, ''), '');
|
||||
@@ -127,7 +153,7 @@ export function createSuite<T extends IStorageService>(params: { setup: () => Pr
|
||||
|
||||
function removeData(scope: StorageScope): void {
|
||||
const storageValueChangeEvents: IStorageValueChangeEvent[] = [];
|
||||
storageService.onDidChangeValue(e => storageValueChangeEvents.push(e));
|
||||
storageService.onDidChangeValue(scope, undefined, new DisposableStore())(e => storageValueChangeEvents.push(e));
|
||||
|
||||
storageService.store('test.remove', 'foobar', scope, StorageTarget.MACHINE);
|
||||
strictEqual('foobar', storageService.get('test.remove', scope, (undefined)!));
|
||||
@@ -143,9 +169,6 @@ export function createSuite<T extends IStorageService>(params: { setup: () => Pr
|
||||
let storageTargetEvent: IStorageTargetChangeEvent | undefined = undefined;
|
||||
storageService.onDidChangeTarget(e => storageTargetEvent = e);
|
||||
|
||||
let storageValueChangeEvent: IStorageValueChangeEvent | undefined = undefined;
|
||||
storageService.onDidChangeValue(e => storageValueChangeEvent = e);
|
||||
|
||||
// Empty
|
||||
for (const scope of [StorageScope.WORKSPACE, StorageScope.PROFILE, StorageScope.APPLICATION]) {
|
||||
for (const target of [StorageTarget.MACHINE, StorageTarget.USER]) {
|
||||
@@ -153,8 +176,12 @@ export function createSuite<T extends IStorageService>(params: { setup: () => Pr
|
||||
}
|
||||
}
|
||||
|
||||
let storageValueChangeEvent: IStorageValueChangeEvent | undefined = undefined;
|
||||
|
||||
// Add values
|
||||
for (const scope of [StorageScope.WORKSPACE, StorageScope.PROFILE, StorageScope.APPLICATION]) {
|
||||
storageService.onDidChangeValue(scope, undefined, new DisposableStore())(e => storageValueChangeEvent = e);
|
||||
|
||||
for (const target of [StorageTarget.MACHINE, StorageTarget.USER]) {
|
||||
storageTargetEvent = Object.create(null);
|
||||
storageValueChangeEvent = Object.create(null);
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { exec } from 'child_process';
|
||||
import { promises as fs } from 'fs';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
@@ -213,9 +212,9 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
|
||||
}
|
||||
if (injection.filesToCopy) {
|
||||
for (const f of injection.filesToCopy) {
|
||||
await fs.mkdir(path.dirname(f.dest), { recursive: true });
|
||||
await Promises.mkdir(path.dirname(f.dest), { recursive: true });
|
||||
try {
|
||||
await fs.copyFile(f.source, f.dest);
|
||||
await Promises.copyFile(f.source, f.dest);
|
||||
} catch {
|
||||
// Swallow error, this should only happen when multiple users are on the same
|
||||
// machine. Since the shell integration scripts rarely change, plus the other user
|
||||
|
||||
@@ -137,7 +137,7 @@ export class Win32UpdateService extends AbstractUpdateService {
|
||||
return this.requestService.request({ url }, CancellationToken.None)
|
||||
.then(context => this.fileService.writeFile(URI.file(downloadPath), context.stream))
|
||||
.then(hash ? () => checksum(downloadPath, update.hash) : () => undefined)
|
||||
.then(() => pfs.Promises.rename(downloadPath, updatePackagePath))
|
||||
.then(() => pfs.Promises.rename(downloadPath, updatePackagePath, false /* no retry */))
|
||||
.then(() => updatePackagePath);
|
||||
});
|
||||
}).then(packagePath => {
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IStorageService, IStorageValueChangeEvent, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { IApplicationStorageValueChangeEvent, IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ALL_SYNC_RESOURCES, getEnablementKey, IUserDataSyncEnablementService, IUserDataSyncStoreManagementService, SyncResource } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
|
||||
@@ -36,7 +36,7 @@ export class UserDataSyncEnablementService extends Disposable implements IUserDa
|
||||
@IUserDataSyncStoreManagementService private readonly userDataSyncStoreManagementService: IUserDataSyncStoreManagementService,
|
||||
) {
|
||||
super();
|
||||
this._register(storageService.onDidChangeValue(e => this.onDidStorageChange(e)));
|
||||
this._register(storageService.onDidChangeValue(StorageScope.APPLICATION, undefined, this._register(new DisposableStore()))(e => this.onDidStorageChange(e)));
|
||||
}
|
||||
|
||||
isEnabled(): boolean {
|
||||
@@ -80,11 +80,7 @@ export class UserDataSyncEnablementService extends Disposable implements IUserDa
|
||||
this.storageService.store(resourceEnablementKey, enabled, StorageScope.APPLICATION, isWeb ? StorageTarget.USER /* sync in web */ : StorageTarget.MACHINE);
|
||||
}
|
||||
|
||||
private onDidStorageChange(storageChangeEvent: IStorageValueChangeEvent): void {
|
||||
if (storageChangeEvent.scope !== StorageScope.APPLICATION) {
|
||||
return;
|
||||
}
|
||||
|
||||
private onDidStorageChange(storageChangeEvent: IApplicationStorageValueChangeEvent): void {
|
||||
if (enablementKey === storageChangeEvent.key) {
|
||||
this._onDidChangeEnablement.fire(this.isEnabled());
|
||||
return;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { CancelablePromise, createCancelablePromise, timeout } from 'vs/base/com
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { getErrorMessage, isCancellationError } from 'vs/base/common/errors';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Mimes } from 'vs/base/common/mime';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
import { ConfigurationSyncStore } from 'vs/base/common/product';
|
||||
@@ -58,7 +58,8 @@ export abstract class AbstractUserDataSyncStoreManagementService extends Disposa
|
||||
) {
|
||||
super();
|
||||
this.updateUserDataSyncStore();
|
||||
this._register(Event.filter(storageService.onDidChangeValue, e => e.key === SYNC_SERVICE_URL_TYPE && e.scope === StorageScope.APPLICATION && this.userDataSyncStoreType !== this.userDataSyncStore?.type)(() => this.updateUserDataSyncStore()));
|
||||
const disposable = this._register(new DisposableStore());
|
||||
this._register(Event.filter(storageService.onDidChangeValue(StorageScope.APPLICATION, SYNC_SERVICE_URL_TYPE, disposable), () => this.userDataSyncStoreType !== this.userDataSyncStore?.type, disposable)(() => this.updateUserDataSyncStore()));
|
||||
}
|
||||
|
||||
protected updateUserDataSyncStore(): void {
|
||||
|
||||
@@ -273,6 +273,7 @@ export interface IWindowConfiguration {
|
||||
export interface IOSConfiguration {
|
||||
readonly release: string;
|
||||
readonly hostname: string;
|
||||
readonly arch: string;
|
||||
}
|
||||
|
||||
export interface INativeWindowConfiguration extends IWindowConfiguration, NativeParsedArgs, ISandboxConfiguration {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { app, BrowserWindow, WebContents, shell } from 'electron';
|
||||
import { Promises } from 'vs/base/node/pfs';
|
||||
import { addUNCHostToAllowlist } from 'vs/base/node/unc';
|
||||
import { hostname, release } from 'os';
|
||||
import { hostname, release, arch } from 'os';
|
||||
import { coalesce, distinct, firstOrDefault } from 'vs/base/common/arrays';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { CharCode } from 'vs/base/common/charCode';
|
||||
@@ -1424,7 +1424,7 @@ export class WindowsMainService extends Disposable implements IWindowsMainServic
|
||||
product,
|
||||
isInitialStartup: options.initialStartup,
|
||||
perfMarks: getMarks(),
|
||||
os: { release: release(), hostname: hostname() },
|
||||
os: { release: release(), hostname: hostname(), arch: arch() },
|
||||
zoomLevel: typeof windowConfig?.zoomLevel === 'number' ? windowConfig.zoomLevel : undefined,
|
||||
|
||||
autoDetectHighContrast: windowConfig?.autoDetectHighContrast ?? true,
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { promises as fsp, createReadStream } from 'fs';
|
||||
import { createReadStream } from 'fs';
|
||||
import { Promises } from 'vs/base/node/pfs';
|
||||
import * as path from 'path';
|
||||
import * as http from 'http';
|
||||
import * as url from 'url';
|
||||
@@ -55,7 +56,7 @@ export const enum CacheControl {
|
||||
*/
|
||||
export async function serveFile(filePath: string, cacheControl: CacheControl, logService: ILogService, req: http.IncomingMessage, res: http.ServerResponse, responseHeaders: Record<string, string>): Promise<void> {
|
||||
try {
|
||||
const stat = await fsp.stat(filePath); // throws an error if file doesn't exist
|
||||
const stat = await Promises.stat(filePath); // throws an error if file doesn't exist
|
||||
if (cacheControl === CacheControl.ETAG) {
|
||||
|
||||
// Check if file modified since
|
||||
@@ -318,7 +319,7 @@ export class WebClientServer {
|
||||
|
||||
if (!this._environmentService.isBuilt) {
|
||||
try {
|
||||
const productOverrides = JSON.parse((await fsp.readFile(join(APP_ROOT, 'product.overrides.json'))).toString());
|
||||
const productOverrides = JSON.parse((await Promises.readFile(join(APP_ROOT, 'product.overrides.json'))).toString());
|
||||
Object.assign(productConfiguration, productOverrides);
|
||||
} catch (err) {/* Ignore Error */ }
|
||||
}
|
||||
@@ -346,7 +347,7 @@ export class WebClientServer {
|
||||
if (useTestResolver) {
|
||||
const bundledExtensions: { extensionPath: string; packageJSON: IExtensionManifest }[] = [];
|
||||
for (const extensionPath of ['vscode-test-resolver', 'github-authentication']) {
|
||||
const packageJSON = JSON.parse((await fsp.readFile(FileAccess.asFileUri(`${builtinExtensionsPath}/${extensionPath}/package.json`).fsPath)).toString());
|
||||
const packageJSON = JSON.parse((await Promises.readFile(FileAccess.asFileUri(`${builtinExtensionsPath}/${extensionPath}/package.json`).fsPath)).toString());
|
||||
bundledExtensions.push({ extensionPath, packageJSON });
|
||||
}
|
||||
values['WORKBENCH_BUILTIN_EXTENSIONS'] = asJSON(bundledExtensions);
|
||||
@@ -354,7 +355,7 @@ export class WebClientServer {
|
||||
|
||||
let data;
|
||||
try {
|
||||
const workbenchTemplate = (await fsp.readFile(filePath)).toString();
|
||||
const workbenchTemplate = (await Promises.readFile(filePath)).toString();
|
||||
data = workbenchTemplate.replace(/\{\{([^}]+)\}\}/g, (_, key) => values[key] ?? 'undefined');
|
||||
} catch (e) {
|
||||
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
||||
@@ -421,7 +422,7 @@ export class WebClientServer {
|
||||
*/
|
||||
private async _handleCallback(res: http.ServerResponse): Promise<void> {
|
||||
const filePath = FileAccess.asFileUri('vs/code/browser/workbench/callback.html').fsPath;
|
||||
const data = (await fsp.readFile(filePath)).toString();
|
||||
const data = (await Promises.readFile(filePath)).toString();
|
||||
const cspDirectives = [
|
||||
'default-src \'self\';',
|
||||
'img-src \'self\' https: data: blob:;',
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { MainThreadStorageShape, MainContext, ExtHostStorageShape, ExtHostContext } from '../common/extHost.protocol';
|
||||
import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
import { IExtensionIdWithVersion, IExtensionStorageService } from 'vs/platform/extensionManagement/common/extensionStorage';
|
||||
import { migrateExtensionStorage } from 'vs/workbench/services/extensions/common/extensionStorageMigration';
|
||||
@@ -17,7 +17,7 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
export class MainThreadStorage implements MainThreadStorageShape {
|
||||
|
||||
private readonly _proxy: ExtHostStorageShape;
|
||||
private readonly _storageListener: IDisposable;
|
||||
private readonly _storageListener = new DisposableStore();
|
||||
private readonly _sharedStorageKeysToWatch: Map<string, boolean> = new Map<string, boolean>();
|
||||
|
||||
constructor(
|
||||
@@ -29,15 +29,14 @@ export class MainThreadStorage implements MainThreadStorageShape {
|
||||
) {
|
||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostStorage);
|
||||
|
||||
this._storageListener = this._storageService.onDidChangeValue(e => {
|
||||
const shared = e.scope === StorageScope.PROFILE;
|
||||
if (shared && this._sharedStorageKeysToWatch.has(e.key)) {
|
||||
const rawState = this._extensionStorageService.getExtensionStateRaw(e.key, shared);
|
||||
this._storageListener.add(this._storageService.onDidChangeValue(StorageScope.PROFILE, undefined, this._storageListener)(e => {
|
||||
if (this._sharedStorageKeysToWatch.has(e.key)) {
|
||||
const rawState = this._extensionStorageService.getExtensionStateRaw(e.key, true);
|
||||
if (typeof rawState === 'string') {
|
||||
this._proxy.$acceptValue(shared, e.key, rawState);
|
||||
this._proxy.$acceptValue(true, e.key, rawState);
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
|
||||
@@ -18,7 +18,7 @@ import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { LogLevel, createHttpPatch, createProxyResolver, createTlsPatch, ProxySupportSetting, ProxyAgentParams, createNetPatch } from '@vscode/proxy-agent';
|
||||
|
||||
const systemCertificatesV2Default = true;
|
||||
const systemCertificatesV2Default = false;
|
||||
|
||||
export function connectProxyResolver(
|
||||
extHostWorkspace: IExtHostWorkspaceProvider,
|
||||
|
||||
@@ -177,18 +177,18 @@ class OpenNewsletterSignupUrlAction extends Action2 {
|
||||
}
|
||||
}
|
||||
|
||||
class OpenTwitterUrlAction extends Action2 {
|
||||
class OpenYouTubeUrlAction extends Action2 {
|
||||
|
||||
static readonly ID = 'workbench.action.openTwitterUrl';
|
||||
static readonly AVAILABLE = !!product.twitterUrl;
|
||||
static readonly ID = 'workbench.action.openYouTubeUrl';
|
||||
static readonly AVAILABLE = !!product.youTubeUrl;
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
id: OpenTwitterUrlAction.ID,
|
||||
id: OpenYouTubeUrlAction.ID,
|
||||
title: {
|
||||
value: localize('openTwitterUrl', "Join Us on Twitter"),
|
||||
mnemonicTitle: localize({ key: 'miTwitter', comment: ['&& denotes a mnemonic'] }, "&&Join Us on Twitter"),
|
||||
original: 'Join Us on Twitter'
|
||||
value: localize('openYouTubeUrl', "Join Us on YouTube"),
|
||||
mnemonicTitle: localize({ key: 'miYouTube', comment: ['&& denotes a mnemonic'] }, "&&Join Us on YouTube"),
|
||||
original: 'Join Us on YouTube'
|
||||
},
|
||||
category: Categories.Help,
|
||||
f1: true,
|
||||
@@ -204,8 +204,8 @@ class OpenTwitterUrlAction extends Action2 {
|
||||
const productService = accessor.get(IProductService);
|
||||
const openerService = accessor.get(IOpenerService);
|
||||
|
||||
if (productService.twitterUrl) {
|
||||
openerService.open(URI.parse(productService.twitterUrl));
|
||||
if (productService.youTubeUrl) {
|
||||
openerService.open(URI.parse(productService.youTubeUrl));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -337,8 +337,8 @@ if (OpenNewsletterSignupUrlAction.AVAILABLE) {
|
||||
registerAction2(OpenNewsletterSignupUrlAction);
|
||||
}
|
||||
|
||||
if (OpenTwitterUrlAction.AVAILABLE) {
|
||||
registerAction2(OpenTwitterUrlAction);
|
||||
if (OpenYouTubeUrlAction.AVAILABLE) {
|
||||
registerAction2(OpenYouTubeUrlAction);
|
||||
}
|
||||
|
||||
if (OpenRequestFeatureUrlAction.AVAILABLE) {
|
||||
|
||||
@@ -2469,7 +2469,7 @@ class LayoutStateModel extends Disposable {
|
||||
}
|
||||
|
||||
// Register for runtime key changes
|
||||
this._register(this.storageService.onDidChangeValue(storageChangeEvent => {
|
||||
this._register(this.storageService.onDidChangeValue(StorageScope.PROFILE, undefined, this._register(new DisposableStore()))(storageChangeEvent => {
|
||||
let key: keyof typeof LayoutStateKeys;
|
||||
for (key in LayoutStateKeys) {
|
||||
const stateKey = LayoutStateKeys[key] as WorkbenchLayoutStateKey<StorageKeyType>;
|
||||
|
||||
@@ -19,7 +19,7 @@ import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND,
|
||||
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { CompositeBar, ICompositeBarItem, CompositeDragAndDrop } from 'vs/workbench/browser/parts/compositeBar';
|
||||
import { Dimension, createCSSRule, asCSSUrl, addDisposableListener, EventType, isAncestor } from 'vs/base/browser/dom';
|
||||
import { IStorageService, StorageScope, IStorageValueChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { IStorageService, StorageScope, StorageTarget, IProfileStorageValueChangeEvent } from 'vs/platform/storage/common/storage';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { ToggleCompositePinnedAction, ICompositeBarColors, ActivityAction, ICompositeActivity, IActivityHoverOptions, ToggleCompositeBadgeAction } from 'vs/workbench/browser/parts/compositeBarActions';
|
||||
@@ -247,7 +247,7 @@ export class ActivitybarPart extends Part implements IPaneCompositeSelectorPart
|
||||
disposables.clear();
|
||||
this.onDidRegisterExtensions();
|
||||
this.compositeBar.onDidChange(() => this.saveCachedViewContainers(), this, disposables);
|
||||
this.storageService.onDidChangeValue(e => this.onDidStorageValueChange(e), this, disposables);
|
||||
this.storageService.onDidChangeValue(StorageScope.PROFILE, ActivitybarPart.PINNED_VIEW_CONTAINERS, disposables)(e => this.onDidStorageValueChange(e), this, disposables);
|
||||
}));
|
||||
|
||||
// Register for configuration changes
|
||||
@@ -807,9 +807,8 @@ export class ActivitybarPart extends Part implements IPaneCompositeSelectorPart
|
||||
return this.viewDescriptorService.getViewContainersByLocation(this.location);
|
||||
}
|
||||
|
||||
private onDidStorageValueChange(e: IStorageValueChangeEvent): void {
|
||||
if (e.key === ActivitybarPart.PINNED_VIEW_CONTAINERS && e.scope === StorageScope.PROFILE
|
||||
&& this.pinnedViewContainersValue !== this.getStoredPinnedViewContainersValue() /* This checks if current window changed the value or not */) {
|
||||
private onDidStorageValueChange(e: IProfileStorageValueChangeEvent): void {
|
||||
if (this.pinnedViewContainersValue !== this.getStoredPinnedViewContainersValue() /* This checks if current window changed the value or not */) {
|
||||
this._pinnedViewContainersValue = undefined;
|
||||
this._cachedViewContainers = undefined;
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ export const DEFAULT_EDITOR_PART_OPTIONS: IEditorPartOptions = {
|
||||
tabSizingFixedMinWidth: 50,
|
||||
tabSizingFixedMaxWidth: 160,
|
||||
pinnedTabSizing: 'normal',
|
||||
preventPinnedEditorClose: 'keyboardAndMouse',
|
||||
titleScrollbarSizing: 'default',
|
||||
focusRecentEditorAfterClose: true,
|
||||
showIcons: true,
|
||||
|
||||
@@ -783,15 +783,17 @@ function registerCloseEditorCommands() {
|
||||
const editorGroupsService = accessor.get(IEditorGroupsService);
|
||||
const editorService = accessor.get(IEditorService);
|
||||
|
||||
let keepStickyEditors = true;
|
||||
let keepStickyEditors: boolean | undefined = undefined;
|
||||
if (forceCloseStickyEditors) {
|
||||
keepStickyEditors = false; // explicitly close sticky editors
|
||||
} else if (resourceOrContext || context) {
|
||||
keepStickyEditors = false; // we have a context, as such this command was used e.g. from the tab context menu
|
||||
} else {
|
||||
keepStickyEditors = editorGroupsService.partOptions.preventPinnedEditorClose === 'keyboard' || editorGroupsService.partOptions.preventPinnedEditorClose === 'keyboardAndMouse'; // respect setting otherwise
|
||||
}
|
||||
|
||||
// Without context: skip over sticky editor and select next if active editor is sticky
|
||||
if (keepStickyEditors && !resourceOrContext && !context) {
|
||||
// Skip over sticky editor and select next if we are configured to do so
|
||||
if (keepStickyEditors) {
|
||||
const activeGroup = editorGroupsService.activeGroup;
|
||||
const activeEditor = activeGroup.activeEditor;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/notabstitlecontrol';
|
||||
import { EditorResourceAccessor, Verbosity, IEditorPartOptions, SideBySideEditor } from 'vs/workbench/common/editor';
|
||||
import { EditorResourceAccessor, Verbosity, IEditorPartOptions, SideBySideEditor, preventEditorClose, EditorCloseMethod } from 'vs/workbench/common/editor';
|
||||
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
import { TitleControl, IToolbarActions, ITitleControlDimensions } from 'vs/workbench/browser/parts/editor/titleControl';
|
||||
import { ResourceLabel, IResourceLabel } from 'vs/workbench/browser/labels';
|
||||
@@ -105,7 +105,9 @@ export class NoTabsTitleControl extends TitleControl {
|
||||
if (e.button === 1 /* Middle Button */ && this.group.activeEditor) {
|
||||
EventHelper.stop(e, true /* for https://github.com/microsoft/vscode/issues/56715 */);
|
||||
|
||||
this.group.closeEditor(this.group.activeEditor);
|
||||
if (!preventEditorClose(this.group, this.group.activeEditor, EditorCloseMethod.MOUSE, this.accessor.partOptions)) {
|
||||
this.group.closeEditor(this.group.activeEditor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import 'vs/css!./media/tabstitlecontrol';
|
||||
import { isMacintosh, isWindows } from 'vs/base/common/platform';
|
||||
import { shorten } from 'vs/base/common/labels';
|
||||
import { EditorResourceAccessor, GroupIdentifier, Verbosity, IEditorPartOptions, SideBySideEditor, DEFAULT_EDITOR_ASSOCIATION, EditorInputCapabilities, IUntypedEditorInput } from 'vs/workbench/common/editor';
|
||||
import { EditorResourceAccessor, GroupIdentifier, Verbosity, IEditorPartOptions, SideBySideEditor, DEFAULT_EDITOR_ASSOCIATION, EditorInputCapabilities, IUntypedEditorInput, preventEditorClose, EditorCloseMethod } from 'vs/workbench/common/editor';
|
||||
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
import { computeEditorAriaLabel } from 'vs/workbench/browser/editor';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
@@ -847,10 +847,10 @@ export class TabsTitleControl extends TitleControl {
|
||||
}
|
||||
|
||||
// Open tabs editor
|
||||
const input = this.group.getEditorByIndex(index);
|
||||
if (input) {
|
||||
const editor = this.group.getEditorByIndex(index);
|
||||
if (editor) {
|
||||
// Even if focus is preserved make sure to activate the group.
|
||||
this.group.openEditor(input, { preserveFocus, activation: EditorActivation.ACTIVATE });
|
||||
this.group.openEditor(editor, { preserveFocus, activation: EditorActivation.ACTIVATE });
|
||||
}
|
||||
|
||||
return undefined;
|
||||
@@ -859,9 +859,9 @@ export class TabsTitleControl extends TitleControl {
|
||||
const showContextMenu = (e: Event) => {
|
||||
EventHelper.stop(e);
|
||||
|
||||
const input = this.group.getEditorByIndex(index);
|
||||
if (input) {
|
||||
this.onContextMenu(input, e, tab);
|
||||
const editor = this.group.getEditorByIndex(index);
|
||||
if (editor) {
|
||||
this.onContextMenu(editor, e, tab);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -886,6 +886,11 @@ export class TabsTitleControl extends TitleControl {
|
||||
if (e.button === 1 /* Middle Button*/) {
|
||||
EventHelper.stop(e, true /* for https://github.com/microsoft/vscode/issues/56715 */);
|
||||
|
||||
const editor = this.group.getEditorByIndex(index);
|
||||
if (editor && preventEditorClose(this.group, editor, EditorCloseMethod.MOUSE, this.accessor.partOptions)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.blockRevealActiveTabOnce();
|
||||
this.closeEditorAction.run({ groupId: this.group.id, editorIndex: index });
|
||||
}
|
||||
@@ -912,9 +917,9 @@ export class TabsTitleControl extends TitleControl {
|
||||
// Run action on Enter/Space
|
||||
if (event.equals(KeyCode.Enter) || event.equals(KeyCode.Space)) {
|
||||
handled = true;
|
||||
const input = this.group.getEditorByIndex(index);
|
||||
if (input) {
|
||||
this.group.openEditor(input);
|
||||
const editor = this.group.getEditorByIndex(index);
|
||||
if (editor) {
|
||||
this.group.openEditor(editor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -973,9 +978,9 @@ export class TabsTitleControl extends TitleControl {
|
||||
disposables.add(addDisposableListener(tab, EventType.CONTEXT_MENU, e => {
|
||||
EventHelper.stop(e, true);
|
||||
|
||||
const input = this.group.getEditorByIndex(index);
|
||||
if (input) {
|
||||
this.onContextMenu(input, e, tab);
|
||||
const editor = this.group.getEditorByIndex(index);
|
||||
if (editor) {
|
||||
this.onContextMenu(editor, e, tab);
|
||||
}
|
||||
}, true /* use capture to fix https://github.com/microsoft/vscode/issues/19145 */));
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import { ActionsOrientation, prepareActions } from 'vs/base/browser/ui/actionbar
|
||||
import { ActivePanelContext, PanelFocusContext, getEnabledViewContainerContextKey } from 'vs/workbench/common/contextkeys';
|
||||
import { CompositePart, ICompositeTitleLabel } from 'vs/workbench/browser/parts/compositePart';
|
||||
import { IWorkbenchLayoutService, Parts, Position } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { IStorageService, StorageScope, IStorageValueChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
@@ -417,7 +417,7 @@ export abstract class BasePanelPart extends CompositePart<PaneComposite> impleme
|
||||
disposables.clear();
|
||||
this.onDidRegisterExtensions();
|
||||
this.compositeBar.onDidChange(() => this.saveCachedPanels(), this, disposables);
|
||||
this.storageService.onDidChangeValue(e => this.onDidStorageValueChange(e), this, disposables);
|
||||
this.storageService.onDidChangeValue(StorageScope.PROFILE, this.pinnedPanelsKey, disposables)(() => this.onDidStorageValueChange(), this, disposables);
|
||||
}));
|
||||
|
||||
}
|
||||
@@ -781,9 +781,8 @@ export abstract class BasePanelPart extends CompositePart<PaneComposite> impleme
|
||||
return this.toolBar.getItemsWidth() + (this.globalToolBar?.getItemsWidth() ?? 0);
|
||||
}
|
||||
|
||||
private onDidStorageValueChange(e: IStorageValueChangeEvent): void {
|
||||
if (e.key === this.pinnedPanelsKey && e.scope === StorageScope.PROFILE
|
||||
&& this.cachedPanelsValue !== this.getStoredCachedPanelsValue() /* This checks if current window changed the value or not */) {
|
||||
private onDidStorageValueChange(): void {
|
||||
if (this.cachedPanelsValue !== this.getStoredCachedPanelsValue() /* This checks if current window changed the value or not */) {
|
||||
this._cachedPanelsValue = undefined;
|
||||
const newCompositeItems: ICompositeBarItem[] = [];
|
||||
const compositeItems = this.compositeBar.getCompositeBarItems();
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { isStatusbarEntryLocation, IStatusbarEntryPriority, StatusbarAlignment } from 'vs/workbench/services/statusbar/browser/statusbar';
|
||||
import { hide, show, isAncestor } from 'vs/base/browser/dom';
|
||||
import { IStorageService, StorageScope, IStorageValueChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
|
||||
export interface IStatusbarViewModelEntry {
|
||||
@@ -57,43 +57,41 @@ export class StatusbarViewModel extends Disposable {
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
this._register(this.storageService.onDidChangeValue(e => this.onDidStorageValueChange(e)));
|
||||
this._register(this.storageService.onDidChangeValue(StorageScope.PROFILE, StatusbarViewModel.HIDDEN_ENTRIES_KEY, this._register(new DisposableStore()))(() => this.onDidStorageValueChange()));
|
||||
}
|
||||
|
||||
private onDidStorageValueChange(event: IStorageValueChangeEvent): void {
|
||||
if (event.key === StatusbarViewModel.HIDDEN_ENTRIES_KEY && event.scope === StorageScope.PROFILE) {
|
||||
private onDidStorageValueChange(): void {
|
||||
|
||||
// Keep current hidden entries
|
||||
const currentlyHidden = new Set(this.hidden);
|
||||
// Keep current hidden entries
|
||||
const currentlyHidden = new Set(this.hidden);
|
||||
|
||||
// Load latest state of hidden entries
|
||||
this.hidden.clear();
|
||||
this.restoreState();
|
||||
// Load latest state of hidden entries
|
||||
this.hidden.clear();
|
||||
this.restoreState();
|
||||
|
||||
const changed = new Set<string>();
|
||||
const changed = new Set<string>();
|
||||
|
||||
// Check for each entry that is now visible
|
||||
for (const id of currentlyHidden) {
|
||||
if (!this.hidden.has(id)) {
|
||||
changed.add(id);
|
||||
}
|
||||
// Check for each entry that is now visible
|
||||
for (const id of currentlyHidden) {
|
||||
if (!this.hidden.has(id)) {
|
||||
changed.add(id);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for each entry that is now hidden
|
||||
for (const id of this.hidden) {
|
||||
if (!currentlyHidden.has(id)) {
|
||||
changed.add(id);
|
||||
}
|
||||
// Check for each entry that is now hidden
|
||||
for (const id of this.hidden) {
|
||||
if (!currentlyHidden.has(id)) {
|
||||
changed.add(id);
|
||||
}
|
||||
}
|
||||
|
||||
// Update visibility for entries have changed
|
||||
if (changed.size > 0) {
|
||||
for (const entry of this._entries) {
|
||||
if (changed.has(entry.id)) {
|
||||
this.updateVisibility(entry.id, true);
|
||||
// Update visibility for entries have changed
|
||||
if (changed.size > 0) {
|
||||
for (const entry of this._entries) {
|
||||
if (changed.has(entry.id)) {
|
||||
this.updateVisibility(entry.id, true);
|
||||
|
||||
changed.delete(entry.id);
|
||||
}
|
||||
changed.delete(entry.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,6 +176,18 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
|
||||
],
|
||||
'markdownDescription': localize({ comment: ['This is the description for a setting. Values surrounded by single quotes are not to be translated.'], key: 'pinnedTabSizing' }, "Controls the size of pinned editor tabs. Pinned tabs are sorted to the beginning of all opened tabs and typically do not close until unpinned. This value is ignored when `#workbench.editor.showTabs#` is disabled.")
|
||||
},
|
||||
'workbench.editor.preventPinnedEditorClose': {
|
||||
'type': 'string',
|
||||
'enum': ['keyboardAndMouse', 'keyboard', 'mouse', 'never'],
|
||||
'default': 'keyboardAndMouse',
|
||||
'enumDescriptions': [
|
||||
localize('workbench.editor.preventPinnedEditorClose.always', "Always prevent closing the pinned editor when using mouse middle click or keyboard."),
|
||||
localize('workbench.editor.preventPinnedEditorClose.onlyKeyboard', "Prevent closing the pinned editor when using the keyboard."),
|
||||
localize('workbench.editor.preventPinnedEditorClose.onlyMouse', "Prevent closing the pinned editor when using mouse middle click."),
|
||||
localize('workbench.editor.preventPinnedEditorClose.never', "Never prevent closing a pinned editor.")
|
||||
],
|
||||
description: localize('workbench.editor.preventPinnedEditorClose', "Controls whether pinned editors should close when keyboard or middle mouse click is used for closing."),
|
||||
},
|
||||
'workbench.editor.splitSizing': {
|
||||
'type': 'string',
|
||||
'enum': ['auto', 'distribute', 'split'],
|
||||
@@ -194,7 +206,7 @@ const registry = Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Con
|
||||
},
|
||||
'workbench.editor.focusRecentEditorAfterClose': {
|
||||
'type': 'boolean',
|
||||
'description': localize('focusRecentEditorAfterClose', "Controls whether tabs are closed in most recently used order or from left to right."),
|
||||
'description': localize('focusRecentEditorAfterClose', "Controls whether editors are closed in most recently used order or from left to right."),
|
||||
'default': true
|
||||
},
|
||||
'workbench.editor.showIcons': {
|
||||
|
||||
@@ -1098,6 +1098,7 @@ interface IEditorPartConfiguration {
|
||||
tabSizingFixedMinWidth?: number;
|
||||
tabSizingFixedMaxWidth?: number;
|
||||
pinnedTabSizing?: 'normal' | 'compact' | 'shrink';
|
||||
preventPinnedEditorClose?: PreventPinnedEditorClose;
|
||||
titleScrollbarSizing?: 'default' | 'large';
|
||||
focusRecentEditorAfterClose?: boolean;
|
||||
showIcons?: boolean;
|
||||
@@ -1340,6 +1341,28 @@ class EditorResourceAccessorImpl {
|
||||
}
|
||||
}
|
||||
|
||||
export type PreventPinnedEditorClose = 'keyboardAndMouse' | 'keyboard' | 'mouse' | 'never' | undefined;
|
||||
|
||||
export enum EditorCloseMethod {
|
||||
UNKNOWN,
|
||||
KEYBOARD,
|
||||
MOUSE
|
||||
}
|
||||
|
||||
export function preventEditorClose(group: IEditorGroup, editor: EditorInput, method: EditorCloseMethod, configuration: IEditorPartConfiguration): boolean {
|
||||
if (!group.isSticky(editor)) {
|
||||
return false; // only interested in sticky editors
|
||||
}
|
||||
|
||||
switch (configuration.preventPinnedEditorClose) {
|
||||
case 'keyboardAndMouse': return method === EditorCloseMethod.MOUSE || method === EditorCloseMethod.KEYBOARD;
|
||||
case 'mouse': return method === EditorCloseMethod.MOUSE;
|
||||
case 'keyboard': return method === EditorCloseMethod.KEYBOARD;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export const EditorResourceAccessor = new EditorResourceAccessorImpl();
|
||||
|
||||
export const enum CloseDirection {
|
||||
|
||||
@@ -26,10 +26,10 @@ import { getSimpleEditorOptions } from 'vs/workbench/contrib/codeEditor/browser/
|
||||
import { CodeActionController } from 'vs/editor/contrib/codeAction/browser/codeActionController';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { AccessibilityVerbositySettingId, AccessibleViewAction, AccessibleViewNextAction, AccessibleViewPreviousAction } from 'vs/workbench/contrib/accessibility/browser/accessibilityContribution';
|
||||
import { ILayoutService } from 'vs/platform/layout/browser/layoutService';
|
||||
|
||||
const enum DEFAULT {
|
||||
WIDTH = 800,
|
||||
TOP = 3
|
||||
const enum DIMENSIONS {
|
||||
MAX_WIDTH = 600
|
||||
}
|
||||
|
||||
export interface IAccessibleContentProvider {
|
||||
@@ -89,7 +89,8 @@ class AccessibleView extends Disposable {
|
||||
@IContextViewService private readonly _contextViewService: IContextViewService,
|
||||
@IContextKeyService private readonly _contextKeyService: IContextKeyService,
|
||||
@IAccessibilityService private readonly _accessibilityService: IAccessibilityService,
|
||||
@IKeybindingService private readonly _keybindingService: IKeybindingService
|
||||
@IKeybindingService private readonly _keybindingService: IKeybindingService,
|
||||
@ILayoutService private readonly _layoutService: ILayoutService
|
||||
) {
|
||||
super();
|
||||
this._accessiblityHelpIsShown = accessibilityHelpIsShown.bindTo(this._contextKeyService);
|
||||
@@ -128,7 +129,7 @@ class AccessibleView extends Disposable {
|
||||
|
||||
show(provider: IAccessibleContentProvider): void {
|
||||
const delegate: IContextViewDelegate = {
|
||||
getAnchor: () => { return { x: (window.innerWidth / 2) - (DEFAULT.WIDTH / 2), y: DEFAULT.TOP }; },
|
||||
getAnchor: () => { return { x: (window.innerWidth / 2) - ((Math.min(this._layoutService.dimension.width * 0.62 /* golden cut */, DIMENSIONS.MAX_WIDTH)) / 2), y: this._layoutService.offset.quickPickTop }; },
|
||||
render: (container) => {
|
||||
container.classList.add('accessible-view-container');
|
||||
return this._render(provider, container);
|
||||
@@ -228,11 +229,16 @@ class AccessibleView extends Disposable {
|
||||
}));
|
||||
disposableStore.add(this._editorWidget.onDidBlurEditorText(() => this._contextViewService.hideContextView()));
|
||||
disposableStore.add(this._editorWidget.onDidContentSizeChange(() => this._layout()));
|
||||
disposableStore.add(this._layoutService.onDidLayout(() => this._layout()));
|
||||
return disposableStore;
|
||||
}
|
||||
|
||||
private _layout(): void {
|
||||
this._editorWidget.layout({ width: DEFAULT.WIDTH, height: this._editorWidget.getContentHeight() });
|
||||
const dimension = this._layoutService.dimension;
|
||||
const maxHeight = dimension.height && dimension.height * .4;
|
||||
const height = Math.min(maxHeight, this._editorWidget.getContentHeight());
|
||||
const width = Math.min(dimension.width * 0.62 /* golden cut */, DIMENSIONS.MAX_WIDTH);
|
||||
this._editorWidget.layout({ width, height });
|
||||
}
|
||||
|
||||
private async _getTextModel(resource: URI): Promise<ITextModel | null> {
|
||||
|
||||
@@ -9,4 +9,7 @@
|
||||
color: var(--vscode-editorWidget-foreground);
|
||||
box-shadow: 0 2px 8px var(--vscode-widget-shadow);
|
||||
border: 2px solid var(--vscode-focusBorder);
|
||||
border-radius: 6px;
|
||||
margin-top: -1px;
|
||||
z-index: 2550;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { localize } from 'vs/nls';
|
||||
import { Action2, MenuId, MenuRegistry, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
import { ContextKeyExpr, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
@@ -11,7 +11,7 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { IQuickInputService, IQuickPickItem, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IStorageService, IStorageValueChangeEvent, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { createSyncHeaders, IAuthenticationProvider, IResourceRefHandle } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
import { AuthenticationSession, AuthenticationSessionsChangeEvent, IAuthenticationService } from 'vs/workbench/services/authentication/common/authentication';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
@@ -91,7 +91,7 @@ export class EditSessionsWorkbenchService extends Disposable implements IEditSes
|
||||
this._register(this.authenticationService.onDidChangeSessions((e) => this.onDidChangeSessions(e.event)));
|
||||
|
||||
// If another window changes the preferred session storage, reset our cached auth state in memory
|
||||
this._register(this.storageService.onDidChangeValue(e => this.onDidChangeStorage(e)));
|
||||
this._register(this.storageService.onDidChangeValue(StorageScope.APPLICATION, EditSessionsWorkbenchService.CACHED_SESSION_STORAGE_KEY, this._register(new DisposableStore()))(() => this.onDidChangeStorage()));
|
||||
|
||||
this.registerSignInAction();
|
||||
this.registerResetAuthenticationAction();
|
||||
@@ -431,18 +431,14 @@ export class EditSessionsWorkbenchService extends Disposable implements IEditSes
|
||||
return accounts.find((account) => account.session.id === this.existingSessionId);
|
||||
}
|
||||
|
||||
private async onDidChangeStorage(e: IStorageValueChangeEvent): Promise<void> {
|
||||
if (e.key === EditSessionsWorkbenchService.CACHED_SESSION_STORAGE_KEY
|
||||
&& e.scope === StorageScope.APPLICATION
|
||||
) {
|
||||
const newSessionId = this.existingSessionId;
|
||||
const previousSessionId = this.authenticationInfo?.sessionId;
|
||||
private async onDidChangeStorage(): Promise<void> {
|
||||
const newSessionId = this.existingSessionId;
|
||||
const previousSessionId = this.authenticationInfo?.sessionId;
|
||||
|
||||
if (previousSessionId !== newSessionId) {
|
||||
this.logService.trace(`Resetting authentication state because authentication session ID preference changed from ${previousSessionId} to ${newSessionId}.`);
|
||||
this.authenticationInfo = undefined;
|
||||
this.initialized = false;
|
||||
}
|
||||
if (previousSessionId !== newSessionId) {
|
||||
this.logService.trace(`Resetting authentication state because authentication session ID preference changed from ${previousSessionId} to ${newSessionId}.`);
|
||||
this.authenticationInfo = undefined;
|
||||
this.initialized = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +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 { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { FeedbackStatusbarConribution } from 'vs/workbench/contrib/feedback/browser/feedbackStatusbarItem';
|
||||
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
|
||||
import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle';
|
||||
|
||||
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(FeedbackStatusbarConribution, LifecyclePhase.Starting);
|
||||
@@ -1,455 +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 'vs/css!./media/feedback';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IDisposable, DisposableStore, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IIntegrityService } from 'vs/workbench/services/integrity/common/integrity';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { editorWidgetBackground, editorWidgetForeground, widgetShadow, inputBorder, inputForeground, inputBackground, editorBackground, asCssVariable, asCssVariableWithDefault, widgetBorder, contrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { append, $, addDisposableListener, EventType, EventHelper, prepend } from 'vs/base/browser/dom';
|
||||
import { IAnchor } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { Button } from 'vs/base/browser/ui/button/button';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions';
|
||||
import { IStatusbarService } from 'vs/workbench/services/statusbar/browser/statusbar';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { ThemeIcon } from 'vs/base/common/themables';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
import { defaultButtonStyles } from 'vs/platform/theme/browser/defaultStyles';
|
||||
|
||||
export interface IFeedback {
|
||||
feedback: string;
|
||||
sentiment: number;
|
||||
}
|
||||
|
||||
export interface IFeedbackDelegate {
|
||||
submitFeedback(feedback: IFeedback, openerService: IOpenerService): void;
|
||||
getCharacterLimit(sentiment: number): number;
|
||||
}
|
||||
|
||||
export interface IFeedbackWidgetOptions {
|
||||
feedbackService: IFeedbackDelegate;
|
||||
}
|
||||
|
||||
export class FeedbackWidget extends Disposable {
|
||||
private visible: boolean | undefined;
|
||||
private _onDidChangeVisibility = new Emitter<boolean>();
|
||||
readonly onDidChangeVisibility = this._onDidChangeVisibility.event;
|
||||
|
||||
private maxFeedbackCharacters: number;
|
||||
|
||||
private feedback: string = '';
|
||||
private sentiment: number = 1;
|
||||
|
||||
private readonly feedbackDelegate: IFeedbackDelegate;
|
||||
|
||||
private feedbackForm: HTMLFormElement | undefined = undefined;
|
||||
private feedbackDescriptionInput: HTMLTextAreaElement | undefined = undefined;
|
||||
private smileyInput: HTMLElement | undefined = undefined;
|
||||
private frownyInput: HTMLElement | undefined = undefined;
|
||||
private sendButton: Button | undefined = undefined;
|
||||
private hideButton: HTMLInputElement | undefined = undefined;
|
||||
private remainingCharacterCount: HTMLElement | undefined = undefined;
|
||||
|
||||
private requestFeatureLink: string | undefined;
|
||||
|
||||
private isPure: boolean = true;
|
||||
|
||||
constructor(
|
||||
options: IFeedbackWidgetOptions,
|
||||
@IContextViewService private readonly contextViewService: IContextViewService,
|
||||
@IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
|
||||
@ICommandService private readonly commandService: ICommandService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@IIntegrityService private readonly integrityService: IIntegrityService,
|
||||
@IThemeService private readonly themeService: IThemeService,
|
||||
@IStatusbarService private readonly statusbarService: IStatusbarService,
|
||||
@IProductService productService: IProductService,
|
||||
@IOpenerService private readonly openerService: IOpenerService
|
||||
) {
|
||||
super();
|
||||
|
||||
this.feedbackDelegate = options.feedbackService;
|
||||
this.maxFeedbackCharacters = this.feedbackDelegate.getCharacterLimit(this.sentiment);
|
||||
|
||||
if (productService.sendASmile) {
|
||||
this.requestFeatureLink = productService.sendASmile.requestFeatureUrl;
|
||||
}
|
||||
|
||||
this.integrityService.isPure().then(result => {
|
||||
if (!result.isPure) {
|
||||
this.isPure = false;
|
||||
}
|
||||
});
|
||||
|
||||
// Hide feedback widget whenever notifications appear
|
||||
this._register(this.layoutService.onDidChangeNotificationsVisibility(visible => {
|
||||
if (visible) {
|
||||
this.hide();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private getAnchor(): IAnchor {
|
||||
const dimension = this.layoutService.dimension;
|
||||
|
||||
return {
|
||||
x: dimension.width - 8,
|
||||
y: dimension.height - 31
|
||||
};
|
||||
}
|
||||
|
||||
private renderContents(container: HTMLElement): IDisposable {
|
||||
const disposables = new DisposableStore();
|
||||
|
||||
container.classList.add('monaco-menu-container');
|
||||
|
||||
// Form
|
||||
this.feedbackForm = append<HTMLFormElement>(container, $('form.feedback-form'));
|
||||
this.feedbackForm.setAttribute('action', 'javascript:void(0);');
|
||||
|
||||
// Title
|
||||
append(this.feedbackForm, $('h2.title')).textContent = localize("label.sendASmile", "Tweet us your feedback.");
|
||||
|
||||
// Close Button (top right)
|
||||
const closeBtn = append(this.feedbackForm, $(`div.cancel${ThemeIcon.asCSSSelector(Codicon.close)}`));
|
||||
closeBtn.tabIndex = 0;
|
||||
closeBtn.setAttribute('role', 'button');
|
||||
closeBtn.title = localize('close', "Close");
|
||||
|
||||
disposables.add(addDisposableListener(container, EventType.KEY_DOWN, keyboardEvent => {
|
||||
const standardKeyboardEvent = new StandardKeyboardEvent(keyboardEvent);
|
||||
if (standardKeyboardEvent.keyCode === KeyCode.Escape) {
|
||||
this.hide();
|
||||
}
|
||||
}));
|
||||
|
||||
disposables.add(addDisposableListener(closeBtn, EventType.MOUSE_OVER, () => {
|
||||
const theme = this.themeService.getColorTheme();
|
||||
let darkenFactor: number | undefined;
|
||||
switch (theme.type) {
|
||||
case 'light':
|
||||
darkenFactor = 0.1;
|
||||
break;
|
||||
case 'dark':
|
||||
darkenFactor = 0.2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (darkenFactor) {
|
||||
const backgroundBaseColor = theme.getColor(editorWidgetBackground);
|
||||
if (backgroundBaseColor) {
|
||||
const backgroundColor = backgroundBaseColor.darken(darkenFactor);
|
||||
if (backgroundColor) {
|
||||
closeBtn.style.backgroundColor = backgroundColor.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
disposables.add(addDisposableListener(closeBtn, EventType.MOUSE_OUT, () => {
|
||||
closeBtn.style.backgroundColor = '';
|
||||
}));
|
||||
|
||||
this.invoke(closeBtn, disposables, () => this.hide());
|
||||
|
||||
// Content
|
||||
const content = append(this.feedbackForm, $('div.content'));
|
||||
|
||||
// Sentiment Buttons
|
||||
const sentimentContainer = append(content, $('div'));
|
||||
|
||||
if (!this.isPure) {
|
||||
append(sentimentContainer, $('span')).textContent = localize("patchedVersion1", "Your installation is corrupt.");
|
||||
sentimentContainer.appendChild(document.createElement('br'));
|
||||
append(sentimentContainer, $('span')).textContent = localize("patchedVersion2", "Please specify this if you submit a bug.");
|
||||
sentimentContainer.appendChild(document.createElement('br'));
|
||||
}
|
||||
|
||||
append(sentimentContainer, $('span')).textContent = localize("sentiment", "How was your experience?");
|
||||
|
||||
const feedbackSentiment = append(sentimentContainer, $('div.feedback-sentiment'));
|
||||
|
||||
// Sentiment: Smiley
|
||||
this.smileyInput = append(feedbackSentiment, $('div.sentiment'));
|
||||
this.smileyInput.classList.add('smile');
|
||||
this.smileyInput.setAttribute('aria-checked', 'false');
|
||||
this.smileyInput.setAttribute('aria-label', localize('smileCaption', "Happy Feedback Sentiment"));
|
||||
this.smileyInput.setAttribute('role', 'checkbox');
|
||||
this.smileyInput.title = localize('smileCaption', "Happy Feedback Sentiment");
|
||||
this.smileyInput.tabIndex = 0;
|
||||
|
||||
this.invoke(this.smileyInput, disposables, () => this.setSentiment(true));
|
||||
|
||||
// Sentiment: Frowny
|
||||
this.frownyInput = append(feedbackSentiment, $('div.sentiment'));
|
||||
this.frownyInput.classList.add('frown');
|
||||
this.frownyInput.setAttribute('aria-checked', 'false');
|
||||
this.frownyInput.setAttribute('aria-label', localize('frownCaption', "Sad Feedback Sentiment"));
|
||||
this.frownyInput.setAttribute('role', 'checkbox');
|
||||
this.frownyInput.title = localize('frownCaption', "Sad Feedback Sentiment");
|
||||
this.frownyInput.tabIndex = 0;
|
||||
|
||||
this.invoke(this.frownyInput, disposables, () => this.setSentiment(false));
|
||||
|
||||
if (this.sentiment === 1) {
|
||||
this.smileyInput.classList.add('checked');
|
||||
this.smileyInput.setAttribute('aria-checked', 'true');
|
||||
} else {
|
||||
this.frownyInput.classList.add('checked');
|
||||
this.frownyInput.setAttribute('aria-checked', 'true');
|
||||
}
|
||||
|
||||
// Contact Us Box
|
||||
const contactUsContainer = append(content, $('div.contactus'));
|
||||
|
||||
append(contactUsContainer, $('span')).textContent = localize("other ways to contact us", "Other ways to contact us");
|
||||
|
||||
const channelsContainer = append(contactUsContainer, $('div.channels'));
|
||||
|
||||
// Contact: Submit a Bug
|
||||
const submitBugLinkContainer = append(channelsContainer, $('div'));
|
||||
|
||||
const submitBugLink = append(submitBugLinkContainer, $('a'));
|
||||
submitBugLink.setAttribute('target', '_blank');
|
||||
submitBugLink.setAttribute('href', '#');
|
||||
submitBugLink.textContent = localize("submit a bug", "Submit a bug");
|
||||
submitBugLink.tabIndex = 0;
|
||||
|
||||
disposables.add(addDisposableListener(submitBugLink, 'click', e => {
|
||||
EventHelper.stop(e);
|
||||
const actionId = 'workbench.action.openIssueReporter';
|
||||
this.commandService.executeCommand(actionId);
|
||||
this.hide();
|
||||
this.telemetryService.publicLog2<WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification>('workbenchActionExecuted', { id: actionId, from: 'feedback' });
|
||||
}));
|
||||
|
||||
// Contact: Request a Feature
|
||||
if (!!this.requestFeatureLink) {
|
||||
const requestFeatureLinkContainer = append(channelsContainer, $('div'));
|
||||
|
||||
const requestFeatureLink = append(requestFeatureLinkContainer, $('a'));
|
||||
requestFeatureLink.setAttribute('target', '_blank');
|
||||
requestFeatureLink.setAttribute('href', this.requestFeatureLink);
|
||||
requestFeatureLink.textContent = localize("request a missing feature", "Request a missing feature");
|
||||
requestFeatureLink.tabIndex = 0;
|
||||
|
||||
disposables.add(addDisposableListener(requestFeatureLink, 'click', e => this.hide()));
|
||||
}
|
||||
|
||||
// Remaining Characters
|
||||
const remainingCharacterCountContainer = append(this.feedbackForm, $('h3'));
|
||||
remainingCharacterCountContainer.textContent = localize("tell us why", "Tell us why?");
|
||||
|
||||
this.remainingCharacterCount = append(remainingCharacterCountContainer, $('span.char-counter'));
|
||||
this.remainingCharacterCount.textContent = this.getCharCountText(0);
|
||||
|
||||
// Feedback Input Form
|
||||
this.feedbackDescriptionInput = append<HTMLTextAreaElement>(this.feedbackForm, $('textarea.feedback-description'));
|
||||
this.feedbackDescriptionInput.rows = 3;
|
||||
this.feedbackDescriptionInput.maxLength = this.maxFeedbackCharacters;
|
||||
this.feedbackDescriptionInput.textContent = this.feedback;
|
||||
this.feedbackDescriptionInput.required = true;
|
||||
this.feedbackDescriptionInput.setAttribute('aria-label', localize("feedbackTextInput", "Tell us your feedback"));
|
||||
this.feedbackDescriptionInput.focus();
|
||||
|
||||
disposables.add(addDisposableListener(this.feedbackDescriptionInput, 'keyup', () => this.updateCharCountText()));
|
||||
|
||||
// Feedback Input Form Buttons Container
|
||||
const buttonsContainer = append(this.feedbackForm, $('div.form-buttons'));
|
||||
|
||||
// Checkbox: Hide Feedback Smiley
|
||||
const hideButtonContainer = append(buttonsContainer, $('div.hide-button-container'));
|
||||
|
||||
this.hideButton = append(hideButtonContainer, $('input.hide-button')) as HTMLInputElement;
|
||||
this.hideButton.type = 'checkbox';
|
||||
this.hideButton.checked = true;
|
||||
this.hideButton.id = 'hide-button';
|
||||
|
||||
const hideButtonLabel = append(hideButtonContainer, $('label'));
|
||||
hideButtonLabel.setAttribute('for', 'hide-button');
|
||||
hideButtonLabel.textContent = localize('showFeedback', "Show Feedback Icon in Status Bar");
|
||||
|
||||
// Button: Send Feedback
|
||||
this.sendButton = new Button(buttonsContainer, defaultButtonStyles);
|
||||
this.sendButton.enabled = false;
|
||||
this.sendButton.label = localize('tweet', "Tweet");
|
||||
prepend(this.sendButton.element, $(`span${ThemeIcon.asCSSSelector(Codicon.twitter)}`));
|
||||
this.sendButton.element.classList.add('send');
|
||||
this.sendButton.element.title = localize('tweetFeedback', "Tweet Feedback");
|
||||
|
||||
this.sendButton.onDidClick(() => this.onSubmit());
|
||||
|
||||
if (this.feedbackForm) {
|
||||
this.feedbackForm.style.backgroundColor = asCssVariable(editorWidgetBackground);
|
||||
this.feedbackForm.style.color = asCssVariable(editorWidgetForeground);
|
||||
this.feedbackForm.style.boxShadow = `0 0 8px 2px ${asCssVariable(widgetShadow)}`;
|
||||
this.feedbackForm.style.border = `1px solid ${asCssVariable(widgetBorder)}`;
|
||||
}
|
||||
if (this.feedbackDescriptionInput) {
|
||||
this.feedbackDescriptionInput.style.backgroundColor = asCssVariable(inputBackground);
|
||||
this.feedbackDescriptionInput.style.color = asCssVariable(inputForeground);
|
||||
this.feedbackDescriptionInput.style.border = `1px solid ${asCssVariableWithDefault(inputBorder, 'transparent')}`;
|
||||
}
|
||||
|
||||
contactUsContainer.style.backgroundColor = asCssVariable(editorBackground);
|
||||
contactUsContainer.style.border = `1px solid ${asCssVariableWithDefault(contrastBorder, 'transparent')}`;
|
||||
|
||||
|
||||
return {
|
||||
dispose: () => {
|
||||
this.feedbackForm = undefined;
|
||||
this.feedbackDescriptionInput = undefined;
|
||||
this.smileyInput = undefined;
|
||||
this.frownyInput = undefined;
|
||||
|
||||
disposables.dispose();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private updateFeedbackDescription() {
|
||||
if (this.feedbackDescriptionInput && this.feedbackDescriptionInput.textLength > this.maxFeedbackCharacters) {
|
||||
this.feedbackDescriptionInput.value = this.feedbackDescriptionInput.value.substring(0, this.maxFeedbackCharacters);
|
||||
}
|
||||
}
|
||||
|
||||
private getCharCountText(charCount: number): string {
|
||||
const remaining = this.maxFeedbackCharacters - charCount;
|
||||
const text = (remaining === 1)
|
||||
? localize("character left", "character left")
|
||||
: localize("characters left", "characters left");
|
||||
|
||||
return `(${remaining} ${text})`;
|
||||
}
|
||||
|
||||
private updateCharCountText(): void {
|
||||
if (this.feedbackDescriptionInput && this.remainingCharacterCount && this.sendButton) {
|
||||
this.remainingCharacterCount.innerText = this.getCharCountText(this.feedbackDescriptionInput.value.length);
|
||||
this.sendButton.enabled = this.feedbackDescriptionInput.value.length > 0;
|
||||
}
|
||||
}
|
||||
|
||||
private setSentiment(smile: boolean): void {
|
||||
if (smile) {
|
||||
if (this.smileyInput) {
|
||||
this.smileyInput.classList.add('checked');
|
||||
this.smileyInput.setAttribute('aria-checked', 'true');
|
||||
}
|
||||
if (this.frownyInput) {
|
||||
this.frownyInput.classList.remove('checked');
|
||||
this.frownyInput.setAttribute('aria-checked', 'false');
|
||||
}
|
||||
} else {
|
||||
if (this.frownyInput) {
|
||||
this.frownyInput.classList.add('checked');
|
||||
this.frownyInput.setAttribute('aria-checked', 'true');
|
||||
}
|
||||
if (this.smileyInput) {
|
||||
this.smileyInput.classList.remove('checked');
|
||||
this.smileyInput.setAttribute('aria-checked', 'false');
|
||||
}
|
||||
}
|
||||
|
||||
this.sentiment = smile ? 1 : 0;
|
||||
this.maxFeedbackCharacters = this.feedbackDelegate.getCharacterLimit(this.sentiment);
|
||||
this.updateFeedbackDescription();
|
||||
this.updateCharCountText();
|
||||
if (this.feedbackDescriptionInput) {
|
||||
this.feedbackDescriptionInput.maxLength = this.maxFeedbackCharacters;
|
||||
}
|
||||
}
|
||||
|
||||
private invoke(element: HTMLElement, disposables: DisposableStore, callback: () => void): HTMLElement {
|
||||
disposables.add(addDisposableListener(element, 'click', callback));
|
||||
|
||||
disposables.add(addDisposableListener(element, 'keypress', e => {
|
||||
if (e instanceof KeyboardEvent) {
|
||||
const keyboardEvent = <KeyboardEvent>e;
|
||||
if (keyboardEvent.keyCode === 13 || keyboardEvent.keyCode === 32) { // Enter or Spacebar
|
||||
callback();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
show(): void {
|
||||
if (this.visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.visible = true;
|
||||
this.contextViewService.showContextView({
|
||||
getAnchor: () => this.getAnchor(),
|
||||
|
||||
render: (container) => {
|
||||
return this.renderContents(container);
|
||||
},
|
||||
|
||||
onDOMEvent: (e, activeElement) => {
|
||||
this.onEvent(e, activeElement);
|
||||
},
|
||||
|
||||
onHide: () => this._onDidChangeVisibility.fire(false)
|
||||
});
|
||||
|
||||
this._onDidChangeVisibility.fire(true);
|
||||
|
||||
this.updateCharCountText();
|
||||
}
|
||||
|
||||
hide(): void {
|
||||
if (!this.visible) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.feedbackDescriptionInput) {
|
||||
this.feedback = this.feedbackDescriptionInput.value;
|
||||
}
|
||||
|
||||
if (this.hideButton && !this.hideButton.checked) {
|
||||
this.statusbarService.updateEntryVisibility('status.feedback', false);
|
||||
}
|
||||
|
||||
this.visible = false;
|
||||
this.contextViewService.hideContextView();
|
||||
}
|
||||
|
||||
isVisible(): boolean {
|
||||
return !!this.visible;
|
||||
}
|
||||
|
||||
private onEvent(e: Event, activeElement: HTMLElement): void {
|
||||
if (e instanceof KeyboardEvent) {
|
||||
const keyboardEvent = <KeyboardEvent>e;
|
||||
if (keyboardEvent.keyCode === 27) { // Escape
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private onSubmit(): void {
|
||||
if (!this.feedbackForm || !this.feedbackDescriptionInput || (this.feedbackForm.checkValidity && !this.feedbackForm.checkValidity())) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.feedbackDelegate.submitFeedback({
|
||||
feedback: this.feedbackDescriptionInput.value,
|
||||
sentiment: this.sentiment
|
||||
}, this.openerService);
|
||||
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
@@ -1,118 +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 { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { FeedbackWidget, IFeedback, IFeedbackDelegate } from 'vs/workbench/contrib/feedback/browser/feedback';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { IStatusbarService, StatusbarAlignment, IStatusbarEntry, IStatusbarEntryAccessor } from 'vs/workbench/services/statusbar/browser/statusbar';
|
||||
import { localize } from 'vs/nls';
|
||||
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions';
|
||||
import { Categories } from 'vs/platform/action/common/actionCommonCategories';
|
||||
import { HIDE_NOTIFICATIONS_CENTER, HIDE_NOTIFICATION_TOAST } from 'vs/workbench/browser/parts/notifications/notificationsCommands';
|
||||
import { isIOS } from 'vs/base/common/platform';
|
||||
|
||||
class TwitterFeedbackService implements IFeedbackDelegate {
|
||||
|
||||
private static TWITTER_URL: string = 'https://twitter.com/intent/tweet';
|
||||
private static VIA_NAME: string = 'code';
|
||||
private static HASHTAGS: string[] = ['HappyCoding'];
|
||||
|
||||
private combineHashTagsAsString(): string {
|
||||
return TwitterFeedbackService.HASHTAGS.join(',');
|
||||
}
|
||||
|
||||
submitFeedback(feedback: IFeedback, openerService: IOpenerService): void {
|
||||
const queryString = `?${feedback.sentiment === 1 ? `hashtags=${this.combineHashTagsAsString()}&` : ''}ref_src=twsrc%5Etfw&related=twitterapi%2Ctwitter&text=${encodeURIComponent(feedback.feedback)}&tw_p=tweetbutton&via=${TwitterFeedbackService.VIA_NAME}`;
|
||||
const url = TwitterFeedbackService.TWITTER_URL + queryString;
|
||||
|
||||
openerService.open(URI.parse(url));
|
||||
}
|
||||
|
||||
getCharacterLimit(sentiment: number): number {
|
||||
let length: number = 0;
|
||||
if (sentiment === 1) {
|
||||
TwitterFeedbackService.HASHTAGS.forEach(element => {
|
||||
length += element.length + 2;
|
||||
});
|
||||
}
|
||||
|
||||
if (TwitterFeedbackService.VIA_NAME) {
|
||||
length += ` via @${TwitterFeedbackService.VIA_NAME}`.length;
|
||||
}
|
||||
|
||||
return 280 - length;
|
||||
}
|
||||
}
|
||||
|
||||
export class FeedbackStatusbarConribution extends Disposable implements IWorkbenchContribution {
|
||||
|
||||
private static readonly TOGGLE_FEEDBACK_COMMAND = 'help.tweetFeedback';
|
||||
|
||||
private widget: FeedbackWidget | undefined;
|
||||
private entry: IStatusbarEntryAccessor | undefined;
|
||||
|
||||
constructor(
|
||||
@IStatusbarService private readonly statusbarService: IStatusbarService,
|
||||
@IProductService productService: IProductService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@ICommandService private readonly commandService: ICommandService) {
|
||||
super();
|
||||
|
||||
if (productService.sendASmile && !isIOS) {
|
||||
this.createFeedbackStatusEntry();
|
||||
}
|
||||
}
|
||||
|
||||
private createFeedbackStatusEntry(): void {
|
||||
|
||||
// Status entry
|
||||
this.entry = this._register(this.statusbarService.addEntry(this.getStatusEntry(), 'status.feedback', StatusbarAlignment.RIGHT, -100 /* towards the end of the right hand side */));
|
||||
|
||||
// Command to toggle
|
||||
CommandsRegistry.registerCommand(FeedbackStatusbarConribution.TOGGLE_FEEDBACK_COMMAND, () => this.toggleFeedback());
|
||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
|
||||
command: {
|
||||
id: FeedbackStatusbarConribution.TOGGLE_FEEDBACK_COMMAND,
|
||||
category: Categories.Help,
|
||||
title: localize('status.feedback', "Tweet Feedback")
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private toggleFeedback(): void {
|
||||
if (!this.widget) {
|
||||
this.widget = this._register(this.instantiationService.createInstance(FeedbackWidget, {
|
||||
feedbackService: this.instantiationService.createInstance(TwitterFeedbackService)
|
||||
}));
|
||||
this._register(this.widget.onDidChangeVisibility(visible => this.entry!.update(this.getStatusEntry(visible))));
|
||||
}
|
||||
|
||||
if (this.widget) {
|
||||
if (!this.widget.isVisible()) {
|
||||
this.commandService.executeCommand(HIDE_NOTIFICATION_TOAST);
|
||||
this.commandService.executeCommand(HIDE_NOTIFICATIONS_CENTER);
|
||||
this.widget.show();
|
||||
} else {
|
||||
this.widget.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private getStatusEntry(showBeak?: boolean): IStatusbarEntry {
|
||||
return {
|
||||
name: localize('status.feedback.name', "Feedback"),
|
||||
text: '$(feedback)',
|
||||
ariaLabel: localize('status.feedback', "Tweet Feedback"),
|
||||
tooltip: localize('status.feedback', "Tweet Feedback"),
|
||||
command: FeedbackStatusbarConribution.TOGGLE_FEEDBACK_COMMAND,
|
||||
showBeak
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,245 +0,0 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-workbench .feedback-form {
|
||||
width: 420px;
|
||||
top: 30px;
|
||||
right: 6px;
|
||||
padding: 1em;
|
||||
cursor: default;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form h2 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-weight: normal;
|
||||
font-size: 1.8em;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form h3 {
|
||||
margin: 1em 0 0;
|
||||
padding: 0;
|
||||
font-weight: normal;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .content {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .content > div {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .content .contactus {
|
||||
padding: 10px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .content .channels {
|
||||
margin-top: 5px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.monaco-workbench .char-counter {
|
||||
padding-left: 3px;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .content .channels a {
|
||||
padding: 2px 0;
|
||||
color: var(--vscode-textLink-foreground, var(--vscode-contrastBorder));
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .content .channels a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .feedback-alias, .monaco-workbench .feedback-form .feedback-description {
|
||||
resize: none;
|
||||
font-size: 1.1em;
|
||||
margin: 6px 0 0;
|
||||
width: 100%;
|
||||
padding: 3px 2px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .feedback-empty {
|
||||
margin-top: .2em;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .feedback-alias-checkbox {
|
||||
display: inline-block;
|
||||
vertical-align: text-top;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .feedback-alias {
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .feedback-alias:disabled {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .cancel {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
padding: .5em;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .form-buttons {
|
||||
margin-top: 18px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .sentiment {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
display: inline-block;
|
||||
margin: .5em 0;
|
||||
cursor: pointer;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .sentiment:hover {
|
||||
background-color: #eaeaea;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .sentiment.checked {
|
||||
border: 1px solid var(--vscode-inputOption-activeBorder);
|
||||
}
|
||||
|
||||
/* Theming */
|
||||
.monaco-workbench.vs .feedback-form .feedback-alias,
|
||||
.monaco-workbench.vs .feedback-form .feedback-description {
|
||||
font-family: inherit;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .form-buttons {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .form-buttons .hide-button-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .form-buttons .hide-button-container input,
|
||||
.monaco-workbench .feedback-form .form-buttons .hide-button-container label {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .form-buttons .send {
|
||||
width: auto;
|
||||
padding: 8px 12px;
|
||||
margin-left: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .form-buttons .send .codicon {
|
||||
color: currentColor;
|
||||
font-size: 20px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .form-buttons .send.in-progress,
|
||||
.monaco-workbench .feedback-form .form-buttons .send:hover {
|
||||
background-color: #006BB3;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .form-buttons .send:disabled {
|
||||
pointer-events: none;
|
||||
cursor: not-allowed;
|
||||
opacity: .65;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .form-buttons .send.success {
|
||||
background-color: #2d883e;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .form-buttons .send.error {
|
||||
background-color: #E51400;
|
||||
}
|
||||
|
||||
.monaco-workbench.vs-dark .feedback-form h3 {
|
||||
font-weight: normal;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.monaco-workbench.vs-dark .feedback-form .sentiment:hover {
|
||||
background-color: rgba(30,30,30,0.8);
|
||||
}
|
||||
|
||||
.monaco-workbench.vs-dark .feedback-form .feedback-alias,
|
||||
.monaco-workbench.vs-dark .feedback-form .feedback-description {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .sentiment.smile {
|
||||
background-image: url('happy.svg');
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.monaco-workbench .feedback-form .sentiment.frown {
|
||||
background-image: url('sad.svg');
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
/* High Contrast Theming */
|
||||
.monaco-workbench.hc-black .feedback-form {
|
||||
outline: 2px solid #6fc3df;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.monaco-workbench.hc-light .feedback-form {
|
||||
outline: 2px solid #0F4A85;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
|
||||
.monaco-workbench.hc-black .feedback-form .feedback-alias,
|
||||
.monaco-workbench.hc-black .feedback-form .feedback-description,
|
||||
.monaco-workbench.hc-light .feedback-form .feedback-alias,
|
||||
.monaco-workbench.hc-light .feedback-form .feedback-description {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.monaco-workbench.hc-black .feedback-form .content .contactus,
|
||||
.monaco-workbench.hc-light .feedback-form .content .contactus {
|
||||
padding: 10px;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.monaco-workbench.hc-black .feedback-form .form-buttons .send,
|
||||
.monaco-workbench.hc-black .feedback-form .form-buttons .send.in-progress,
|
||||
.monaco-workbench.hc-black .feedback-form .form-buttons .send.success {
|
||||
background-color: #0C141F;
|
||||
color: #D4D4D4;
|
||||
border: 1px solid #6FC3DF;
|
||||
}
|
||||
|
||||
.monaco-workbench.hc-light .feedback-form .form-buttons .send,
|
||||
.monaco-workbench.hc-light .feedback-form .form-buttons .send.in-progress,
|
||||
.monaco-workbench.hc-light .feedback-form .form-buttons .send.success {
|
||||
background-color: #FFFFFF;
|
||||
color: #292929;
|
||||
border: 1px solid #0F4A85;
|
||||
}
|
||||
|
||||
.monaco-workbench.hc-black .feedback-form .form-buttons .send:hover {
|
||||
background-color: #0C141F;
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><g><path fill="#fc0" d="M8 1c-3.866 0-7 3.134-7 7s3.134 7 7 7 7-3.134 7-7-3.134-7-7-7z"/><path fill="#424242" d="M11 6.5c0 .5-.447.5-1 .5s-1 0-1-.5c0-1.104 1-1.5 1-1.5s1 .396 1 1.5z"/><path fill="#424242" d="M10.943 9.025c-.457 1.177-1.644 2.058-2.943 2.058s-2.455-.881-2.899-2.058h-.952c.455 1.709 1.999 2.975 3.851 2.975 1.853 0 3.396-1.266 3.851-2.975h-.908z"/><path fill="#424242" d="M7 6.5s-.447.5-1 .5-1 0-1-.5c0-1.104 1-1.5 1-1.5s1 .396 1 1.5z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 580 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 16 16" enable-background="new 0 0 16 16"><g><circle fill="#fc0" cx="8" cy="8" r="7"/><path fill="#424242" d="M10.973 6.5c0 .5-.447.5-1 .5s-1 0-1-.5c0-1.104 1-1.5 1-1.5s1 .396 1 1.5z"/><path fill="#424242" d="M6.973 6.5c0 .5-.447.5-1 .5s-1 0-1-.5c0-1.104 1-1.5 1-1.5s1 .396 1 1.5z"/><path fill="#424242" d="M5.104 12c.459-1.146 1.593-2 2.869-2 1.277 0 2.439.854 2.912 2h.916c-.475-1.678-1.998-2.917-3.828-2.917s-3.355 1.239-3.83 2.917h.961z"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 528 B |
@@ -13,7 +13,7 @@ import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiati
|
||||
import { IEditorGroupsService, IEditorGroup, GroupsOrder, GroupOrientation } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { Verbosity, EditorResourceAccessor, SideBySideEditor, IEditorIdentifier, GroupModelChangeKind } from 'vs/workbench/common/editor';
|
||||
import { Verbosity, EditorResourceAccessor, SideBySideEditor, IEditorIdentifier, GroupModelChangeKind, preventEditorClose, EditorCloseMethod } from 'vs/workbench/common/editor';
|
||||
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
import { SaveAllInGroupAction, CloseGroupAction } from 'vs/workbench/contrib/files/browser/fileActions';
|
||||
import { OpenEditorsFocusedContext, ExplorerFocusedContext, IFilesConfiguration, OpenEditor } from 'vs/workbench/contrib/files/common/files';
|
||||
@@ -268,6 +268,10 @@ export class OpenEditorsView extends ViewPane {
|
||||
// Open when selecting via keyboard
|
||||
this._register(this.list.onMouseMiddleClick(e => {
|
||||
if (e && e.element instanceof OpenEditor) {
|
||||
if (preventEditorClose(e.element.group, e.element.editor, EditorCloseMethod.MOUSE, this.editorGroupService.partOptions)) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.element.group.closeEditor(e.element.editor, { preserveFocus: true });
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -26,7 +26,7 @@ import { MarkdownString } from 'vs/base/common/htmlContent';
|
||||
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { IStorageService, IStorageValueChangeEvent, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
|
||||
import { equals } from 'vs/base/common/arrays';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
|
||||
@@ -83,7 +83,7 @@ class EditorStatusContribution implements IWorkbenchContribution {
|
||||
@IOpenerService private readonly _openerService: IOpenerService,
|
||||
@IStorageService private readonly _storageService: IStorageService,
|
||||
) {
|
||||
_storageService.onDidChangeValue(this._handleStorageChange, this, this._disposables);
|
||||
_storageService.onDidChangeValue(StorageScope.PROFILE, EditorStatusContribution._keyDedicatedItems, this._disposables)(this._handleStorageChange, this, this._disposables);
|
||||
this._restoreState();
|
||||
this._interactionCounter = new StoredCounter(_storageService, 'languageStatus.interactCount');
|
||||
|
||||
@@ -110,10 +110,7 @@ class EditorStatusContribution implements IWorkbenchContribution {
|
||||
|
||||
// --- persisting dedicated items
|
||||
|
||||
private _handleStorageChange(e: IStorageValueChangeEvent) {
|
||||
if (e.key !== EditorStatusContribution._keyDedicatedItems) {
|
||||
return;
|
||||
}
|
||||
private _handleStorageChange() {
|
||||
this._restoreState();
|
||||
this._update();
|
||||
}
|
||||
|
||||
@@ -2527,7 +2527,7 @@ class ApplySettingToAllProfilesAction extends Action {
|
||||
|
||||
const newValue = distinct(value);
|
||||
if (this.checked) {
|
||||
await this.configService.updateValue(this.setting.key, this.configService.inspect(this.setting.key).userLocal?.value, ConfigurationTarget.USER_LOCAL);
|
||||
await this.configService.updateValue(this.setting.key, this.configService.inspect(this.setting.key).application?.value, ConfigurationTarget.USER_LOCAL);
|
||||
await this.configService.updateValue(APPLY_ALL_PROFILES_SETTING, newValue.length ? newValue : undefined, ConfigurationTarget.USER_LOCAL);
|
||||
} else {
|
||||
await this.configService.updateValue(APPLY_ALL_PROFILES_SETTING, newValue.length ? newValue : undefined, ConfigurationTarget.USER_LOCAL);
|
||||
|
||||
@@ -214,15 +214,13 @@ export class RemoteTunnelWorkbenchContribution extends Disposable implements IWo
|
||||
return true;
|
||||
};
|
||||
if (await shouldRecommend()) {
|
||||
const storageListener = this.storageService.onDidChangeValue(async e => {
|
||||
if (e.key === REMOTE_TUNNEL_USED_STORAGE_KEY) {
|
||||
const success = await recommed();
|
||||
if (success) {
|
||||
storageListener.dispose();
|
||||
}
|
||||
|
||||
const disposables = this._register(new DisposableStore());
|
||||
disposables.add(this.storageService.onDidChangeValue(StorageScope.APPLICATION, REMOTE_TUNNEL_USED_STORAGE_KEY, disposables)(async () => {
|
||||
const success = await recommed();
|
||||
if (success) {
|
||||
disposables.dispose();
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1237,16 +1237,16 @@ class ViewModel {
|
||||
|
||||
this.disposables.add(this.tree.onDidChangeCollapseState(() => this._treeViewStateIsStale = true));
|
||||
|
||||
this.storageService.onWillSaveState(e => {
|
||||
this.disposables.add(this.storageService.onWillSaveState(e => {
|
||||
if (e.reason === WillSaveStateReason.SHUTDOWN) {
|
||||
this.storageService.store(`scm.viewState`, JSON.stringify(this.treeViewState), StorageScope.WORKSPACE, StorageTarget.MACHINE);
|
||||
}
|
||||
|
||||
this.mode = this.getViewModelMode();
|
||||
this.sortKey = this.getViewModelSortKey();
|
||||
});
|
||||
}));
|
||||
|
||||
this.storageService.onDidChangeValue(e => {
|
||||
this.disposables.add(this.storageService.onDidChangeValue(StorageScope.WORKSPACE, undefined, this.disposables)(e => {
|
||||
switch (e.key) {
|
||||
case 'scm.viewMode':
|
||||
this.mode = this.getViewModelMode();
|
||||
@@ -1255,7 +1255,7 @@ class ViewModel {
|
||||
this.sortKey = this.getViewModelSortKey();
|
||||
break;
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
private onDidChangeConfiguration(e?: IConfigurationChangeEvent): void {
|
||||
|
||||
@@ -263,22 +263,20 @@ export class SearchView extends ViewPane {
|
||||
this._saveSearchHistoryService();
|
||||
}));
|
||||
|
||||
this._register(this.storageService.onDidChangeValue((v) => {
|
||||
if (v.key === SearchHistoryService.SEARCH_HISTORY_KEY) {
|
||||
const restoredHistory = this.searchHistoryService.load();
|
||||
this._register(this.storageService.onDidChangeValue(StorageScope.WORKSPACE, SearchHistoryService.SEARCH_HISTORY_KEY, this._register(new DisposableStore()))(() => {
|
||||
const restoredHistory = this.searchHistoryService.load();
|
||||
|
||||
if (restoredHistory.include) {
|
||||
this.inputPatternIncludes.prependHistory(restoredHistory.include);
|
||||
}
|
||||
if (restoredHistory.exclude) {
|
||||
this.inputPatternExcludes.prependHistory(restoredHistory.exclude);
|
||||
}
|
||||
if (restoredHistory.search) {
|
||||
this.searchWidget.prependSearchHistory(restoredHistory.search);
|
||||
}
|
||||
if (restoredHistory.replace) {
|
||||
this.searchWidget.prependReplaceHistory(restoredHistory.replace);
|
||||
}
|
||||
if (restoredHistory.include) {
|
||||
this.inputPatternIncludes.prependHistory(restoredHistory.include);
|
||||
}
|
||||
if (restoredHistory.exclude) {
|
||||
this.inputPatternExcludes.prependHistory(restoredHistory.exclude);
|
||||
}
|
||||
if (restoredHistory.search) {
|
||||
this.searchWidget.prependSearchHistory(restoredHistory.search);
|
||||
}
|
||||
if (restoredHistory.replace) {
|
||||
this.searchWidget.prependReplaceHistory(restoredHistory.replace);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ suite('extractRangeFromFilter', () => {
|
||||
assert.strictEqual(res?.range.startColumn, 20);
|
||||
});
|
||||
|
||||
suite('unless', async function () {
|
||||
suite('unless', function () {
|
||||
const testSpecs = [
|
||||
// alpha-only symbol after unless
|
||||
{ filter: '/some/path/file.txt@alphasymbol', unless: ['@'], result: undefined },
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { env } from 'vs/base/common/process';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { LRUCache } from 'vs/base/common/map';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { FileOperationError, FileOperationResult, IFileContent, IFileService } from 'vs/platform/files/common/files';
|
||||
@@ -128,18 +128,18 @@ export class TerminalPersistedHistory<T> extends Disposable implements ITerminal
|
||||
this._entries = new LRUCache<string, T>(this._getHistoryLimit());
|
||||
|
||||
// Listen for config changes to set history limit
|
||||
this._configurationService.onDidChangeConfiguration(e => {
|
||||
this._register(this._configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration(TerminalSettingId.ShellIntegrationCommandHistory)) {
|
||||
this._entries.limit = this._getHistoryLimit();
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
// Listen to cache changes from other windows
|
||||
this._storageService.onDidChangeValue(e => {
|
||||
if (e.key === this._getTimestampStorageKey() && !this._isStale) {
|
||||
this._register(this._storageService.onDidChangeValue(StorageScope.APPLICATION, this._getTimestampStorageKey(), this._register(new DisposableStore()))(() => {
|
||||
if (!this._isStale) {
|
||||
this._isStale = this._storageService.getNumber(this._getTimestampStorageKey(), StorageScope.APPLICATION, 0) !== this._timestamp;
|
||||
}
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
add(key: string, value: T) {
|
||||
|
||||
@@ -71,7 +71,7 @@ suite('DecorationAddon', () => {
|
||||
instantiationService.dispose();
|
||||
});
|
||||
|
||||
suite('registerDecoration', async () => {
|
||||
suite('registerDecoration', () => {
|
||||
test('should throw when command has no marker', async () => {
|
||||
throws(() => decorationAddon.registerCommandDecoration({ command: 'cd src', timestamp: Date.now(), hasOutput: () => false } as ITerminalCommand));
|
||||
});
|
||||
|
||||
@@ -39,7 +39,7 @@ suite('ShellIntegrationAddon', () => {
|
||||
capabilities = shellIntegrationAddon.capabilities;
|
||||
});
|
||||
|
||||
suite('cwd detection', async () => {
|
||||
suite('cwd detection', () => {
|
||||
test('should activate capability on the cwd sequence (OSC 633 ; P ; Cwd=<cwd> ST)', async () => {
|
||||
strictEqual(capabilities.has(TerminalCapability.CwdDetection), false);
|
||||
await writeP(xterm, 'foo');
|
||||
@@ -70,7 +70,7 @@ suite('ShellIntegrationAddon', () => {
|
||||
}
|
||||
});
|
||||
|
||||
suite('detect `SetCwd` sequence: `OSC 7; scheme://cwd ST`', async () => {
|
||||
suite('detect `SetCwd` sequence: `OSC 7; scheme://cwd ST`', () => {
|
||||
test('should accept well-formatted URLs', async () => {
|
||||
type TestCase = [title: string, input: string, expected: string];
|
||||
const cases: TestCase[] = [
|
||||
@@ -133,7 +133,7 @@ suite('ShellIntegrationAddon', () => {
|
||||
});
|
||||
});
|
||||
|
||||
suite('command tracking', async () => {
|
||||
suite('command tracking', () => {
|
||||
test('should activate capability on the prompt start sequence (OSC 633 ; A ST)', async () => {
|
||||
strictEqual(capabilities.has(TerminalCapability.CommandDetection), false);
|
||||
await writeP(xterm, 'foo');
|
||||
@@ -212,7 +212,7 @@ suite('ShellIntegrationAddon', () => {
|
||||
mock.verify();
|
||||
});
|
||||
});
|
||||
suite('BufferMarkCapability', async () => {
|
||||
suite('BufferMarkCapability', () => {
|
||||
test('SetMark', async () => {
|
||||
strictEqual(capabilities.has(TerminalCapability.BufferMarkDetection), false);
|
||||
await writeP(xterm, 'foo');
|
||||
|
||||
@@ -160,7 +160,7 @@ suite('Terminal history', () => {
|
||||
});
|
||||
|
||||
if (!isWindows) {
|
||||
suite('local', async () => {
|
||||
suite('local', () => {
|
||||
let originalEnvValues: { HOME: string | undefined };
|
||||
setup(() => {
|
||||
originalEnvValues = { HOME: env['HOME'] };
|
||||
@@ -344,7 +344,7 @@ suite('Terminal history', () => {
|
||||
instantiationService.dispose();
|
||||
});
|
||||
|
||||
suite('local', async () => {
|
||||
suite('local', () => {
|
||||
let originalEnvValues: { HOME: string | undefined; APPDATA: string | undefined };
|
||||
setup(() => {
|
||||
originalEnvValues = { HOME: env['HOME'], APPDATA: env['APPDATA'] };
|
||||
|
||||
@@ -92,7 +92,7 @@ suite('Workbench - TerminalProfiles', () => {
|
||||
const expected = [{ profileName: 'Git Bash', path: 'C:\\Program Files\\Git\\bin\\bash.exe', args: [], isAutoDetected: undefined, overrideName: undefined, isDefault: true }];
|
||||
profilesEqual(profiles, expected);
|
||||
});
|
||||
suite('pwsh source detection/fallback', async () => {
|
||||
suite('pwsh source detection/fallback', () => {
|
||||
const pwshSourceConfig = ({
|
||||
profiles: {
|
||||
windows: {
|
||||
|
||||
+2
-2
@@ -73,7 +73,7 @@ suite('QuickFixAddon', () => {
|
||||
instantiationService.dispose();
|
||||
});
|
||||
suite('registerCommandFinishedListener & getMatchActions', () => {
|
||||
suite('gitSimilarCommand', async () => {
|
||||
suite('gitSimilarCommand', () => {
|
||||
const expectedMap = new Map();
|
||||
const command = `git sttatus`;
|
||||
let output = `git: 'sttatus' is not a git command. See 'git --help'.
|
||||
@@ -149,7 +149,7 @@ suite('QuickFixAddon', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
suite('gitTwoDashes', async () => {
|
||||
suite('gitTwoDashes', () => {
|
||||
const expectedMap = new Map();
|
||||
const command = `git add . -all`;
|
||||
const output = 'error: did you mean `--all` (with two dashes)?';
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user