', 'javascript', ' return;\n foo(); ');
});
});
diff --git a/extensions/html-language-features/server/yarn.lock b/extensions/html-language-features/server/yarn.lock
index c467e1ac9b4..2532ccb506a 100644
--- a/extensions/html-language-features/server/yarn.lock
+++ b/extensions/html-language-features/server/yarn.lock
@@ -67,12 +67,7 @@ vscode-nls@^5.2.0:
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.2.0.tgz#3cb6893dd9bd695244d8a024bdf746eea665cc3f"
integrity sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==
-vscode-uri@^3.0.4:
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.4.tgz#703c6dd7c0b727ee1c34a1287434138fb52d054f"
- integrity sha512-aEmKD6H8Sg8gaQAUrnadG0BMeWXtiWhRsj1a94n2FYsMkDpgnK7BRVzZjOUYIvkv2B+bp5Bmt4ImZCpYbnJwkg==
-
-vscode-uri@^3.0.5:
- version "3.0.5"
- resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.5.tgz#3dd5a9e154e7c9a40de5eaa450a0ce59b435e584"
- integrity sha512-bBp2pi1o6ynwlnGL8Tt6UBL1w3VsVZtHCU/Sl73bRfqjno3jMcVSCybdY+hj+31A8FQOELZJWwY+shLVLtcNew==
+vscode-uri@^3.0.6, vscode-uri@^3.0.4:
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.6.tgz#5e6e2e1a4170543af30151b561a41f71db1d6f91"
+ integrity sha512-fmL7V1eiDBFRRnu+gfRWTzyPpNIHJTc4mWnFkwBUmO9U3KPgJAmTx7oxi2bl/Rh6HLdU7+4C9wlj0k2E4AdKFQ==
diff --git a/extensions/html-language-features/yarn.lock b/extensions/html-language-features/yarn.lock
index cfe8b8f7ad1..478e8548591 100644
--- a/extensions/html-language-features/yarn.lock
+++ b/extensions/html-language-features/yarn.lock
@@ -116,10 +116,10 @@ vscode-nls@^5.2.0:
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.2.0.tgz#3cb6893dd9bd695244d8a024bdf746eea665cc3f"
integrity sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==
-vscode-uri@^3.0.5:
- version "3.0.5"
- resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.5.tgz#3dd5a9e154e7c9a40de5eaa450a0ce59b435e584"
- integrity sha512-bBp2pi1o6ynwlnGL8Tt6UBL1w3VsVZtHCU/Sl73bRfqjno3jMcVSCybdY+hj+31A8FQOELZJWwY+shLVLtcNew==
+vscode-uri@^3.0.6:
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.6.tgz#5e6e2e1a4170543af30151b561a41f71db1d6f91"
+ integrity sha512-fmL7V1eiDBFRRnu+gfRWTzyPpNIHJTc4mWnFkwBUmO9U3KPgJAmTx7oxi2bl/Rh6HLdU7+4C9wlj0k2E4AdKFQ==
yallist@^4.0.0:
version "4.0.0"
diff --git a/extensions/html/package.json b/extensions/html/package.json
index aad035c05cc..238f1348955 100644
--- a/extensions/html/package.json
+++ b/extensions/html/package.json
@@ -76,6 +76,12 @@
"meta.tag string.quoted": "other"
}
}
+ ],
+ "snippets": [
+ {
+ "language": "html",
+ "path": "./snippets/html.code-snippets"
+ }
]
},
"repository": {
diff --git a/extensions/html/snippets/html.code-snippets b/extensions/html/snippets/html.code-snippets
new file mode 100644
index 00000000000..62d61b43b7b
--- /dev/null
+++ b/extensions/html/snippets/html.code-snippets
@@ -0,0 +1,18 @@
+{
+ "html doc": {
+ "isFileTemplate": true,
+ "body": [
+ "",
+ "",
+ "",
+ "\t
",
+ "\t
${1:title}",
+ "",
+ "",
+ "\t$0",
+ "",
+ ""
+ ],
+ "description": "HTML Document"
+ }
+}
diff --git a/extensions/image-preview/README.md b/extensions/image-preview/README.md
deleted file mode 100644
index d3f0bd6cb6c..00000000000
--- a/extensions/image-preview/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# Image Preview
-
-**Notice:** This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled.
-
-## Features
-
-This extension provides VS Code's built-in image preview functionality.
-
-Supported image formats:
-
-- `*.jpg`, `*.jpe`, `*.jpeg`
-- `*.png`
-- `*.bmp`
-- `*.gif`
-- `*.ico`
-- `*.webp`
diff --git a/extensions/ipynb/src/notebookAttachmentCleaner.ts b/extensions/ipynb/src/notebookAttachmentCleaner.ts
index 265c284d984..a72761754df 100644
--- a/extensions/ipynb/src/notebookAttachmentCleaner.ts
+++ b/extensions/ipynb/src/notebookAttachmentCleaner.ts
@@ -153,16 +153,16 @@ export class AttachmentCleaner implements vscode.CodeActionProvider {
this.saveAllAttachmentsToCache(cell.metadata, notebookUri, cellFragment);
}
- if (this.checkMetadataAttachmentsExistence(cell.metadata)) {
+ if (this.checkMetadataHasAttachmentsField(cell.metadata)) {
// the cell metadata contains attachments, check if any are used in the markdown source
- for (const currFilename of Object.keys(cell.metadata.attachments)) {
+ for (const [currFilename, attachment] of Object.entries(cell.metadata.attachments)) {
// means markdown reference is present in the metadata, rendering will work properly
// therefore, we don't need to check it in the next loop either
if (markdownAttachmentsRefedInCell.has(currFilename)) {
// attachment reference is present in the markdown source, no need to cache it
markdownAttachmentsRefedInCell.get(currFilename)!.valid = true;
- markdownAttachmentsInUse[currFilename] = cell.metadata.attachments[currFilename];
+ markdownAttachmentsInUse[currFilename] = attachment as IAttachmentData;
} else {
// attachment reference is not present in the markdown source, cache it
this.saveAttachmentToCache(notebookUri, cellFragment, currFilename, cell.metadata);
@@ -227,7 +227,7 @@ export class AttachmentCleaner implements vscode.CodeActionProvider {
const diagnostics: IAttachmentDiagnostic[] = [];
const markdownAttachments = this.getAttachmentNames(document);
- if (this.checkMetadataAttachmentsExistence(activeCell.metadata)) {
+ if (this.checkMetadataHasAttachmentsField(activeCell.metadata)) {
for (const [currFilename, attachment] of markdownAttachments) {
if (!activeCell.metadata.attachments[currFilename]) {
// no attachment reference in the metadata
@@ -295,8 +295,8 @@ export class AttachmentCleaner implements vscode.CodeActionProvider {
* @param metadata metadata of cell
* @returns boolean representing the presence of any attachments
*/
- private checkMetadataAttachmentsExistence(metadata: { [key: string]: any }): boolean {
- return !!(metadata.attachments);
+ private checkMetadataHasAttachmentsField(metadata: { [key: string]: unknown }): metadata is { readonly attachments: Record
} {
+ return !!metadata.attachments && typeof metadata.attachments === 'object';
}
/**
@@ -305,14 +305,16 @@ export class AttachmentCleaner implements vscode.CodeActionProvider {
* @param notebookUri uri for the notebook being edited
* @param cellFragment fragment of cell being edited
*/
- private saveAllAttachmentsToCache(metadata: { [key: string]: any }, notebookUri: string, cellFragment: string): void {
+ private saveAllAttachmentsToCache(metadata: { [key: string]: unknown }, notebookUri: string, cellFragment: string): void {
const documentCache = this._attachmentCache.get(notebookUri) ?? new Map();
this._attachmentCache.set(notebookUri, documentCache);
const cellCache = documentCache.get(cellFragment) ?? new Map();
documentCache.set(cellFragment, cellCache);
- for (const currFilename of Object.keys(metadata.attachments)) {
- cellCache.set(currFilename, metadata.attachments[currFilename]);
+ if (metadata.attachments && typeof metadata.attachments === 'object') {
+ for (const [currFilename, attachment] of Object.entries(metadata.attachments)) {
+ cellCache.set(currFilename, attachment);
+ }
}
}
diff --git a/extensions/jake/package.json b/extensions/jake/package.json
index 5ffa78e3981..4e6a94a8b24 100644
--- a/extensions/jake/package.json
+++ b/extensions/jake/package.json
@@ -17,7 +17,7 @@
"watch": "gulp watch-extension:jake"
},
"dependencies": {
- "vscode-nls": "^5.1.0"
+ "vscode-nls": "^5.2.0"
},
"devDependencies": {
"@types/node": "16.x"
diff --git a/extensions/jake/yarn.lock b/extensions/jake/yarn.lock
index 90475ddc7e0..8b8c7a6c15b 100644
--- a/extensions/jake/yarn.lock
+++ b/extensions/jake/yarn.lock
@@ -7,7 +7,7 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae"
integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==
-vscode-nls@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.1.0.tgz#443b301a7465d88c81c0f4e1914f9857f0dce1e4"
- integrity sha512-37Ha44QrLFwR2IfSSYdOArzUvOyoWbOYTwQC+wS0NfqKjhW7s0WQ1lMy5oJXgSZy9sAiZS5ifELhbpXodeMR8w==
+vscode-nls@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.2.0.tgz#3cb6893dd9bd695244d8a024bdf746eea665cc3f"
+ integrity sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==
diff --git a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json
index 1695f820fcc..ed2e78282ca 100644
--- a/extensions/javascript/syntaxes/JavaScript.tmLanguage.json
+++ b/extensions/javascript/syntaxes/JavaScript.tmLanguage.json
@@ -4,7 +4,7 @@
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request."
],
- "version": "https://github.com/microsoft/TypeScript-TmLanguage/commit/73af17bf3e45339df06d92751ab366ce96c38516",
+ "version": "https://github.com/microsoft/TypeScript-TmLanguage/commit/c2744520e325330d0608fc1d1993d7fe98e66202",
"name": "JavaScript (with React support)",
"scopeName": "source.js",
"patterns": [
@@ -2674,7 +2674,7 @@
{
"name": "meta.object.member.js meta.object-literal.key.js",
"begin": "(?=[\\'\\\"\\`])",
- "end": "(?=:)|((?<=[\\'\\\"\\`])(?=((\\s*[\\(\\<,}])|(\\s+(as)\\s+))))",
+ "end": "(?=:)|((?<=[\\'\\\"\\`])(?=((\\s*[\\(\\<,}])|(\\s+(as|satisifies)\\s+))))",
"patterns": [
{
"include": "#comment"
@@ -2687,7 +2687,7 @@
{
"name": "meta.object.member.js meta.object-literal.key.js",
"begin": "(?x)(?=(\\b(?]|\\|\\||\\&\\&|\\!\\=\\=|$|^|((?]|\\|\\||\\&\\&|\\!\\=\\=|$|^|((?]|\\|\\||\\&\\&|\\!\\=\\=|$|((?]|\\|\\||\\&\\&|\\!\\=\\=|$|((?]|\\|\\||\\&\\&|\\!\\=\\=|$|^|((?]|\\|\\||\\&\\&|\\!\\=\\=|$|^|((?]|\\|\\||\\&\\&|\\!\\=\\=|$|((?]|\\|\\||\\&\\&|\\!\\=\\=|$|((?(
+ const alwaysItem: vscode.MessageItem = {
+ title: localize('always.title', "Always automatically update Markdown Links"),
+ };
+
+ const neverItem: vscode.MessageItem = {
+ title: localize('never.title', "Never automatically update Markdown Links"),
+ };
+
+ const choice = await vscode.window.showInformationMessage(
newResources.length === 1
? localize('prompt', "Update Markdown links for '{0}'?", path.basename(newResources[0].fsPath))
: this.getConfirmMessage(localize('promptMoreThanOne', "Update Markdown link for the following {0} files?", newResources.length), newResources), {
modal: true,
- }, {
- title: localize('reject.title', "No"),
- choice: Choice.Reject,
- isCloseAffordance: true,
- }, {
- title: localize('accept.title', "Yes"),
- choice: Choice.Accept,
- }, {
- title: localize('always.title', "Always automatically update Markdown Links"),
- choice: Choice.Always,
- }, {
- title: localize('never.title', "Never automatically update Markdown Links"),
- choice: Choice.Never,
- });
+ }, rejectItem, acceptItem, alwaysItem, neverItem);
- if (!response) {
- return false;
- }
-
- switch (response.choice) {
- case Choice.Accept: {
+ switch (choice) {
+ case acceptItem: {
return true;
}
- case Choice.Reject: {
+ case rejectItem: {
return false;
}
- case Choice.Always: {
+ case alwaysItem: {
const config = vscode.workspace.getConfiguration('markdown', newResources[0]);
config.update(
settingNames.enabled,
@@ -174,7 +162,7 @@ class UpdateLinksOnFileRenameHandler extends Disposable {
this.getConfigTargetScope(config, settingNames.enabled));
return true;
}
- case Choice.Never: {
+ case neverItem: {
const config = vscode.workspace.getConfiguration('markdown', newResources[0]);
config.update(
settingNames.enabled,
@@ -182,9 +170,10 @@ class UpdateLinksOnFileRenameHandler extends Disposable {
this.getConfigTargetScope(config, settingNames.enabled));
return false;
}
+ default: {
+ return false;
+ }
}
-
- return false;
}
private async getEditsForFileRename(renames: readonly RenameAction[], token: vscode.CancellationToken): Promise<{ edit: vscode.WorkspaceEdit; resourcesBeingRenamed: vscode.Uri[] } | undefined> {
diff --git a/extensions/markdown-language-features/src/preview/preview.ts b/extensions/markdown-language-features/src/preview/preview.ts
index 26f94614ad8..51348bd7128 100644
--- a/extensions/markdown-language-features/src/preview/preview.ts
+++ b/extensions/markdown-language-features/src/preview/preview.ts
@@ -158,7 +158,7 @@ class MarkdownPreview extends Disposable implements WebviewResourceProvider {
this._register(watcher.onDidChange(uri => {
if (this.isPreviewOf(uri)) {
// Only use the file system event when VS Code does not already know about the file
- if (!vscode.workspace.textDocuments.some(doc => doc.uri.toString() !== uri.toString())) {
+ if (!vscode.workspace.textDocuments.some(doc => doc.uri.toString() === uri.toString())) {
this.refresh();
}
}
diff --git a/extensions/markdown-language-features/yarn.lock b/extensions/markdown-language-features/yarn.lock
index 5ffe3ff4b82..6bd778ed899 100644
--- a/extensions/markdown-language-features/yarn.lock
+++ b/extensions/markdown-language-features/yarn.lock
@@ -258,10 +258,10 @@ vscode-nls@^5.0.1:
resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.0.1.tgz#ba23fc4d4420d25e7f886c8e83cbdcec47aa48b2"
integrity sha512-hHQV6iig+M21lTdItKPkJAaWrxALQb/nqpVffakO4knJOh3DrU2SXOMzUzNgo1eADPzu3qSsJY1weCzvR52q9A==
-vscode-nls@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.1.0.tgz#443b301a7465d88c81c0f4e1914f9857f0dce1e4"
- integrity sha512-37Ha44QrLFwR2IfSSYdOArzUvOyoWbOYTwQC+wS0NfqKjhW7s0WQ1lMy5oJXgSZy9sAiZS5ifELhbpXodeMR8w==
+vscode-nls@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.2.0.tgz#3cb6893dd9bd695244d8a024bdf746eea665cc3f"
+ integrity sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==
vscode-uri@^3.0.3:
version "3.0.3"
diff --git a/extensions/image-preview/.vscodeignore b/extensions/media-preview/.vscodeignore
similarity index 100%
rename from extensions/image-preview/.vscodeignore
rename to extensions/media-preview/.vscodeignore
diff --git a/extensions/media-preview/README.md b/extensions/media-preview/README.md
new file mode 100644
index 00000000000..30bb44b87a1
--- /dev/null
+++ b/extensions/media-preview/README.md
@@ -0,0 +1,29 @@
+# Media Preview
+
+**Notice:** This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled.
+
+## Features
+
+This extension provides basic preview for images, audio and video files.
+
+### Supported image file extensions
+
+- `.jpg`, `.jpe`, `.jpeg`
+- `.png`
+- `.bmp`
+- `.gif`
+- `.ico`
+- `.webp`
+- `.avif`
+
+
+### Supported audio formats
+
+- `.mp3`
+- `.wav`
+- `.ogg`
+
+### Supported video formats
+
+- `.mp4` (does not support `aac` audio track)
+- `.webm` (vp8 only)
diff --git a/extensions/image-preview/extension-browser.webpack.config.js b/extensions/media-preview/extension-browser.webpack.config.js
similarity index 100%
rename from extensions/image-preview/extension-browser.webpack.config.js
rename to extensions/media-preview/extension-browser.webpack.config.js
diff --git a/extensions/image-preview/extension.webpack.config.js b/extensions/media-preview/extension.webpack.config.js
similarity index 100%
rename from extensions/image-preview/extension.webpack.config.js
rename to extensions/media-preview/extension.webpack.config.js
diff --git a/extensions/image-preview/icon.png b/extensions/media-preview/icon.png
similarity index 100%
rename from extensions/image-preview/icon.png
rename to extensions/media-preview/icon.png
diff --git a/extensions/image-preview/media/audioPreview.css b/extensions/media-preview/media/audioPreview.css
similarity index 100%
rename from extensions/image-preview/media/audioPreview.css
rename to extensions/media-preview/media/audioPreview.css
diff --git a/extensions/image-preview/media/audioPreview.js b/extensions/media-preview/media/audioPreview.js
similarity index 100%
rename from extensions/image-preview/media/audioPreview.js
rename to extensions/media-preview/media/audioPreview.js
diff --git a/extensions/image-preview/media/imagePreview.css b/extensions/media-preview/media/imagePreview.css
similarity index 100%
rename from extensions/image-preview/media/imagePreview.css
rename to extensions/media-preview/media/imagePreview.css
diff --git a/extensions/image-preview/media/imagePreview.js b/extensions/media-preview/media/imagePreview.js
similarity index 100%
rename from extensions/image-preview/media/imagePreview.js
rename to extensions/media-preview/media/imagePreview.js
diff --git a/extensions/image-preview/media/loading-dark.svg b/extensions/media-preview/media/loading-dark.svg
similarity index 100%
rename from extensions/image-preview/media/loading-dark.svg
rename to extensions/media-preview/media/loading-dark.svg
diff --git a/extensions/image-preview/media/loading-hc.svg b/extensions/media-preview/media/loading-hc.svg
similarity index 100%
rename from extensions/image-preview/media/loading-hc.svg
rename to extensions/media-preview/media/loading-hc.svg
diff --git a/extensions/image-preview/media/loading.svg b/extensions/media-preview/media/loading.svg
similarity index 100%
rename from extensions/image-preview/media/loading.svg
rename to extensions/media-preview/media/loading.svg
diff --git a/extensions/image-preview/media/videoPreview.css b/extensions/media-preview/media/videoPreview.css
similarity index 100%
rename from extensions/image-preview/media/videoPreview.css
rename to extensions/media-preview/media/videoPreview.css
diff --git a/extensions/image-preview/media/videoPreview.js b/extensions/media-preview/media/videoPreview.js
similarity index 98%
rename from extensions/image-preview/media/videoPreview.js
rename to extensions/media-preview/media/videoPreview.js
index a8f1f6955fd..54aa60ad86f 100644
--- a/extensions/image-preview/media/videoPreview.js
+++ b/extensions/media-preview/media/videoPreview.js
@@ -30,6 +30,7 @@
if (settings.src !== null) {
video.src = settings.src;
}
+ video.playsInline = true;
video.controls = true;
function onLoaded() {
diff --git a/extensions/image-preview/package.json b/extensions/media-preview/package.json
similarity index 90%
rename from extensions/image-preview/package.json
rename to extensions/media-preview/package.json
index 03c2784a533..b82a4eef836 100644
--- a/extensions/image-preview/package.json
+++ b/extensions/media-preview/package.json
@@ -1,5 +1,5 @@
{
- "name": "image-preview",
+ "name": "media-preview",
"displayName": "%displayName%",
"description": "%description%",
"extensionKind": [
@@ -50,7 +50,7 @@
"priority": "builtin",
"selector": [
{
- "filenamePattern": "*.{mp3,wav,opus,aac}"
+ "filenamePattern": "*.{mp3,wav,ogg}"
}
]
},
@@ -93,16 +93,16 @@
}
},
"scripts": {
- "compile": "gulp compile-extension:image-preview",
- "watch": "npm run build-preview && gulp watch-extension:image-preview",
+ "compile": "gulp compile-extension:media-preview",
+ "watch": "npm run build-preview && gulp watch-extension:media-preview",
"vscode:prepublish": "npm run build-ext",
- "build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:image-preview ./tsconfig.json",
+ "build-ext": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:media-preview ./tsconfig.json",
"compile-web": "npx webpack-cli --config extension-browser.webpack.config --mode none",
"watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose"
},
"dependencies": {
"@vscode/extension-telemetry": "0.6.2",
- "vscode-nls": "^5.1.0"
+ "vscode-nls": "^5.2.0"
},
"repository": {
"type": "git",
diff --git a/extensions/image-preview/package.nls.json b/extensions/media-preview/package.nls.json
similarity index 67%
rename from extensions/image-preview/package.nls.json
rename to extensions/media-preview/package.nls.json
index 423aaf0c82b..3e45e4d0d2e 100644
--- a/extensions/image-preview/package.nls.json
+++ b/extensions/media-preview/package.nls.json
@@ -1,6 +1,6 @@
{
- "displayName": "Image Preview",
- "description": "Provides VS Code's built-in image preview",
+ "displayName": "Media Preview",
+ "description": "Provides VS Code's built-in previews for images, audio, and video",
"customEditor.audioPreview.displayName": "Audio Preview",
"customEditor.imagePreview.displayName": "Image Preview",
"customEditor.videoPreview.displayName": "Video Preview",
diff --git a/extensions/image-preview/src/audioPreview.ts b/extensions/media-preview/src/audioPreview.ts
similarity index 100%
rename from extensions/image-preview/src/audioPreview.ts
rename to extensions/media-preview/src/audioPreview.ts
diff --git a/extensions/image-preview/src/binarySizeStatusBarEntry.ts b/extensions/media-preview/src/binarySizeStatusBarEntry.ts
similarity index 100%
rename from extensions/image-preview/src/binarySizeStatusBarEntry.ts
rename to extensions/media-preview/src/binarySizeStatusBarEntry.ts
diff --git a/extensions/image-preview/src/extension.ts b/extensions/media-preview/src/extension.ts
similarity index 100%
rename from extensions/image-preview/src/extension.ts
rename to extensions/media-preview/src/extension.ts
diff --git a/extensions/image-preview/src/imagePreview/index.ts b/extensions/media-preview/src/imagePreview/index.ts
similarity index 100%
rename from extensions/image-preview/src/imagePreview/index.ts
rename to extensions/media-preview/src/imagePreview/index.ts
diff --git a/extensions/image-preview/src/imagePreview/sizeStatusBarEntry.ts b/extensions/media-preview/src/imagePreview/sizeStatusBarEntry.ts
similarity index 100%
rename from extensions/image-preview/src/imagePreview/sizeStatusBarEntry.ts
rename to extensions/media-preview/src/imagePreview/sizeStatusBarEntry.ts
diff --git a/extensions/image-preview/src/imagePreview/zoomStatusBarEntry.ts b/extensions/media-preview/src/imagePreview/zoomStatusBarEntry.ts
similarity index 100%
rename from extensions/image-preview/src/imagePreview/zoomStatusBarEntry.ts
rename to extensions/media-preview/src/imagePreview/zoomStatusBarEntry.ts
diff --git a/extensions/image-preview/src/mediaPreview.ts b/extensions/media-preview/src/mediaPreview.ts
similarity index 100%
rename from extensions/image-preview/src/mediaPreview.ts
rename to extensions/media-preview/src/mediaPreview.ts
diff --git a/extensions/image-preview/src/ownedStatusBarEntry.ts b/extensions/media-preview/src/ownedStatusBarEntry.ts
similarity index 100%
rename from extensions/image-preview/src/ownedStatusBarEntry.ts
rename to extensions/media-preview/src/ownedStatusBarEntry.ts
diff --git a/extensions/image-preview/src/util/dispose.ts b/extensions/media-preview/src/util/dispose.ts
similarity index 100%
rename from extensions/image-preview/src/util/dispose.ts
rename to extensions/media-preview/src/util/dispose.ts
diff --git a/extensions/image-preview/src/util/dom.ts b/extensions/media-preview/src/util/dom.ts
similarity index 100%
rename from extensions/image-preview/src/util/dom.ts
rename to extensions/media-preview/src/util/dom.ts
diff --git a/extensions/image-preview/src/videoPreview.ts b/extensions/media-preview/src/videoPreview.ts
similarity index 100%
rename from extensions/image-preview/src/videoPreview.ts
rename to extensions/media-preview/src/videoPreview.ts
diff --git a/extensions/image-preview/tsconfig.json b/extensions/media-preview/tsconfig.json
similarity index 100%
rename from extensions/image-preview/tsconfig.json
rename to extensions/media-preview/tsconfig.json
diff --git a/extensions/image-preview/yarn.lock b/extensions/media-preview/yarn.lock
similarity index 92%
rename from extensions/image-preview/yarn.lock
rename to extensions/media-preview/yarn.lock
index 61a6bb946db..a9af1f07de4 100644
--- a/extensions/image-preview/yarn.lock
+++ b/extensions/media-preview/yarn.lock
@@ -46,7 +46,7 @@
"@microsoft/1ds-core-js" "^3.2.3"
"@microsoft/1ds-post-js" "^3.2.3"
-vscode-nls@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.1.0.tgz#443b301a7465d88c81c0f4e1914f9857f0dce1e4"
- integrity sha512-37Ha44QrLFwR2IfSSYdOArzUvOyoWbOYTwQC+wS0NfqKjhW7s0WQ1lMy5oJXgSZy9sAiZS5ifELhbpXodeMR8w==
+vscode-nls@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.2.0.tgz#3cb6893dd9bd695244d8a024bdf746eea665cc3f"
+ integrity sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==
diff --git a/extensions/merge-conflict/package.json b/extensions/merge-conflict/package.json
index 978341508f8..caba136ce52 100644
--- a/extensions/merge-conflict/package.json
+++ b/extensions/merge-conflict/package.json
@@ -166,7 +166,7 @@
}
},
"dependencies": {
- "vscode-nls": "^5.1.0"
+ "vscode-nls": "^5.2.0"
},
"devDependencies": {
"@types/node": "16.x"
diff --git a/extensions/merge-conflict/yarn.lock b/extensions/merge-conflict/yarn.lock
index 90475ddc7e0..8b8c7a6c15b 100644
--- a/extensions/merge-conflict/yarn.lock
+++ b/extensions/merge-conflict/yarn.lock
@@ -7,7 +7,7 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae"
integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w==
-vscode-nls@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.1.0.tgz#443b301a7465d88c81c0f4e1914f9857f0dce1e4"
- integrity sha512-37Ha44QrLFwR2IfSSYdOArzUvOyoWbOYTwQC+wS0NfqKjhW7s0WQ1lMy5oJXgSZy9sAiZS5ifELhbpXodeMR8w==
+vscode-nls@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.2.0.tgz#3cb6893dd9bd695244d8a024bdf746eea665cc3f"
+ integrity sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==
diff --git a/extensions/microsoft-authentication/package.json b/extensions/microsoft-authentication/package.json
index 07f803a5930..8bf6cd70855 100644
--- a/extensions/microsoft-authentication/package.json
+++ b/extensions/microsoft-authentication/package.json
@@ -62,7 +62,7 @@
"stream": "0.0.2",
"uuid": "^8.2.0",
"@vscode/extension-telemetry": "0.6.2",
- "vscode-nls": "^5.1.0"
+ "vscode-nls": "^5.2.0"
},
"repository": {
"type": "git",
diff --git a/extensions/microsoft-authentication/yarn.lock b/extensions/microsoft-authentication/yarn.lock
index 6706f6a4aae..8d01670e906 100644
--- a/extensions/microsoft-authentication/yarn.lock
+++ b/extensions/microsoft-authentication/yarn.lock
@@ -198,10 +198,10 @@ uuid@^8.2.0:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.2.0.tgz#cb10dd6b118e2dada7d0cd9730ba7417c93d920e"
integrity sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==
-vscode-nls@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.1.0.tgz#443b301a7465d88c81c0f4e1914f9857f0dce1e4"
- integrity sha512-37Ha44QrLFwR2IfSSYdOArzUvOyoWbOYTwQC+wS0NfqKjhW7s0WQ1lMy5oJXgSZy9sAiZS5ifELhbpXodeMR8w==
+vscode-nls@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.2.0.tgz#3cb6893dd9bd695244d8a024bdf746eea665cc3f"
+ integrity sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==
webidl-conversions@^3.0.0:
version "3.0.1"
diff --git a/extensions/npm/package.json b/extensions/npm/package.json
index 9cc9ac5dedb..cae1fd7eab1 100644
--- a/extensions/npm/package.json
+++ b/extensions/npm/package.json
@@ -22,7 +22,7 @@
"jsonc-parser": "^2.2.1",
"minimatch": "^3.0.4",
"request-light": "^0.5.7",
- "vscode-nls": "^5.1.0",
+ "vscode-nls": "^5.2.0",
"which": "^2.0.2",
"which-pm": "^2.0.0"
},
diff --git a/extensions/npm/yarn.lock b/extensions/npm/yarn.lock
index 3479f1c58b6..bfd3b4b3de1 100644
--- a/extensions/npm/yarn.lock
+++ b/extensions/npm/yarn.lock
@@ -192,10 +192,10 @@ to-regex-range@^5.0.1:
dependencies:
is-number "^7.0.0"
-vscode-nls@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.1.0.tgz#443b301a7465d88c81c0f4e1914f9857f0dce1e4"
- integrity sha512-37Ha44QrLFwR2IfSSYdOArzUvOyoWbOYTwQC+wS0NfqKjhW7s0WQ1lMy5oJXgSZy9sAiZS5ifELhbpXodeMR8w==
+vscode-nls@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.2.0.tgz#3cb6893dd9bd695244d8a024bdf746eea665cc3f"
+ integrity sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==
which-pm@^2.0.0:
version "2.0.0"
diff --git a/extensions/package.json b/extensions/package.json
index 8f1df05f4e5..e12225cc76f 100644
--- a/extensions/package.json
+++ b/extensions/package.json
@@ -4,7 +4,7 @@
"license": "MIT",
"description": "Dependencies shared by all extensions",
"dependencies": {
- "typescript": "4.8.3"
+ "typescript": "4.8.4"
},
"scripts": {
"postinstall": "node ./postinstall.mjs"
diff --git a/extensions/php-language-features/package.json b/extensions/php-language-features/package.json
index 8782b3d83b4..dd7f6445d1a 100644
--- a/extensions/php-language-features/package.json
+++ b/extensions/php-language-features/package.json
@@ -74,7 +74,7 @@
"watch": "npx gulp watch-extension:php-language-features"
},
"dependencies": {
- "vscode-nls": "^5.1.0",
+ "vscode-nls": "^5.2.0",
"which": "^2.0.2"
},
"devDependencies": {
diff --git a/extensions/php-language-features/yarn.lock b/extensions/php-language-features/yarn.lock
index 62c8b33e55d..baafbeb7ca3 100644
--- a/extensions/php-language-features/yarn.lock
+++ b/extensions/php-language-features/yarn.lock
@@ -17,10 +17,10 @@ isexe@^2.0.0:
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
-vscode-nls@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.1.0.tgz#443b301a7465d88c81c0f4e1914f9857f0dce1e4"
- integrity sha512-37Ha44QrLFwR2IfSSYdOArzUvOyoWbOYTwQC+wS0NfqKjhW7s0WQ1lMy5oJXgSZy9sAiZS5ifELhbpXodeMR8w==
+vscode-nls@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.2.0.tgz#3cb6893dd9bd695244d8a024bdf746eea665cc3f"
+ integrity sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==
which@^2.0.2:
version "2.0.2"
diff --git a/extensions/php/snippets/php.code-snippets b/extensions/php/snippets/php.code-snippets
index 9c061291647..3c213765b4b 100644
--- a/extensions/php/snippets/php.code-snippets
+++ b/extensions/php/snippets/php.code-snippets
@@ -12,6 +12,7 @@
},
"PHPDoc class …": {
"prefix": "doc_class",
+ "isFileTemplate": true,
"body": [
"/**",
" * ${6:undocumented class}",
@@ -42,6 +43,7 @@
},
"PHPDoc function …": {
"prefix": "doc_f",
+ "isFileTemplate": true,
"body": [
"/**",
" * ${1:undocumented function summary}",
diff --git a/extensions/python/test/colorize-fixtures/test.py b/extensions/python/test/colorize-fixtures/test.py
index c92f2c70a8b..c32f12e4f8b 100644
--- a/extensions/python/test/colorize-fixtures/test.py
+++ b/extensions/python/test/colorize-fixtures/test.py
@@ -19,13 +19,10 @@ class Monkey:
}=42):
pass
-if 1900 < year < 2100 and 1 <= month <= 12 \
- and 1 <= day <= 31 and 0 <= hour < 24 \
- and 0 <= minute < 60 and 0 <= second < 60: # Looks like a valid date
- return 1
+pass
def firstn(g, n):
- for i in range(n):
+ for _ in range(n):
yield g.next()
reduce(lambda x,y: x+y, [47,11,42,13])
@@ -37,15 +34,14 @@ mydictionary = {
}
def steuern(einkommen):
- """Berechnung der zu zahlenden Steuern fuer ein zu versteuerndes Einkommen von x"""
- if einkommen <= 8004:
- steuer = 0
- elif einkommen <= 13469:
- y = (einkommen -8004.0)/10000.0
- steuer = (912.17 * y + 1400)*y
- else:
- steuer = einkommen * 0.44 - 15694
- return steuer
+ """Berechnung der zu zahlenden Steuern fuer ein zu versteuerndes Einkommen von x"""
+ if einkommen <= 8004:
+ return 0
+ elif einkommen <= 13469:
+ y = (einkommen -8004.0)/10000.0
+ return (912.17 * y + 1400)*y
+ else:
+ return einkommen * 0.44 - 15694
def beliebig(x, y, *mehr):
print "x=", x, ", x=", y
diff --git a/extensions/razor/cgmanifest.json b/extensions/razor/cgmanifest.json
index 2ad1d82c1ea..c0de1392dd5 100644
--- a/extensions/razor/cgmanifest.json
+++ b/extensions/razor/cgmanifest.json
@@ -10,8 +10,32 @@
}
},
"license": "MIT",
- "version": "0.3.0"
+ "version": "0.3.0",
+ "licenseDetail": [
+ "The MIT License (MIT)",
+ "",
+ "Copyright (c) 2014 James Summerton",
+ "",
+ "Permission is hereby granted, free of charge, to any person obtaining",
+ "a copy of this software and associated documentation files (the",
+ "\"Software\"), to deal in the Software without restriction, including",
+ "without limitation the rights to use, copy, modify, merge, publish,",
+ "distribute, sublicense, and/or sell copies of the Software, and to",
+ "permit persons to whom the Software is furnished to do so, subject to",
+ "the following conditions:",
+ "",
+ "The above copyright notice and this permission notice shall be",
+ "included in all copies or substantial portions of the Software.",
+ "",
+ "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,",
+ "EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF",
+ "MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND",
+ "NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE",
+ "LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION",
+ "OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION",
+ "WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
+ ]
}
],
"version": 1
-}
\ No newline at end of file
+}
diff --git a/extensions/references-view/package.json b/extensions/references-view/package.json
index 4176cda3d1a..d3fcadcbffd 100644
--- a/extensions/references-view/package.json
+++ b/extensions/references-view/package.json
@@ -407,7 +407,7 @@
"watch": "npx gulp watch-extension:references-view"
},
"dependencies": {
- "vscode-nls": "^5.1.0"
+ "vscode-nls": "^5.2.0"
},
"devDependencies": {
"@types/node": "16.x"
diff --git a/extensions/references-view/yarn.lock b/extensions/references-view/yarn.lock
index 76eaba8dd6f..1661be7c5d2 100644
--- a/extensions/references-view/yarn.lock
+++ b/extensions/references-view/yarn.lock
@@ -7,7 +7,7 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.33.tgz#566713b1b626f781c5c58fe3531307283e00720c"
integrity sha512-0PJ0vg+JyU0MIan58IOIFRtSvsb7Ri+7Wltx2qAg94eMOrpg4+uuP3aUHCpxXc1i0jCXiC+zIamSZh3l9AbcQA==
-vscode-nls@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.1.0.tgz#443b301a7465d88c81c0f4e1914f9857f0dce1e4"
- integrity sha512-37Ha44QrLFwR2IfSSYdOArzUvOyoWbOYTwQC+wS0NfqKjhW7s0WQ1lMy5oJXgSZy9sAiZS5ifELhbpXodeMR8w==
+vscode-nls@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.2.0.tgz#3cb6893dd9bd695244d8a024bdf746eea665cc3f"
+ integrity sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==
diff --git a/extensions/scss/cgmanifest.json b/extensions/scss/cgmanifest.json
index a67a4f54609..12247769ce2 100644
--- a/extensions/scss/cgmanifest.json
+++ b/extensions/scss/cgmanifest.json
@@ -6,12 +6,12 @@
"git": {
"name": "atom/language-sass",
"repositoryUrl": "https://github.com/atom/language-sass",
- "commitHash": "303bbf0c250fe380b9e57375598cfd916110758b"
+ "commitHash": "f52ab12f7f9346cc2568129d8c4419bd3d506b47"
}
},
"license": "MIT",
"description": "The file syntaxes/scss.json was derived from the Atom package https://github.com/atom/language-sass which was originally converted from the TextMate bundle https://github.com/alexsancho/SASS.tmbundle.",
- "version": "0.61.4"
+ "version": "0.62.1"
}
],
"version": 1
diff --git a/extensions/shared.webpack.config.js b/extensions/shared.webpack.config.js
index a8f24c1a572..8be35296ddf 100644
--- a/extensions/shared.webpack.config.js
+++ b/extensions/shared.webpack.config.js
@@ -113,15 +113,6 @@ function withBrowserDefaults(/**@type WebpackConfig*/extConfig, /** @type Additi
test: /\.ts$/,
exclude: /node_modules/,
use: [
- // TODO: bring this back once vscode-nls-dev supports browser
- // {
- // // vscode-nls-dev loader:
- // // * rewrite nls-calls
- // loader: 'vscode-nls-dev/lib/webpack-loader',
- // options: {
- // base: path.join(extConfig.context, 'src')
- // }
- // },
{
// configure TypeScript loader:
// * enable sources maps for end-to-end source maps
@@ -137,7 +128,6 @@ function withBrowserDefaults(/**@type WebpackConfig*/extConfig, /** @type Additi
},
externals: {
'vscode': 'commonjs vscode', // ignored because it doesn't exist,
- 'vscode-nls-web-data': 'commonjs vscode-nls-web-data', // ignored because this is injected by the webworker extension host
'applicationinsights-native-metrics': 'commonjs applicationinsights-native-metrics', // ignored because we don't ship native module
'@opentelemetry/tracing': 'commonjs @opentelemetry/tracing' // ignored because we don't ship this module
},
diff --git a/extensions/simple-browser/package.json b/extensions/simple-browser/package.json
index fe3f4de2a5f..2db456cb387 100644
--- a/extensions/simple-browser/package.json
+++ b/extensions/simple-browser/package.json
@@ -68,7 +68,7 @@
},
"dependencies": {
"@vscode/extension-telemetry": "0.6.2",
- "vscode-nls": "^5.1.0"
+ "vscode-nls": "^5.2.0"
},
"devDependencies": {
"@types/vscode-webview": "^1.57.0",
diff --git a/extensions/simple-browser/yarn.lock b/extensions/simple-browser/yarn.lock
index 32215e9059b..97902582dea 100644
--- a/extensions/simple-browser/yarn.lock
+++ b/extensions/simple-browser/yarn.lock
@@ -56,7 +56,7 @@ vscode-codicons@^0.0.14:
resolved "https://registry.yarnpkg.com/vscode-codicons/-/vscode-codicons-0.0.14.tgz#e0d05418e2e195564ff6f6a2199d70415911c18f"
integrity sha512-6CEH5KT9ct5WMw7n5dlX7rB8ya4CUI2FSq1Wk36XaW+c5RglFtAanUV0T+gvZVVFhl/WxfjTvFHq06Hz9c1SLA==
-vscode-nls@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.1.0.tgz#443b301a7465d88c81c0f4e1914f9857f0dce1e4"
- integrity sha512-37Ha44QrLFwR2IfSSYdOArzUvOyoWbOYTwQC+wS0NfqKjhW7s0WQ1lMy5oJXgSZy9sAiZS5ifELhbpXodeMR8w==
+vscode-nls@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.2.0.tgz#3cb6893dd9bd695244d8a024bdf746eea665cc3f"
+ integrity sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==
diff --git a/extensions/theme-abyss/themes/abyss-color-theme.json b/extensions/theme-abyss/themes/abyss-color-theme.json
index 3157d39b234..7ce14d2de22 100644
--- a/extensions/theme-abyss/themes/abyss-color-theme.json
+++ b/extensions/theme-abyss/themes/abyss-color-theme.json
@@ -409,6 +409,7 @@
// "activityBar.foreground": "",
// "activityBarBadge.background": "",
// "activityBarBadge.foreground": "",
+ "activityBarItem.settingsProfilesBackground": "#082877",
// Workbench: Panel
// "panel.background": "",
diff --git a/extensions/theme-defaults/themes/light_vs.json b/extensions/theme-defaults/themes/light_vs.json
index 7a80ebf00e0..0a6eaf61703 100644
--- a/extensions/theme-defaults/themes/light_vs.json
+++ b/extensions/theme-defaults/themes/light_vs.json
@@ -2,6 +2,7 @@
"$schema": "vscode://schemas/color-theme",
"name": "Light (Visual Studio)",
"colors": {
+ "activityBarItem.settingsProfilesBackground": "#4d4d4d",
"editor.background": "#FFFFFF",
"editor.foreground": "#000000",
"editor.inactiveSelectionBackground": "#E5EBF1",
diff --git a/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json b/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json
index 76cdb8a9753..8208d90f102 100644
--- a/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json
+++ b/extensions/theme-kimbie-dark/themes/kimbie-dark-color-theme.json
@@ -32,6 +32,7 @@
"ports.iconRunningProcessForeground": "#369432",
"activityBar.background": "#221a0f",
"activityBar.foreground": "#d3af86",
+ "activityBarItem.settingsProfilesBackground": "#47351d",
"sideBar.background": "#362712",
"menu.background": "#362712",
"menu.foreground": "#CCCCCC",
diff --git a/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-color-theme.json b/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-color-theme.json
index eef990db889..45f1a1d55b0 100644
--- a/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-color-theme.json
+++ b/extensions/theme-tomorrow-night-blue/themes/tomorrow-night-blue-color-theme.json
@@ -36,6 +36,7 @@
"statusBar.noFolderBackground": "#001126",
"statusBar.debuggingBackground": "#001126",
"activityBar.background": "#001733",
+ "activityBarItem.settingsProfilesBackground": "#003271",
"progressBar.background": "#bbdaffcc",
"badge.background": "#bbdaffcc",
"badge.foreground": "#001733",
diff --git a/extensions/typescript-basics/cgmanifest.json b/extensions/typescript-basics/cgmanifest.json
index cf253fb2b95..7e93b3d9ab0 100644
--- a/extensions/typescript-basics/cgmanifest.json
+++ b/extensions/typescript-basics/cgmanifest.json
@@ -6,7 +6,7 @@
"git": {
"name": "TypeScript-TmLanguage",
"repositoryUrl": "https://github.com/microsoft/TypeScript-TmLanguage",
- "commitHash": "73af17bf3e45339df06d92751ab366ce96c38516"
+ "commitHash": "c2744520e325330d0608fc1d1993d7fe98e66202"
}
},
"license": "MIT",
diff --git a/extensions/typescript-basics/snippets/typescript.code-snippets b/extensions/typescript-basics/snippets/typescript.code-snippets
index 0162ef50975..35b2aa1711c 100644
--- a/extensions/typescript-basics/snippets/typescript.code-snippets
+++ b/extensions/typescript-basics/snippets/typescript.code-snippets
@@ -14,6 +14,7 @@
},
"Class Definition": {
"prefix": "class",
+ "isFileTemplate": true,
"body": [
"class ${1:name} {",
"\tconstructor(${2:parameters}) {",
diff --git a/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json b/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json
index 681581e93d6..636fad5e441 100644
--- a/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json
+++ b/extensions/typescript-basics/syntaxes/TypeScript.tmLanguage.json
@@ -4,7 +4,7 @@
"If you want to provide a fix or improvement, please create a pull request against the original repository.",
"Once accepted there, we are happy to receive an update request."
],
- "version": "https://github.com/microsoft/TypeScript-TmLanguage/commit/73af17bf3e45339df06d92751ab366ce96c38516",
+ "version": "https://github.com/microsoft/TypeScript-TmLanguage/commit/c2744520e325330d0608fc1d1993d7fe98e66202",
"name": "TypeScript",
"scopeName": "source.ts",
"patterns": [
@@ -2671,7 +2671,7 @@
{
"name": "meta.object.member.ts meta.object-literal.key.ts",
"begin": "(?=[\\'\\\"\\`])",
- "end": "(?=:)|((?<=[\\'\\\"\\`])(?=((\\s*[\\(\\<,}])|(\\s+(as)\\s+))))",
+ "end": "(?=:)|((?<=[\\'\\\"\\`])(?=((\\s*[\\(\\<,}])|(\\s+(as|satisifies)\\s+))))",
"patterns": [
{
"include": "#comment"
@@ -2684,7 +2684,7 @@
{
"name": "meta.object.member.ts meta.object-literal.key.ts",
"begin": "(?x)(?=(\\b(?]|\\|\\||\\&\\&|\\!\\=\\=|$|^|((?]|\\|\\||\\&\\&|\\!\\=\\=|$|^|((?]|\\|\\||\\&\\&|\\!\\=\\=|$|((?]|\\|\\||\\&\\&|\\!\\=\\=|$|((?]|\\|\\||\\&\\&|\\!\\=\\=|$|^|((?]|\\|\\||\\&\\&|\\!\\=\\=|$|^|((?]|\\|\\||\\&\\&|\\!\\=\\=|$|((?]|\\|\\||\\&\\&|\\!\\=\\=|$|((?(
+ const neverItem: vscode.MessageItem = {
+ title: localize('never.title', "Never automatically update imports"),
+ };
+
+ const response = await vscode.window.showInformationMessage(
newResources.length === 1
? localize('prompt', "Update imports for '{0}'?", path.basename(newResources[0].fsPath))
: this.getConfirmMessage(localize('promptMoreThanOne', "Update imports for the following {0} files?", newResources.length), newResources), {
modal: true,
- }, {
- title: localize('reject.title', "No"),
- choice: Choice.Reject,
- isCloseAffordance: true,
- }, {
- title: localize('accept.title', "Yes"),
- choice: Choice.Accept,
- }, {
- title: localize('always.title', "Always automatically update imports"),
- choice: Choice.Always,
- }, {
- title: localize('never.title', "Never automatically update imports"),
- choice: Choice.Never,
- });
+ }, rejectItem, acceptItem, alwaysItem, neverItem);
- if (!response) {
- return false;
- }
- switch (response.choice) {
- case Choice.Accept:
- {
- return true;
- }
- case Choice.Reject:
- {
- return false;
- }
- case Choice.Always:
- {
- const config = this.getConfiguration(newResources[0]);
- config.update(
- updateImportsOnFileMoveName,
- UpdateImportsOnFileMoveSetting.Always,
- this.getConfigTargetScope(config, updateImportsOnFileMoveName));
- return true;
- }
- case Choice.Never:
+ switch (response) {
+ case acceptItem: {
+ return true;
+ }
+ case rejectItem: {
+ return false;
+ }
+ case alwaysItem: {
+ const config = this.getConfiguration(newResources[0]);
+ config.update(
+ updateImportsOnFileMoveName,
+ UpdateImportsOnFileMoveSetting.Always,
+ this.getConfigTargetScope(config, updateImportsOnFileMoveName));
+ return true;
+ }
+ case neverItem:
{
const config = this.getConfiguration(newResources[0]);
config.update(
@@ -211,9 +196,10 @@ class UpdateImportsOnFileRenameHandler extends Disposable {
this.getConfigTargetScope(config, updateImportsOnFileMoveName));
return false;
}
+ default: {
+ return false;
+ }
}
-
- return false;
}
private async getJsTsFileBeingMoved(resource: vscode.Uri): Promise {
diff --git a/extensions/typescript-language-features/yarn.lock b/extensions/typescript-language-features/yarn.lock
index 08e22bf4c15..89f3521b9b6 100644
--- a/extensions/typescript-language-features/yarn.lock
+++ b/extensions/typescript-language-features/yarn.lock
@@ -85,10 +85,10 @@ tas-client@0.1.58:
dependencies:
axios "^0.26.1"
-vscode-nls@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.1.0.tgz#443b301a7465d88c81c0f4e1914f9857f0dce1e4"
- integrity sha512-37Ha44QrLFwR2IfSSYdOArzUvOyoWbOYTwQC+wS0NfqKjhW7s0WQ1lMy5oJXgSZy9sAiZS5ifELhbpXodeMR8w==
+vscode-nls@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/vscode-nls/-/vscode-nls-5.2.0.tgz#3cb6893dd9bd695244d8a024bdf746eea665cc3f"
+ integrity sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==
vscode-tas-client@^0.1.63:
version "0.1.63"
diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/env.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/env.test.ts
index a445753483d..d02e5a44442 100644
--- a/extensions/vscode-api-tests/src/singlefolder-tests/env.test.ts
+++ b/extensions/vscode-api-tests/src/singlefolder-tests/env.test.ts
@@ -32,7 +32,7 @@ suite('vscode API - env', () => {
test('env.remoteName', function () {
const remoteName = env.remoteName;
const knownWorkspaceExtension = extensions.getExtension('vscode.git');
- const knownUiAndWorkspaceExtension = extensions.getExtension('vscode.image-preview');
+ const knownUiAndWorkspaceExtension = extensions.getExtension('vscode.media-preview');
if (typeof remoteName === 'undefined') {
// not running in remote, so we expect both extensions
assert.ok(knownWorkspaceExtension);
diff --git a/extensions/yarn.lock b/extensions/yarn.lock
index 919cf0aa6a8..619417cb66c 100644
--- a/extensions/yarn.lock
+++ b/extensions/yarn.lock
@@ -42,10 +42,10 @@ node-gyp-build@^4.3.0:
resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.3.0.tgz#9f256b03e5826150be39c764bf51e993946d71a3"
integrity sha512-iWjXZvmboq0ja1pUGULQBexmxq8CV4xBhX7VDOTbL7ZR4FOowwY/VOtRxBN/yKxmdGoIp4j5ysNT4u3S2pDQ3Q==
-typescript@4.8.3:
- version "4.8.3"
- resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.3.tgz#d59344522c4bc464a65a730ac695007fdb66dd88"
- integrity sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==
+typescript@4.8.4:
+ version "4.8.4"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6"
+ integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==
vscode-grammar-updater@^1.1.0:
version "1.1.0"
diff --git a/package.json b/package.json
index 6aef60a69eb..e741661bd4a 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "code-oss-dev",
"version": "1.72.0",
- "distro": "d9fc5ec0abd44d6d2eab4ad5c0cf4ca9c4e839e1",
+ "distro": "d4b1b117d224d627ec65bb0fd0b02fdee65303aa",
"author": {
"name": "Microsoft Corporation"
},
@@ -86,13 +86,13 @@
"vscode-proxy-agent": "^0.12.0",
"vscode-regexpp": "^3.1.0",
"vscode-textmate": "7.0.1",
- "xterm": "5.1.0-beta.10",
+ "xterm": "5.1.0-beta.15",
"xterm-addon-canvas": "0.3.0-beta.1",
"xterm-addon-search": "0.11.0-beta.1",
"xterm-addon-serialize": "0.9.0-beta.2",
"xterm-addon-unicode11": "0.5.0-beta.1",
"xterm-addon-webgl": "0.14.0-beta.8",
- "xterm-headless": "5.1.0-beta.10",
+ "xterm-headless": "5.1.0-beta.15",
"yauzl": "^2.9.2",
"yazl": "^2.4.3"
},
diff --git a/product.json b/product.json
index d97f6cc80b5..6e124afcf90 100644
--- a/product.json
+++ b/product.json
@@ -46,7 +46,7 @@
},
{
"name": "ms-vscode.js-debug",
- "version": "1.71.1",
+ "version": "1.72.0",
"repo": "https://github.com/microsoft/vscode-js-debug",
"metadata": {
"id": "25629058-ddac-4e17-abba-74678e126c5d",
diff --git a/remote/package.json b/remote/package.json
index 399771595e0..5a2b2bb40a5 100644
--- a/remote/package.json
+++ b/remote/package.json
@@ -24,13 +24,13 @@
"vscode-proxy-agent": "^0.12.0",
"vscode-regexpp": "^3.1.0",
"vscode-textmate": "7.0.1",
- "xterm": "5.1.0-beta.10",
+ "xterm": "5.1.0-beta.15",
"xterm-addon-canvas": "0.3.0-beta.1",
"xterm-addon-search": "0.11.0-beta.1",
"xterm-addon-serialize": "0.9.0-beta.2",
"xterm-addon-unicode11": "0.5.0-beta.1",
"xterm-addon-webgl": "0.14.0-beta.8",
- "xterm-headless": "5.1.0-beta.10",
+ "xterm-headless": "5.1.0-beta.15",
"yauzl": "^2.9.2",
"yazl": "^2.4.3"
},
diff --git a/remote/web/package.json b/remote/web/package.json
index ced3eb18679..090bd1fb4ce 100644
--- a/remote/web/package.json
+++ b/remote/web/package.json
@@ -11,7 +11,7 @@
"tas-client-umd": "0.1.6",
"vscode-oniguruma": "1.6.1",
"vscode-textmate": "7.0.1",
- "xterm": "5.1.0-beta.10",
+ "xterm": "5.1.0-beta.15",
"xterm-addon-canvas": "0.3.0-beta.1",
"xterm-addon-search": "0.11.0-beta.1",
"xterm-addon-unicode11": "0.5.0-beta.1",
diff --git a/remote/web/yarn.lock b/remote/web/yarn.lock
index 72a9a2160ac..246b60bc896 100644
--- a/remote/web/yarn.lock
+++ b/remote/web/yarn.lock
@@ -88,7 +88,7 @@ xterm-addon-webgl@0.14.0-beta.8:
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.14.0-beta.8.tgz#486ae22b2eb88a12ebded366c4019ee26409cbb8"
integrity sha512-G0F70f6zGWtXuZxKiTn9BQswaVz85wcCuadnWRdPFDBlgdEfcboCvVZgQetklOIkluVpt8tYYK013/25iMRKTA==
-xterm@5.1.0-beta.10:
- version "5.1.0-beta.10"
- resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.1.0-beta.10.tgz#2f55e4e6d63b45152c768857accc06c47920f898"
- integrity sha512-McztCKJJ2QvY28oXwK9ACMbbNTKiKQSbli+tZJIROkICmA7QFizwsQBQDoOtAw0po0dP1CInLJXwurqZmfCymQ==
+xterm@5.1.0-beta.15:
+ version "5.1.0-beta.15"
+ resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.1.0-beta.15.tgz#146b70c81fd286dbb003d18449918326fa355b6b"
+ integrity sha512-fO87pEPFMr+h7eo51+6+ew3OhzLm2wwSYz6w/y5lH986rD1lgAeEqFuzjr64pjBzwAihnoaTpumYg5lTZDQpSA==
diff --git a/remote/yarn.lock b/remote/yarn.lock
index f1b96db5bb3..09e066c08c8 100644
--- a/remote/yarn.lock
+++ b/remote/yarn.lock
@@ -813,15 +813,15 @@ xterm-addon-webgl@0.14.0-beta.8:
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.14.0-beta.8.tgz#486ae22b2eb88a12ebded366c4019ee26409cbb8"
integrity sha512-G0F70f6zGWtXuZxKiTn9BQswaVz85wcCuadnWRdPFDBlgdEfcboCvVZgQetklOIkluVpt8tYYK013/25iMRKTA==
-xterm-headless@5.1.0-beta.10:
- version "5.1.0-beta.10"
- resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.1.0-beta.10.tgz#2a747a1fa96a877c26aea3311b0a62ddae7e2578"
- integrity sha512-tRoXL1e87XOIuZ5yIjK43q3x9/MqZ+K24Na7UTl+AqmkXjb5svXfShMV3x8HiNAyxcrnL/MXNilfLoniQGacIA==
+xterm-headless@5.1.0-beta.15:
+ version "5.1.0-beta.15"
+ resolved "https://registry.yarnpkg.com/xterm-headless/-/xterm-headless-5.1.0-beta.15.tgz#fba76c8e95b552e922354409864c0f55d3b499f7"
+ integrity sha512-LVtB+KkHs1R2RG8ug3IfOOU0J+qEGttfXagGxfzNq8zxxoSsgoY4D0YvLpM7M/5FK6eGK5K8/yol9XAK63ENog==
-xterm@5.1.0-beta.10:
- version "5.1.0-beta.10"
- resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.1.0-beta.10.tgz#2f55e4e6d63b45152c768857accc06c47920f898"
- integrity sha512-McztCKJJ2QvY28oXwK9ACMbbNTKiKQSbli+tZJIROkICmA7QFizwsQBQDoOtAw0po0dP1CInLJXwurqZmfCymQ==
+xterm@5.1.0-beta.15:
+ version "5.1.0-beta.15"
+ resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.1.0-beta.15.tgz#146b70c81fd286dbb003d18449918326fa355b6b"
+ integrity sha512-fO87pEPFMr+h7eo51+6+ew3OhzLm2wwSYz6w/y5lH986rD1lgAeEqFuzjr64pjBzwAihnoaTpumYg5lTZDQpSA==
yallist@^4.0.0:
version "4.0.0"
diff --git a/src/vs/base/browser/defaultWorkerFactory.ts b/src/vs/base/browser/defaultWorkerFactory.ts
index 9d2a34494be..87103de1a54 100644
--- a/src/vs/base/browser/defaultWorkerFactory.ts
+++ b/src/vs/base/browser/defaultWorkerFactory.ts
@@ -43,11 +43,20 @@ export function getWorkerBootstrapUrl(scriptPath: string, label: string): string
return URL.createObjectURL(blob);
}
- const result = new URL(scriptPath);
- COI.addSearchParam(result.searchParams, true, true);
- result.hash = label;
- return result.href;
+ const start = scriptPath.lastIndexOf('?');
+ const end = scriptPath.lastIndexOf('#', start);
+ const params = start > 0
+ ? new URLSearchParams(scriptPath.substring(start + 1, ~end ? end : undefined))
+ : new URLSearchParams();
+ COI.addSearchParam(params, true, true);
+ const search = params.toString();
+
+ if (!search) {
+ return `${scriptPath}#${label}`;
+ } else {
+ return `${scriptPath}?${params.toString()}#${label}`;
+ }
}
// ESM-comment-end
diff --git a/src/vs/base/browser/globalPointerMoveMonitor.ts b/src/vs/base/browser/globalPointerMoveMonitor.ts
index d5c432114d7..0348db2528f 100644
--- a/src/vs/base/browser/globalPointerMoveMonitor.ts
+++ b/src/vs/base/browser/globalPointerMoveMonitor.ts
@@ -64,7 +64,17 @@ export class GlobalPointerMoveMonitor implements IDisposable {
try {
initialElement.setPointerCapture(pointerId);
this._hooks.add(toDisposable(() => {
- initialElement.releasePointerCapture(pointerId);
+ try {
+ initialElement.releasePointerCapture(pointerId);
+ } catch (err) {
+ // See https://github.com/microsoft/vscode/issues/161731
+ //
+ // `releasePointerCapture` sometimes fails when being invoked with the exception:
+ // DOMException: Failed to execute 'releasePointerCapture' on 'Element':
+ // No active pointer with the given id is found.
+ //
+ // There's no need to do anything in case of failure
+ }
}));
} catch (err) {
// See https://github.com/microsoft/vscode/issues/144584
diff --git a/src/vs/base/browser/ui/codicons/codicon/codicon.ttf b/src/vs/base/browser/ui/codicons/codicon/codicon.ttf
index d8ac87cba86..bab11139af8 100644
Binary files a/src/vs/base/browser/ui/codicons/codicon/codicon.ttf and b/src/vs/base/browser/ui/codicons/codicon/codicon.ttf differ
diff --git a/src/vs/base/browser/ui/inputbox/inputBox.ts b/src/vs/base/browser/ui/inputbox/inputBox.ts
index ae89cb33f38..a9f2b326c28 100644
--- a/src/vs/base/browser/ui/inputbox/inputBox.ts
+++ b/src/vs/base/browser/ui/inputbox/inputBox.ts
@@ -58,7 +58,7 @@ export interface IInputValidator {
}
export interface IMessage {
- readonly content: string;
+ readonly content?: string;
readonly formatContent?: boolean; // defaults to false
readonly type?: MessageType;
}
@@ -396,7 +396,7 @@ export class InputBox extends Widget {
const styles = this.stylesForType(this.message.type);
this.element.style.border = styles.border ? `1px solid ${styles.border}` : '';
- if (this.hasFocus() || force) {
+ if (this.message.content && (this.hasFocus() || force)) {
this._showMessage();
}
}
@@ -477,8 +477,8 @@ export class InputBox extends Widget {
};
const spanElement = (this.message.formatContent
- ? renderFormattedText(this.message.content, renderOptions)
- : renderText(this.message.content, renderOptions));
+ ? renderFormattedText(this.message.content!, renderOptions)
+ : renderText(this.message.content!, renderOptions));
spanElement.classList.add(this.classForType(this.message.type));
const styles = this.stylesForType(this.message.type);
diff --git a/src/vs/base/browser/ui/sash/sash.ts b/src/vs/base/browser/ui/sash/sash.ts
index 4bc8ff1b8ee..5cbf7e6f192 100644
--- a/src/vs/base/browser/ui/sash/sash.ts
+++ b/src/vs/base/browser/ui/sash/sash.ts
@@ -5,7 +5,7 @@
import { $, append, createStyleSheet, EventHelper, EventLike } from 'vs/base/browser/dom';
import { DomEmitter } from 'vs/base/browser/event';
-import { EventType, Gesture, GestureEvent } from 'vs/base/browser/touch';
+import { EventType, Gesture } from 'vs/base/browser/touch';
import { Delayer } from 'vs/base/common/async';
import { memoize } from 'vs/base/common/decorators';
import { Emitter, Event } from 'vs/base/common/event';
@@ -155,6 +155,7 @@ interface PointerEvent extends EventLike {
readonly pageY: number;
readonly altKey: boolean;
readonly target: EventTarget | null;
+ readonly initialTarget?: EventTarget | undefined;
}
interface IPointerEventFactory {
@@ -419,17 +420,22 @@ export class Sash extends Disposable {
this._register(Gesture.addTarget(this.el));
- const onTouchStart = Event.map(this._register(new DomEmitter(this.el, EventType.Start)).event, e => ({ ...e, target: e.initialTarget ?? null }));
+ const onTouchStart = this._register(new DomEmitter(this.el, EventType.Start)).event;
this._register(onTouchStart(e => this.onPointerStart(e, new GestureEventFactory(this.el)), this));
const onTap = this._register(new DomEmitter(this.el, EventType.Tap)).event;
- const onDoubleTap = Event.map(
- Event.filter(
- Event.debounce(onTap, (res, event) => ({ event, count: (res?.count ?? 0) + 1 }), 250),
- ({ count }) => count === 2
- ),
- ({ event }) => ({ ...event, target: event.initialTarget ?? null })
- );
- this._register(onDoubleTap(this.onPointerDoublePress, this));
+
+ let doubleTapTimeout: any = undefined;
+ this._register(onTap(event => {
+ if (doubleTapTimeout) {
+ clearTimeout(doubleTapTimeout);
+ doubleTapTimeout = undefined;
+ this.onPointerDoublePress(event);
+ return;
+ }
+
+ clearTimeout(doubleTapTimeout);
+ doubleTapTimeout = setTimeout(() => doubleTapTimeout = undefined, 250);
+ }, this));
if (typeof options.size === 'number') {
this.size = options.size;
@@ -645,12 +651,14 @@ export class Sash extends Disposable {
}
private getOrthogonalSash(e: PointerEvent): Sash | undefined {
- if (!e.target || !(e.target instanceof HTMLElement)) {
+ const target = e.initialTarget ?? e.target;
+
+ if (!target || !(target instanceof HTMLElement)) {
return undefined;
}
- if (e.target.classList.contains('orthogonal-drag-handle')) {
- return e.target.classList.contains('start') ? this.orthogonalStartSash : this.orthogonalEndSash;
+ if (target.classList.contains('orthogonal-drag-handle')) {
+ return target.classList.contains('start') ? this.orthogonalStartSash : this.orthogonalEndSash;
}
return undefined;
diff --git a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts
index cc09126b530..cfdaca03d75 100644
--- a/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts
+++ b/src/vs/base/browser/ui/selectBox/selectBoxCustom.ts
@@ -15,7 +15,7 @@ import { ISelectBoxDelegate, ISelectBoxOptions, ISelectBoxStyles, ISelectData, I
import * as arrays from 'vs/base/common/arrays';
import { Emitter, Event } from 'vs/base/common/event';
import { KeyCode, KeyCodeUtils } from 'vs/base/common/keyCodes';
-import { Disposable, dispose, IDisposable } from 'vs/base/common/lifecycle';
+import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { isMacintosh } from 'vs/base/common/platform';
import { ScrollbarVisibility } from 'vs/base/common/scrollable';
import 'vs/css!./selectBoxCustom';
@@ -31,7 +31,6 @@ interface ISelectListTemplateData {
text: HTMLElement;
detail: HTMLElement;
decoratorRight: HTMLElement;
- disposables: IDisposable[];
}
class SelectListRenderer implements IListRenderer {
@@ -40,7 +39,6 @@ class SelectListRenderer implements IListRenderer implements IListRenderer
private hideTwistiesOfChildlessElements: boolean = false;
private shouldRenderIndentGuides: boolean = false;
- private renderedIndentGuides = new SetMap, HTMLDivElement>();
private activeIndentNodes = new Set>();
private indentGuidesDisposable: IDisposable = Disposable.None;
@@ -348,6 +347,7 @@ class TreeRenderer implements IListRenderer
private modelProvider: () => ITreeModel,
onDidChangeCollapseState: Event>,
private activeNodes: Collection>,
+ private renderedIndentGuides: SetMap, HTMLDivElement>,
options: ITreeRendererOptions = {}
) {
this.templateId = renderer.templateId;
@@ -695,6 +695,14 @@ class FindWidget extends Disposable {
this.findInput.inputBox.setPlaceHolder(mode === TreeFindMode.Filter ? localize('type to filter', "Type to filter") : localize('type to search', "Type to search"));
}
+ get value(): string {
+ return this.findInput.inputBox.value;
+ }
+
+ set value(value: string) {
+ this.findInput.inputBox.value = value;
+ }
+
private readonly modeToggle: ModeToggle;
private readonly findInput: FindInput;
private readonly actionbar: ActionBar;
@@ -876,6 +884,7 @@ class FindController implements IDisposable {
private _pattern = '';
get pattern(): string { return this._pattern; }
+ private previousPattern = '';
private _mode: TreeFindMode;
get mode(): TreeFindMode { return this._mode; }
@@ -940,6 +949,9 @@ class FindController implements IDisposable {
this.widget.layout(this.width);
this.widget.focus();
+ this.widget.value = this.previousPattern;
+ this.widget.select();
+
this._onDidChangeOpenState.fire(true);
}
@@ -953,6 +965,7 @@ class FindController implements IDisposable {
this.enabledDisposables.dispose();
this.enabledDisposables = new DisposableStore();
+ this.previousPattern = this.pattern;
this.onDidChangeValue('');
this.tree.domFocus();
@@ -996,7 +1009,11 @@ class FindController implements IDisposable {
const noMatches = this.filter.totalCount > 0 && this.filter.matchCount === 0;
if (this.pattern && noMatches) {
- this.widget?.showMessage({ type: MessageType.WARNING, content: localize('not found', "No elements found.") });
+ if (this.tree.options.showNotFoundMessage ?? true) {
+ this.widget?.showMessage({ type: MessageType.WARNING, content: localize('not found', "No elements found.") });
+ } else {
+ this.widget?.showMessage({ type: MessageType.WARNING });
+ }
} else {
this.widget?.clearMessage();
}
@@ -1062,6 +1079,7 @@ export interface IAbstractTreeOptionsUpdate extends ITreeRendererOptions {
readonly typeNavigationEnabled?: boolean;
readonly typeNavigationMode?: TypeNavigationMode;
readonly defaultFindMode?: TreeFindMode;
+ readonly showNotFoundMessage?: boolean;
readonly smoothScrolling?: boolean;
readonly horizontalScrolling?: boolean;
readonly mouseWheelScrollSensitivity?: number;
@@ -1430,7 +1448,8 @@ export abstract class AbstractTree implements IDisposable
const onDidChangeCollapseStateRelay = new Relay>();
const onDidChangeActiveNodes = new Relay[]>();
const activeNodes = this.disposables.add(new EventCollection(onDidChangeActiveNodes.event));
- this.renderers = renderers.map(r => new TreeRenderer(r, () => this.model, onDidChangeCollapseStateRelay.event, activeNodes, _options));
+ const renderedIndentGuides = new SetMap, HTMLDivElement>();
+ this.renderers = renderers.map(r => new TreeRenderer(r, () => this.model, onDidChangeCollapseStateRelay.event, activeNodes, renderedIndentGuides, _options));
for (const r of this.renderers) {
this.disposables.add(r);
}
diff --git a/src/vs/base/common/map.ts b/src/vs/base/common/map.ts
index 2a78f7afb18..1c2e42bba59 100644
--- a/src/vs/base/common/map.ts
+++ b/src/vs/base/common/map.ts
@@ -576,12 +576,16 @@ export class TernarySearchTree {
if (!node.mid && !node.value) {
if (node.left && node.right) {
// full node
+ // replace deleted-node with the min-node of the right branch.
+ // If there is no true min-node leave things as they are
const min = this._min(node.right);
- const { key, value, segment } = min;
- this._delete(min.key!, false);
- node.key = key;
- node.value = value;
- node.segment = segment;
+ if (min.key) {
+ const { key, value, segment } = min;
+ this._delete(min.key!, false);
+ node.key = key;
+ node.value = value;
+ node.segment = segment;
+ }
} else {
// empty or half empty
diff --git a/src/vs/base/common/network.ts b/src/vs/base/common/network.ts
index 243bb3b82d3..648a6391131 100644
--- a/src/vs/base/common/network.ts
+++ b/src/vs/base/common/network.ts
@@ -150,7 +150,7 @@ class RemoteAuthoritiesImpl {
}
const authority = uri.authority;
let host = this._hosts[authority];
- if (host && host.indexOf(':') !== -1) {
+ if (host && host.indexOf(':') !== -1 && host.indexOf('[') === -1) {
host = `[${host}]`;
}
const port = this._ports[authority];
diff --git a/src/vs/base/parts/ipc/node/ipc.net.ts b/src/vs/base/parts/ipc/node/ipc.net.ts
index bff8e41d8e5..810ba41d106 100644
--- a/src/vs/base/parts/ipc/node/ipc.net.ts
+++ b/src/vs/base/parts/ipc/node/ipc.net.ts
@@ -32,6 +32,9 @@ export class NodeSocket implements ISocket {
public readonly debugLabel: string;
public readonly socket: Socket;
private readonly _errorListener: (err: any) => void;
+ private readonly _closeListener: (hadError: boolean) => void;
+ private readonly _endListener: () => void;
+ private _canWrite = true;
public traceSocketEvent(type: SocketDiagnosticsEventType, data?: VSBuffer | Uint8Array | ArrayBuffer | ArrayBufferView | any): void {
SocketDiagnostics.traceSocketEvent(this.socket, this.debugLabel, type, data);
@@ -57,10 +60,24 @@ export class NodeSocket implements ISocket {
}
};
this.socket.on('error', this._errorListener);
+
+ this._closeListener = (hadError: boolean) => {
+ this.traceSocketEvent(SocketDiagnosticsEventType.Close, { hadError });
+ this._canWrite = false;
+ };
+ this.socket.on('close', this._closeListener);
+
+ this._endListener = () => {
+ this.traceSocketEvent(SocketDiagnosticsEventType.NodeEndReceived);
+ this._canWrite = false;
+ };
+ this.socket.on('end', this._endListener);
}
public dispose(): void {
this.socket.off('error', this._errorListener);
+ this.socket.off('close', this._closeListener);
+ this.socket.off('end', this._endListener);
this.socket.destroy();
}
@@ -77,7 +94,6 @@ export class NodeSocket implements ISocket {
public onClose(listener: (e: SocketCloseEvent) => void): IDisposable {
const adapter = (hadError: boolean) => {
- this.traceSocketEvent(SocketDiagnosticsEventType.Close, { hadError });
listener({
type: SocketCloseEventType.NodeSocketCloseEvent,
hadError: hadError,
@@ -92,7 +108,6 @@ export class NodeSocket implements ISocket {
public onEnd(listener: () => void): IDisposable {
const adapter = () => {
- this.traceSocketEvent(SocketDiagnosticsEventType.NodeEndReceived);
listener();
};
this.socket.on('end', adapter);
@@ -103,7 +118,7 @@ export class NodeSocket implements ISocket {
public write(buffer: VSBuffer): void {
// return early if socket has been destroyed in the meantime
- if (this.socket.destroyed) {
+ if (this.socket.destroyed || !this._canWrite) {
return;
}
diff --git a/src/vs/base/parts/quickinput/browser/quickInput.ts b/src/vs/base/parts/quickinput/browser/quickInput.ts
index 41e7da28efa..ec55bbc810b 100644
--- a/src/vs/base/parts/quickinput/browser/quickInput.ts
+++ b/src/vs/base/parts/quickinput/browser/quickInput.ts
@@ -1166,11 +1166,14 @@ class InputBox extends QuickInput implements IInputBox {
if (!this.visible) {
return;
}
+
+ this.ui.container.classList.remove('hidden-input');
const visibilities: Visibilities = {
title: !!this.title || !!this.step || !!this.buttons.length,
description: !!this.description || !!this.step,
inputBox: true, message: true
};
+
this.ui.setVisibilities(visibilities);
super.update();
if (this.ui.inputBox.value !== this.value) {
@@ -1186,7 +1189,6 @@ class InputBox extends QuickInput implements IInputBox {
if (this.ui.inputBox.password !== this.password) {
this.ui.inputBox.password = this.password;
}
-
}
}
diff --git a/src/vs/base/test/common/event.test.ts b/src/vs/base/test/common/event.test.ts
index 79816c693e2..d87a96adda5 100644
--- a/src/vs/base/test/common/event.test.ts
+++ b/src/vs/base/test/common/event.test.ts
@@ -9,6 +9,7 @@ import { errorHandler, setUnexpectedErrorHandler } from 'vs/base/common/errors';
import { AsyncEmitter, DebounceEmitter, Emitter, Event, EventBufferer, EventMultiplexer, IWaitUntil, MicrotaskEmitter, PauseableEmitter, Relay } from 'vs/base/common/event';
import { DisposableStore, IDisposable, isDisposable, setDisposableTracker, toDisposable } from 'vs/base/common/lifecycle';
import { observableValue, transaction } from 'vs/base/common/observable';
+import { runWithFakedTimers } from 'vs/base/test/common/timeTravelScheduler';
import { DisposableTracker, ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
namespace Samples {
@@ -317,26 +318,29 @@ suite('Event', function () {
});
test('DebounceEmitter', async function () {
- let callCount = 0;
- let sum = 0;
- const emitter = new DebounceEmitter({
- merge: arr => {
- callCount += 1;
- return arr.reduce((p, c) => p + c);
- }
+ return runWithFakedTimers({}, async function () {
+
+ let callCount = 0;
+ let sum = 0;
+ const emitter = new DebounceEmitter({
+ merge: arr => {
+ callCount += 1;
+ return arr.reduce((p, c) => p + c);
+ }
+ });
+
+ emitter.event(e => { sum = e; });
+
+ const p = Event.toPromise(emitter.event);
+
+ emitter.fire(1);
+ emitter.fire(2);
+
+ await p;
+
+ assert.strictEqual(callCount, 1);
+ assert.strictEqual(sum, 3);
});
-
- emitter.event(e => { sum = e; });
-
- const p = Event.toPromise(emitter.event);
-
- emitter.fire(1);
- emitter.fire(2);
-
- await p;
-
- assert.strictEqual(callCount, 1);
- assert.strictEqual(sum, 3);
});
test('Microtask Emitter', (done) => {
@@ -410,59 +414,64 @@ suite('AsyncEmitter', function () {
});
test('sequential delivery', async function () {
+ return runWithFakedTimers({}, async function () {
- interface E extends IWaitUntil {
- foo: boolean;
- }
+ interface E extends IWaitUntil {
+ foo: boolean;
+ }
- let globalState = 0;
- const emitter = new AsyncEmitter();
+ let globalState = 0;
+ const emitter = new AsyncEmitter();
- emitter.event(e => {
- e.waitUntil(timeout(10).then(_ => {
- assert.strictEqual(globalState, 0);
- globalState += 1;
- }));
+ emitter.event(e => {
+ e.waitUntil(timeout(10).then(_ => {
+ assert.strictEqual(globalState, 0);
+ globalState += 1;
+ }));
+ });
+
+ emitter.event(e => {
+ e.waitUntil(timeout(1).then(_ => {
+ assert.strictEqual(globalState, 1);
+ globalState += 1;
+ }));
+ });
+
+ await emitter.fireAsync({ foo: true }, CancellationToken.None);
+ assert.strictEqual(globalState, 2);
});
-
- emitter.event(e => {
- e.waitUntil(timeout(1).then(_ => {
- assert.strictEqual(globalState, 1);
- globalState += 1;
- }));
- });
-
- await emitter.fireAsync({ foo: true }, CancellationToken.None);
- assert.strictEqual(globalState, 2);
});
test('sequential, in-order delivery', async function () {
- interface E extends IWaitUntil {
- foo: number;
- }
- const events: number[] = [];
- let done = false;
- const emitter = new AsyncEmitter();
+ return runWithFakedTimers({}, async function () {
- // e1
- emitter.event(e => {
- e.waitUntil(timeout(10).then(async _ => {
- if (e.foo === 1) {
- await emitter.fireAsync({ foo: 2 }, CancellationToken.None);
- assert.deepStrictEqual(events, [1, 2]);
- done = true;
- }
- }));
+ interface E extends IWaitUntil {
+ foo: number;
+ }
+ const events: number[] = [];
+ let done = false;
+ const emitter = new AsyncEmitter();
+
+ // e1
+ emitter.event(e => {
+ e.waitUntil(timeout(10).then(async _ => {
+ if (e.foo === 1) {
+ await emitter.fireAsync({ foo: 2 }, CancellationToken.None);
+ assert.deepStrictEqual(events, [1, 2]);
+ done = true;
+ }
+ }));
+ });
+
+ // e2
+ emitter.event(e => {
+ events.push(e.foo);
+ e.waitUntil(timeout(7));
+ });
+
+ await emitter.fireAsync({ foo: 1 }, CancellationToken.None);
+ assert.ok(done);
});
-
- // e2
- emitter.event(e => {
- events.push(e.foo);
- e.waitUntil(timeout(7));
- });
-
- await emitter.fireAsync({ foo: 1 }, CancellationToken.None);
- assert.ok(done);
});
test('catch errors', async function () {
diff --git a/src/vs/base/test/common/map.test.ts b/src/vs/base/test/common/map.test.ts
index 896d06ec812..0d3f3dfe131 100644
--- a/src/vs/base/test/common/map.test.ts
+++ b/src/vs/base/test/common/map.test.ts
@@ -862,6 +862,49 @@ suite('Map', () => {
}
});
+ test('TernarySearchTree: Cannot read properties of undefined (reading \'length\'): #161618 (simple)', function () {
+ const raw = 'config.debug.toolBarLocation,floating,config.editor.renderControlCharacters,true,config.editor.renderWhitespace,selection,config.files.autoSave,off,config.git.enabled,true,config.notebook.globalToolbar,true,config.terminal.integrated.tabs.enabled,true,config.terminal.integrated.tabs.showActions,singleTerminalOrNarrow,config.terminal.integrated.tabs.showActiveTerminal,singleTerminalOrNarrow,config.workbench.activityBar.visible,true,config.workbench.experimental.settingsProfiles.enabled,true,config.workbench.layoutControl.type,both,config.workbench.sideBar.location,left,config.workbench.statusBar.visible,true';
+ const array = raw.split(',');
+ const tuples: [string, string][] = [];
+ for (let i = 0; i < array.length; i += 2) {
+ tuples.push([array[i], array[i + 1]]);
+ }
+
+ const map = TernarySearchTree.forConfigKeys();
+ map.fill(tuples);
+
+ assert.strictEqual([...map].join(), raw);
+ assert.ok(map.has('config.editor.renderWhitespace'));
+
+ const len = [...map].length;
+ map.delete('config.editor.renderWhitespace');
+ assert.ok(map._isBalanced());
+ assert.strictEqual([...map].length, len - 1);
+ });
+
+ test('TernarySearchTree: Cannot read properties of undefined (reading \'length\'): #161618 (random)', function () {
+ const raw = 'config.debug.toolBarLocation,floating,config.editor.renderControlCharacters,true,config.editor.renderWhitespace,selection,config.files.autoSave,off,config.git.enabled,true,config.notebook.globalToolbar,true,config.terminal.integrated.tabs.enabled,true,config.terminal.integrated.tabs.showActions,singleTerminalOrNarrow,config.terminal.integrated.tabs.showActiveTerminal,singleTerminalOrNarrow,config.workbench.activityBar.visible,true,config.workbench.experimental.settingsProfiles.enabled,true,config.workbench.layoutControl.type,both,config.workbench.sideBar.location,left,config.workbench.statusBar.visible,true';
+ const array = raw.split(',');
+ const tuples: [string, string][] = [];
+ for (let i = 0; i < array.length; i += 2) {
+ tuples.push([array[i], array[i + 1]]);
+ }
+
+ for (let round = 100; round >= 0; round--) {
+ shuffle(tuples);
+ const map = TernarySearchTree.forConfigKeys();
+ map.fill(tuples);
+
+ assert.strictEqual([...map].join(), raw);
+ assert.ok(map.has('config.editor.renderWhitespace'));
+
+ const len = [...map].length;
+ map.delete('config.editor.renderWhitespace');
+ assert.ok(map._isBalanced());
+ assert.strictEqual([...map].length, len - 1);
+ }
+ });
+
test('TernarySearchTree (PathSegments) - lookup', function () {
const map = new TernarySearchTree(new PathIterator());
diff --git a/src/vs/editor/browser/services/bulkEditService.ts b/src/vs/editor/browser/services/bulkEditService.ts
index 12d1417489a..4f06c9ca68b 100644
--- a/src/vs/editor/browser/services/bulkEditService.ts
+++ b/src/vs/editor/browser/services/bulkEditService.ts
@@ -108,6 +108,7 @@ export interface IBulkEditOptions {
export interface IBulkEditResult {
ariaSummary: string;
+ isApplied: boolean;
}
export type IBulkEditPreviewHandler = (edits: ResourceEdit[], options?: IBulkEditOptions) => Promise;
diff --git a/src/vs/editor/browser/viewParts/blockDecorations/blockDecorations.ts b/src/vs/editor/browser/viewParts/blockDecorations/blockDecorations.ts
index 48f52d6d231..87057ba9ce6 100644
--- a/src/vs/editor/browser/viewParts/blockDecorations/blockDecorations.ts
+++ b/src/vs/editor/browser/viewParts/blockDecorations/blockDecorations.ts
@@ -82,10 +82,20 @@ export class BlockDecorations extends ViewPart {
block = this.blocks[count] = createFastDomNode(document.createElement('div'));
this.domNode.appendChild(block);
}
- const top = ctx.getVerticalOffsetForLineNumber(decoration.range.startLineNumber, true);
- const bottom = decoration.range.isEmpty()
- ? ctx.getVerticalOffsetForLineNumber(decoration.range.startLineNumber, false)
- : ctx.getVerticalOffsetAfterLineNumber(decoration.range.endLineNumber, true);
+
+ let top: number;
+ let bottom: number;
+
+ if (decoration.options.blockIsAfterEnd) {
+ // range must be empty
+ top = ctx.getVerticalOffsetAfterLineNumber(decoration.range.endLineNumber, false);
+ bottom = ctx.getVerticalOffsetAfterLineNumber(decoration.range.endLineNumber, true);
+ } else {
+ top = ctx.getVerticalOffsetForLineNumber(decoration.range.startLineNumber, true);
+ bottom = decoration.range.isEmpty()
+ ? ctx.getVerticalOffsetForLineNumber(decoration.range.startLineNumber, false)
+ : ctx.getVerticalOffsetAfterLineNumber(decoration.range.endLineNumber, true);
+ }
block.setClassName('blockDecorations-block ' + decoration.options.blockClassName);
block.setLeft(ctx.scrollLeft);
diff --git a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts
index f45578d9f15..37c8f7ac5d0 100644
--- a/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts
+++ b/src/vs/editor/browser/viewParts/contentWidgets/contentWidgets.ts
@@ -432,6 +432,12 @@ class Widget {
}
}
+ // Left-align widgets that should appear :before content
+ if (this._affinity === PositionAffinity.LeftOfInjectedText &&
+ this._viewRange.startColumn === 1) {
+ firstLineMinLeft = 0;
+ }
+
let lastLineMinLeft = Constants.MAX_SAFE_SMALL_INTEGER;//lastLine.Constants.MAX_SAFE_SMALL_INTEGER;
for (const visibleRange of lastLine.ranges) {
if (visibleRange.left < lastLineMinLeft) {
diff --git a/src/vs/editor/browser/viewParts/lines/viewLines.css b/src/vs/editor/browser/viewParts/lines/viewLines.css
index 315306d65f2..f83ea79dd02 100644
--- a/src/vs/editor/browser/viewParts/lines/viewLines.css
+++ b/src/vs/editor/browser/viewParts/lines/viewLines.css
@@ -25,6 +25,15 @@
user-select: none;
-webkit-user-select: none;
}
+/* Use user-select: text for lookup feature on macOS */
+/* https://github.com/microsoft/vscode/issues/85632 */
+.monaco-editor.mac .lines-content:hover,
+.monaco-editor.mac .view-line:hover,
+.monaco-editor.mac .view-lines:hover {
+ user-select: text;
+ -webkit-user-select: text;
+ -ms-user-select: text;
+}
.monaco-editor.enable-user-select {
user-select: initial;
diff --git a/src/vs/editor/common/diff/standardLinesDiffComputer.ts b/src/vs/editor/common/diff/standardLinesDiffComputer.ts
index ce0b07c8a2e..464d33592fb 100644
--- a/src/vs/editor/common/diff/standardLinesDiffComputer.ts
+++ b/src/vs/editor/common/diff/standardLinesDiffComputer.ts
@@ -57,13 +57,45 @@ export class StandardLinesDiffComputer implements ILinesDiffComputer {
})();
const alignments: RangeMapping[] = [];
+
+ const scanForWhitespaceChanges = (equalLinesCount: number) => {
+ for (let i = 0; i < equalLinesCount; i++) {
+ const seq1Offset = seq1LastStart + i;
+ const seq2Offset = seq2LastStart + i;
+ if (originalLines[seq1Offset] !== modifiedLines[seq2Offset]) {
+ // This is because of whitespace changes, diff these lines
+ const characterDiffs = this.refineDiff(originalLines, modifiedLines, new SequenceDiff(
+ new OffsetRange(seq1Offset, seq1Offset + 1),
+ new OffsetRange(seq2Offset, seq2Offset + 1)
+ ));
+ for (const a of characterDiffs) {
+ alignments.push(a);
+ }
+ }
+ }
+ };
+
+ let seq1LastStart = 0;
+ let seq2LastStart = 0;
+
for (const diff of lineAlignments) {
+ assertFn(() => diff.seq1Range.start - seq1LastStart === diff.seq2Range.start - seq2LastStart);
+
+ const equalLinesCount = diff.seq1Range.start - seq1LastStart;
+
+ scanForWhitespaceChanges(equalLinesCount);
+
+ seq1LastStart = diff.seq1Range.endExclusive;
+ seq2LastStart = diff.seq2Range.endExclusive;
+
const characterDiffs = this.refineDiff(originalLines, modifiedLines, diff);
for (const a of characterDiffs) {
alignments.push(a);
}
}
+ scanForWhitespaceChanges(originalLines.length - seq1LastStart);
+
const changes: LineRangeMapping[] = lineRangeMappingFromRangeMappings(alignments);
return {
diff --git a/src/vs/editor/common/model.ts b/src/vs/editor/common/model.ts
index 5cefe83dfc8..6c7badf0b8a 100644
--- a/src/vs/editor/common/model.ts
+++ b/src/vs/editor/common/model.ts
@@ -92,6 +92,11 @@ export interface IModelDecorationOptions {
*/
className?: string | null;
blockClassName?: string | null;
+ /**
+ * Indicates if this block should be rendered after the last line.
+ * In this case, the range must be empty and set to the last line.
+ */
+ blockIsAfterEnd?: boolean | null;
/**
* Message to be rendered when hovering over the glyph margin decoration.
*/
diff --git a/src/vs/editor/common/model/textModel.ts b/src/vs/editor/common/model/textModel.ts
index 102dc04c973..27ee2e71319 100644
--- a/src/vs/editor/common/model/textModel.ts
+++ b/src/vs/editor/common/model/textModel.ts
@@ -2231,6 +2231,7 @@ export class ModelDecorationOptions implements model.IModelDecorationOptions {
readonly description: string;
readonly blockClassName: string | null;
+ readonly blockIsAfterEnd: boolean | null;
readonly stickiness: model.TrackedRangeStickiness;
readonly zIndex: number;
readonly className: string | null;
@@ -2258,6 +2259,7 @@ export class ModelDecorationOptions implements model.IModelDecorationOptions {
private constructor(options: model.IModelDecorationOptions) {
this.description = options.description;
this.blockClassName = options.blockClassName ? cleanClassName(options.blockClassName) : null;
+ this.blockIsAfterEnd = options.blockIsAfterEnd ?? null;
this.stickiness = options.stickiness || model.TrackedRangeStickiness.AlwaysGrowsWhenTypingAtEdges;
this.zIndex = options.zIndex || 0;
this.className = options.className ? cleanClassName(options.className) : null;
diff --git a/src/vs/editor/common/services/languageFeatureDebounce.ts b/src/vs/editor/common/services/languageFeatureDebounce.ts
index e4e67bd700f..417a2d9dc08 100644
--- a/src/vs/editor/common/services/languageFeatureDebounce.ts
+++ b/src/vs/editor/common/services/languageFeatureDebounce.ts
@@ -8,7 +8,7 @@ import { LRUCache } from 'vs/base/common/map';
import { clamp, MovingAverage, SlidingWindowAverage } from 'vs/base/common/numbers';
import { LanguageFeatureRegistry } from 'vs/editor/common/languageFeatureRegistry';
import { ITextModel } from 'vs/editor/common/model';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { ILogService } from 'vs/platform/log/common/log';
import { matchesScheme } from 'vs/platform/opener/common/opener';
@@ -136,4 +136,4 @@ export class LanguageFeatureDebounceService implements ILanguageFeatureDebounceS
}
}
-registerSingleton(ILanguageFeatureDebounceService, LanguageFeatureDebounceService, true);
+registerSingleton(ILanguageFeatureDebounceService, LanguageFeatureDebounceService, InstantiationType.Delayed);
diff --git a/src/vs/editor/common/services/languageFeaturesService.ts b/src/vs/editor/common/services/languageFeaturesService.ts
index 4059a90b370..35d321b4ef2 100644
--- a/src/vs/editor/common/services/languageFeaturesService.ts
+++ b/src/vs/editor/common/services/languageFeaturesService.ts
@@ -7,7 +7,7 @@ import { URI } from 'vs/base/common/uri';
import { LanguageFeatureRegistry, NotebookInfo, NotebookInfoResolver } from 'vs/editor/common/languageFeatureRegistry';
import { CodeActionProvider, CodeLensProvider, CompletionItemProvider, DocumentPasteEditProvider, DeclarationProvider, DefinitionProvider, DocumentColorProvider, DocumentFormattingEditProvider, DocumentHighlightProvider, DocumentOnDropEditProvider, DocumentRangeFormattingEditProvider, DocumentRangeSemanticTokensProvider, DocumentSemanticTokensProvider, DocumentSymbolProvider, EvaluatableExpressionProvider, FoldingRangeProvider, HoverProvider, ImplementationProvider, InlayHintsProvider, InlineCompletionsProvider, InlineValuesProvider, LinkedEditingRangeProvider, LinkProvider, OnTypeFormattingEditProvider, ReferenceProvider, RenameProvider, SelectionRangeProvider, SignatureHelpProvider, TypeDefinitionProvider } from 'vs/editor/common/languages';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
export class LanguageFeaturesService implements ILanguageFeaturesService {
@@ -55,4 +55,4 @@ export class LanguageFeaturesService implements ILanguageFeaturesService {
}
-registerSingleton(ILanguageFeaturesService, LanguageFeaturesService, true);
+registerSingleton(ILanguageFeaturesService, LanguageFeaturesService, InstantiationType.Delayed);
diff --git a/src/vs/editor/contrib/codeAction/browser/codeActionUi.ts b/src/vs/editor/contrib/codeAction/browser/codeActionUi.ts
index 13e0d5fe187..3066ae54574 100644
--- a/src/vs/editor/contrib/codeAction/browser/codeActionUi.ts
+++ b/src/vs/editor/contrib/codeAction/browser/codeActionUi.ts
@@ -15,6 +15,7 @@ import { CodeActionTriggerType } from 'vs/editor/common/languages';
import { CodeActionItem, CodeActionSet } from 'vs/editor/contrib/codeAction/browser/codeAction';
import { MessageController } from 'vs/editor/contrib/message/browser/messageController';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
+import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { CodeActionsState } from './codeActionModel';
import { CodeActionShowOptions, CodeActionWidget } from './codeActionWidget';
@@ -34,8 +35,9 @@ export class CodeActionUi extends Disposable {
private readonly delegate: {
applyCodeAction: (action: CodeActionItem, regtriggerAfterApply: boolean, preview: boolean) => Promise;
},
- @IInstantiationService private readonly _instantiationService: IInstantiationService,
@IConfigurationService private readonly _configurationService: IConfigurationService,
+ @IContextKeyService private readonly _contextKeyService: IContextKeyService,
+ @IInstantiationService private readonly _instantiationService: IInstantiationService,
) {
super();
@@ -166,7 +168,7 @@ export class CodeActionUi extends Disposable {
onHide: () => {
this._editor?.focus();
},
- });
+ }, this._contextKeyService);
}
private toCoords(position: IPosition): IAnchor {
diff --git a/src/vs/editor/contrib/codeAction/browser/codeActionWidget.css b/src/vs/editor/contrib/codeAction/browser/codeActionWidget.css
index 2561c7f4f04..c788bfe5d1e 100644
--- a/src/vs/editor/contrib/codeAction/browser/codeActionWidget.css
+++ b/src/vs/editor/contrib/codeAction/browser/codeActionWidget.css
@@ -12,10 +12,8 @@
display: block;
width: 100%;
border: 1px solid var(--vscode-editorWidget-border) !important;
- border-color: none;
background-color: var(--vscode-editorWidget-background);
- color: var(--vscode--editorWidget-foreground);
- box-shadow: var(--vscode-widget-shadow) 0 2px 8px;
+ color: var(--vscode-editorWidget-foreground);
}
.codeActionWidget .monaco-list {
@@ -42,7 +40,7 @@
width: 100%;
}
-.codeActionWidget .monaco-list .monaco-list-row.code-action.focused:not(.option-disabled) {
+.codeActionWidget .monaco-list .monaco-list-row.code-action.focused:not(.option-disabled) {
background-color: var(--vscode-quickInputList-focusBackground);
color: var(--vscode-quickInputList-focusForeground);
outline: 1px solid var(--vscode-menu-selectionBorder, transparent);
@@ -51,7 +49,7 @@
.codeActionWidget .monaco-list-row.group-header {
color: var(--vscode-pickerGroup-foreground);
- font-weight: bold;
+ font-weight: 600;
}
.codeActionWidget .monaco-list .group-header,
@@ -72,7 +70,7 @@
.codeActionWidget .monaco-list-row.code-action {
display: flex;
- gap: 10px;
+ gap: 6px;
align-items: center;
}
@@ -98,28 +96,30 @@
.codeActionWidget .codeActionWidget-action-bar {
margin-top: 4px;
- margin-bottom: 4px;
+ background-color: var(--vscode-editorHoverWidget-statusBarBackground);
+ border-top: 1px solid var(--vscode-editorHoverWidget-border);
}
.codeActionWidget .codeActionWidget-action-bar::before {
display: block;
content: "";
width: 100%;
- margin-bottom: 4px;
- border-bottom: 1px solid var(--vscode-menu-separatorBackground);
}
.codeActionWidget .codeActionWidget-action-bar .actions-container {
- padding: 0 10px;
+ padding: 0 8px;
}
.codeActionWidget-action-bar .action-label {
color: var(--vscode-textLink-activeForeground);
+ font-size: 12px;
+ line-height: 22px;
+ padding: 0;
pointer-events: all;
}
.codeActionWidget-action-bar .action-item {
- margin-right: 10px;
+ margin-right: 16px;
pointer-events: none;
}
diff --git a/src/vs/editor/contrib/codeAction/browser/codeActionWidget.ts b/src/vs/editor/contrib/codeAction/browser/codeActionWidget.ts
index 7c3180aa563..a35cb65a441 100644
--- a/src/vs/editor/contrib/codeAction/browser/codeActionWidget.ts
+++ b/src/vs/editor/contrib/codeAction/browser/codeActionWidget.ts
@@ -20,7 +20,7 @@ import { CodeActionKind, CodeActionTrigger, CodeActionTriggerSource } from 'vs/e
import 'vs/editor/contrib/symbolIcons/browser/symbolIcons'; // The codicon symbol colors are defined here and must be loaded to get colors
import { localize } from 'vs/nls';
import { ICommandService } from 'vs/platform/commands/common/commands';
-import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
+import { IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
@@ -369,40 +369,44 @@ export class CodeActionWidget extends Disposable {
readonly container: HTMLElement | undefined;
readonly codeActions: CodeActionSet;
readonly delegate: CodeActionWidgetDelegate;
+ readonly contextKeyService: IContextKeyService;
};
- private readonly _ctxMenuWidgetVisible: IContextKey;
-
constructor(
@ICommandService private readonly _commandService: ICommandService,
- @IContextKeyService private readonly _contextKeyService: IContextKeyService,
@IContextViewService private readonly _contextViewService: IContextViewService,
@IKeybindingService private readonly _keybindingService: IKeybindingService,
@ITelemetryService private readonly _telemetryService: ITelemetryService,
) {
super();
-
- this._ctxMenuWidgetVisible = Context.Visible.bindTo(this._contextKeyService);
}
get isVisible(): boolean {
return !!this.currentShowingContext;
}
- public async show(trigger: CodeActionTrigger, codeActions: CodeActionSet, anchor: IAnchor, container: HTMLElement | undefined, options: CodeActionShowOptions, delegate: CodeActionWidgetDelegate): Promise {
+ public async show(trigger: CodeActionTrigger, codeActions: CodeActionSet, anchor: IAnchor, container: HTMLElement | undefined, options: CodeActionShowOptions, delegate: CodeActionWidgetDelegate, contextKeyService: IContextKeyService): Promise {
this.currentShowingContext = undefined;
+ const visibleContext = Context.Visible.bindTo(contextKeyService);
const actionsToShow = options.includeDisabledActions && (showDisabled || codeActions.validActions.length === 0) ? codeActions.allActions : codeActions.validActions;
if (!actionsToShow.length) {
+ visibleContext.reset();
return;
}
- this.currentShowingContext = { trigger, codeActions, anchor, container, delegate, options };
+ this.currentShowingContext = { trigger, codeActions, anchor, container, delegate, options, contextKeyService };
this._contextViewService.showContextView({
getAnchor: () => anchor,
- render: (container: HTMLElement) => this.renderWidget(container, trigger, codeActions, options, actionsToShow, delegate),
- onHide: (didCancel: boolean) => this.onWidgetClosed(trigger, options, codeActions, didCancel, delegate),
+ render: (container: HTMLElement) => {
+ visibleContext.set(true);
+ return this.renderWidget(container, trigger, codeActions, options, actionsToShow, delegate);
+ },
+ onHide: (didCancel: boolean) => {
+ visibleContext.reset();
+ return this.onWidgetClosed(trigger, options, codeActions, didCancel, delegate);
+ },
}, container, false);
}
@@ -419,7 +423,6 @@ export class CodeActionWidget extends Disposable {
}
public hide() {
- this._ctxMenuWidgetVisible.reset();
this.codeActionList.clear();
this._contextViewService.hideContextView();
}
@@ -488,8 +491,6 @@ export class CodeActionWidget extends Disposable {
const focusTracker = renderDisposables.add(dom.trackFocus(element));
renderDisposables.add(focusTracker.onDidBlur(() => this.hide()));
- this._ctxMenuWidgetVisible.set(true);
-
return renderDisposables;
}
@@ -504,7 +505,7 @@ export class CodeActionWidget extends Disposable {
showDisabled = newShowDisabled;
if (previousCtx) {
- this.show(previousCtx.trigger, previousCtx.codeActions, previousCtx.anchor, previousCtx.container, previousCtx.options, previousCtx.delegate);
+ this.show(previousCtx.trigger, previousCtx.codeActions, previousCtx.anchor, previousCtx.container, previousCtx.options, previousCtx.delegate, previousCtx.contextKeyService);
}
}
@@ -530,6 +531,7 @@ export class CodeActionWidget extends Disposable {
});
this.currentShowingContext = undefined;
+
delegate.onHide(cancelled);
}
diff --git a/src/vs/editor/contrib/codelens/browser/codeLensCache.ts b/src/vs/editor/contrib/codelens/browser/codeLensCache.ts
index f6696e42746..4ab8835ae2f 100644
--- a/src/vs/editor/contrib/codelens/browser/codeLensCache.ts
+++ b/src/vs/editor/contrib/codelens/browser/codeLensCache.ts
@@ -10,7 +10,7 @@ import { Range } from 'vs/editor/common/core/range';
import { ITextModel } from 'vs/editor/common/model';
import { CodeLens, CodeLensList, CodeLensProvider } from 'vs/editor/common/languages';
import { CodeLensModel } from 'vs/editor/contrib/codelens/browser/codelens';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IStorageService, StorageScope, StorageTarget, WillSaveStateReason } from 'vs/platform/storage/common/storage';
@@ -129,4 +129,4 @@ export class CodeLensCache implements ICodeLensCache {
}
}
-registerSingleton(ICodeLensCache, CodeLensCache, true);
+registerSingleton(ICodeLensCache, CodeLensCache, InstantiationType.Delayed);
diff --git a/src/vs/editor/contrib/documentSymbols/browser/outlineModel.ts b/src/vs/editor/contrib/documentSymbols/browser/outlineModel.ts
index bbebc0a585e..e9746fec571 100644
--- a/src/vs/editor/contrib/documentSymbols/browser/outlineModel.ts
+++ b/src/vs/editor/contrib/documentSymbols/browser/outlineModel.ts
@@ -17,7 +17,7 @@ import { DocumentSymbol, DocumentSymbolProvider } from 'vs/editor/common/languag
import { MarkerSeverity } from 'vs/platform/markers/common/markers';
import { IFeatureDebounceInformation, ILanguageFeatureDebounceService } from 'vs/editor/common/services/languageFeatureDebounce';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IModelService } from 'vs/editor/common/services/model';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { LanguageFeatureRegistry } from 'vs/editor/common/languageFeatureRegistry';
@@ -485,4 +485,4 @@ export class OutlineModelService implements IOutlineModelService {
}
}
-registerSingleton(IOutlineModelService, OutlineModelService, true);
+registerSingleton(IOutlineModelService, OutlineModelService, InstantiationType.Delayed);
diff --git a/src/vs/editor/contrib/find/browser/findOptionsWidget.ts b/src/vs/editor/contrib/find/browser/findOptionsWidget.ts
index ca04b53497d..7169c362279 100644
--- a/src/vs/editor/contrib/find/browser/findOptionsWidget.ts
+++ b/src/vs/editor/contrib/find/browser/findOptionsWidget.ts
@@ -43,6 +43,7 @@ export class FindOptionsWidget extends Widget implements IOverlayWidget {
this._domNode.className = 'findOptionsWidget';
this._domNode.style.display = 'none';
this._domNode.style.top = '10px';
+ this._domNode.style.zIndex = '12';
this._domNode.setAttribute('role', 'presentation');
this._domNode.setAttribute('aria-hidden', 'true');
diff --git a/src/vs/editor/contrib/gotoError/browser/markerNavigationService.ts b/src/vs/editor/contrib/gotoError/browser/markerNavigationService.ts
index 8e7e0bb70d6..1162ef145ea 100644
--- a/src/vs/editor/contrib/gotoError/browser/markerNavigationService.ts
+++ b/src/vs/editor/contrib/gotoError/browser/markerNavigationService.ts
@@ -12,7 +12,7 @@ import { URI } from 'vs/base/common/uri';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { ITextModel } from 'vs/editor/common/model';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IMarker, IMarkerService, MarkerSeverity } from 'vs/platform/markers/common/markers';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
@@ -221,4 +221,4 @@ class MarkerNavigationService implements IMarkerNavigationService, IMarkerListPr
}
}
-registerSingleton(IMarkerNavigationService, MarkerNavigationService, true);
+registerSingleton(IMarkerNavigationService, MarkerNavigationService, InstantiationType.Delayed);
diff --git a/src/vs/editor/contrib/gotoSymbol/browser/goToCommands.ts b/src/vs/editor/contrib/gotoSymbol/browser/goToCommands.ts
index cc7d0b8c67a..c3f073892da 100644
--- a/src/vs/editor/contrib/gotoSymbol/browser/goToCommands.ts
+++ b/src/vs/editor/contrib/gotoSymbol/browser/goToCommands.ts
@@ -79,9 +79,11 @@ export abstract class SymbolNavigationAction extends EditorAction2 {
private static _allSymbolNavigationCommands = new Map();
private static _activeAlternativeCommands = new Set();
- readonly configuration: SymbolNavigationActionConfig;
+ static all(): IterableIterator {
+ return SymbolNavigationAction._allSymbolNavigationCommands.values();
+ }
- private static aaa(opts: IAction2Options): IAction2Options {
+ private static _patchConfig(opts: IAction2Options): IAction2Options {
const result = { ...opts, f1: true };
// patch context menu when clause
if (result.menu) {
@@ -95,8 +97,10 @@ export abstract class SymbolNavigationAction extends EditorAction2 {
return result;
}
+ readonly configuration: SymbolNavigationActionConfig;
+
constructor(configuration: SymbolNavigationActionConfig, opts: IAction2Options) {
- super(SymbolNavigationAction.aaa(opts));
+ super(SymbolNavigationAction._patchConfig(opts));
this.configuration = configuration;
SymbolNavigationAction._allSymbolNavigationCommands.set(opts.id, this);
}
diff --git a/src/vs/editor/contrib/gotoSymbol/browser/link/clickLinkGesture.ts b/src/vs/editor/contrib/gotoSymbol/browser/link/clickLinkGesture.ts
index c11b578b773..78b3bdbfed5 100644
--- a/src/vs/editor/contrib/gotoSymbol/browser/link/clickLinkGesture.ts
+++ b/src/vs/editor/contrib/gotoSymbol/browser/link/clickLinkGesture.ts
@@ -25,9 +25,11 @@ export class ClickLinkMouseEvent {
public readonly hasTriggerModifier: boolean;
public readonly hasSideBySideModifier: boolean;
public readonly isNoneOrSingleMouseDown: boolean;
+ public readonly hasRightClick: boolean;
constructor(source: IEditorMouseEvent, opts: ClickLinkOptions) {
this.target = source.target;
+ this.hasRightClick = source.event.rightButton;
this.hasTriggerModifier = hasModifier(source.event, opts.triggerModifier);
this.hasSideBySideModifier = hasModifier(source.event, opts.triggerSideBySideModifier);
this.isNoneOrSingleMouseDown = (source.event.detail <= 1);
diff --git a/src/vs/editor/contrib/gotoSymbol/browser/symbolNavigation.ts b/src/vs/editor/contrib/gotoSymbol/browser/symbolNavigation.ts
index e0ff47c0935..2c7046f3d31 100644
--- a/src/vs/editor/contrib/gotoSymbol/browser/symbolNavigation.ts
+++ b/src/vs/editor/contrib/gotoSymbol/browser/symbolNavigation.ts
@@ -15,7 +15,7 @@ import { OneReference, ReferencesModel } from 'vs/editor/contrib/gotoSymbol/brow
import { localize } from 'vs/nls';
import { IContextKey, IContextKeyService, RawContextKey } from 'vs/platform/contextkey/common/contextkey';
import { TextEditorSelectionRevealType } from 'vs/platform/editor/common/editor';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { createDecorator, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
@@ -149,7 +149,7 @@ class SymbolNavigationService implements ISymbolNavigationService {
}
}
-registerSingleton(ISymbolNavigationService, SymbolNavigationService, true);
+registerSingleton(ISymbolNavigationService, SymbolNavigationService, InstantiationType.Delayed);
registerEditorCommand(new class extends EditorCommand {
diff --git a/src/vs/editor/contrib/hover/browser/contentHover.ts b/src/vs/editor/contrib/hover/browser/contentHover.ts
index e827d2cec6c..30de80e0952 100644
--- a/src/vs/editor/contrib/hover/browser/contentHover.ts
+++ b/src/vs/editor/contrib/hover/browser/contentHover.ts
@@ -13,7 +13,7 @@ import { ContentWidgetPositionPreference, IActiveCodeEditor, ICodeEditor, IConte
import { ConfigurationChangedEvent, EditorOption } from 'vs/editor/common/config/editorOptions';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
-import { IModelDecoration } from 'vs/editor/common/model';
+import { IModelDecoration, PositionAffinity } from 'vs/editor/common/model';
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
import { TokenizationRegistry } from 'vs/editor/common/languages';
import { HoverOperation, HoverStartMode, IHoverComputer } from 'vs/editor/contrib/hover/browser/hoverOperation';
@@ -129,8 +129,8 @@ export class ContentHoverController extends Disposable {
}
// The hover is currently visible
-
- const isGettingCloser = (mouseEvent && this._widget.isMouseGettingCloser(mouseEvent.event.posx, mouseEvent.event.posy));
+ const hoverIsSticky = this._editor.getOption(EditorOption.hover).sticky;
+ const isGettingCloser = (hoverIsSticky && mouseEvent && this._widget.isMouseGettingCloser(mouseEvent.event.posx, mouseEvent.event.posy));
if (isGettingCloser) {
// The mouse is getting closer to the hover, so we will keep the hover untouched
// But we will kick off a hover update at the new anchor, insisting on keeping the hover visible.
@@ -261,6 +261,9 @@ export class ContentHoverController extends Disposable {
disposables.add(participant.renderHoverParts(context, hoverParts));
}
}
+
+ const isBeforeContent = messages.some(m => m.isBeforeContent);
+
if (statusBar.hasContent) {
fragment.appendChild(statusBar.hoverElement);
}
@@ -283,6 +286,7 @@ export class ContentHoverController extends Disposable {
showAtRange,
this._editor.getOption(EditorOption.hover).above,
this._computer.shouldFocus,
+ isBeforeContent,
anchor.initialMousePosX,
anchor.initialMousePosY,
disposables
@@ -368,6 +372,7 @@ class ContentHoverVisibleData {
public readonly showAtRange: Range,
public readonly preferAbove: boolean,
public readonly stoleFocus: boolean,
+ public readonly isBeforeContent: boolean,
public initialMousePosX: number | undefined,
public initialMousePosY: number | undefined,
public readonly disposables: DisposableStore
@@ -439,6 +444,10 @@ export class ContentHoverWidget extends Disposable implements IContentWidget {
// Prefer rendering above if the suggest widget is visible
preferAbove = true;
}
+
+ // :before content can align left of the text content
+ const affinity = this._visibleData.isBeforeContent ? PositionAffinity.LeftOfInjectedText : undefined;
+
return {
position: this._visibleData.showAtPosition,
range: this._visibleData.showAtRange,
@@ -447,6 +456,7 @@ export class ContentHoverWidget extends Disposable implements IContentWidget {
? [ContentWidgetPositionPreference.ABOVE, ContentWidgetPositionPreference.BELOW]
: [ContentWidgetPositionPreference.BELOW, ContentWidgetPositionPreference.ABOVE]
),
+ positionAffinity: affinity
};
}
diff --git a/src/vs/editor/contrib/hover/browser/hoverTypes.ts b/src/vs/editor/contrib/hover/browser/hoverTypes.ts
index 2f74d533f26..f07090dea59 100644
--- a/src/vs/editor/contrib/hover/browser/hoverTypes.ts
+++ b/src/vs/editor/contrib/hover/browser/hoverTypes.ts
@@ -26,6 +26,11 @@ export interface IHoverPart {
* even in the case of multiple hover parts.
*/
readonly forceShowAtRange?: boolean;
+
+ /**
+ * If true, the hover item should appear before content
+ */
+ readonly isBeforeContent?: boolean;
/**
* Is this hover part still valid for this new anchor?
*/
diff --git a/src/vs/editor/contrib/hover/browser/markdownHoverParticipant.ts b/src/vs/editor/contrib/hover/browser/markdownHoverParticipant.ts
index c2e2f56a91e..19d151cf757 100644
--- a/src/vs/editor/contrib/hover/browser/markdownHoverParticipant.ts
+++ b/src/vs/editor/contrib/hover/browser/markdownHoverParticipant.ts
@@ -30,6 +30,7 @@ export class MarkdownHover implements IHoverPart {
public readonly owner: IEditorHoverParticipant,
public readonly range: Range,
public readonly contents: IMarkdownString[],
+ public readonly isBeforeContent: boolean,
public readonly ordinal: number
) { }
@@ -55,7 +56,7 @@ export class MarkdownHoverParticipant implements IEditorHoverParticipant= maxTokenizationLineLength) {
result.push(new MarkdownHover(this, anchor.range, [{
value: nls.localize('too many characters', "Tokenization is skipped for long lines for performance reasons. This can be configured via `editor.maxTokenizationLineLength`.")
- }], index++));
+ }], false, index++));
}
+ let isBeforeContent = false;
+
for (const d of lineDecorations) {
const startColumn = (d.range.startLineNumber === lineNumber) ? d.range.startColumn : 1;
const endColumn = (d.range.endLineNumber === lineNumber) ? d.range.endColumn : maxColumn;
@@ -90,8 +93,12 @@ export class MarkdownHoverParticipant implements IEditorHoverParticipant !isEmptyMarkdownString(item.hover.contents))
.map(item => {
const rng = item.hover.range ? Range.lift(item.hover.range) : anchor.range;
- return new MarkdownHover(this, rng, item.hover.contents, item.ordinal);
+ return new MarkdownHover(this, rng, item.hover.contents, false, item.ordinal);
});
}
diff --git a/src/vs/editor/contrib/inlayHints/browser/inlayHintsController.ts b/src/vs/editor/contrib/inlayHints/browser/inlayHintsController.ts
index 0e59778b739..4e7cce9783d 100644
--- a/src/vs/editor/contrib/inlayHints/browser/inlayHintsController.ts
+++ b/src/vs/editor/contrib/inlayHints/browser/inlayHintsController.ts
@@ -29,7 +29,7 @@ import { ClickLinkGesture, ClickLinkMouseEvent } from 'vs/editor/contrib/gotoSym
import { InlayHintAnchor, InlayHintItem, InlayHintsFragments } from 'vs/editor/contrib/inlayHints/browser/inlayHints';
import { goToDefinitionWithLocation, showGoToContextMenu } from 'vs/editor/contrib/inlayHints/browser/inlayHintsLocations';
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import * as colors from 'vs/platform/theme/common/colorRegistry';
@@ -60,7 +60,7 @@ class InlayHintsCache {
interface IInlayHintsCache extends InlayHintsCache { }
const IInlayHintsCache = createDecorator('IInlayHintsCache');
-registerSingleton(IInlayHintsCache, InlayHintsCache, true);
+registerSingleton(IInlayHintsCache, InlayHintsCache, InstantiationType.Delayed);
// --- rendered label
diff --git a/src/vs/editor/contrib/inlayHints/browser/inlayHintsHover.ts b/src/vs/editor/contrib/inlayHints/browser/inlayHintsHover.ts
index e04c6514d7a..f9781fcf029 100644
--- a/src/vs/editor/contrib/inlayHints/browser/inlayHintsHover.ts
+++ b/src/vs/editor/contrib/inlayHints/browser/inlayHintsHover.ts
@@ -92,11 +92,11 @@ export class InlayHintsHover extends MarkdownHoverParticipant implements IEditor
itemTooltip = part.item.hint.tooltip;
}
if (itemTooltip) {
- executor.emitOne(new MarkdownHover(this, anchor.range, [itemTooltip], 0));
+ executor.emitOne(new MarkdownHover(this, anchor.range, [itemTooltip], false, 0));
}
// (1.2) Inlay dbl-click gesture
if (isNonEmptyArray(part.item.hint.textEdits)) {
- executor.emitOne(new MarkdownHover(this, anchor.range, [new MarkdownString().appendText(localize('hint.dbl', "Double click to insert"))], 10001));
+ executor.emitOne(new MarkdownHover(this, anchor.range, [new MarkdownString().appendText(localize('hint.dbl', "Double click to insert"))], false, 10001));
}
// (2) Inlay Label Part Tooltip
@@ -107,7 +107,7 @@ export class InlayHintsHover extends MarkdownHoverParticipant implements IEditor
partTooltip = part.part.tooltip;
}
if (partTooltip) {
- executor.emitOne(new MarkdownHover(this, anchor.range, [partTooltip], 1));
+ executor.emitOne(new MarkdownHover(this, anchor.range, [partTooltip], false, 1));
}
// (2.2) Inlay Label Part Help Hover
@@ -130,7 +130,7 @@ export class InlayHintsHover extends MarkdownHoverParticipant implements IEditor
linkHint = new MarkdownString(`[${localize('hint.cmd', "Execute Command")}](${asCommandLink(part.part.command)} "${part.part.command.title}") (${kb})`, { isTrusted: true });
}
if (linkHint) {
- executor.emitOne(new MarkdownHover(this, anchor.range, [linkHint], 10000));
+ executor.emitOne(new MarkdownHover(this, anchor.range, [linkHint], false, 10000));
}
}
@@ -156,7 +156,7 @@ export class InlayHintsHover extends MarkdownHoverParticipant implements IEditor
}
return getHover(this._languageFeaturesService.hoverProvider, model, new Position(range.startLineNumber, range.startColumn), token)
.filter(item => !isEmptyMarkdownString(item.hover.contents))
- .map(item => new MarkdownHover(this, part.item.anchor.range, item.hover.contents, 2 + item.ordinal));
+ .map(item => new MarkdownHover(this, part.item.anchor.range, item.hover.contents, false, 2 + item.ordinal));
} finally {
ref.dispose();
}
diff --git a/src/vs/editor/contrib/inlayHints/browser/inlayHintsLocations.ts b/src/vs/editor/contrib/inlayHints/browser/inlayHintsLocations.ts
index 89f650807bb..77706619c1c 100644
--- a/src/vs/editor/contrib/inlayHints/browser/inlayHintsLocations.ts
+++ b/src/vs/editor/contrib/inlayHints/browser/inlayHintsLocations.ts
@@ -7,7 +7,6 @@ import * as dom from 'vs/base/browser/dom';
import { Action, IAction, Separator } from 'vs/base/common/actions';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IActiveCodeEditor, ICodeEditor } from 'vs/editor/browser/editorBrowser';
-import { EditorExtensionsRegistry } from 'vs/editor/browser/editorExtensions';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { Range } from 'vs/editor/common/core/range';
import { Location } from 'vs/editor/common/languages';
@@ -16,7 +15,7 @@ import { DefinitionAction, SymbolNavigationAction, SymbolNavigationAnchor } from
import { ClickLinkMouseEvent } from 'vs/editor/contrib/gotoSymbol/browser/link/clickLinkGesture';
import { RenderedInlayHintLabelPart } from 'vs/editor/contrib/inlayHints/browser/inlayHintsController';
import { PeekContext } from 'vs/editor/contrib/peekView/browser/peekView';
-import { isIMenuItem, MenuId, MenuRegistry } from 'vs/platform/actions/common/actions';
+import { isIMenuItem, MenuId, MenuItemAction, MenuRegistry } from 'vs/platform/actions/common/actions';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
@@ -41,13 +40,13 @@ export async function showGoToContextMenu(accessor: ServicesAccessor, editor: IC
const menuActions: IAction[] = [];
// from all registered (not active) context menu actions select those
- // that are a symbol navigation action
+ // that are a symbol navigation actions
const filter = new Set(MenuRegistry.getMenuItems(MenuId.EditorContext)
.map(item => isIMenuItem(item) ? item.command.id : ''));
- for (const delegate of EditorExtensionsRegistry.getEditorActions()) {
- if (delegate instanceof SymbolNavigationAction && filter.has(delegate.id)) {
- menuActions.push(new Action(delegate.id, delegate.label, undefined, true, async () => {
+ for (const delegate of SymbolNavigationAction.all()) {
+ if (filter.has(delegate.desc.id)) {
+ menuActions.push(new Action(delegate.desc.id, MenuItemAction.label(delegate.desc, { renderShortTitle: true }), undefined, true, async () => {
const ref = await resolverService.createModelReference(location.uri);
try {
await instaService.invokeFunction(delegate.run.bind(delegate), editor, new SymbolNavigationAnchor(ref.object.textEditorModel, Range.getStartPosition(location.range)));
diff --git a/src/vs/editor/contrib/stickyScroll/browser/stickyScroll.css b/src/vs/editor/contrib/stickyScroll/browser/stickyScroll.css
index 78ce346f864..f3dc213f679 100644
--- a/src/vs/editor/contrib/stickyScroll/browser/stickyScroll.css
+++ b/src/vs/editor/contrib/stickyScroll/browser/stickyScroll.css
@@ -29,7 +29,7 @@
.monaco-editor .sticky-widget {
width : 100%;
- box-shadow : var(--vscode-scrollbar-shadow) 0 2px 6px -2px;
+ box-shadow : var(--vscode-scrollbar-shadow) 0 3px 2px -2px;
z-index : 2;
background-color : var(--vscode-editorStickyScroll-background);
}
diff --git a/src/vs/editor/contrib/stickyScroll/browser/stickyScrollActions.ts b/src/vs/editor/contrib/stickyScroll/browser/stickyScrollActions.ts
index a1c6cac5baf..6f0c4adff12 100644
--- a/src/vs/editor/contrib/stickyScroll/browser/stickyScrollActions.ts
+++ b/src/vs/editor/contrib/stickyScroll/browser/stickyScrollActions.ts
@@ -5,6 +5,7 @@
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { localize } from 'vs/nls';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { Action2, MenuId } from 'vs/platform/actions/common/actions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
@@ -16,15 +17,19 @@ export class ToggleStickyScroll extends Action2 {
id: 'editor.action.toggleStickyScroll',
title: {
value: localize('toggleStickyScroll', "Toggle Sticky Scroll"),
- mnemonicTitle: localize('miStickyScroll', "&&Sticky Scroll"),
+ mnemonicTitle: localize('mitoggleStickyScroll', "&&Toggle Sticky Scroll"),
original: 'Toggle Sticky Scroll',
},
- // Hardcoding due to import violation
- category: { value: localize('view', "View"), original: 'View' },
- toggled: ContextKeyExpr.equals('config.editor.stickyScroll.enabled', true),
+ category: Categories.View,
+ toggled: {
+ condition: ContextKeyExpr.equals('config.editor.stickyScroll.enabled', true),
+ title: localize('stickyScroll', "Sticky Scroll"),
+ mnemonicTitle: localize('miStickyScroll', "&&Sticky Scroll"),
+ },
menu: [
{ id: MenuId.CommandPalette },
{ id: MenuId.MenubarViewMenu, group: '5_editor', order: 6 },
+ { id: MenuId.StickyScrollContext }
]
});
}
diff --git a/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts b/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts
index 47fbfec59b9..a5dc15c6e41 100644
--- a/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts
+++ b/src/vs/editor/contrib/stickyScroll/browser/stickyScrollController.ts
@@ -12,6 +12,9 @@ import { StickyScrollWidget, StickyScrollWidgetState } from './stickyScrollWidge
import { StickyLineCandidateProvider, StickyRange } from './stickyScrollProvider';
import { IModelTokensChangedEvent } from 'vs/editor/common/textModelEvents';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
+import * as dom from 'vs/base/browser/dom';
+import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
+import { MenuId } from 'vs/platform/actions/common/actions';
export class StickyScrollController extends Disposable implements IEditorContribution {
@@ -26,6 +29,7 @@ export class StickyScrollController extends Disposable implements IEditorContrib
_editor: ICodeEditor,
@ILanguageFeaturesService _languageFeaturesService: ILanguageFeaturesService,
@IInstantiationService _instaService: IInstantiationService,
+ @IContextMenuService private readonly _contextMenuService: IContextMenuService,
) {
super();
this._editor = _editor;
@@ -41,6 +45,9 @@ export class StickyScrollController extends Disposable implements IEditorContrib
}
}));
this.readConfiguration();
+ this._register(dom.addDisposableListener(this._stickyScrollWidget.getDomNode(), dom.EventType.CONTEXT_MENU, async (event: MouseEvent) => {
+ this.onContextMenu(event);
+ }));
}
public get stickyScrollCandidateProvider() {
@@ -51,6 +58,13 @@ export class StickyScrollController extends Disposable implements IEditorContrib
return this._widgetState;
}
+ private onContextMenu(event: MouseEvent) {
+ this._contextMenuService.showContextMenu({
+ menuId: MenuId.StickyScrollContext,
+ getAnchor: () => event,
+ });
+ }
+
private readConfiguration() {
const options = this._editor.getOption(EditorOption.stickyScroll);
if (options.enabled === false) {
diff --git a/src/vs/editor/contrib/stickyScroll/browser/stickyScrollWidget.ts b/src/vs/editor/contrib/stickyScroll/browser/stickyScrollWidget.ts
index f35d88029b6..777154b9891 100644
--- a/src/vs/editor/contrib/stickyScroll/browser/stickyScrollWidget.ts
+++ b/src/vs/editor/contrib/stickyScroll/browser/stickyScrollWidget.ts
@@ -152,7 +152,7 @@ export class StickyScrollWidget extends Disposable implements IOverlayWidget {
this._editor.revealPosition({ lineNumber: this._hoverOnLine, column: 1 });
}
this._instaService.invokeFunction(goToDefinitionWithLocation, e, this._editor as IActiveCodeEditor, { uri: this._editor.getModel()!.uri, range: this._stickyRangeProjectedOnEditor } as Location);
- } else {
+ } else if (!e.hasRightClick) {
// Normal click
this._editor.revealPosition({ lineNumber: this._hoverOnLine, column: 1 });
}
@@ -275,7 +275,7 @@ export class StickyScrollWidget extends Disposable implements IOverlayWidget {
const mouseOverEvent = new StandardMouseEvent(e);
const text = mouseOverEvent.target.innerText;
this._hoverOnLine = line;
- // TODO: workaround to find the column index, perhaps need more solid solution
+ // TODO: workaround to find the column index, perhaps need a more solid solution
this._hoverOnColumn = this._editor.getModel().getLineContent(line).indexOf(text) + 1 || -1;
}
}));
@@ -296,8 +296,9 @@ export class StickyScrollWidget extends Disposable implements IOverlayWidget {
const minimapSide = this._editor.getOption(EditorOption.minimap).side;
if (minimapSide === 'left') {
this._rootDomNode.style.marginLeft = this._editor.getLayoutInfo().minimap.minimapCanvasOuterWidth + 'px';
- } else if (minimapSide === 'right') {
- this._rootDomNode.style.marginLeft = '0px';
+ }
+ else if (minimapSide === 'right') {
+ this._rootDomNode.style.marginLeft = '1px';
}
this._rootDomNode.style.zIndex = '11';
}
diff --git a/src/vs/editor/contrib/stickyScroll/test/browser/stickyScroll.test.ts b/src/vs/editor/contrib/stickyScroll/test/browser/stickyScroll.test.ts
index 4f7e077bfbf..9e4e01fb994 100644
--- a/src/vs/editor/contrib/stickyScroll/test/browser/stickyScroll.test.ts
+++ b/src/vs/editor/contrib/stickyScroll/test/browser/stickyScroll.test.ts
@@ -13,12 +13,15 @@ import { DocumentSymbol, SymbolKind } from 'vs/editor/common/languages';
import { StickyLineCandidate, StickyLineCandidateProvider } from 'vs/editor/contrib/stickyScroll/browser/stickyScrollProvider';
import { EditorOption } from 'vs/editor/common/config/editorOptions';
import { ILogService, NullLogService } from 'vs/platform/log/common/log';
+import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
+import { mock } from 'vs/base/test/common/mock';
suite('Sticky Scroll Tests', () => {
const serviceCollection = new ServiceCollection(
[ILanguageFeaturesService, new LanguageFeaturesService()],
- [ILogService, new NullLogService()]
+ [ILogService, new NullLogService()],
+ [IContextMenuService, new class extends mock() { }]
);
const text = [
diff --git a/src/vs/editor/contrib/suggest/browser/suggestMemory.ts b/src/vs/editor/contrib/suggest/browser/suggestMemory.ts
index 8b2868cbde9..dce5326c6da 100644
--- a/src/vs/editor/contrib/suggest/browser/suggestMemory.ts
+++ b/src/vs/editor/contrib/suggest/browser/suggestMemory.ts
@@ -12,7 +12,7 @@ import { ITextModel } from 'vs/editor/common/model';
import { CompletionItemKind, CompletionItemKinds } from 'vs/editor/common/languages';
import { CompletionItem } from 'vs/editor/contrib/suggest/browser/suggest';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { IStorageService, StorageScope, StorageTarget, WillSaveStateReason } from 'vs/platform/storage/common/storage';
@@ -306,4 +306,4 @@ export interface ISuggestMemoryService {
select(model: ITextModel, pos: IPosition, items: CompletionItem[]): number;
}
-registerSingleton(ISuggestMemoryService, SuggestMemoryService, true);
+registerSingleton(ISuggestMemoryService, SuggestMemoryService, InstantiationType.Delayed);
diff --git a/src/vs/editor/contrib/unicodeHighlighter/browser/unicodeHighlighter.ts b/src/vs/editor/contrib/unicodeHighlighter/browser/unicodeHighlighter.ts
index b9f16e4c68a..bd6d9cd9b84 100644
--- a/src/vs/editor/contrib/unicodeHighlighter/browser/unicodeHighlighter.ts
+++ b/src/vs/editor/contrib/unicodeHighlighter/browser/unicodeHighlighter.ts
@@ -483,7 +483,7 @@ export class UnicodeHighlighterHoverParticipant implements IEditorHoverParticipa
.appendMarkdown(reason)
.appendText(' ')
.appendLink(uri, adjustSettings);
- result.push(new MarkdownHover(this, d.range, [markdown], index++));
+ result.push(new MarkdownHover(this, d.range, [markdown], false, index++));
}
return result;
}
diff --git a/src/vs/editor/standalone/browser/standaloneLayoutService.ts b/src/vs/editor/standalone/browser/standaloneLayoutService.ts
index aba9ec78509..42b7b0786a3 100644
--- a/src/vs/editor/standalone/browser/standaloneLayoutService.ts
+++ b/src/vs/editor/standalone/browser/standaloneLayoutService.ts
@@ -7,7 +7,7 @@ import * as dom from 'vs/base/browser/dom';
import { Event } from 'vs/base/common/event';
import { ILayoutService, ILayoutOffsetInfo } from 'vs/platform/layout/browser/layoutService';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
class StandaloneLayoutService implements ILayoutService {
declare readonly _serviceBrand: undefined;
@@ -63,4 +63,4 @@ export class EditorScopedLayoutService extends StandaloneLayoutService {
}
}
-registerSingleton(ILayoutService, StandaloneLayoutService, true);
+registerSingleton(ILayoutService, StandaloneLayoutService, InstantiationType.Delayed);
diff --git a/src/vs/editor/standalone/browser/standaloneServices.ts b/src/vs/editor/standalone/browser/standaloneServices.ts
index c25434b6c38..5da75b817a5 100644
--- a/src/vs/editor/standalone/browser/standaloneServices.ts
+++ b/src/vs/editor/standalone/browser/standaloneServices.ts
@@ -817,7 +817,8 @@ class StandaloneBulkEditService implements IBulkEditService {
}
return {
- ariaSummary: strings.format(StandaloneServicesNLS.bulkEditServiceSummary, totalEdits, totalFiles)
+ ariaSummary: strings.format(StandaloneServicesNLS.bulkEditServiceSummary, totalEdits, totalFiles),
+ isApplied: totalEdits > 0
};
}
}
@@ -948,9 +949,11 @@ class StandaloneContextMenuService extends ContextMenuService {
@INotificationService notificationService: INotificationService,
@IContextViewService contextViewService: IContextViewService,
@IKeybindingService keybindingService: IKeybindingService,
- @IThemeService themeService: IThemeService
+ @IThemeService themeService: IThemeService,
+ @IMenuService menuService: IMenuService,
+ @IContextKeyService contextKeyService: IContextKeyService,
) {
- super(telemetryService, notificationService, contextViewService, keybindingService, themeService);
+ super(telemetryService, notificationService, contextViewService, keybindingService, themeService, menuService, contextKeyService);
this.configure({ blockMouse: false }); // we do not want that in the standalone editor
}
}
diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts
index 5c9c1a1a25c..5f5e30d1c3f 100644
--- a/src/vs/monaco.d.ts
+++ b/src/vs/monaco.d.ts
@@ -1488,6 +1488,11 @@ declare namespace monaco.editor {
*/
className?: string | null;
blockClassName?: string | null;
+ /**
+ * Indicates if this block should be rendered after the last line.
+ * In this case, the range must be empty and set to the last line.
+ */
+ blockIsAfterEnd?: boolean | null;
/**
* Message to be rendered when hovering over the glyph margin decoration.
*/
diff --git a/src/vs/platform/action/common/action.ts b/src/vs/platform/action/common/action.ts
index 4b3f1b5f0ff..38d336ea603 100644
--- a/src/vs/platform/action/common/action.ts
+++ b/src/vs/platform/action/common/action.ts
@@ -6,6 +6,7 @@
import { URI, UriDto } from 'vs/base/common/uri';
import { ContextKeyExpression } from 'vs/platform/contextkey/common/contextkey';
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
+import { Categories } from './actionCommonCategories';
export interface ILocalizedString {
@@ -30,16 +31,50 @@ export interface ICommandActionTitle extends ILocalizedString {
export type Icon = { dark?: URI; light?: URI } | ThemeIcon;
+export interface ICommandActionToggleInfo {
+
+ /**
+ * The condition that marks the action as toggled.
+ */
+ condition: ContextKeyExpression;
+
+ icon?: Icon;
+
+ tooltip?: string;
+
+ /**
+ * The title that goes well with a a check mark, e.g "(check) Line Numbers" vs "Toggle Line Numbers"
+ */
+ title?: string;
+
+ /**
+ * Like title but with a mnemonic designation.
+ */
+ mnemonicTitle?: string;
+}
+
+export function isICommandActionToggleInfo(thing: ContextKeyExpression | ICommandActionToggleInfo | undefined): thing is ICommandActionToggleInfo {
+ return thing ? (thing).condition !== undefined : false;
+}
+
export interface ICommandAction {
id: string;
title: string | ICommandActionTitle;
shortTitle?: string | ICommandActionTitle;
- category?: string | ILocalizedString;
+ category?: keyof typeof Categories | ILocalizedString | string;
tooltip?: string | ILocalizedString;
icon?: Icon;
source?: string;
precondition?: ContextKeyExpression;
- toggled?: ContextKeyExpression | { condition: ContextKeyExpression; icon?: Icon; tooltip?: string; title?: string | ILocalizedString };
+
+ /**
+ * The action is a toggle action. Define the context key expression that reflects its toggle-state
+ * or define toggle-info including an icon and a title that goes well with a checkmark.
+ */
+ toggled?: ContextKeyExpression | ICommandActionToggleInfo;
+
+ /** @deprecated see https://github.com/microsoft/vscode/issues/162004 */
+ _isFakeAction?: true;
}
export type ISerializableCommandAction = UriDto;
diff --git a/src/vs/platform/action/common/actionCommonCategories.ts b/src/vs/platform/action/common/actionCommonCategories.ts
new file mode 100644
index 00000000000..5a62d7df897
--- /dev/null
+++ b/src/vs/platform/action/common/actionCommonCategories.ts
@@ -0,0 +1,14 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import { localize } from 'vs/nls';
+
+export const Categories = Object.freeze({
+ View: { value: localize('view', "View"), original: 'View' },
+ Help: { value: localize('help', "Help"), original: 'Help' },
+ Test: { value: localize('test', "Test"), original: 'Test' },
+ Preferences: { value: localize('preferences', "Preferences"), original: 'Preferences' },
+ Developer: { value: localize({ key: 'developer', comment: ['A developer on Code itself or someone diagnosing issues in Code'] }, "Developer"), original: 'Developer' }
+});
diff --git a/src/vs/platform/actions/browser/menuEntryActionViewItem.css b/src/vs/platform/actions/browser/menuEntryActionViewItem.css
index 31eb20ba8a8..5f0134dfeae 100644
--- a/src/vs/platform/actions/browser/menuEntryActionViewItem.css
+++ b/src/vs/platform/actions/browser/menuEntryActionViewItem.css
@@ -11,27 +11,29 @@
background-size: 16px;
}
-
@keyframes shift {
0% {
- transform: scale(1);
+ transform: translateX(0px);
}
- 15%{
- transform: scale(1.1);
+ 33%{
+ transform: translateX(0.5px);
}
- 100% {
- transform: scale(1);
+ 66% {
+ transform: translateX(-0.5px);
}
}
.monaco-toolbar.config .monaco-action-bar .action-item {
animation-duration: 1.2s;
- animation-iteration-count: 1;
+ animation-iteration-count: infinite;
animation-name: shift;
}
+.monaco-toolbar.config .monaco-action-bar .action-item:nth-child(odd) {
+ animation-delay: 0.6s;
+}
.monaco-dropdown-with-default {
display: flex !important;
diff --git a/src/vs/platform/actions/browser/menuEntryActionViewItem.ts b/src/vs/platform/actions/browser/menuEntryActionViewItem.ts
index 76c445d5603..41faa91d8d7 100644
--- a/src/vs/platform/actions/browser/menuEntryActionViewItem.ts
+++ b/src/vs/platform/actions/browser/menuEntryActionViewItem.ts
@@ -16,7 +16,7 @@ import { isLinux, isWindows, OS } from 'vs/base/common/platform';
import 'vs/css!./menuEntryActionViewItem';
import { localize } from 'vs/nls';
import { IMenu, IMenuActionOptions, IMenuService, MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions';
-import { ICommandAction, Icon } from 'vs/platform/action/common/action';
+import { ICommandAction, isICommandActionToggleInfo } from 'vs/platform/action/common/action';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -240,7 +240,7 @@ export class MenuEntryActionViewItem extends ActionViewItem {
return;
}
- const icon = this._commandAction.checked && (item.toggled as { icon?: Icon })?.icon ? (item.toggled as { icon: Icon }).icon : item.icon;
+ const icon = this._commandAction.checked && isICommandActionToggleInfo(item.toggled) && item.toggled.icon ? item.toggled.icon : item.icon;
if (!icon) {
return;
diff --git a/src/vs/platform/actions/browser/toolbar.ts b/src/vs/platform/actions/browser/toolbar.ts
index be59a56d5a3..db91b1c67f7 100644
--- a/src/vs/platform/actions/browser/toolbar.ts
+++ b/src/vs/platform/actions/browser/toolbar.ts
@@ -10,7 +10,7 @@ import { coalesceInPlace } from 'vs/base/common/arrays';
import { BugIndicatingError } from 'vs/base/common/errors';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { localize } from 'vs/nls';
-import { createAndFillInActionBarActions, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
+import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IMenuActionOptions, IMenuService, MenuId, MenuItemAction, SubmenuItemAction } from 'vs/platform/actions/common/actions';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
@@ -18,8 +18,12 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
export const enum HiddenItemStrategy {
+ /** This toolbar doesn't support hiding*/
+ NoHide = -1,
+ /** Hidden items aren't shown anywhere */
Ignore = 0,
- RenderInSecondaryGroup = 1
+ /** Hidden items move into the secondary group */
+ RenderInSecondaryGroup = 1,
}
export type IWorkbenchToolBarOptions = IToolBarOptions & {
@@ -96,7 +100,7 @@ export class WorkbenchToolBar extends ToolBar {
}
}
- override setActions(_primary: readonly IAction[], _secondary: readonly IAction[] = []): void {
+ override setActions(_primary: readonly IAction[], _secondary: readonly IAction[] = [], menuIds?: readonly MenuId[]): void {
this._sessionDisposables.clear();
const primary = _primary.slice();
@@ -104,32 +108,33 @@ export class WorkbenchToolBar extends ToolBar {
const toggleActions: IAction[] = [];
let someAreHidden = false;
+ // unless disabled, move all hidden items to secondary group or ignore them
+ if (this._options?.hiddenItemStrategy !== HiddenItemStrategy.NoHide) {
+ let shouldPrependSeparator = secondary.length > 0;
+ for (let i = 0; i < primary.length; i++) {
+ const action = primary[i];
+ if (!(action instanceof MenuItemAction) && !(action instanceof SubmenuItemAction)) {
+ // console.warn(`Action ${action.id}/${action.label} is not a MenuItemAction`);
+ continue;
+ }
+ if (!action.hideActions) {
+ continue;
+ }
- // move all hidden items to secondary group or ignore them
- let shouldPrependSeparator = secondary.length > 0;
- for (let i = 0; i < primary.length; i++) {
- const action = primary[i];
- if (!(action instanceof MenuItemAction) && !(action instanceof SubmenuItemAction)) {
- // console.warn(`Action ${action.id}/${action.label} is not a MenuItemAction`);
- continue;
- }
- if (!action.hideActions) {
- continue;
- }
+ // collect all toggle actions
+ toggleActions.push(action.hideActions.toggle);
- // collect all toggle actions
- toggleActions.push(action.hideActions.toggle);
-
- // hidden items move into overflow or ignore
- if (action.hideActions.isHidden) {
- someAreHidden = true;
- primary[i] = undefined!;
- if (this._options?.hiddenItemStrategy !== HiddenItemStrategy.Ignore) {
- if (shouldPrependSeparator) {
- shouldPrependSeparator = false;
- secondary.unshift(new Separator());
+ // hidden items move into overflow or ignore
+ if (action.hideActions.isHidden) {
+ someAreHidden = true;
+ primary[i] = undefined!;
+ if (this._options?.hiddenItemStrategy !== HiddenItemStrategy.Ignore) {
+ if (shouldPrependSeparator) {
+ shouldPrependSeparator = false;
+ secondary.unshift(new Separator());
+ }
+ secondary.unshift(action);
}
- secondary.unshift(action);
}
}
}
@@ -151,8 +156,14 @@ export class WorkbenchToolBar extends ToolBar {
// add "hide foo" actions
let hideAction: IAction;
- if ((action instanceof MenuItemAction || action instanceof SubmenuItemAction) && action.hideActions) {
+ if (action instanceof MenuItemAction || action instanceof SubmenuItemAction) {
+ if (!action.hideActions) {
+ // no context menu for MenuItemAction instances that support no hiding
+ // those are fake actions and need to be cleaned up
+ return;
+ }
hideAction = action.hideActions.hide;
+
} else {
hideAction = toAction({
id: 'label',
@@ -164,32 +175,27 @@ export class WorkbenchToolBar extends ToolBar {
actions = [hideAction, new Separator(), ...toggleActions];
// add "Reset Menu" action
- if (someAreHidden && this._options?.resetMenu) {
+ if (this._options?.resetMenu && !menuIds) {
+ menuIds = [this._options.resetMenu];
+ }
+ if (someAreHidden && menuIds) {
actions.push(new Separator());
actions.push(toAction({
id: 'resetThisMenu',
label: localize('resetThisMenu', "Reset Menu"),
- run: () => this._menuService.resetHiddenStates(this._options!.resetMenu)
+ run: () => this._menuService.resetHiddenStates(menuIds)
}));
}
- // add context menu actions (iff appicable)
- if (this._options?.contextMenu) {
- const menu = this._menuService.createMenu(this._options.contextMenu, this._contextKeyService);
- const contextMenuActions: IAction[] = [];
- createAndFillInContextMenuActions(menu, { ...this._options?.menuOptions, renderShortTitle: true, }, contextMenuActions);
- menu.dispose();
-
- if (contextMenuActions.length > 0) {
- actions = [...actions, new Separator(), ...contextMenuActions];
- }
- }
-
- this.getElement().classList.toggle('config', true);
+ // this.getElement().classList.toggle('config', true);
this._contextMenuService.showContextMenu({
getAnchor: () => e,
getActions: () => actions,
+ // add context menu actions (iff appicable)
+ menuId: this._options?.contextMenu,
+ menuActionOptions: { renderShortTitle: true, ...this._options?.menuOptions },
+ contextKeyService: this._contextKeyService,
onHide: () => this.getElement().classList.toggle('config', false),
});
}));
diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts
index e32071c164c..87c38c65e32 100644
--- a/src/vs/platform/actions/common/actions.ts
+++ b/src/vs/platform/actions/common/actions.ts
@@ -103,6 +103,7 @@ export class MenuId {
static readonly SearchContext = new MenuId('SearchContext');
static readonly StatusBarWindowIndicatorMenu = new MenuId('StatusBarWindowIndicatorMenu');
static readonly StatusBarRemoteIndicatorMenu = new MenuId('StatusBarRemoteIndicatorMenu');
+ static readonly StickyScrollContext = new MenuId('StickyScrollContext');
static readonly TestItem = new MenuId('TestItem');
static readonly TestItemGutter = new MenuId('TestItemGutter');
static readonly TestPeekElement = new MenuId('TestPeekElement');
@@ -238,7 +239,7 @@ export interface IMenuService {
/**
* Reset the menu's hidden states.
*/
- resetHiddenStates(menuId: MenuId | undefined): void;
+ resetHiddenStates(menuIds: readonly MenuId[] | undefined): void;
}
export type ICommandsMap = Map;
@@ -397,6 +398,12 @@ export interface IMenuItemHide {
// subscribes to events of Action or modified properties
export class MenuItemAction implements IAction {
+ static label(action: ICommandAction, options?: IMenuActionOptions): string {
+ return options?.renderShortTitle && action.shortTitle
+ ? (typeof action.shortTitle === 'string' ? action.shortTitle : action.shortTitle.value)
+ : (typeof action.title === 'string' ? action.title : action.title.value);
+ }
+
readonly item: ICommandAction;
readonly alt: MenuItemAction | undefined;
@@ -418,9 +425,7 @@ export class MenuItemAction implements IAction {
@ICommandService private _commandService: ICommandService
) {
this.id = item.id;
- this.label = options?.renderShortTitle && item.shortTitle
- ? (typeof item.shortTitle === 'string' ? item.shortTitle : item.shortTitle.value)
- : (typeof item.title === 'string' ? item.title : item.title.value);
+ this.label = MenuItemAction.label(item, options);
this.tooltip = (typeof item.tooltip === 'string' ? item.tooltip : item.tooltip?.value) ?? '';
this.enabled = !item.precondition || contextKeyService.contextMatchesRules(item.precondition);
this.checked = undefined;
@@ -554,6 +559,13 @@ export interface IAction2Options extends ICommandAction {
* showing keybindings that have no other UX.
*/
description?: ICommandHandlerDescription;
+
+ /**
+ * @deprecated workaround added for https://github.com/microsoft/vscode/issues/162004
+ * This action doesn't do anything is just a workaround for rendering "something"
+ * inside a specific toolbar
+ */
+ _isFakeAction?: true;
}
export abstract class Action2 {
diff --git a/src/vs/platform/actions/common/menuResetAction.ts b/src/vs/platform/actions/common/menuResetAction.ts
index 84ee76e2b91..6cebce22257 100644
--- a/src/vs/platform/actions/common/menuResetAction.ts
+++ b/src/vs/platform/actions/common/menuResetAction.ts
@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { Action2, IMenuService } from 'vs/platform/actions/common/actions';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { ILogService } from 'vs/platform/log/common/log';
@@ -14,10 +15,10 @@ export class MenuHiddenStatesReset extends Action2 {
super({
id: 'menu.resetHiddenStates',
title: {
- value: localize('title', 'Reset Hidden Menus'),
- original: 'Reset Hidden Menus'
+ value: localize('title', 'Reset All Menus'),
+ original: 'Reset All Menus'
},
- category: localize('cat', 'View'),
+ category: Categories.View,
f1: true
});
}
diff --git a/src/vs/platform/actions/common/menuService.ts b/src/vs/platform/actions/common/menuService.ts
index 86ff1bd3b7e..d1c95179c67 100644
--- a/src/vs/platform/actions/common/menuService.ts
+++ b/src/vs/platform/actions/common/menuService.ts
@@ -10,7 +10,7 @@ import { IMenu, IMenuActionOptions, IMenuChangeEvent, IMenuCreateOptions, IMenuI
import { ICommandAction, ILocalizedString } from 'vs/platform/action/common/action';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { ContextKeyExpression, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
-import { IAction, Separator, toAction } from 'vs/base/common/actions';
+import { Separator, toAction } from 'vs/base/common/actions';
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
import { removeFastWithoutKeepingOrder } from 'vs/base/common/arrays';
import { localize } from 'vs/nls';
@@ -32,8 +32,8 @@ export class MenuService implements IMenuService {
return new MenuImpl(id, this._hiddenStates, { emitEventsForSubmenuChanges: false, eventDebounceDelay: 50, ...options }, this._commandService, contextKeyService);
}
- resetHiddenStates(id?: MenuId): void {
- this._hiddenStates.reset(id);
+ resetHiddenStates(ids?: MenuId[]): void {
+ this._hiddenStates.reset(ids);
}
}
@@ -108,17 +108,19 @@ class PersistedMenuHideState {
this._persist();
}
- reset(menu?: MenuId): void {
- if (menu === undefined) {
+ reset(menus?: MenuId[]): void {
+ if (menus === undefined) {
// reset all
this._data = Object.create(null);
this._persist();
} else {
// reset only for a specific menu
- if (this._data[menu.id]) {
- delete this._data[menu.id];
- this._persist();
+ for (const { id } of menus) {
+ if (this._data[id]) {
+ delete this._data[id];
+ }
}
+ this._persist();
}
}
@@ -215,13 +217,10 @@ class MenuInfo {
createActionGroups(options: IMenuActionOptions | undefined): [string, Array][] {
const result: [string, Array][] = [];
- const allToggleActions: IAction[][] = [];
for (const group of this._menuGroups) {
const [id, items] = group;
- const toggleActions: IAction[] = [];
-
const activeActions: Array = [];
for (const item of items) {
if (this._contextKeyService.contextMatchesRules(item.when)) {
@@ -229,7 +228,8 @@ class MenuInfo {
const menuHide = createMenuHide(this._id, isMenuItem ? item.command : item, this._hiddenStates);
if (isMenuItem) {
// MenuItemAction
- activeActions.push(new MenuItemAction(item.command, item.alt, options, menuHide, this._contextKeyService, this._commandService));
+ const actualMenuHide = item.command._isFakeAction ? undefined : menuHide;
+ activeActions.push(new MenuItemAction(item.command, item.alt, options, actualMenuHide, this._contextKeyService, this._commandService));
} else {
// SubmenuItemAction
@@ -244,9 +244,6 @@ class MenuInfo {
if (activeActions.length > 0) {
result.push([id, activeActions]);
}
- if (toggleActions.length > 0) {
- allToggleActions.push(toggleActions);
- }
}
return result;
}
diff --git a/src/vs/platform/contextkey/browser/contextKeyService.ts b/src/vs/platform/contextkey/browser/contextKeyService.ts
index 07a136ef7b9..0ebe4e7c7ef 100644
--- a/src/vs/platform/contextkey/browser/contextKeyService.ts
+++ b/src/vs/platform/contextkey/browser/contextKeyService.ts
@@ -10,12 +10,14 @@ import { TernarySearchTree } from 'vs/base/common/map';
import { MarshalledObject } from 'vs/base/common/marshalling';
import { MarshalledId } from 'vs/base/common/marshallingIds';
import { cloneAndChange, distinct } from 'vs/base/common/objects';
+import { StopWatch } from 'vs/base/common/stopwatch';
import { URI } from 'vs/base/common/uri';
import { localize } from 'vs/nls';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ContextKeyExpression, ContextKeyInfo, ContextKeyValue, IContext, IContextKey, IContextKeyChangeEvent, IContextKeyService, IContextKeyServiceTarget, IReadableSet, RawContextKey, SET_CONTEXT_COMMAND_ID } from 'vs/platform/contextkey/common/contextkey';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
+import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
const KEYBINDING_CONTEXT_ATTR = 'data-keybinding-context';
@@ -603,7 +605,27 @@ function findContextAttr(domNode: IContextKeyServiceTarget | null): number {
}
export function setContext(accessor: ServicesAccessor, contextKey: any, contextValue: any) {
- accessor.get(IContextKeyService).createKey(String(contextKey), stringifyURIs(contextValue));
+ const contextKeyService = accessor.get(IContextKeyService);
+ const telemetryService = accessor.get(ITelemetryService);
+
+ const sw = new StopWatch(true);
+ contextKeyService.createKey(String(contextKey), stringifyURIs(contextValue));
+ const duration = sw.elapsed();
+
+ type TelemetryData = {
+ duration: number;
+ contextKey: string;
+ };
+ type TelemetryClassification = {
+ owner: 'jrieken';
+ comment: 'Performance numbers of the setContext-API command';
+ duration: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; isMeasurement: true; comment: 'The time it took to set the context key' };
+ contextKey: { classification: 'SystemMetaData'; purpose: 'PerformanceAndHealth'; comment: 'The context key that got set' };
+ };
+ telemetryService.publicLog2('command.setContext', {
+ contextKey: String(contextKey),
+ duration
+ });
}
function stringifyURIs(contextValue: any): any {
diff --git a/src/vs/platform/contextkey/test/browser/contextkey.test.ts b/src/vs/platform/contextkey/test/browser/contextkey.test.ts
index 50309c6fe6b..8cbecda9b4b 100644
--- a/src/vs/platform/contextkey/test/browser/contextkey.test.ts
+++ b/src/vs/platform/contextkey/test/browser/contextkey.test.ts
@@ -6,12 +6,14 @@ import * as assert from 'assert';
import { DeferredPromise } from 'vs/base/common/async';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
+import { mock } from 'vs/base/test/common/mock';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { ContextKeyService, setContext } from 'vs/platform/contextkey/browser/contextKeyService';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
+import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
suite('ContextKeyService', () => {
test('updateParent', () => {
@@ -64,7 +66,12 @@ suite('ContextKeyService', () => {
const contextKeyService: IContextKeyService = disposables.add(new ContextKeyService(configurationService));
const instantiationService = new TestInstantiationService(new ServiceCollection(
[IConfigurationService, configurationService],
- [IContextKeyService, contextKeyService]
+ [IContextKeyService, contextKeyService],
+ [ITelemetryService, new class extends mock() {
+ override async publicLog2() {
+ //
+ }
+ }]
));
const uri = URI.parse('test://abc');
diff --git a/src/vs/platform/contextview/browser/contextMenuService.ts b/src/vs/platform/contextview/browser/contextMenuService.ts
index c80851be9ac..fe80ed05a20 100644
--- a/src/vs/platform/contextview/browser/contextMenuService.ts
+++ b/src/vs/platform/contextview/browser/contextMenuService.ts
@@ -5,14 +5,18 @@
import { IContextMenuDelegate } from 'vs/base/browser/contextmenu';
import { ModifierKeyEmitter } from 'vs/base/browser/dom';
+import { IAction, Separator } from 'vs/base/common/actions';
import { Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
+import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
+import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
+import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { ContextMenuHandler, IContextMenuHandlerOptions } from './contextMenuHandler';
-import { IContextMenuService, IContextViewService } from './contextView';
+import { IContextMenuMenuDelegate, IContextMenuService, IContextViewService } from './contextView';
export class ContextMenuService extends Disposable implements IContextMenuService {
@@ -27,10 +31,10 @@ export class ContextMenuService extends Disposable implements IContextMenuServic
return this._contextMenuHandler;
}
- private readonly _onDidShowContextMenu = new Emitter();
+ private readonly _onDidShowContextMenu = this._store.add(new Emitter());
readonly onDidShowContextMenu = this._onDidShowContextMenu.event;
- private readonly _onDidHideContextMenu = new Emitter();
+ private readonly _onDidHideContextMenu = this._store.add(new Emitter());
readonly onDidHideContextMenu = this._onDidHideContextMenu.event;
constructor(
@@ -38,7 +42,9 @@ export class ContextMenuService extends Disposable implements IContextMenuServic
@INotificationService private readonly notificationService: INotificationService,
@IContextViewService private readonly contextViewService: IContextViewService,
@IKeybindingService private readonly keybindingService: IKeybindingService,
- @IThemeService private readonly themeService: IThemeService
+ @IThemeService private readonly themeService: IThemeService,
+ @IMenuService private readonly menuService: IMenuService,
+ @IContextKeyService private readonly contextKeyService: IContextKeyService,
) {
super();
}
@@ -49,7 +55,10 @@ export class ContextMenuService extends Disposable implements IContextMenuServic
// ContextMenu
- showContextMenu(delegate: IContextMenuDelegate): void {
+ showContextMenu(delegate: IContextMenuDelegate | IContextMenuMenuDelegate): void {
+
+ delegate = ContextMenuMenuDelegate.transform(delegate, this.menuService, this.contextKeyService);
+
this.contextMenuHandler.showContextMenu({
...delegate,
onHide: (didCancel) => {
@@ -62,3 +71,33 @@ export class ContextMenuService extends Disposable implements IContextMenuServic
this._onDidShowContextMenu.fire();
}
}
+
+export namespace ContextMenuMenuDelegate {
+
+ function is(thing: IContextMenuDelegate | IContextMenuMenuDelegate): thing is IContextMenuMenuDelegate {
+ return thing && (thing).menuId instanceof MenuId;
+ }
+
+ export function transform(delegate: IContextMenuDelegate | IContextMenuMenuDelegate, menuService: IMenuService, globalContextKeyService: IContextKeyService): IContextMenuDelegate {
+ if (!is(delegate)) {
+ return delegate;
+ }
+ const { menuId, menuActionOptions, contextKeyService } = delegate;
+ return {
+ ...delegate,
+ getActions: () => {
+ const target: IAction[] = [];
+ if (menuId) {
+ const menu = menuService.createMenu(menuId, contextKeyService ?? globalContextKeyService);
+ createAndFillInContextMenuActions(menu, menuActionOptions, target);
+ menu.dispose();
+ }
+ if (!delegate.getActions) {
+ return target;
+ } else {
+ return Separator.join(delegate.getActions(), target);
+ }
+ }
+ };
+ }
+}
diff --git a/src/vs/platform/contextview/browser/contextView.ts b/src/vs/platform/contextview/browser/contextView.ts
index b99bfdc0aa5..505d76eabfb 100644
--- a/src/vs/platform/contextview/browser/contextView.ts
+++ b/src/vs/platform/contextview/browser/contextView.ts
@@ -5,8 +5,11 @@
import { IContextMenuDelegate } from 'vs/base/browser/contextmenu';
import { AnchorAlignment, AnchorAxisAlignment, IContextViewProvider } from 'vs/base/browser/ui/contextview/contextview';
+import { IAction } from 'vs/base/common/actions';
import { Event } from 'vs/base/common/event';
import { IDisposable } from 'vs/base/common/lifecycle';
+import { IMenuActionOptions, MenuId } from 'vs/platform/actions/common/actions';
+import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
export const IContextViewService = createDecorator('contextViewService');
@@ -44,5 +47,25 @@ export interface IContextMenuService {
readonly onDidShowContextMenu: Event;
readonly onDidHideContextMenu: Event;
- showContextMenu(delegate: IContextMenuDelegate): void;
+ showContextMenu(delegate: IContextMenuDelegate | IContextMenuMenuDelegate): void;
}
+
+export type IContextMenuMenuDelegate = {
+ /**
+ * The MenuId that should be used to populate the context menu.
+ */
+ menuId?: MenuId;
+ /**
+ * Optional options how menu actions are invoked
+ */
+ menuActionOptions?: IMenuActionOptions;
+ /**
+ * Optional context key service which drives the given menu
+ */
+ contextKeyService?: IContextKeyService;
+
+ /**
+ * Optional getter for extra actions. They will be prepended to the menu actions.
+ */
+ getActions?(): IAction[];
+} & Omit;
diff --git a/src/vs/platform/extensionManagement/electron-sandbox/extensionsScannerService.ts b/src/vs/platform/extensionManagement/electron-sandbox/extensionsScannerService.ts
index c13b4c23371..f99ba24598c 100644
--- a/src/vs/platform/extensionManagement/electron-sandbox/extensionsScannerService.ts
+++ b/src/vs/platform/extensionManagement/electron-sandbox/extensionsScannerService.ts
@@ -8,7 +8,7 @@ import { INativeEnvironmentService } from 'vs/platform/environment/common/enviro
import { IExtensionsProfileScannerService } from 'vs/platform/extensionManagement/common/extensionsProfileScannerService';
import { IExtensionsScannerService, NativeExtensionsScannerService, } from 'vs/platform/extensionManagement/common/extensionsScannerService';
import { IFileService } from 'vs/platform/files/common/files';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ILogService } from 'vs/platform/log/common/log';
import { IProductService } from 'vs/platform/product/common/productService';
@@ -35,4 +35,4 @@ export class ExtensionsScannerService extends NativeExtensionsScannerService imp
}
-registerSingleton(IExtensionsScannerService, ExtensionsScannerService, true);
+registerSingleton(IExtensionsScannerService, ExtensionsScannerService, InstantiationType.Delayed);
diff --git a/src/vs/platform/instantiation/common/extensions.ts b/src/vs/platform/instantiation/common/extensions.ts
index 474a9a59ea1..6b3cb6ac484 100644
--- a/src/vs/platform/instantiation/common/extensions.ts
+++ b/src/vs/platform/instantiation/common/extensions.ts
@@ -22,7 +22,7 @@ export const enum InstantiationType {
Delayed = 1
}
-export function registerSingleton(id: ServiceIdentifier, ctor: new (...services: Services) => T, supportsDelayedInstantiation: boolean | InstantiationType): void;
+export function registerSingleton(id: ServiceIdentifier, ctor: new (...services: Services) => T, supportsDelayedInstantiation: false | InstantiationType): void;
export function registerSingleton(id: ServiceIdentifier, descriptor: SyncDescriptor): void;
export function registerSingleton(id: ServiceIdentifier, ctorOrDescriptor: { new(...services: Services): T } | SyncDescriptor, supportsDelayedInstantiation?: boolean | InstantiationType): void {
if (!(ctorOrDescriptor instanceof SyncDescriptor)) {
diff --git a/src/vs/platform/instantiation/common/instantiationService.ts b/src/vs/platform/instantiation/common/instantiationService.ts
index 21908bbcff0..3840b1bec11 100644
--- a/src/vs/platform/instantiation/common/instantiationService.ts
+++ b/src/vs/platform/instantiation/common/instantiationService.ts
@@ -111,7 +111,7 @@ export class InstantiationService implements IInstantiationService {
}
// now create the instance
- return new ctor(...[...args, ...serviceArgs]);
+ return Reflect.construct(ctor, args.concat(serviceArgs));
}
private _setServiceInstance(id: ServiceIdentifier, instance: T): void {
diff --git a/src/vs/platform/list/browser/listService.ts b/src/vs/platform/list/browser/listService.ts
index 197fb970f66..5fb143fc948 100644
--- a/src/vs/platform/list/browser/listService.ts
+++ b/src/vs/platform/list/browser/listService.ts
@@ -1291,7 +1291,7 @@ class WorkbenchTreeInternals {
updateStyleOverrides(overrideStyles?: IColorMapping): void {
dispose(this.styler);
- this.styler = overrideStyles ? attachListStyler(this.tree, this.themeService, overrideStyles) : Disposable.None;
+ this.styler = attachListStyler(this.tree, this.themeService, overrideStyles);
}
dispose(): void {
diff --git a/src/vs/platform/profiling/electron-main/windowProfiling.ts b/src/vs/platform/profiling/electron-main/windowProfiling.ts
index 2b6971c3dd9..18549159fe4 100644
--- a/src/vs/platform/profiling/electron-main/windowProfiling.ts
+++ b/src/vs/platform/profiling/electron-main/windowProfiling.ts
@@ -254,8 +254,6 @@ export class WindowProfiler {
callstack: callstack.join('\n')
};
this._telemetryService.publicLog2('prof.freeze.sample', data);
-
- console.log(data);
}
}
}
diff --git a/src/vs/platform/protocol/electron-main/protocolMainService.ts b/src/vs/platform/protocol/electron-main/protocolMainService.ts
index b4b9544fccf..43ad2167684 100644
--- a/src/vs/platform/protocol/electron-main/protocolMainService.ts
+++ b/src/vs/platform/protocol/electron-main/protocolMainService.ts
@@ -8,7 +8,7 @@ import { validatedIpcMain } from 'vs/base/parts/ipc/electron-main/ipcMain';
import { Disposable, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
import { TernarySearchTree } from 'vs/base/common/map';
import { COI, FileAccess, Schemas } from 'vs/base/common/network';
-import { extname, normalize } from 'vs/base/common/path';
+import { basename, extname, normalize } from 'vs/base/common/path';
import { isLinux } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
@@ -96,7 +96,7 @@ export class ProtocolMainService extends Disposable implements IProtocolMainServ
let headers: Record | undefined;
if (this.environmentService.crossOriginIsolated) {
- if (path.endsWith('/workbench.html') || path.endsWith('/workbench-dev.html')) {
+ if (basename(path) === 'workbench.html' || basename(path) === 'workbench-dev.html') {
headers = COI.CoopAndCoep;
} else {
headers = COI.getHeadersFromQuery(request.url);
diff --git a/src/vs/platform/remote/browser/browserSocketFactory.ts b/src/vs/platform/remote/browser/browserSocketFactory.ts
index cac305317db..46a6dd3a7a7 100644
--- a/src/vs/platform/remote/browser/browserSocketFactory.ts
+++ b/src/vs/platform/remote/browser/browserSocketFactory.ts
@@ -274,7 +274,7 @@ export class BrowserSocketFactory implements ISocketFactory {
connect(host: string, port: number, path: string, query: string, debugLabel: string, callback: IConnectCallback): void {
const webSocketSchema = (/^https:/.test(window.location.href) ? 'wss' : 'ws');
- const socket = this._webSocketFactory.create(`${webSocketSchema}://${/:/.test(host) ? `[${host}]` : host}:${port}${path}?${query}&skipWebSocketFrames=false`, debugLabel);
+ const socket = this._webSocketFactory.create(`${webSocketSchema}://${(/:/.test(host) && !/\[/.test(host)) ? `[${host}]` : host}:${port}${path}?${query}&skipWebSocketFrames=false`, debugLabel);
const errorListener = socket.onError((err) => callback(err, undefined));
socket.onOpen(() => {
errorListener.dispose();
diff --git a/src/vs/platform/terminal/common/capabilities/capabilities.ts b/src/vs/platform/terminal/common/capabilities/capabilities.ts
index 03f863348fc..d68a14d21b8 100644
--- a/src/vs/platform/terminal/common/capabilities/capabilities.ts
+++ b/src/vs/platform/terminal/common/capabilities/capabilities.ts
@@ -221,10 +221,35 @@ export interface ITerminalCommand {
commandStartLineContent?: string;
markProperties?: IMarkProperties;
getOutput(): string | undefined;
- getOutputMatch(outputMatcher: { lineMatcher: string | RegExp; anchor?: 'top' | 'bottom'; offset?: number; length?: number }): RegExpMatchArray | undefined;
+ getOutputMatch(outputMatcher: ITerminalOutputMatcher): RegExpMatchArray | undefined;
hasOutput(): boolean;
}
+
+/**
+ * A matcher that runs on a sub-section of a terminal command's output
+ */
+export interface ITerminalOutputMatcher {
+ /**
+ * A string or regex to match against the unwrapped line. If this is a regex with the multiline
+ * flag, it will scan an amount of lines equal to `\n` instances in the regex + 1.
+ */
+ lineMatcher: string | RegExp;
+ /**
+ * Which side of the output to anchor the {@link offset} and {@link length} against.
+ */
+ anchor: 'top' | 'bottom';
+ /**
+ * How far from either the top or the bottom of the butter to start matching against.
+ */
+ offset: number;
+ /**
+ * The number of rows to match against, this should be as small as possible for performance
+ * reasons.
+ */
+ length: number;
+}
+
/**
* A clone of the IMarker from xterm which cannot be imported from common
*/
diff --git a/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts b/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts
index 757881846c1..5ecd49bee30 100644
--- a/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts
+++ b/src/vs/platform/terminal/common/capabilities/commandDetectionCapability.ts
@@ -7,7 +7,7 @@ import { timeout } from 'vs/base/common/async';
import { debounce } from 'vs/base/common/decorators';
import { Emitter } from 'vs/base/common/event';
import { ILogService } from 'vs/platform/log/common/log';
-import { ICommandDetectionCapability, TerminalCapability, ITerminalCommand, IHandleCommandOptions, ICommandInvalidationRequest, CommandInvalidationReason, ISerializedCommand, ISerializedCommandDetectionCapability } from 'vs/platform/terminal/common/capabilities/capabilities';
+import { ICommandDetectionCapability, TerminalCapability, ITerminalCommand, IHandleCommandOptions, ICommandInvalidationRequest, CommandInvalidationReason, ISerializedCommand, ISerializedCommandDetectionCapability, ITerminalOutputMatcher } from 'vs/platform/terminal/common/capabilities/capabilities';
// Importing types is safe in any layer
// eslint-disable-next-line local/code-import-patterns
@@ -490,7 +490,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
commandStartLineContent: this._currentCommand.commandStartLineContent,
hasOutput: () => !executedMarker?.isDisposed && !endMarker?.isDisposed && !!(executedMarker && endMarker && executedMarker?.line < endMarker!.line),
getOutput: () => getOutputForCommand(executedMarker, endMarker, buffer),
- getOutputMatch: (outputMatcher?: { lineMatcher: string | RegExp; anchor?: 'top' | 'bottom'; offset?: number; length?: number }) => getOutputMatchForCommand(executedMarker, endMarker, buffer, this._terminal.cols, outputMatcher),
+ getOutputMatch: (outputMatcher: ITerminalOutputMatcher) => getOutputMatchForCommand(executedMarker, endMarker, buffer, this._terminal.cols, outputMatcher),
markProperties: options?.markProperties
};
this._commands.push(newCommand);
@@ -615,7 +615,7 @@ export class CommandDetectionCapability implements ICommandDetectionCapability {
exitCode: e.exitCode,
hasOutput: () => !executedMarker?.isDisposed && !endMarker?.isDisposed && !!(executedMarker && endMarker && executedMarker.line < endMarker.line),
getOutput: () => getOutputForCommand(executedMarker, endMarker, buffer),
- getOutputMatch: (outputMatcher: { lineMatcher: string | RegExp; anchor?: 'top' | 'bottom'; offset?: number; length?: number }) => getOutputMatchForCommand(executedMarker, endMarker, buffer, this._terminal.cols, outputMatcher),
+ getOutputMatch: (outputMatcher: ITerminalOutputMatcher) => getOutputMatchForCommand(executedMarker, endMarker, buffer, this._terminal.cols, outputMatcher),
markProperties: e.markProperties
};
this._commands.push(newCommand);
@@ -647,36 +647,47 @@ function getOutputForCommand(executedMarker: IMarker | undefined, endMarker: IMa
return output === '' ? undefined : output;
}
-export function getOutputMatchForCommand(executedMarker: IMarker | undefined, endMarker: IMarker | undefined, buffer: IBuffer, cols: number, outputMatcher: { lineMatcher: string | RegExp; anchor?: 'top' | 'bottom'; offset?: number; length?: number } | undefined): RegExpMatchArray | undefined {
+export function getOutputMatchForCommand(executedMarker: IMarker | undefined, endMarker: IMarker | undefined, buffer: IBuffer, cols: number, outputMatcher: ITerminalOutputMatcher): RegExpMatchArray | undefined {
if (!executedMarker || !endMarker) {
return undefined;
}
const startLine = executedMarker.line;
const endLine = endMarker.line;
- if (startLine === endLine) {
- return undefined;
- }
- if (outputMatcher?.length && (endLine - startLine) < outputMatcher.length) {
- return undefined;
- }
- let output = '';
- let line: string | undefined;
- if (outputMatcher?.anchor === 'bottom') {
+ const matcher = outputMatcher.lineMatcher;
+ const linesToCheck = typeof matcher === 'string' ? 1 : outputMatcher.length || countNewLines(matcher);
+ const lines: string[] = [];
+ if (outputMatcher.anchor === 'bottom') {
for (let i = endLine - (outputMatcher.offset || 0); i >= startLine; i--) {
- line = getXtermLineContent(buffer, i, i, cols);
- output = line + output;
- const match = output.match(outputMatcher.lineMatcher);
+ let wrappedLineStart = i;
+ const wrappedLineEnd = i;
+ while (wrappedLineStart >= startLine && buffer.getLine(wrappedLineStart)?.isWrapped) {
+ wrappedLineStart--;
+ }
+ i = wrappedLineStart;
+ lines.unshift(getXtermLineContent(buffer, wrappedLineStart, wrappedLineEnd, cols));
+ if (lines.length > linesToCheck) {
+ lines.pop();
+ }
+ const match = lines.join('\n').match(matcher);
if (match) {
return match;
}
}
} else {
- for (let i = startLine + (outputMatcher?.offset || 0); i < endLine; i++) {
- line = getXtermLineContent(buffer, i, i, cols);
- output += line;
+ for (let i = startLine + (outputMatcher.offset || 0); i < endLine; i++) {
+ const wrappedLineStart = i;
+ let wrappedLineEnd = i;
+ while (wrappedLineEnd + 1 < endLine && buffer.getLine(wrappedLineEnd + 1)?.isWrapped) {
+ wrappedLineEnd++;
+ }
+ i = wrappedLineEnd;
+ lines.push(getXtermLineContent(buffer, wrappedLineStart, wrappedLineEnd, cols));
+ if (lines.length === linesToCheck) {
+ lines.shift();
+ }
if (outputMatcher) {
- const match = output.match(outputMatcher.lineMatcher);
+ const match = lines.join('\n').match(matcher);
if (match) {
return match;
}
@@ -702,3 +713,17 @@ function getXtermLineContent(buffer: IBuffer, lineStart: number, lineEnd: number
}
return content;
}
+
+function countNewLines(regex: RegExp): number {
+ if (!regex.multiline) {
+ return 1;
+ }
+ const source = regex.source;
+ let count = 1;
+ let i = source.indexOf('\\n');
+ while (i !== -1) {
+ count++;
+ i = source.indexOf('\\n', i + 1);
+ }
+ return count;
+}
diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts
index d45df31b65a..692f8844b9c 100644
--- a/src/vs/platform/terminal/common/terminal.ts
+++ b/src/vs/platform/terminal/common/terminal.ts
@@ -486,7 +486,7 @@ export interface IShellLaunchConfig {
* Whether the terminal process environment should be exactly as provided in
* `TerminalOptions.env`. When this is false (default), the environment will be based on the
* window's environment and also apply configured platform settings like
- * `terminal.integrated.windows.env` on top. When this is true, the complete environment must be
+ * `terminal.integrated.env.windows` on top. When this is true, the complete environment must be
* provided as nothing will be inherited from the process or any configuration.
*/
strictEnv?: boolean;
diff --git a/src/vs/platform/terminal/node/ptyHostMain.ts b/src/vs/platform/terminal/node/ptyHostMain.ts
index 3de63e7d9e6..a1fa938db10 100644
--- a/src/vs/platform/terminal/node/ptyHostMain.ts
+++ b/src/vs/platform/terminal/node/ptyHostMain.ts
@@ -44,7 +44,7 @@ delete process.env.VSCODE_RECONNECT_GRACE_TIME;
delete process.env.VSCODE_RECONNECT_SHORT_GRACE_TIME;
delete process.env.VSCODE_RECONNECT_SCROLLBACK;
-const ptyService = new PtyService(lastPtyId, logService, reconnectConstants);
+const ptyService = new PtyService(lastPtyId, logService, productService, reconnectConstants);
server.registerChannel(TerminalIpcChannels.PtyHost, ProxyChannel.fromService(ptyService));
process.once('exit', () => {
diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts
index 282bf02ff66..85ea2b0cc33 100644
--- a/src/vs/platform/terminal/node/ptyService.ts
+++ b/src/vs/platform/terminal/node/ptyService.ts
@@ -28,6 +28,7 @@ import { ErrorNoTelemetry } from 'vs/base/common/errors';
import { ShellIntegrationAddon } from 'vs/platform/terminal/common/xterm/shellIntegrationAddon';
import { formatMessageForTerminal } from 'vs/platform/terminal/common/terminalStrings';
import { IPtyHostProcessReplayEvent } from 'vs/platform/terminal/common/capabilities/capabilities';
+import { IProductService } from 'vs/platform/product/common/productService';
type WorkspaceId = string;
@@ -64,6 +65,7 @@ export class PtyService extends Disposable implements IPtyService {
constructor(
private _lastPtyId: number,
private readonly _logService: ILogService,
+ private readonly _productService: IProductService,
private readonly _reconnectConstants: IReconnectConstants
) {
super();
@@ -122,7 +124,7 @@ export class PtyService extends Disposable implements IPtyService {
await new Promise((resolve, reject) => {
exec(`kill ${processId}`, {}, (err, stdout) => {
if (err) {
- return reject(`Problem occurred when killing the process w ID: ${processId}`);
+ return reject(`Problem occurred when killing the process with PID: ${processId}`);
}
resolve(stdout);
});
@@ -141,13 +143,13 @@ export class PtyService extends Disposable implements IPtyService {
});
const processesForPort = stdout.split('\n');
if (processesForPort.length >= 1) {
- const capturePid = /LISTENING\s+(\d{3})/;
+ const capturePid = /LISTENING\s+(\d+)/;
const processId = processesForPort[0].match(capturePid)?.[1];
if (processId) {
await new Promise((resolve, reject) => {
exec(`Taskkill /F /PID ${processId}`, {}, (err, stdout) => {
if (err) {
- return reject(`Problem occurred when killing the process w ID: ${processId}`);
+ return reject(`Problem occurred when killing the process with PID: ${processId}`);
}
resolve(stdout);
});
@@ -244,7 +246,7 @@ export class PtyService extends Disposable implements IPtyService {
throw new Error('Attempt to create a process when attach object was provided');
}
const id = ++this._lastPtyId;
- const process = new TerminalProcess(shellLaunchConfig, cwd, cols, rows, env, executableEnv, options, this._logService);
+ const process = new TerminalProcess(shellLaunchConfig, cwd, cols, rows, env, executableEnv, options, this._logService, this._productService);
process.onProcessData(event => this._onProcessData.fire({ id, event }));
const processLaunchOptions: IPersistentTerminalProcessLaunchConfig = {
env,
diff --git a/src/vs/platform/terminal/node/terminalEnvironment.ts b/src/vs/platform/terminal/node/terminalEnvironment.ts
index d1884b8c3ab..9ff09c4322e 100644
--- a/src/vs/platform/terminal/node/terminalEnvironment.ts
+++ b/src/vs/platform/terminal/node/terminalEnvironment.ts
@@ -13,6 +13,7 @@ import { format } from 'vs/base/common/strings';
import { isString } from 'vs/base/common/types';
import * as pfs from 'vs/base/node/pfs';
import { ILogService } from 'vs/platform/log/common/log';
+import { IProductService } from 'vs/platform/product/common/productService';
import { IShellLaunchConfig, ITerminalEnvironment, ITerminalProcessOptions } from 'vs/platform/terminal/common/terminal';
export function getWindowsBuildNumber(): number {
@@ -103,15 +104,16 @@ export interface IShellIntegrationConfigInjection {
*/
export function getShellIntegrationInjection(
shellLaunchConfig: IShellLaunchConfig,
- options: ITerminalProcessOptions['shellIntegration'],
+ options: Pick,
env: ITerminalEnvironment | undefined,
- logService: ILogService
+ logService: ILogService,
+ productService: IProductService
): IShellIntegrationConfigInjection | undefined {
// Shell integration arg injection is disabled when:
// - The global setting is disabled
// - There is no executable (not sure what script to run)
// - The terminal is used by a feature like tasks or debugging
- if (!options.enabled || !shellLaunchConfig.executable || shellLaunchConfig.isFeatureTerminal || shellLaunchConfig.hideFromUser || shellLaunchConfig.ignoreShellIntegration) {
+ if (!options.shellIntegration.enabled || !shellLaunchConfig.executable || shellLaunchConfig.isFeatureTerminal || shellLaunchConfig.hideFromUser || shellLaunchConfig.ignoreShellIntegration || (isWindows && !options.windowsEnableConpty)) {
return undefined;
}
@@ -184,8 +186,9 @@ export function getShellIntegrationInjection(
}
newArgs = [...newArgs]; // Shallow clone the array to avoid setting the default array
newArgs[newArgs.length - 1] = format(newArgs[newArgs.length - 1], appRoot);
+
// Move .zshrc into $ZDOTDIR as the way to activate the script
- const zdotdir = path.join(os.tmpdir(), `${os.userInfo().username}-vscode-zsh`);
+ const zdotdir = path.join(os.tmpdir(), `${os.userInfo().username}-${productService.applicationName}-zsh`);
envMixin['ZDOTDIR'] = zdotdir;
const userZdotdir = env?.ZDOTDIR ?? os.homedir() ?? `~`;
envMixin['USER_ZDOTDIR'] = userZdotdir;
diff --git a/src/vs/platform/terminal/node/terminalProcess.ts b/src/vs/platform/terminal/node/terminalProcess.ts
index 366d57b4d5f..9a670fda3e8 100644
--- a/src/vs/platform/terminal/node/terminalProcess.ts
+++ b/src/vs/platform/terminal/node/terminalProcess.ts
@@ -6,17 +6,16 @@
import { exec } from 'child_process';
import { promises as fs } from 'fs';
import type * as pty from 'node-pty';
-import { tmpdir } from 'os';
import { timeout } from 'vs/base/common/async';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
-import { FileAccess } from 'vs/base/common/network';
import * as path from 'vs/base/common/path';
import { IProcessEnvironment, isLinux, isMacintosh, isWindows } from 'vs/base/common/platform';
import { URI } from 'vs/base/common/uri';
import { Promises } from 'vs/base/node/pfs';
import { localize } from 'vs/nls';
import { ILogService } from 'vs/platform/log/common/log';
+import { IProductService } from 'vs/platform/product/common/productService';
import { FlowControlConstants, IShellLaunchConfig, ITerminalChildProcess, ITerminalLaunchError, IProcessProperty, IProcessPropertyMap as IProcessPropertyMap, ProcessPropertyType, TerminalShellType, IProcessReadyEvent, ITerminalProcessOptions, PosixShellType } from 'vs/platform/terminal/common/terminal';
import { ChildProcessMonitor } from 'vs/platform/terminal/node/childProcessMonitor';
import { findExecutable, getShellIntegrationInjection, getWindowsBuildNumber, IShellIntegrationConfigInjection } from 'vs/platform/terminal/node/terminalEnvironment';
@@ -145,7 +144,8 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
*/
private readonly _executableEnv: IProcessEnvironment,
private readonly _options: ITerminalProcessOptions,
- @ILogService private readonly _logService: ILogService
+ @ILogService private readonly _logService: ILogService,
+ @IProductService private readonly _productService: IProductService
) {
super();
let name: string;
@@ -201,7 +201,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
let injection: IShellIntegrationConfigInjection | undefined;
if (this._options.shellIntegration.enabled) {
- injection = getShellIntegrationInjection(this.shellLaunchConfig, this._options.shellIntegration, this._ptyOptions.env, this._logService);
+ injection = getShellIntegrationInjection(this.shellLaunchConfig, { shellIntegration: this._options.shellIntegration, windowsEnableConpty: this._options.windowsEnableConpty }, this._ptyOptions.env, this._logService, this._productService);
if (injection) {
this._onDidChangeProperty.fire({ type: ProcessPropertyType.UsedShellIntegrationInjection, value: true });
if (injection.envMixin) {
@@ -228,25 +228,6 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess
}
}
- // Handle zsh shell integration - Set $ZDOTDIR to a temp dir and create $ZDOTDIR/.zshrc
- if (this.shellLaunchConfig.env?.['_ZDOTDIR'] === '1') {
- const zdotdir = path.join(tmpdir(), 'vscode-zsh');
- await fs.mkdir(zdotdir, { recursive: true });
- const source = path.join(path.dirname(FileAccess.asFileUri('', require).fsPath), 'out/vs/workbench/contrib/terminal/browser/media/shellIntegration-rc.zsh');
- // TODO: Does filesToCopy make this unnecessary now?
- try {
- await fs.copyFile(source, path.join(zdotdir, '.zshrc'));
- } 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
- // should be using the same version of the server in this case, assume the script is
- // fine if copy fails and swallow the error.
- }
- this._ptyOptions.env = this._ptyOptions.env || {};
- this._ptyOptions.env['ZDOTDIR'] = zdotdir;
- delete this._ptyOptions.env['_ZDOTDIR'];
- }
-
try {
await this.setupPtyProcess(this.shellLaunchConfig, this._ptyOptions, injection);
return undefined;
diff --git a/src/vs/platform/terminal/test/node/terminalEnvironment.test.ts b/src/vs/platform/terminal/test/node/terminalEnvironment.test.ts
index 2ce4d1864e9..3ddda6e00d7 100644
--- a/src/vs/platform/terminal/test/node/terminalEnvironment.test.ts
+++ b/src/vs/platform/terminal/test/node/terminalEnvironment.test.ts
@@ -5,24 +5,33 @@
import { deepStrictEqual, ok, strictEqual } from 'assert';
import { homedir, userInfo } from 'os';
+import { isWindows } from 'vs/base/common/platform';
import { NullLogService } from 'vs/platform/log/common/log';
+import { IProductService } from 'vs/platform/product/common/productService';
import { ITerminalProcessOptions } from 'vs/platform/terminal/common/terminal';
import { getShellIntegrationInjection, IShellIntegrationConfigInjection } from 'vs/platform/terminal/node/terminalEnvironment';
-const enabledProcessOptions: ITerminalProcessOptions['shellIntegration'] = { enabled: true };
-const disabledProcessOptions: ITerminalProcessOptions['shellIntegration'] = { enabled: false };
+const enabledProcessOptions: Pick = { shellIntegration: { enabled: true }, windowsEnableConpty: true };
+const disabledProcessOptions: Pick = { shellIntegration: { enabled: false }, windowsEnableConpty: true };
+const winptyProcessOptions: Pick = { shellIntegration: { enabled: true }, windowsEnableConpty: false };
const pwshExe = process.platform === 'win32' ? 'pwsh.exe' : 'pwsh';
const repoRoot = process.platform === 'win32' ? process.cwd()[0].toLowerCase() + process.cwd().substring(1) : process.cwd();
const logService = new NullLogService();
+const productService = { applicationName: 'vscode' } as IProductService;
const defaultEnvironment = {};
suite('platform - terminalEnvironment', () => {
suite('getShellIntegrationInjection', () => {
suite('should not enable', () => {
test('when isFeatureTerminal or when no executable is provided', () => {
- ok(!getShellIntegrationInjection({ executable: pwshExe, args: ['-l', '-NoLogo'], isFeatureTerminal: true }, enabledProcessOptions, defaultEnvironment, logService));
- ok(getShellIntegrationInjection({ executable: pwshExe, args: ['-l', '-NoLogo'], isFeatureTerminal: false }, enabledProcessOptions, defaultEnvironment, logService));
+ ok(!getShellIntegrationInjection({ executable: pwshExe, args: ['-l', '-NoLogo'], isFeatureTerminal: true }, enabledProcessOptions, defaultEnvironment, logService, productService));
+ ok(getShellIntegrationInjection({ executable: pwshExe, args: ['-l', '-NoLogo'], isFeatureTerminal: false }, enabledProcessOptions, defaultEnvironment, logService, productService));
});
+ if (isWindows) {
+ test('when on windows with conpty false', () => {
+ ok(!getShellIntegrationInjection({ executable: pwshExe, args: ['-l'], isFeatureTerminal: false }, winptyProcessOptions, defaultEnvironment, logService, productService));
+ });
+ }
});
suite('pwsh', () => {
@@ -41,21 +50,21 @@ suite('platform - terminalEnvironment', () => {
}
});
test('when undefined, []', () => {
- deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: [] }, enabledProcessOptions, defaultEnvironment, logService), enabledExpectedResult);
- deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: undefined }, enabledProcessOptions, defaultEnvironment, logService), enabledExpectedResult);
+ deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: [] }, enabledProcessOptions, defaultEnvironment, logService, productService), enabledExpectedResult);
+ deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: undefined }, enabledProcessOptions, defaultEnvironment, logService, productService), enabledExpectedResult);
});
suite('when no logo', () => {
test('array - case insensitive', () => {
- deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: ['-NoLogo'] }, enabledProcessOptions, defaultEnvironment, logService), enabledExpectedResult);
- deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: ['-NOLOGO'] }, enabledProcessOptions, defaultEnvironment, logService), enabledExpectedResult);
- deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: ['-nol'] }, enabledProcessOptions, defaultEnvironment, logService), enabledExpectedResult);
- deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: ['-NOL'] }, enabledProcessOptions, defaultEnvironment, logService), enabledExpectedResult);
+ deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: ['-NoLogo'] }, enabledProcessOptions, defaultEnvironment, logService, productService), enabledExpectedResult);
+ deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: ['-NOLOGO'] }, enabledProcessOptions, defaultEnvironment, logService, productService), enabledExpectedResult);
+ deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: ['-nol'] }, enabledProcessOptions, defaultEnvironment, logService, productService), enabledExpectedResult);
+ deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: ['-NOL'] }, enabledProcessOptions, defaultEnvironment, logService, productService), enabledExpectedResult);
});
test('string - case insensitive', () => {
- deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: '-NoLogo' }, enabledProcessOptions, defaultEnvironment, logService), enabledExpectedResult);
- deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: '-NOLOGO' }, enabledProcessOptions, defaultEnvironment, logService), enabledExpectedResult);
- deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: '-nol' }, enabledProcessOptions, defaultEnvironment, logService), enabledExpectedResult);
- deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: '-NOL' }, enabledProcessOptions, defaultEnvironment, logService), enabledExpectedResult);
+ deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: '-NoLogo' }, enabledProcessOptions, defaultEnvironment, logService, productService), enabledExpectedResult);
+ deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: '-NOLOGO' }, enabledProcessOptions, defaultEnvironment, logService, productService), enabledExpectedResult);
+ deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: '-nol' }, enabledProcessOptions, defaultEnvironment, logService, productService), enabledExpectedResult);
+ deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: '-NOL' }, enabledProcessOptions, defaultEnvironment, logService, productService), enabledExpectedResult);
});
});
});
@@ -72,23 +81,23 @@ suite('platform - terminalEnvironment', () => {
}
});
test('when array contains no logo and login', () => {
- deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: ['-l', '-NoLogo'] }, enabledProcessOptions, defaultEnvironment, logService), enabledExpectedResult);
+ deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: ['-l', '-NoLogo'] }, enabledProcessOptions, defaultEnvironment, logService, productService), enabledExpectedResult);
});
test('when string', () => {
- deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: '-l' }, enabledProcessOptions, defaultEnvironment, logService), enabledExpectedResult);
+ deepStrictEqual(getShellIntegrationInjection({ executable: pwshExe, args: '-l' }, enabledProcessOptions, defaultEnvironment, logService, productService), enabledExpectedResult);
});
});
suite('should not modify args', () => {
test('when shell integration is disabled', () => {
- strictEqual(getShellIntegrationInjection({ executable: pwshExe, args: ['-l'] }, disabledProcessOptions, defaultEnvironment, logService), undefined);
- strictEqual(getShellIntegrationInjection({ executable: pwshExe, args: '-l' }, disabledProcessOptions, defaultEnvironment, logService), undefined);
- strictEqual(getShellIntegrationInjection({ executable: pwshExe, args: undefined }, disabledProcessOptions, defaultEnvironment, logService), undefined);
+ strictEqual(getShellIntegrationInjection({ executable: pwshExe, args: ['-l'] }, disabledProcessOptions, defaultEnvironment, logService, productService), undefined);
+ strictEqual(getShellIntegrationInjection({ executable: pwshExe, args: '-l' }, disabledProcessOptions, defaultEnvironment, logService, productService), undefined);
+ strictEqual(getShellIntegrationInjection({ executable: pwshExe, args: undefined }, disabledProcessOptions, defaultEnvironment, logService, productService), undefined);
});
test('when using unrecognized arg', () => {
- strictEqual(getShellIntegrationInjection({ executable: pwshExe, args: ['-l', '-NoLogo', '-i'] }, disabledProcessOptions, defaultEnvironment, logService), undefined);
+ strictEqual(getShellIntegrationInjection({ executable: pwshExe, args: ['-l', '-NoLogo', '-i'] }, disabledProcessOptions, defaultEnvironment, logService, productService), undefined);
});
test('when using unrecognized arg (string)', () => {
- strictEqual(getShellIntegrationInjection({ executable: pwshExe, args: '-i' }, disabledProcessOptions, defaultEnvironment, logService), undefined);
+ strictEqual(getShellIntegrationInjection({ executable: pwshExe, args: '-i' }, disabledProcessOptions, defaultEnvironment, logService, productService), undefined);
});
});
});
@@ -127,37 +136,37 @@ suite('platform - terminalEnvironment', () => {
ok(result.filesToCopy[3].source.match(expectedSources[3]));
}
test('when undefined, []', () => {
- const result1 = getShellIntegrationInjection({ executable: 'zsh', args: [] }, enabledProcessOptions, defaultEnvironment, logService);
+ const result1 = getShellIntegrationInjection({ executable: 'zsh', args: [] }, enabledProcessOptions, defaultEnvironment, logService, productService);
deepStrictEqual(result1?.newArgs, ['-i']);
assertIsEnabled(result1);
- const result2 = getShellIntegrationInjection({ executable: 'zsh', args: undefined }, enabledProcessOptions, defaultEnvironment, logService);
+ const result2 = getShellIntegrationInjection({ executable: 'zsh', args: undefined }, enabledProcessOptions, defaultEnvironment, logService, productService);
deepStrictEqual(result2?.newArgs, ['-i']);
assertIsEnabled(result2);
});
suite('should incorporate login arg', () => {
test('when array', () => {
- const result = getShellIntegrationInjection({ executable: 'zsh', args: ['-l'] }, enabledProcessOptions, defaultEnvironment, logService);
+ const result = getShellIntegrationInjection({ executable: 'zsh', args: ['-l'] }, enabledProcessOptions, defaultEnvironment, logService, productService);
deepStrictEqual(result?.newArgs, ['-il']);
assertIsEnabled(result);
});
});
suite('should not modify args', () => {
test('when shell integration is disabled', () => {
- strictEqual(getShellIntegrationInjection({ executable: 'zsh', args: ['-l'] }, disabledProcessOptions, defaultEnvironment, logService), undefined);
- strictEqual(getShellIntegrationInjection({ executable: 'zsh', args: undefined }, disabledProcessOptions, defaultEnvironment, logService), undefined);
+ strictEqual(getShellIntegrationInjection({ executable: 'zsh', args: ['-l'] }, disabledProcessOptions, defaultEnvironment, logService, productService), undefined);
+ strictEqual(getShellIntegrationInjection({ executable: 'zsh', args: undefined }, disabledProcessOptions, defaultEnvironment, logService, productService), undefined);
});
test('when using unrecognized arg', () => {
- strictEqual(getShellIntegrationInjection({ executable: 'zsh', args: ['-l', '-fake'] }, disabledProcessOptions, defaultEnvironment, logService), undefined);
+ strictEqual(getShellIntegrationInjection({ executable: 'zsh', args: ['-l', '-fake'] }, disabledProcessOptions, defaultEnvironment, logService, productService), undefined);
});
});
suite('should incorporate global ZDOTDIR env variable', () => {
test('when custom ZDOTDIR', () => {
- const result1 = getShellIntegrationInjection({ executable: 'zsh', args: [] }, enabledProcessOptions, { ...defaultEnvironment, ZDOTDIR: customZdotdir }, logService);
+ const result1 = getShellIntegrationInjection({ executable: 'zsh', args: [] }, enabledProcessOptions, { ...defaultEnvironment, ZDOTDIR: customZdotdir }, logService, productService);
deepStrictEqual(result1?.newArgs, ['-i']);
assertIsEnabled(result1, customZdotdir);
});
test('when undefined', () => {
- const result1 = getShellIntegrationInjection({ executable: 'zsh', args: [] }, enabledProcessOptions, undefined, logService);
+ const result1 = getShellIntegrationInjection({ executable: 'zsh', args: [] }, enabledProcessOptions, undefined, logService, productService);
deepStrictEqual(result1?.newArgs, ['-i']);
assertIsEnabled(result1);
});
@@ -176,9 +185,9 @@ suite('platform - terminalEnvironment', () => {
VSCODE_INJECTION: '1'
}
});
- deepStrictEqual(getShellIntegrationInjection({ executable: 'bash', args: [] }, enabledProcessOptions, defaultEnvironment, logService), enabledExpectedResult);
- deepStrictEqual(getShellIntegrationInjection({ executable: 'bash', args: '' }, enabledProcessOptions, defaultEnvironment, logService), enabledExpectedResult);
- deepStrictEqual(getShellIntegrationInjection({ executable: 'bash', args: undefined }, enabledProcessOptions, defaultEnvironment, logService), enabledExpectedResult);
+ deepStrictEqual(getShellIntegrationInjection({ executable: 'bash', args: [] }, enabledProcessOptions, defaultEnvironment, logService, productService), enabledExpectedResult);
+ deepStrictEqual(getShellIntegrationInjection({ executable: 'bash', args: '' }, enabledProcessOptions, defaultEnvironment, logService, productService), enabledExpectedResult);
+ deepStrictEqual(getShellIntegrationInjection({ executable: 'bash', args: undefined }, enabledProcessOptions, defaultEnvironment, logService, productService), enabledExpectedResult);
});
suite('should set login env variable and not modify args', () => {
const enabledExpectedResult = Object.freeze({
@@ -192,16 +201,16 @@ suite('platform - terminalEnvironment', () => {
}
});
test('when array', () => {
- deepStrictEqual(getShellIntegrationInjection({ executable: 'bash', args: ['-l'] }, enabledProcessOptions, defaultEnvironment, logService), enabledExpectedResult);
+ deepStrictEqual(getShellIntegrationInjection({ executable: 'bash', args: ['-l'] }, enabledProcessOptions, defaultEnvironment, logService, productService), enabledExpectedResult);
});
});
suite('should not modify args', () => {
test('when shell integration is disabled', () => {
- strictEqual(getShellIntegrationInjection({ executable: 'bash', args: ['-l'] }, disabledProcessOptions, defaultEnvironment, logService), undefined);
- strictEqual(getShellIntegrationInjection({ executable: 'bash', args: undefined }, disabledProcessOptions, defaultEnvironment, logService), undefined);
+ strictEqual(getShellIntegrationInjection({ executable: 'bash', args: ['-l'] }, disabledProcessOptions, defaultEnvironment, logService, productService), undefined);
+ strictEqual(getShellIntegrationInjection({ executable: 'bash', args: undefined }, disabledProcessOptions, defaultEnvironment, logService, productService), undefined);
});
test('when custom array entry', () => {
- strictEqual(getShellIntegrationInjection({ executable: 'bash', args: ['-l', '-i'] }, disabledProcessOptions, defaultEnvironment, logService), undefined);
+ strictEqual(getShellIntegrationInjection({ executable: 'bash', args: ['-l', '-i'] }, disabledProcessOptions, defaultEnvironment, logService, productService), undefined);
});
});
});
diff --git a/src/vs/platform/theme/common/colorRegistry.ts b/src/vs/platform/theme/common/colorRegistry.ts
index 01f9f4743ad..d4ba695131b 100644
--- a/src/vs/platform/theme/common/colorRegistry.ts
+++ b/src/vs/platform/theme/common/colorRegistry.ts
@@ -387,8 +387,8 @@ export const editorActiveLinkForeground = registerColor('editorLink.activeForegr
/**
* Inline hints
*/
-export const editorInlayHintForeground = registerColor('editorInlayHint.foreground', { dark: transparent(badgeForeground, .8), light: transparent(badgeForeground, .8), hcDark: badgeForeground, hcLight: badgeForeground }, nls.localize('editorInlayHintForeground', 'Foreground color of inline hints'));
-export const editorInlayHintBackground = registerColor('editorInlayHint.background', { dark: transparent(badgeBackground, .6), light: transparent(badgeBackground, .3), hcDark: badgeBackground, hcLight: badgeBackground }, nls.localize('editorInlayHintBackground', 'Background color of inline hints'));
+export const editorInlayHintForeground = registerColor('editorInlayHint.foreground', { dark: badgeForeground, light: badgeForeground, hcDark: Color.black, hcLight: badgeForeground }, nls.localize('editorInlayHintForeground', 'Foreground color of inline hints'));
+export const editorInlayHintBackground = registerColor('editorInlayHint.background', { dark: transparent(badgeBackground, .8), light: transparent(badgeBackground, .6), hcDark: '#f38518', hcLight: badgeBackground }, nls.localize('editorInlayHintBackground', 'Background color of inline hints'));
export const editorInlayHintTypeForeground = registerColor('editorInlayHint.typeForeground', { dark: editorInlayHintForeground, light: editorInlayHintForeground, hcDark: editorInlayHintForeground, hcLight: editorInlayHintForeground }, nls.localize('editorInlayHintForegroundTypes', 'Foreground color of inline hints for types'));
export const editorInlayHintTypeBackground = registerColor('editorInlayHint.typeBackground', { dark: editorInlayHintBackground, light: editorInlayHintBackground, hcDark: editorInlayHintBackground, hcLight: editorInlayHintBackground }, nls.localize('editorInlayHintBackgroundTypes', 'Background color of inline hints for types'));
export const editorInlayHintParameterForeground = registerColor('editorInlayHint.parameterForeground', { dark: editorInlayHintForeground, light: editorInlayHintForeground, hcDark: editorInlayHintForeground, hcLight: editorInlayHintForeground }, nls.localize('editorInlayHintForegroundParameter', 'Foreground color of inline hints for parameters'));
@@ -406,8 +406,8 @@ export const editorLightBulbAutoFixForeground = registerColor('editorLightBulbAu
export const defaultInsertColor = new Color(new RGBA(155, 185, 85, .2));
export const defaultRemoveColor = new Color(new RGBA(255, 0, 0, .2));
-export const diffInserted = registerColor('diffEditor.insertedTextBackground', { dark: '#9ccc2c33', light: '#9ccc2c66', hcDark: null, hcLight: null }, nls.localize('diffEditorInserted', 'Background color for text that got inserted. The color must not be opaque so as not to hide underlying decorations.'), true);
-export const diffRemoved = registerColor('diffEditor.removedTextBackground', { dark: '#ff000066', light: '#ff00004d', hcDark: null, hcLight: null }, nls.localize('diffEditorRemoved', 'Background color for text that got removed. The color must not be opaque so as not to hide underlying decorations.'), true);
+export const diffInserted = registerColor('diffEditor.insertedTextBackground', { dark: '#9ccc2c33', light: '#9ccc2c40', hcDark: null, hcLight: null }, nls.localize('diffEditorInserted', 'Background color for text that got inserted. The color must not be opaque so as not to hide underlying decorations.'), true);
+export const diffRemoved = registerColor('diffEditor.removedTextBackground', { dark: '#ff000033', light: '#ff000033', hcDark: null, hcLight: null }, nls.localize('diffEditorRemoved', 'Background color for text that got removed. The color must not be opaque so as not to hide underlying decorations.'), true);
export const diffInsertedLine = registerColor('diffEditor.insertedLineBackground', { dark: defaultInsertColor, light: defaultInsertColor, hcDark: null, hcLight: null }, nls.localize('diffEditorInsertedLines', 'Background color for lines that got inserted. The color must not be opaque so as not to hide underlying decorations.'), true);
export const diffRemovedLine = registerColor('diffEditor.removedLineBackground', { dark: defaultRemoveColor, light: defaultRemoveColor, hcDark: null, hcLight: null }, nls.localize('diffEditorRemovedLines', 'Background color for lines that got removed. The color must not be opaque so as not to hide underlying decorations.'), true);
diff --git a/src/vs/platform/tunnel/common/tunnel.ts b/src/vs/platform/tunnel/common/tunnel.ts
index 29b07680481..1c0d70f63ff 100644
--- a/src/vs/platform/tunnel/common/tunnel.ts
+++ b/src/vs/platform/tunnel/common/tunnel.ts
@@ -129,6 +129,7 @@ export interface ITunnelService {
closeTunnel(remoteHost: string, remotePort: number): Promise;
setTunnelProvider(provider: ITunnelProvider | undefined): IDisposable;
setTunnelFeatures(features: TunnelProviderFeatures): void;
+ isPortPrivileged(port: number): boolean;
}
export function extractLocalHostUriMetaDataForPortMapping(uri: URI): { address: string; port: number } | undefined {
@@ -402,6 +403,24 @@ export abstract class AbstractTunnelService implements ITunnelService {
return !!extractLocalHostUriMetaDataForPortMapping(uri);
}
+ public abstract isPortPrivileged(port: number): boolean;
+
+ protected doIsPortPrivileged(port: number, isWindows: boolean, isMacintosh: boolean, osRelease: string): boolean {
+ if (isWindows) {
+ return false;
+ } else if (isMacintosh) {
+ const osVersion = (/(\d+)\.(\d+)\.(\d+)/g).exec(osRelease);
+ if (osVersion?.length === 4) {
+ const major = parseInt(osVersion[1]);
+ const minor = parseInt(osVersion[2]);
+ if (((major > 10) || (major === 10 && minor >= 14))) {
+ return false;
+ }
+ }
+ }
+ return port < 1024;
+ }
+
protected abstract retainOrCreateTunnel(addressProvider: IAddressProvider, remoteHost: string, remotePort: number, localPort: number | undefined, elevateIfNeeded: boolean, privacy?: string, protocol?: string): Promise | undefined;
protected createWithProvider(tunnelProvider: ITunnelProvider, remoteHost: string, remotePort: number, localPort: number | undefined, elevateIfNeeded: boolean, privacy?: string, protocol?: string): Promise | undefined {
@@ -409,7 +428,7 @@ export abstract class AbstractTunnelService implements ITunnelService {
const key = remotePort;
this._factoryInProgress.add(key);
const preferredLocalPort = localPort === undefined ? remotePort : localPort;
- const creationInfo = { elevationRequired: elevateIfNeeded ? isPortPrivileged(preferredLocalPort) : false };
+ const creationInfo = { elevationRequired: elevateIfNeeded ? this.isPortPrivileged(preferredLocalPort) : false };
const tunnelOptions: TunnelOptions = { remoteAddress: { host: remoteHost, port: remotePort }, localAddressPort: localPort, privacy, public: privacy ? (privacy !== TunnelPrivacyId.Private) : undefined, protocol };
const tunnel = tunnelProvider.forwardPort(tunnelOptions, creationInfo);
if (tunnel) {
diff --git a/src/vs/platform/tunnel/node/tunnelService.ts b/src/vs/platform/tunnel/node/tunnelService.ts
index 7cdd91afd53..50a7cb920af 100644
--- a/src/vs/platform/tunnel/node/tunnelService.ts
+++ b/src/vs/platform/tunnel/node/tunnelService.ts
@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as net from 'net';
+import * as os from 'os';
import { BROWSER_RESTRICTED_PORTS, findFreePortFaster } from 'vs/base/node/ports';
import { NodeSocket } from 'vs/base/parts/ipc/node/ipc.net';
import { nodeSocketFactory } from 'vs/platform/remote/node/nodeSocketFactory';
@@ -16,6 +17,7 @@ import { IProductService } from 'vs/platform/product/common/productService';
import { connectRemoteAgentTunnel, IAddressProvider, IConnectionOptions, ISocketFactory } from 'vs/platform/remote/common/remoteAgentConnection';
import { AbstractTunnelService, isAllInterfaces, ISharedTunnelsService as ISharedTunnelsService, isLocalhost, ITunnelService, RemoteTunnel, TunnelPrivacyId } from 'vs/platform/tunnel/common/tunnel';
import { ISignService } from 'vs/platform/sign/common/sign';
+import { isMacintosh, isWindows } from 'vs/base/common/platform';
async function createRemoteTunnel(options: IConnectionOptions, defaultTunnelHost: string, tunnelRemoteHost: string, tunnelRemotePort: number, tunnelLocalPort?: number): Promise {
let readyTunnel: NodeRemoteTunnel | undefined;
@@ -165,6 +167,10 @@ export class BaseTunnelService extends AbstractTunnelService {
return (!settingValue || settingValue === 'localhost') ? '127.0.0.1' : '0.0.0.0';
}
+ public isPortPrivileged(port: number): boolean {
+ return this.doIsPortPrivileged(port, isWindows, isMacintosh, os.release());
+ }
+
protected retainOrCreateTunnel(addressProvider: IAddressProvider, remoteHost: string, remotePort: number, localPort: number | undefined, elevateIfNeeded: boolean, privacy?: string, protocol?: string): Promise | undefined {
const existing = this.getTunnelFromMap(remoteHost, remotePort);
if (existing) {
diff --git a/src/vs/platform/uriIdentity/common/uriIdentityService.ts b/src/vs/platform/uriIdentity/common/uriIdentityService.ts
index a0bbc55fa66..a4a23090906 100644
--- a/src/vs/platform/uriIdentity/common/uriIdentityService.ts
+++ b/src/vs/platform/uriIdentity/common/uriIdentityService.ts
@@ -5,7 +5,7 @@
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
import { URI } from 'vs/base/common/uri';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IFileService, FileSystemProviderCapabilities, IFileSystemProviderCapabilitiesChangeEvent, IFileSystemProviderRegistrationEvent } from 'vs/platform/files/common/files';
import { ExtUri, IExtUri, normalizePath } from 'vs/base/common/resources';
import { SkipList } from 'vs/base/common/skipList';
@@ -114,4 +114,4 @@ export class UriIdentityService implements IUriIdentityService {
}
}
-registerSingleton(IUriIdentityService, UriIdentityService, true);
+registerSingleton(IUriIdentityService, UriIdentityService, InstantiationType.Delayed);
diff --git a/src/vs/platform/userDataProfile/common/userDataProfile.ts b/src/vs/platform/userDataProfile/common/userDataProfile.ts
index 668a16b7c50..c68e5cf1c99 100644
--- a/src/vs/platform/userDataProfile/common/userDataProfile.ts
+++ b/src/vs/platform/userDataProfile/common/userDataProfile.ts
@@ -354,7 +354,12 @@ export class UserDataProfilesService extends Disposable implements IUserDataProf
joiners.push(promise);
}
});
- await Promises.settled(joiners);
+
+ try {
+ await Promise.allSettled(joiners);
+ } catch (error) {
+ this.logService.error(error);
+ }
if (profile.id === this.profilesObject.emptyWindow?.id) {
this.profilesObject.emptyWindow = undefined;
diff --git a/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts b/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts
index 2507e379501..3cf12e871af 100644
--- a/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts
+++ b/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts
@@ -204,8 +204,8 @@ export class UserDataAutoSyncService extends Disposable implements IUserDataAuto
await this.userDataSyncService.resetLocal();
}
} catch (error) {
+ this.logService.error(error);
if (softTurnOffOnError) {
- this.logService.error(error);
this.updateEnablement(false);
} else {
throw error;
@@ -411,7 +411,6 @@ class AutoSync extends Disposable {
this.syncTask?.stop();
this.logService.info('Auto Sync: Stopped');
}));
- this.logService.info('Auto Sync: Started');
this.sync(AutoSync.INTERVAL_SYNCING, false);
}
diff --git a/src/vs/platform/userDataSync/common/userDataSyncService.ts b/src/vs/platform/userDataSync/common/userDataSyncService.ts
index 02cd2ff1c7a..828b37cef34 100644
--- a/src/vs/platform/userDataSync/common/userDataSyncService.ts
+++ b/src/vs/platform/userDataSync/common/userDataSyncService.ts
@@ -92,7 +92,6 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
@IUserDataSyncEnablementService private readonly userDataSyncEnablementService: IUserDataSyncEnablementService,
@IUserDataProfilesService private readonly userDataProfilesService: IUserDataProfilesService,
@IProductService private readonly productService: IProductService,
- @IConfigurationService private readonly configurationService: IConfigurationService,
@IEnvironmentService private readonly environmentService: IEnvironmentService,
) {
super();
@@ -104,6 +103,8 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
async createSyncTask(manifest: IUserDataManifest | null, disableCache?: boolean): Promise {
this.checkEnablement();
+ this.logService.info('Sync started.');
+ const startTime = new Date().getTime();
const executionId = generateUuid();
try {
const syncHeaders = createSyncHeaders(executionId);
@@ -127,7 +128,9 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
throw new Error('Can run a task only once');
}
cancellablePromise = createCancelablePromise(token => that.sync(manifest, false, executionId, token));
- return cancellablePromise.finally(() => cancellablePromise = undefined);
+ await cancellablePromise.finally(() => cancellablePromise = undefined);
+ that.logService.info(`Sync done. Took ${new Date().getTime() - startTime}ms`);
+ that.updateLastSyncTime();
},
stop(): Promise {
cancellablePromise?.cancel();
@@ -143,9 +146,10 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
throw new UserDataSyncError('Cannot start manual sync when sync is enabled', UserDataSyncErrorCode.LocalError);
}
+ this.logService.info('Sync started.');
+ const startTime = new Date().getTime();
const executionId = generateUuid();
const syncHeaders = createSyncHeaders(executionId);
-
let manifest: IUserDataManifest | null;
try {
manifest = await this.userDataSyncStoreService.manifest(null, syncHeaders);
@@ -166,12 +170,9 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
return that.sync(manifest, true, executionId, cancellableToken.token);
},
async apply(): Promise {
- for (const profileSynchronizer of that.getActiveProfileSynchronizers()) {
- if (cancellableToken.token.isCancellationRequested) {
- return;
- }
- await profileSynchronizer.apply(executionId, cancellableToken.token);
- }
+ await that.applyManualSync(manifest, executionId, cancellableToken.token);
+ that.logService.info(`Sync done. Took ${new Date().getTime() - startTime}ms`);
+ that.updateLastSyncTime();
},
stop(): Promise {
cancellableToken.cancel();
@@ -185,14 +186,8 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
}
private async sync(manifest: IUserDataManifest | null, merge: boolean, executionId: string, token: CancellationToken): Promise {
- // Return if cancellation is requested
- if (token.isCancellationRequested) {
- return;
- }
- const startTime = new Date().getTime();
this._syncErrors = [];
try {
- this.logService.info('Sync started.');
if (this.status !== SyncStatus.HasConflicts) {
this.setStatus(SyncStatus.Syncing);
}
@@ -208,27 +203,56 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
if (token.isCancellationRequested) {
return;
}
- for (const syncProfile of syncProfiles) {
- if (token.isCancellationRequested) {
- return;
- }
- const profile = this.userDataProfilesService.profiles.find(p => p.id === syncProfile.id);
- if (!profile) {
- this.logService.error(`Settings Profile with id:${syncProfile.id} and name: ${syncProfile.name} does not exist locally to sync.`);
- continue;
- }
- this.logService.info('Syncing profile.', syncProfile.name);
- const profileSynchronizer = this.getOrCreateActiveProfileSynchronizer(profile, syncProfile);
- this._syncErrors.push(...await this.syncProfile(profileSynchronizer, manifest, merge, executionId, token));
- }
+ await this.syncRemoteProfiles(syncProfiles, manifest, merge, executionId, token);
}
- this.logService.info(`Sync done. Took ${new Date().getTime() - startTime}ms`);
- this.updateLastSyncTime();
} finally {
this._onSyncErrors.fire(this._syncErrors);
}
}
+ private async syncRemoteProfiles(remoteProfiles: ISyncUserDataProfile[], manifest: IUserDataManifest | null, merge: boolean, executionId: string, token: CancellationToken): Promise {
+ for (const syncProfile of remoteProfiles) {
+ if (token.isCancellationRequested) {
+ return;
+ }
+ const profile = this.userDataProfilesService.profiles.find(p => p.id === syncProfile.id);
+ if (!profile) {
+ this.logService.error(`Settings Profile with id:${syncProfile.id} and name: ${syncProfile.name} does not exist locally to sync.`);
+ continue;
+ }
+ this.logService.info('Syncing profile.', syncProfile.name);
+ const profileSynchronizer = this.getOrCreateActiveProfileSynchronizer(profile, syncProfile);
+ this._syncErrors.push(...await this.syncProfile(profileSynchronizer, manifest, merge, executionId, token));
+ }
+ }
+
+ private async applyManualSync(manifest: IUserDataManifest | null, executionId: string, token: CancellationToken): Promise {
+ const profileSynchronizers = this.getActiveProfileSynchronizers();
+ for (const profileSynchronizer of profileSynchronizers) {
+ if (token.isCancellationRequested) {
+ return;
+ }
+ await profileSynchronizer.apply(executionId, token);
+ }
+
+ const defaultProfileSynchronizer = profileSynchronizers.find(s => s.profile.isDefault);
+ if (!defaultProfileSynchronizer) {
+ return;
+ }
+
+ const userDataProfileManifestSynchronizer = defaultProfileSynchronizer.enabled.find(s => s.resource === SyncResource.Profiles);
+ if (!userDataProfileManifestSynchronizer) {
+ return;
+ }
+
+ // Sync remote profiles which are not synced locally
+ const remoteProfiles = (await (userDataProfileManifestSynchronizer as UserDataProfilesManifestSynchroniser).getRemoteSyncedProfiles(manifest?.latest ?? null)) || [];
+ const remoteProfilesToSync = remoteProfiles.filter(remoteProfile => profileSynchronizers.every(s => s.profile.id !== remoteProfile.id));
+ if (remoteProfilesToSync.length) {
+ await this.syncRemoteProfiles(remoteProfilesToSync, manifest, false, executionId, token);
+ }
+ }
+
private async syncProfile(profileSynchronizer: ProfileSynchronizer, manifest: IUserDataManifest | null, merge: boolean, executionId: string, token: CancellationToken): Promise {
const errors = await profileSynchronizer.sync(manifest, merge, executionId, token);
return errors.map(([syncResource, error]) => ({ profile: profileSynchronizer.profile, syncResource, error }));
@@ -367,16 +391,14 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
async resetLocal(): Promise {
this.checkEnablement();
this.storageService.remove(LAST_SYNC_TIME_KEY, StorageScope.APPLICATION);
- if (this.activeProfileSynchronizers) {
- for (const [synchronizer] of this.activeProfileSynchronizers.values()) {
- try {
- await synchronizer.resetLocal();
- } catch (e) {
- this.logService.error(e);
- }
+ for (const [synchronizer] of this.activeProfileSynchronizers.values()) {
+ try {
+ await synchronizer.resetLocal();
+ } catch (e) {
+ this.logService.error(e);
}
- this.clearActiveProfileSynchronizers();
}
+ this.clearActiveProfileSynchronizers();
this._onDidResetLocal.fire();
this.logService.info('Did reset the local sync state.');
}
@@ -396,7 +418,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
return isUndefined(result) ? null : result;
}
- if (this.environmentService.isBuilt && !(this.productService.enableSyncingProfiles && this.configurationService.getValue('settingsSync.enableSyncingProfiles'))) {
+ if (this.environmentService.isBuilt && (!this.productService.enableSyncingProfiles || isEqual(this.userDataSyncStoreManagementService.userDataSyncStore?.url, this.userDataSyncStoreManagementService.userDataSyncStore?.stableUrl))) {
return null;
}
@@ -568,7 +590,7 @@ class ProfileSynchronizer extends Disposable {
if (!this._profile.isDefault) {
return;
}
- if (this.environmentService.isBuilt && !(this.productService.enableSyncingProfiles && this.configurationService.getValue('settingsSync.enableSyncingProfiles'))) {
+ if (this.environmentService.isBuilt && (!this.productService.enableSyncingProfiles || isEqual(this.userDataSyncStoreManagementService.userDataSyncStore?.url, this.userDataSyncStoreManagementService.userDataSyncStore?.stableUrl))) {
this.logService.debug('Skipping profiles sync');
return;
}
diff --git a/src/vs/platform/userDataSync/common/userDataSyncServiceIpc.ts b/src/vs/platform/userDataSync/common/userDataSyncServiceIpc.ts
index 2697c75eb94..c6605c7ad7c 100644
--- a/src/vs/platform/userDataSync/common/userDataSyncServiceIpc.ts
+++ b/src/vs/platform/userDataSync/common/userDataSyncServiceIpc.ts
@@ -17,8 +17,8 @@ import {
type ManualSyncTaskEvent = { manualSyncTaskId: string; data: T };
-function reviewSyncResource(syncResource: IUserDataSyncResource, userDataProfilesService: IUserDataProfilesService) {
- return { ...syncResource, profie: reviveProfile(syncResource.profile, userDataProfilesService.profilesHome.scheme) };
+function reviewSyncResource(syncResource: IUserDataSyncResource, userDataProfilesService: IUserDataProfilesService): IUserDataSyncResource {
+ return { ...syncResource, profile: reviveProfile(syncResource.profile, userDataProfilesService.profilesHome.scheme) };
}
export class UserDataSyncChannel implements IServerChannel {
diff --git a/src/vs/server/node/webClientServer.ts b/src/vs/server/node/webClientServer.ts
index 433e12a7b15..e57259fc731 100644
--- a/src/vs/server/node/webClientServer.ts
+++ b/src/vs/server/node/webClientServer.ts
@@ -302,7 +302,7 @@ export class WebClientServer {
const workbenchWebConfiguration = {
remoteAuthority,
_wrapWebWorkerExtHostInIframe,
- developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined },
+ developmentOptions: { enableSmokeTestDriver: this._environmentService.args['enable-smoke-test-driver'] ? true : undefined, logLevel: this._logService.getLevel() },
settingsSyncOptions: !this._environmentService.isBuilt && this._environmentService.args['enable-sync'] ? { enabled: true } : undefined,
enableWorkspaceTrust: !this._environmentService.args['disable-workspace-trust'],
folderUri: resolveWorkspaceURI(this._environmentService.args['default-folder']),
diff --git a/src/vs/workbench/api/browser/extensionHost.contribution.ts b/src/vs/workbench/api/browser/extensionHost.contribution.ts
index 203f680485c..38a27b2cea4 100644
--- a/src/vs/workbench/api/browser/extensionHost.contribution.ts
+++ b/src/vs/workbench/api/browser/extensionHost.contribution.ts
@@ -90,4 +90,4 @@ export class ExtensionPoints implements IWorkbenchContribution {
}
}
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(ExtensionPoints, 'ExtensionPoints', LifecyclePhase.Starting);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(ExtensionPoints, LifecyclePhase.Starting);
diff --git a/src/vs/workbench/api/browser/mainThreadBulkEdits.ts b/src/vs/workbench/api/browser/mainThreadBulkEdits.ts
index dabd351f2d8..0c59eb78b5a 100644
--- a/src/vs/workbench/api/browser/mainThreadBulkEdits.ts
+++ b/src/vs/workbench/api/browser/mainThreadBulkEdits.ts
@@ -27,7 +27,7 @@ export class MainThreadBulkEdits implements MainThreadBulkEditsShape {
$tryApplyWorkspaceEdit(dto: IWorkspaceEditDto, undoRedoGroupId?: number, isRefactoring?: boolean): Promise {
const edits = reviveWorkspaceEditDto(dto, this._uriIdentService);
- return this._bulkEditService.apply(edits, { undoRedoGroupId, respectAutoSaveConfig: isRefactoring }).then(() => true, err => {
+ return this._bulkEditService.apply(edits, { undoRedoGroupId, respectAutoSaveConfig: isRefactoring }).then((res) => res.isApplied, err => {
this._logService.warn(`IGNORING workspace edit: ${err}`);
return false;
});
diff --git a/src/vs/workbench/api/browser/mainThreadEditorTabs.ts b/src/vs/workbench/api/browser/mainThreadEditorTabs.ts
index bda93934177..09efeab8cde 100644
--- a/src/vs/workbench/api/browser/mainThreadEditorTabs.ts
+++ b/src/vs/workbench/api/browser/mainThreadEditorTabs.ts
@@ -194,7 +194,7 @@ export class MainThreadEditorTabs implements MainThreadEditorTabsShape {
private _generateTabId(editor: EditorInput, groupId: number) {
let resourceString: string | undefined;
// Properly get the resource and account for side by side editors
- const resource = EditorResourceAccessor.getOriginalUri(editor, { supportSideBySide: SideBySideEditor.BOTH });
+ const resource = EditorResourceAccessor.getCanonicalUri(editor, { supportSideBySide: SideBySideEditor.BOTH });
if (resource instanceof URI) {
resourceString = resource.toString();
} else {
diff --git a/src/vs/workbench/api/browser/mainThreadTunnelService.ts b/src/vs/workbench/api/browser/mainThreadTunnelService.ts
index c43a9e82756..ea4f8198698 100644
--- a/src/vs/workbench/api/browser/mainThreadTunnelService.ts
+++ b/src/vs/workbench/api/browser/mainThreadTunnelService.ts
@@ -8,7 +8,7 @@ import { MainThreadTunnelServiceShape, MainContext, ExtHostContext, ExtHostTunne
import { TunnelDtoConverter } from 'vs/workbench/api/common/extHostTunnelService';
import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers';
import { CandidatePort, IRemoteExplorerService, makeAddress, PORT_AUTO_FORWARD_SETTING, PORT_AUTO_SOURCE_SETTING, PORT_AUTO_SOURCE_SETTING_OUTPUT, PORT_AUTO_SOURCE_SETTING_PROCESS, TunnelSource } from 'vs/workbench/services/remote/common/remoteExplorerService';
-import { ITunnelProvider, ITunnelService, TunnelCreationOptions, TunnelProviderFeatures, TunnelOptions, RemoteTunnel, isPortPrivileged, ProvidedPortAttributes, PortAttributesProvider, TunnelProtocol } from 'vs/platform/tunnel/common/tunnel';
+import { ITunnelProvider, ITunnelService, TunnelCreationOptions, TunnelProviderFeatures, TunnelOptions, RemoteTunnel, ProvidedPortAttributes, PortAttributesProvider, TunnelProtocol } from 'vs/platform/tunnel/common/tunnel';
import { Disposable } from 'vs/base/common/lifecycle';
import type { TunnelDescription } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
@@ -111,7 +111,7 @@ export class MainThreadTunnelService extends Disposable implements MainThreadTun
if (!this.elevateionRetry
&& (tunnelOptions.localAddressPort !== undefined)
&& (tunnel.tunnelLocalPort !== undefined)
- && isPortPrivileged(tunnelOptions.localAddressPort)
+ && this.tunnelService.isPortPrivileged(tunnelOptions.localAddressPort)
&& (tunnel.tunnelLocalPort !== tunnelOptions.localAddressPort)
&& this.tunnelService.canElevate) {
diff --git a/src/vs/workbench/api/browser/viewsExtensionPoint.ts b/src/vs/workbench/api/browser/viewsExtensionPoint.ts
index 92b4f91954d..87e69afc783 100644
--- a/src/vs/workbench/api/browser/viewsExtensionPoint.ts
+++ b/src/vs/workbench/api/browser/viewsExtensionPoint.ts
@@ -642,4 +642,4 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
}
const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench);
-workbenchRegistry.registerWorkbenchContribution(ViewsExtensionHandler, 'ViewsExtensionHandler', LifecyclePhase.Starting);
+workbenchRegistry.registerWorkbenchContribution(ViewsExtensionHandler, LifecyclePhase.Starting);
diff --git a/src/vs/workbench/api/common/extHost.common.services.ts b/src/vs/workbench/api/common/extHost.common.services.ts
index 4658a622298..f00aebebc47 100644
--- a/src/vs/workbench/api/common/extHost.common.services.ts
+++ b/src/vs/workbench/api/common/extHost.common.services.ts
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IExtHostOutputService, ExtHostOutputService } from 'vs/workbench/api/common/extHostOutput';
import { IExtHostWorkspace, ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import { IExtHostDecorations, ExtHostDecorations } from 'vs/workbench/api/common/extHostDecorations';
@@ -30,9 +30,9 @@ import { ExtHostVariableResolverProviderService, IExtHostVariableResolverProvide
import { ExtHostTelemetryLogService, IExtHostTelemetryLogService } from 'vs/workbench/api/common/extHostTelemetryLogService';
import { ExtHostLocalizationService, IExtHostLocalizationService } from 'vs/workbench/api/common/extHostLocalizationService';
-registerSingleton(IExtHostLocalizationService, ExtHostLocalizationService, true);
-registerSingleton(ILoggerService, ExtHostLoggerService, true);
-registerSingleton(ILogService, ExtHostLogService, true);
+registerSingleton(IExtHostLocalizationService, ExtHostLocalizationService, InstantiationType.Delayed);
+registerSingleton(ILoggerService, ExtHostLoggerService, InstantiationType.Delayed);
+registerSingleton(ILogService, ExtHostLogService, InstantiationType.Delayed);
registerSingleton(IExtHostApiDeprecationService, ExtHostApiDeprecationService, false);
registerSingleton(IExtHostCommands, ExtHostCommands, false);
registerSingleton(IExtHostConfiguration, ExtHostConfiguration, false);
@@ -41,7 +41,7 @@ registerSingleton(IExtHostDebugService, WorkerExtHostDebugService, false);
registerSingleton(IExtHostDecorations, ExtHostDecorations, false);
registerSingleton(IExtHostDocumentsAndEditors, ExtHostDocumentsAndEditors, false);
registerSingleton(IExtHostFileSystemInfo, ExtHostFileSystemInfo, false);
-registerSingleton(IExtHostOutputService, ExtHostOutputService, true);
+registerSingleton(IExtHostOutputService, ExtHostOutputService, InstantiationType.Delayed);
registerSingleton(IExtHostSearch, ExtHostSearch, false);
registerSingleton(IExtHostStorage, ExtHostStorage, false);
registerSingleton(IExtHostTask, WorkerExtHostTask, false);
diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts
index 5e21c84cd15..50ad7f3c9e3 100644
--- a/src/vs/workbench/api/common/extHost.protocol.ts
+++ b/src/vs/workbench/api/common/extHost.protocol.ts
@@ -2199,7 +2199,7 @@ export interface ExtHostTestingShape {
export interface ExtHostLocalizationShape {
getMessage(extensionId: string, details: IStringDetails): string;
- getBundle(extensionId: string): { [key: string]: string };
+ getBundle(extensionId: string): { [key: string]: string } | undefined;
getBundleUri(extensionId: string): URI | undefined;
initializeLocalizedMessages(extension: IExtensionDescription): Promise;
}
diff --git a/src/vs/workbench/api/common/extHostBulkEdits.ts b/src/vs/workbench/api/common/extHostBulkEdits.ts
index 59e0bbc2426..bdbfe2e5ba8 100644
--- a/src/vs/workbench/api/common/extHostBulkEdits.ts
+++ b/src/vs/workbench/api/common/extHostBulkEdits.ts
@@ -8,7 +8,6 @@ import { MainContext, MainThreadBulkEditsShape } from 'vs/workbench/api/common/e
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { WorkspaceEdit } from 'vs/workbench/api/common/extHostTypeConverters';
-import { isProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import type * as vscode from 'vscode';
export class ExtHostBulkEdits {
@@ -29,11 +28,6 @@ export class ExtHostBulkEdits {
}
applyWorkspaceEdit(edit: vscode.WorkspaceEdit, extension: IExtensionDescription, metadata: vscode.WorkspaceEditMetadata | undefined): Promise {
- const allowIsRefactoring = isProposedApiEnabled(extension, 'workspaceEditIsRefactoring');
- if (metadata && !allowIsRefactoring) {
- console.warn(`Extension '${extension.identifier.value}' uses a proposed API 'workspaceEditIsRefactoring' which is NOT enabled for it`);
- metadata = undefined;
- }
const dto = WorkspaceEdit.from(edit, this._versionInformationProvider);
return this._proxy.$tryApplyWorkspaceEdit(dto, undefined, metadata?.isRefactoring ?? false);
}
diff --git a/src/vs/workbench/api/common/extHostLocalizationService.ts b/src/vs/workbench/api/common/extHostLocalizationService.ts
index 38f3b41f632..335fdf88ac6 100644
--- a/src/vs/workbench/api/common/extHostLocalizationService.ts
+++ b/src/vs/workbench/api/common/extHostLocalizationService.ts
@@ -35,7 +35,7 @@ export class ExtHostLocalizationService implements ExtHostLocalizationShape {
getMessage(extensionId: string, details: IStringDetails): string {
const { message, args, comment } = details;
if (this.isDefaultLanguage) {
- return format(message, args);
+ return format(message, ...(args ?? []));
}
let key = message;
@@ -46,11 +46,11 @@ export class ExtHostLocalizationService implements ExtHostLocalizationShape {
if (!str) {
this.logService.warn(`Using default string since no string found in i18n bundle that has the key: ${key}`);
}
- return format(str ?? key, args);
+ return format(str ?? key, ...(args ?? []));
}
- getBundle(extensionId: string): { [key: string]: string } {
- return this.bundleCache.get(extensionId)?.contents ?? {};
+ getBundle(extensionId: string): { [key: string]: string } | undefined {
+ return this.bundleCache.get(extensionId)?.contents;
}
getBundleUri(extensionId: string): URI | undefined {
diff --git a/src/vs/workbench/api/common/extHostOutput.ts b/src/vs/workbench/api/common/extHostOutput.ts
index abe63cff8da..09741ef4a3c 100644
--- a/src/vs/workbench/api/common/extHostOutput.ts
+++ b/src/vs/workbench/api/common/extHostOutput.ts
@@ -35,6 +35,7 @@ class ExtHostOutputChannel extends AbstractMessageLogger implements vscode.LogOu
readonly extension: IExtensionDescription,
) {
super();
+ this._register(logger.onDidChangeLogLevel(level => this.setLevel(level)));
}
appendLine(value: string): void {
@@ -235,7 +236,7 @@ export class ExtHostOutputService implements ExtHostOutputServiceShape {
...this.createExtHostOutputChannel(name, channelPromise),
trace(value: string, ...args: any[]): void {
validate();
- channelPromise.then(channel => channel.info(value, ...args));
+ channelPromise.then(channel => channel.trace(value, ...args));
},
debug(value: string, ...args: any[]): void {
validate();
diff --git a/src/vs/workbench/api/common/extHostTestItem.ts b/src/vs/workbench/api/common/extHostTestItem.ts
index 25fa2780a45..496cc12a035 100644
--- a/src/vs/workbench/api/common/extHostTestItem.ts
+++ b/src/vs/workbench/api/common/extHostTestItem.ts
@@ -175,6 +175,8 @@ export class TestItemImpl implements vscode.TestItem {
}
export class TestItemRootImpl extends TestItemImpl {
+ public readonly _isRoot = true;
+
constructor(controllerId: string, label: string) {
super(controllerId, controllerId, label, undefined);
}
diff --git a/src/vs/workbench/api/common/extHostTesting.ts b/src/vs/workbench/api/common/extHostTesting.ts
index c436a936cf6..bf44c8939d4 100644
--- a/src/vs/workbench/api/common/extHostTesting.ts
+++ b/src/vs/workbench/api/common/extHostTesting.ts
@@ -751,7 +751,8 @@ class MirroredChangeCollector extends IncrementalChangeCollector => {
return treeView.reveal(element, options);
diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts
index 2be8385ad85..8721bb81444 100644
--- a/src/vs/workbench/api/common/extHostTypeConverters.ts
+++ b/src/vs/workbench/api/common/extHostTypeConverters.ts
@@ -1846,7 +1846,8 @@ export namespace TestResults {
const byInternalId = new Map();
for (const item of serialized.items) {
byInternalId.set(item.item.extId, item);
- if (serialized.request.targets.some(t => t.controllerId === item.controllerId && t.testIds.includes(item.item.extId))) {
+ const controllerId = TestId.root(item.item.extId);
+ if (serialized.request.targets.some(t => t.controllerId === controllerId && t.testIds.includes(item.item.extId))) {
roots.push(item);
}
}
diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts
index 57c2608bdfc..7f44f88a23e 100644
--- a/src/vs/workbench/api/common/extHostTypes.ts
+++ b/src/vs/workbench/api/common/extHostTypes.ts
@@ -28,12 +28,21 @@ import type * as vscode from 'vscode';
* but new ones must not be added
* */
function es5ClassCompat(target: Function): any {
- ///@ts-expect-error
- function _() { return Reflect.construct(target, arguments, this.constructor); }
- Object.defineProperty(_, 'name', Object.getOwnPropertyDescriptor(target, 'name')!);
- Object.setPrototypeOf(_, target);
- Object.setPrototypeOf(_.prototype, target.prototype);
- return _;
+ const interceptFunctions = {
+ apply: function () {
+ const args = arguments.length === 1 ? [] : arguments[1];
+ return Reflect.construct(target, args, arguments[0].constructor);
+ },
+ call: function () {
+ if (arguments.length === 0) {
+ return Reflect.construct(target, []);
+ } else {
+ const [thisArg, ...restArgs] = arguments;
+ return Reflect.construct(target, restArgs, thisArg.constructor);
+ }
+ }
+ };
+ return Object.assign(target, interceptFunctions);
}
@es5ClassCompat
@@ -2460,6 +2469,22 @@ export enum ProgressLocation {
Notification = 15
}
+export namespace ViewBadge {
+ export function isViewBadge(thing: any): thing is vscode.ViewBadge {
+ const viewBadgeThing = thing as vscode.ViewBadge;
+
+ if (!isNumber(viewBadgeThing.value)) {
+ console.log('INVALID view badge, invalid value', viewBadgeThing.value);
+ return false;
+ }
+ if (viewBadgeThing.tooltip && !isString(viewBadgeThing.tooltip)) {
+ console.log('INVALID view badge, invalid tooltip', viewBadgeThing.tooltip);
+ return false;
+ }
+ return true;
+ }
+}
+
@es5ClassCompat
export class TreeItem {
diff --git a/src/vs/workbench/api/node/extHost.node.services.ts b/src/vs/workbench/api/node/extHost.node.services.ts
index 27562ce32ca..98d300f7d8c 100644
--- a/src/vs/workbench/api/node/extHost.node.services.ts
+++ b/src/vs/workbench/api/node/extHost.node.services.ts
@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ExtHostTerminalService } from 'vs/workbench/api/node/extHostTerminalService';
import { ExtHostTask } from 'vs/workbench/api/node/extHostTask';
import { ExtHostDebugService } from 'vs/workbench/api/node/extHostDebugService';
@@ -30,7 +30,7 @@ import { IExtHostVariableResolverProvider } from 'vs/workbench/api/common/extHos
// #########################################################################
registerSingleton(IExtHostExtensionService, ExtHostExtensionService, false);
-registerSingleton(ILoggerService, ExtHostLoggerService, true);
+registerSingleton(ILoggerService, ExtHostLoggerService, InstantiationType.Delayed);
registerSingleton(IExtensionStoragePaths, ExtensionStoragePaths, false);
registerSingleton(IExtHostDebugService, ExtHostDebugService, false);
diff --git a/src/vs/workbench/api/test/browser/extHostDiagnostics.test.ts b/src/vs/workbench/api/test/browser/extHostDiagnostics.test.ts
index 021725f35f0..f7d92af7f58 100644
--- a/src/vs/workbench/api/test/browser/extHostDiagnostics.test.ts
+++ b/src/vs/workbench/api/test/browser/extHostDiagnostics.test.ts
@@ -16,6 +16,7 @@ import type * as vscode from 'vscode';
import { nullExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { ExtUri, extUri } from 'vs/base/common/resources';
import { IExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo';
+import { runWithFakedTimers } from 'vs/base/test/common/timeTravelScheduler';
suite('ExtHostDiagnostics', () => {
@@ -438,43 +439,46 @@ suite('ExtHostDiagnostics', () => {
});
test('Diagnostics created by tasks aren\'t accessible to extensions #47292', async function () {
- const diags = new ExtHostDiagnostics(new class implements IMainContext {
- getProxy(id: any): any {
- return {};
- }
- set(): any {
- return null;
- }
- dispose() { }
- assertRegistered(): void {
+ return runWithFakedTimers({}, async function () {
- }
- drain() {
- return undefined!;
- }
- }, new NullLogService(), fileSystemInfoService);
+ const diags = new ExtHostDiagnostics(new class implements IMainContext {
+ getProxy(id: any): any {
+ return {};
+ }
+ set(): any {
+ return null;
+ }
+ dispose() { }
+ assertRegistered(): void {
+
+ }
+ drain() {
+ return undefined!;
+ }
+ }, new NullLogService(), fileSystemInfoService);
- //
- const uri = URI.parse('foo:bar');
- const data: IMarkerData[] = [{
- message: 'message',
- startLineNumber: 1,
- startColumn: 1,
- endLineNumber: 1,
- endColumn: 1,
- severity: 3
- }];
+ //
+ const uri = URI.parse('foo:bar');
+ const data: IMarkerData[] = [{
+ message: 'message',
+ startLineNumber: 1,
+ startColumn: 1,
+ endLineNumber: 1,
+ endColumn: 1,
+ severity: 3
+ }];
- const p1 = Event.toPromise(diags.onDidChangeDiagnostics);
- diags.$acceptMarkersChange([[uri, data]]);
- await p1;
- assert.strictEqual(diags.getDiagnostics(uri).length, 1);
+ const p1 = Event.toPromise(diags.onDidChangeDiagnostics);
+ diags.$acceptMarkersChange([[uri, data]]);
+ await p1;
+ assert.strictEqual(diags.getDiagnostics(uri).length, 1);
- const p2 = Event.toPromise(diags.onDidChangeDiagnostics);
- diags.$acceptMarkersChange([[uri, []]]);
- await p2;
- assert.strictEqual(diags.getDiagnostics(uri).length, 0);
+ const p2 = Event.toPromise(diags.onDidChangeDiagnostics);
+ diags.$acceptMarkersChange([[uri, []]]);
+ await p2;
+ assert.strictEqual(diags.getDiagnostics(uri).length, 0);
+ });
});
test('languages.getDiagnostics doesn\'t handle case insensitivity correctly #128198', function () {
diff --git a/src/vs/workbench/api/test/browser/extHostTesting.test.ts b/src/vs/workbench/api/test/browser/extHostTesting.test.ts
index dad5ae26397..80645717880 100644
--- a/src/vs/workbench/api/test/browser/extHostTesting.test.ts
+++ b/src/vs/workbench/api/test/browser/extHostTesting.test.ts
@@ -102,19 +102,19 @@ suite('ExtHost Testing', () => {
assert.deepStrictEqual(single.collectDiff(), [
{
op: TestDiffOpType.Add,
- item: { controllerId: 'ctrlId', parent: null, expand: TestItemExpandState.BusyExpanding, item: { ...convert.TestItem.from(single.root) } }
+ item: { controllerId: 'ctrlId', expand: TestItemExpandState.BusyExpanding, item: { ...convert.TestItem.from(single.root) } }
},
{
op: TestDiffOpType.Add,
- item: { controllerId: 'ctrlId', parent: single.root.id, expand: TestItemExpandState.BusyExpanding, item: { ...convert.TestItem.from(a) } }
+ item: { controllerId: 'ctrlId', expand: TestItemExpandState.BusyExpanding, item: { ...convert.TestItem.from(a) } }
},
{
op: TestDiffOpType.Add,
- item: { controllerId: 'ctrlId', parent: new TestId(['ctrlId', 'id-a']).toString(), expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(a.children.get('id-aa') as TestItemImpl) }
+ item: { controllerId: 'ctrlId', expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(a.children.get('id-aa') as TestItemImpl) }
},
{
op: TestDiffOpType.Add,
- item: { controllerId: 'ctrlId', parent: new TestId(['ctrlId', 'id-a']).toString(), expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(a.children.get('id-ab') as TestItemImpl) }
+ item: { controllerId: 'ctrlId', expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(a.children.get('id-ab') as TestItemImpl) }
},
{
op: TestDiffOpType.Update,
@@ -122,7 +122,7 @@ suite('ExtHost Testing', () => {
},
{
op: TestDiffOpType.Add,
- item: { controllerId: 'ctrlId', parent: single.root.id, expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(b) }
+ item: { controllerId: 'ctrlId', expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(b) }
},
{
op: TestDiffOpType.Update,
@@ -141,6 +141,19 @@ suite('ExtHost Testing', () => {
assert.strictEqual(ab.parent, a);
});
+ test('can add an item with same ID as root', () => {
+ single.collectDiff();
+
+ const child = new TestItemImpl('ctrlId', 'ctrlId', 'c', undefined);
+ single.root.children.add(child);
+ assert.deepStrictEqual(single.collectDiff(), [
+ {
+ op: TestDiffOpType.Add,
+ item: { controllerId: 'ctrlId', expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(child) },
+ }
+ ]);
+ });
+
test('no-ops if items not changed', () => {
single.collectDiff();
assert.deepStrictEqual(single.collectDiff(), []);
@@ -184,7 +197,6 @@ suite('ExtHost Testing', () => {
{
op: TestDiffOpType.Add, item: {
controllerId: 'ctrlId',
- parent: new TestId(['ctrlId', 'id-a']).toString(),
expand: TestItemExpandState.NotExpandable,
item: convert.TestItem.from(child),
}
@@ -213,7 +225,6 @@ suite('ExtHost Testing', () => {
{
op: TestDiffOpType.Add, item: {
controllerId: 'ctrlId',
- parent: new TestId(['ctrlId', 'id-a']).toString(),
expand: TestItemExpandState.NotExpandable,
item: convert.TestItem.from(child),
}
@@ -326,7 +337,7 @@ suite('ExtHost Testing', () => {
},
{
op: TestDiffOpType.Add,
- item: { controllerId: 'ctrlId', parent: new TestId(['ctrlId', 'id-a']).toString(), expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(b) }
+ item: { controllerId: 'ctrlId', expand: TestItemExpandState.NotExpandable, item: convert.TestItem.from(b) }
},
]);
diff --git a/src/vs/workbench/browser/actions/developerActions.ts b/src/vs/workbench/browser/actions/developerActions.ts
index 5a0d08a8623..9de0788c23f 100644
--- a/src/vs/workbench/browser/actions/developerActions.ts
+++ b/src/vs/workbench/browser/actions/developerActions.ts
@@ -27,7 +27,7 @@ import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'v
import { ILogService } from 'vs/platform/log/common/log';
import { IWorkingCopyService } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { IWorkingCopyBackupService } from 'vs/workbench/services/workingCopy/common/workingCopyBackup';
class InspectContextKeysAction extends Action2 {
@@ -36,7 +36,7 @@ class InspectContextKeysAction extends Action2 {
super({
id: 'workbench.action.inspectContextKeys',
title: { value: localize('inspect context keys', "Inspect Context Keys"), original: 'Inspect Context Keys' },
- category: CATEGORIES.Developer,
+ category: Categories.Developer,
f1: true
});
}
@@ -96,7 +96,7 @@ class ToggleScreencastModeAction extends Action2 {
super({
id: 'workbench.action.toggleScreencastMode',
title: { value: localize('toggle screencast mode', "Toggle Screencast Mode"), original: 'Toggle Screencast Mode' },
- category: CATEGORIES.Developer,
+ category: Categories.Developer,
f1: true
});
}
@@ -267,7 +267,7 @@ class LogStorageAction extends Action2 {
super({
id: 'workbench.action.logStorage',
title: { value: localize({ key: 'logStorage', comment: ['A developer only action to log the contents of the storage for the current window.'] }, "Log Storage Database Contents"), original: 'Log Storage Database Contents' },
- category: CATEGORIES.Developer,
+ category: Categories.Developer,
f1: true
});
}
@@ -283,7 +283,7 @@ class LogWorkingCopiesAction extends Action2 {
super({
id: 'workbench.action.logWorkingCopies',
title: { value: localize({ key: 'logWorkingCopies', comment: ['A developer only action to log the working copies that exist.'] }, "Log Working Copies"), original: 'Log Working Copies' },
- category: CATEGORIES.Developer,
+ category: Categories.Developer,
f1: true
});
}
diff --git a/src/vs/workbench/browser/actions/helpActions.ts b/src/vs/workbench/browser/actions/helpActions.ts
index 227492a8fce..d05f5a9e391 100644
--- a/src/vs/workbench/browser/actions/helpActions.ts
+++ b/src/vs/workbench/browser/actions/helpActions.ts
@@ -14,7 +14,7 @@ import { KeyChord, KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { IProductService } from 'vs/platform/product/common/productService';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
class KeybindingsReferenceAction extends Action2 {
@@ -29,7 +29,7 @@ class KeybindingsReferenceAction extends Action2 {
mnemonicTitle: localize({ key: 'miKeyboardShortcuts', comment: ['&& denotes a mnemonic'] }, "&&Keyboard Shortcuts Reference"),
original: 'Keyboard Shortcuts Reference'
},
- category: CATEGORIES.Help,
+ category: Categories.Help,
f1: true,
keybinding: {
weight: KeybindingWeight.WorkbenchContrib,
@@ -68,7 +68,7 @@ class OpenIntroductoryVideosUrlAction extends Action2 {
mnemonicTitle: localize({ key: 'miVideoTutorials', comment: ['&& denotes a mnemonic'] }, "&&Video Tutorials"),
original: 'Video Tutorials'
},
- category: CATEGORIES.Help,
+ category: Categories.Help,
f1: true,
menu: {
id: MenuId.MenubarHelpMenu,
@@ -101,7 +101,7 @@ class OpenTipsAndTricksUrlAction extends Action2 {
mnemonicTitle: localize({ key: 'miTipsAndTricks', comment: ['&& denotes a mnemonic'] }, "Tips and Tri&&cks"),
original: 'Tips and Tricks'
},
- category: CATEGORIES.Help,
+ category: Categories.Help,
f1: true,
menu: {
id: MenuId.MenubarHelpMenu,
@@ -134,7 +134,7 @@ class OpenDocumentationUrlAction extends Action2 {
mnemonicTitle: localize({ key: 'miDocumentation', comment: ['&& denotes a mnemonic'] }, "&&Documentation"),
original: 'Documentation'
},
- category: CATEGORIES.Help,
+ category: Categories.Help,
f1: true,
menu: {
id: MenuId.MenubarHelpMenu,
@@ -163,7 +163,7 @@ class OpenNewsletterSignupUrlAction extends Action2 {
super({
id: OpenNewsletterSignupUrlAction.ID,
title: { value: localize('newsletterSignup', "Signup for the VS Code Newsletter"), original: 'Signup for the VS Code Newsletter' },
- category: CATEGORIES.Help,
+ category: Categories.Help,
f1: true
});
}
@@ -192,7 +192,7 @@ class OpenTwitterUrlAction extends Action2 {
mnemonicTitle: localize({ key: 'miTwitter', comment: ['&& denotes a mnemonic'] }, "&&Join Us on Twitter"),
original: 'Join Us on Twitter'
},
- category: CATEGORIES.Help,
+ category: Categories.Help,
f1: true,
menu: {
id: MenuId.MenubarHelpMenu,
@@ -225,7 +225,7 @@ class OpenRequestFeatureUrlAction extends Action2 {
mnemonicTitle: localize({ key: 'miUserVoice', comment: ['&& denotes a mnemonic'] }, "&&Search Feature Requests"),
original: 'Search Feature Requests'
},
- category: CATEGORIES.Help,
+ category: Categories.Help,
f1: true,
menu: {
id: MenuId.MenubarHelpMenu,
@@ -258,7 +258,7 @@ class OpenLicenseUrlAction extends Action2 {
mnemonicTitle: localize({ key: 'miLicense', comment: ['&& denotes a mnemonic'] }, "View &&License"),
original: 'View License'
},
- category: CATEGORIES.Help,
+ category: Categories.Help,
f1: true,
menu: {
id: MenuId.MenubarHelpMenu,
@@ -296,7 +296,7 @@ class OpenPrivacyStatementUrlAction extends Action2 {
mnemonicTitle: localize({ key: 'miPrivacyStatement', comment: ['&& denotes a mnemonic'] }, "Privac&&y Statement"),
original: 'Privacy Statement'
},
- category: CATEGORIES.Help,
+ category: Categories.Help,
f1: true,
menu: {
id: MenuId.MenubarHelpMenu,
diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts
index 89651caa991..61f8d64c69f 100644
--- a/src/vs/workbench/browser/actions/layoutActions.ts
+++ b/src/vs/workbench/browser/actions/layoutActions.ts
@@ -6,7 +6,7 @@
import { localize } from 'vs/nls';
import Severity from 'vs/base/common/severity';
import { MenuId, MenuRegistry, registerAction2, Action2 } from 'vs/platform/actions/common/actions';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkbenchLayoutService, Parts, Position, positionToString } from 'vs/workbench/services/layout/browser/layoutService';
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -58,7 +58,7 @@ registerAction2(class extends Action2 {
super({
id: 'workbench.action.closeSidebar',
title: { value: localize('closeSidebar', "Close Primary Side Bar"), original: 'Close Primary Side Bar' },
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true
});
}
@@ -84,7 +84,7 @@ export class ToggleActivityBarVisibilityAction extends Action2 {
mnemonicTitle: localize({ key: 'miActivityBar', comment: ['&& denotes a mnemonic'] }, "&&Activity Bar"),
original: 'Toggle Activity Bar Visibility'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true,
toggled: ContextKeyExpr.equals('config.workbench.activityBar.visible', true),
menu: [{
@@ -120,7 +120,7 @@ registerAction2(class extends Action2 {
mnemonicTitle: localize({ key: 'miToggleCenteredLayout', comment: ['&& denotes a mnemonic'] }, "&&Centered Layout"),
original: 'Toggle Centered Layout'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true,
toggled: IsCenteredLayoutContext,
menu: [{
@@ -201,7 +201,7 @@ export class ToggleSidebarPositionAction extends Action2 {
super({
id: ToggleSidebarPositionAction.ID,
title: { value: localize('toggleSidebarPosition', "Toggle Primary Side Bar Position"), original: 'Toggle Primary Side Bar Position' },
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true
});
}
@@ -329,7 +329,7 @@ registerAction2(class extends Action2 {
mnemonicTitle: localize({ key: 'miShowEditorArea', comment: ['&& denotes a mnemonic'] }, "Show &&Editor Area"),
original: 'Toggle Editor Area Visibility'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true,
toggled: EditorAreaVisibleContext,
// the workbench grid currently prevents us from supporting panel maximization with non-center panel alignment
@@ -359,7 +359,7 @@ class ToggleSidebarVisibilityAction extends Action2 {
super({
id: ToggleSidebarVisibilityAction.ID,
title: { value: localize('toggleSidebar', "Toggle Primary Side Bar Visibility"), original: 'Toggle Primary Side Bar Visibility' },
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true,
keybinding: {
weight: KeybindingWeight.WorkbenchContrib,
@@ -467,7 +467,7 @@ export class ToggleStatusbarVisibilityAction extends Action2 {
mnemonicTitle: localize({ key: 'miStatusbar', comment: ['&& denotes a mnemonic'] }, "S&&tatus Bar"),
original: 'Toggle Status Bar Visibility'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true,
toggled: ContextKeyExpr.equals('config.workbench.statusBar.visible', true),
menu: [{
@@ -502,7 +502,7 @@ registerAction2(class extends Action2 {
value: localize('toggleTabs', "Toggle Tab Visibility"),
original: 'Toggle Tab Visibility'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true
});
}
@@ -529,7 +529,7 @@ registerAction2(class extends Action2 {
mnemonicTitle: localize('miToggleZenMode', "Zen Mode"),
original: 'Toggle Zen Mode'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true,
keybinding: {
weight: KeybindingWeight.WorkbenchContrib,
@@ -576,7 +576,7 @@ if (isWindows || isLinux || isWeb) {
mnemonicTitle: localize({ key: 'miMenuBar', comment: ['&& denotes a mnemonic'] }, "Menu &&Bar"),
original: 'Toggle Menu Bar'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true,
toggled: ContextKeyExpr.and(IsMacNativeContext.toNegated(), ContextKeyExpr.notEquals('config.window.menuBarVisibility', 'hidden'), ContextKeyExpr.notEquals('config.window.menuBarVisibility', 'toggle'), ContextKeyExpr.notEquals('config.window.menuBarVisibility', 'compact')),
menu: [{
@@ -614,7 +614,7 @@ registerAction2(class extends Action2 {
value: localize('resetViewLocations', "Reset View Locations"),
original: 'Reset View Locations'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true
});
}
@@ -635,7 +635,7 @@ registerAction2(class extends Action2 {
value: localize('moveView', "Move View"),
original: 'Move View'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true
});
}
@@ -780,7 +780,7 @@ class MoveFocusedViewAction extends Action2 {
value: localize('moveFocusedView', "Move Focused View"),
original: 'Move Focused View'
},
- category: CATEGORIES.View,
+ category: Categories.View,
precondition: FocusedViewContext.notEqualsTo(''),
f1: true
});
@@ -939,7 +939,7 @@ registerAction2(class extends Action2 {
value: localize('resetFocusedViewLocation', "Reset Focused View Location"),
original: 'Reset Focused View Location'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true,
precondition: FocusedViewContext.notEqualsTo('')
});
diff --git a/src/vs/workbench/browser/actions/navigationActions.ts b/src/vs/workbench/browser/actions/navigationActions.ts
index 86fca131e3f..9c3c8e0b1c1 100644
--- a/src/vs/workbench/browser/actions/navigationActions.ts
+++ b/src/vs/workbench/browser/actions/navigationActions.ts
@@ -9,7 +9,8 @@ import { Action } from 'vs/base/common/actions';
import { IEditorGroupsService, GroupDirection, GroupLocation, IFindGroupScope } from 'vs/workbench/services/editor/common/editorGroupsService';
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
-import { IWorkbenchActionRegistry, Extensions, CATEGORIES } from 'vs/workbench/common/actions';
+import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { Direction } from 'vs/base/browser/ui/grid/grid';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
@@ -312,9 +313,9 @@ export class FocusPreviousPart extends Action {
const actionsRegistry = Registry.as(Extensions.WorkbenchActions);
-actionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateUpAction, undefined), 'View: Navigate to the View Above', CATEGORIES.View.value);
-actionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateDownAction, undefined), 'View: Navigate to the View Below', CATEGORIES.View.value);
-actionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateLeftAction, undefined), 'View: Navigate to the View on the Left', CATEGORIES.View.value);
-actionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateRightAction, undefined), 'View: Navigate to the View on the Right', CATEGORIES.View.value);
-actionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(FocusNextPart, { primary: KeyCode.F6 }), 'View: Focus Next Part', CATEGORIES.View.value);
-actionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(FocusPreviousPart, { primary: KeyMod.Shift | KeyCode.F6 }), 'View: Focus Previous Part', CATEGORIES.View.value);
+actionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateUpAction, undefined), 'View: Navigate to the View Above', Categories.View.value);
+actionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateDownAction, undefined), 'View: Navigate to the View Below', Categories.View.value);
+actionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateLeftAction, undefined), 'View: Navigate to the View on the Left', Categories.View.value);
+actionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateRightAction, undefined), 'View: Navigate to the View on the Right', Categories.View.value);
+actionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(FocusNextPart, { primary: KeyCode.F6 }), 'View: Focus Next Part', Categories.View.value);
+actionsRegistry.registerWorkbenchAction(SyncActionDescriptor.from(FocusPreviousPart, { primary: KeyMod.Shift | KeyCode.F6 }), 'View: Focus Previous Part', Categories.View.value);
diff --git a/src/vs/workbench/browser/actions/textInputActions.ts b/src/vs/workbench/browser/actions/textInputActions.ts
index 993f595d69e..60dad795312 100644
--- a/src/vs/workbench/browser/actions/textInputActions.ts
+++ b/src/vs/workbench/browser/actions/textInputActions.ts
@@ -99,4 +99,4 @@ export class TextInputActionsProvider extends Disposable implements IWorkbenchCo
}
}
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(TextInputActionsProvider, 'TextInputActionsProvider', LifecyclePhase.Ready);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(TextInputActionsProvider, LifecyclePhase.Ready);
diff --git a/src/vs/workbench/browser/actions/windowActions.ts b/src/vs/workbench/browser/actions/windowActions.ts
index 8858f514ec5..eaa2db307dd 100644
--- a/src/vs/workbench/browser/actions/windowActions.ts
+++ b/src/vs/workbench/browser/actions/windowActions.ts
@@ -10,7 +10,7 @@ import { MenuRegistry, MenuId, Action2, registerAction2, IAction2Options } from
import { KeyChord, KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { IsFullscreenContext } from 'vs/workbench/common/contextkeys';
import { IsMacNativeContext, IsDevelopmentContext, IsWebContext, IsIOSContext } from 'vs/platform/contextkey/common/contextkeys';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IQuickInputButton, IQuickInputService, IQuickPickSeparator, IKeyMods, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
import { IWorkspaceContextService, IWorkspaceIdentifier } from 'vs/platform/workspace/common/workspace';
@@ -289,7 +289,7 @@ class ToggleFullScreenAction extends Action2 {
mnemonicTitle: localize({ key: 'miToggleFullScreen', comment: ['&& denotes a mnemonic'] }, "&&Full Screen"),
original: 'Toggle Full Screen'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true,
keybinding: {
weight: KeybindingWeight.WorkbenchContrib,
@@ -323,7 +323,7 @@ export class ReloadWindowAction extends Action2 {
super({
id: ReloadWindowAction.ID,
title: { value: localize('reloadWindow', "Reload Window"), original: 'Reload Window' },
- category: CATEGORIES.Developer,
+ category: Categories.Developer,
f1: true,
keybinding: {
weight: KeybindingWeight.WorkbenchContrib + 50,
@@ -350,7 +350,7 @@ class ShowAboutDialogAction extends Action2 {
mnemonicTitle: localize({ key: 'miAbout', comment: ['&& denotes a mnemonic'] }, "&&About"),
original: 'About'
},
- category: CATEGORIES.Help,
+ category: Categories.Help,
f1: true,
menu: {
id: MenuId.MenubarHelpMenu,
diff --git a/src/vs/workbench/browser/codeeditor.ts b/src/vs/workbench/browser/codeeditor.ts
index 00be0866e3e..3a77af1f995 100644
--- a/src/vs/workbench/browser/codeeditor.ts
+++ b/src/vs/workbench/browser/codeeditor.ts
@@ -26,6 +26,7 @@ import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IAction } from 'vs/base/common/actions';
+import { EmbeddedCodeEditorWidget } from 'vs/editor/browser/widget/embeddedCodeEditorWidget';
export interface IRangeHighlightDecoration {
resource: URI;
@@ -224,28 +225,31 @@ export class FloatingClickMenu extends Disposable implements IEditorContribution
) {
super();
- const menu = menuService.createMenu(MenuId.EditorContent, contextKeyService);
- const menuDisposables = new DisposableStore();
- const renderMenuAsFloatingClickBtn = () => {
- menuDisposables.clear();
- if (!editor.hasModel() || editor.getOption(EditorOption.inDiffEditor)) {
- return;
- }
- const actions: IAction[] = [];
- createAndFillInActionBarActions(menu, { renderShortTitle: true, shouldForwardArgs: true }, actions);
- if (actions.length === 0) {
- return;
- }
- // todo@jrieken find a way to handle N actions, like showing a context menu
- const [first] = actions;
- const widget = instantiationService.createInstance(FloatingClickWidget, editor, first.label, first.id);
- menuDisposables.add(widget);
- menuDisposables.add(widget.onClick(() => first.run(editor.getModel().uri)));
- widget.render();
- };
- this._store.add(menu);
- this._store.add(menuDisposables);
- this._store.add(menu.onDidChange(renderMenuAsFloatingClickBtn));
- renderMenuAsFloatingClickBtn();
+ // DISABLED for embedded editors. In the future we can use a different MenuId for embedded editors
+ if (!(editor instanceof EmbeddedCodeEditorWidget)) {
+ const menu = menuService.createMenu(MenuId.EditorContent, contextKeyService);
+ const menuDisposables = new DisposableStore();
+ const renderMenuAsFloatingClickBtn = () => {
+ menuDisposables.clear();
+ if (!editor.hasModel() || editor.getOption(EditorOption.inDiffEditor)) {
+ return;
+ }
+ const actions: IAction[] = [];
+ createAndFillInActionBarActions(menu, { renderShortTitle: true, shouldForwardArgs: true }, actions);
+ if (actions.length === 0) {
+ return;
+ }
+ // todo@jrieken find a way to handle N actions, like showing a context menu
+ const [first] = actions;
+ const widget = instantiationService.createInstance(FloatingClickWidget, editor, first.label, first.id);
+ menuDisposables.add(widget);
+ menuDisposables.add(widget.onClick(() => first.run(editor.getModel().uri)));
+ widget.render();
+ };
+ this._store.add(menu);
+ this._store.add(menuDisposables);
+ this._store.add(menu.onDidChange(renderMenuAsFloatingClickBtn));
+ renderMenuAsFloatingClickBtn();
+ }
}
}
diff --git a/src/vs/workbench/browser/composite.ts b/src/vs/workbench/browser/composite.ts
index a619fe25a1f..ca2f9cdf638 100644
--- a/src/vs/workbench/browser/composite.ts
+++ b/src/vs/workbench/browser/composite.ts
@@ -15,6 +15,7 @@ import { IStorageService } from 'vs/platform/storage/common/storage';
import { Disposable } from 'vs/base/common/lifecycle';
import { assertIsDefined } from 'vs/base/common/types';
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
+import { MenuId } from 'vs/platform/actions/common/actions';
/**
* Composites are layed out in the sidebar and panel part of the workbench. At a time only one composite
@@ -161,6 +162,15 @@ export abstract class Composite extends Component implements IComposite {
super.updateStyles();
}
+
+ /**
+ *
+ * @returns the action runner for this composite
+ */
+ getMenuIds(): readonly MenuId[] {
+ return [];
+ }
+
/**
* Returns an array of actions to show in the action bar of the composite.
*/
diff --git a/src/vs/workbench/browser/contextkeys.ts b/src/vs/workbench/browser/contextkeys.ts
index 2ac8feeba1f..08c286d1e84 100644
--- a/src/vs/workbench/browser/contextkeys.ts
+++ b/src/vs/workbench/browser/contextkeys.ts
@@ -6,7 +6,7 @@
import { Event } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
-import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext } from 'vs/platform/contextkey/common/contextkeys';
+import { InputFocusedContext, IsMacContext, IsLinuxContext, IsWindowsContext, IsWebContext, IsMacNativeContext, IsDevelopmentContext, IsIOSContext, ProductQualityContext, IsMobileContext } from 'vs/platform/contextkey/common/contextkeys';
import { SplitEditorsVertically, InEditorZenModeContext, ActiveEditorCanRevertContext, ActiveEditorGroupLockedContext, ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext, AuxiliaryBarVisibleContext, SideBarVisibleContext, PanelAlignmentContext, PanelMaximizedContext, PanelVisibleContext, ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, EditorTabsVisibleContext, IsCenteredLayoutContext, ActiveEditorGroupIndexContext, ActiveEditorGroupLastContext, ActiveEditorReadonlyContext, EditorAreaVisibleContext, ActiveEditorAvailableEditorIdsContext, DirtyWorkingCopiesContext, EmptyWorkspaceSupportContext, EnterMultiRootWorkspaceSupportContext, HasWebFileSystemAccess, IsFullscreenContext, OpenFolderWorkspaceSupportContext, RemoteNameContext, VirtualWorkspaceContext, WorkbenchStateContext, WorkspaceFolderCountContext, PanelPositionContext, TemporaryWorkspaceContext } from 'vs/workbench/common/contextkeys';
import { TEXT_DIFF_EDITOR_ID, EditorInputCapabilities, SIDE_BY_SIDE_EDITOR_ID, DEFAULT_EDITOR_ASSOCIATION } from 'vs/workbench/common/editor';
import { trackFocus, addDisposableListener, EventType } from 'vs/base/browser/dom';
@@ -96,6 +96,7 @@ export class WorkbenchContextKeysHandler extends Disposable {
IsWebContext.bindTo(this.contextKeyService);
IsMacNativeContext.bindTo(this.contextKeyService);
IsIOSContext.bindTo(this.contextKeyService);
+ IsMobileContext.bindTo(this.contextKeyService);
RemoteNameContext.bindTo(this.contextKeyService).set(getRemoteName(this.environmentService.remoteAuthority) || '');
diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts
index ea93a14b908..8d367d84589 100644
--- a/src/vs/workbench/browser/layout.ts
+++ b/src/vs/workbench/browser/layout.ts
@@ -1061,11 +1061,6 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
return true;
}
- // with the command center enabled, we should always show
- if (this.configurationService.getValue('window.commandCenter')) {
- return true;
- }
-
// remaining behavior is based on menubar visibility
switch (getMenuBarVisibility(this.configurationService)) {
case 'classic':
diff --git a/src/vs/workbench/browser/panecomposite.ts b/src/vs/workbench/browser/panecomposite.ts
index 21230d84325..246e899675a 100644
--- a/src/vs/workbench/browser/panecomposite.ts
+++ b/src/vs/workbench/browser/panecomposite.ts
@@ -10,7 +10,7 @@ import { URI } from 'vs/base/common/uri';
import { Dimension } from 'vs/base/browser/dom';
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
import { IAction, Separator } from 'vs/base/common/actions';
-import { SubmenuItemAction } from 'vs/platform/actions/common/actions';
+import { MenuId, SubmenuItemAction } from 'vs/platform/actions/common/actions';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -73,6 +73,17 @@ export abstract class PaneComposite extends Composite implements IPaneComposite
return this.viewPaneContainer?.menuActions?.getContextMenuActions() ?? [];
}
+ override getMenuIds(): MenuId[] {
+ const result: MenuId[] = [];
+ if (this.viewPaneContainer?.menuActions) {
+ result.push(this.viewPaneContainer.menuActions.menuId);
+ if (this.viewPaneContainer.isViewMergedWithContainer()) {
+ result.push(this.viewPaneContainer.panes[0].menuActions.menuId);
+ }
+ }
+ return result;
+ }
+
override getActions(): readonly IAction[] {
const result = [];
if (this.viewPaneContainer?.menuActions) {
diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts
index bee1974abd0..d4db825ca72 100644
--- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts
+++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts
@@ -17,9 +17,9 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { activeContrastBorder, focusBorder } from 'vs/platform/theme/common/colorRegistry';
import { IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService';
import { ActivityAction, ActivityActionViewItem, IActivityActionViewItemOptions, IActivityHoverOptions, ICompositeBar, ICompositeBarColors, ToggleCompositePinnedAction } from 'vs/workbench/browser/parts/compositeBarActions';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { IActivity } from 'vs/workbench/common/activity';
-import { ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_ACTIVE_FOCUS_BORDER, ACTIVITY_BAR_ACTIVE_BACKGROUND, ACTIVITY_BAR_SETTINGS_PROFILE_HOVER_FOREGROUND } from 'vs/workbench/common/theme';
+import { ACTIVITY_BAR_FOREGROUND, ACTIVITY_BAR_ACTIVE_BORDER, ACTIVITY_BAR_ACTIVE_FOCUS_BORDER, ACTIVITY_BAR_ACTIVE_BACKGROUND, ACTIVITY_BAR_SETTINGS_PROFILE_BACKGROUND, ACTIVITY_BAR_SETTINGS_PROFILE_HOVER_FOREGROUND } from 'vs/workbench/common/theme';
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
@@ -37,8 +37,7 @@ import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/b
import { ViewContainerLocation } from 'vs/workbench/common/views';
import { IPaneCompositePart } from 'vs/workbench/browser/parts/paneCompositePart';
import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
-import { ICommandService } from 'vs/platform/commands/common/commands';
-import { IUserDataProfileService, MANAGE_PROFILES_ACTION_ID, PROFILES_CATEGORY } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
+import { IUserDataProfileService, ManageProfilesSubMenu, PROFILES_CATEGORY } from 'vs/workbench/services/userDataProfile/common/userDataProfile';
export class ViewContainerActivityAction extends ActivityAction {
@@ -186,6 +185,7 @@ class MenuActivityActionViewItem extends AbstractGlobalActivityActionViewItem {
private readonly menuId: MenuId,
action: ActivityAction,
contextMenuActionsProvider: () => IAction[],
+ icon: boolean,
colors: (theme: IColorTheme) => ICompositeBarColors,
hoverOptions: IActivityHoverOptions,
@IThemeService themeService: IThemeService,
@@ -197,7 +197,7 @@ class MenuActivityActionViewItem extends AbstractGlobalActivityActionViewItem {
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
@IKeybindingService keybindingService: IKeybindingService,
) {
- super(action, contextMenuActionsProvider, { draggable: false, colors, icon: true, hasPopup: true, hoverOptions }, themeService, hoverService, menuService, contextMenuService, contextKeyService, configurationService, environmentService, keybindingService);
+ super(action, contextMenuActionsProvider, { draggable: false, colors, icon, hasPopup: true, hoverOptions }, themeService, hoverService, menuService, contextMenuService, contextKeyService, configurationService, environmentService, keybindingService);
}
protected async run(): Promise {
@@ -245,7 +245,7 @@ export class AccountsActivityActionViewItem extends MenuActivityActionViewItem {
@IKeybindingService keybindingService: IKeybindingService,
@ICredentialsService private readonly credentialsService: ICredentialsService,
) {
- super(MenuId.AccountsContext, action, contextMenuActionsProvider, colors, activityHoverOptions, themeService, hoverService, menuService, contextMenuService, contextKeyService, configurationService, environmentService, keybindingService);
+ super(MenuId.AccountsContext, action, contextMenuActionsProvider, true, colors, activityHoverOptions, themeService, hoverService, menuService, contextMenuService, contextKeyService, configurationService, environmentService, keybindingService);
}
protected override async resolveMainMenuActions(accountsMenu: IMenu, disposables: DisposableStore): Promise {
@@ -340,7 +340,7 @@ export interface IProfileActivity extends IActivity {
readonly icon: boolean;
}
-export class ProfilesActivityActionViewItem extends AbstractGlobalActivityActionViewItem {
+export class ProfilesActivityActionViewItem extends MenuActivityActionViewItem {
static readonly PROFILES_VISIBILITY_PREFERENCE_KEY = 'workbench.activity.showProfiles';
@@ -350,7 +350,6 @@ export class ProfilesActivityActionViewItem extends AbstractGlobalActivityAction
colors: (theme: IColorTheme) => ICompositeBarColors,
hoverOptions: IActivityHoverOptions,
@IUserDataProfileService private readonly userDataProfileService: IUserDataProfileService,
- @ICommandService private readonly commandService: ICommandService,
@IStorageService private readonly storageService: IStorageService,
@IThemeService themeService: IThemeService,
@IHoverService hoverService: IHoverService,
@@ -361,11 +360,12 @@ export class ProfilesActivityActionViewItem extends AbstractGlobalActivityAction
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
@IKeybindingService keybindingService: IKeybindingService,
) {
- super(action, contextMenuActionsProvider, { draggable: false, colors, icon: (action.activity).icon, hasPopup: true, hoverOptions }, themeService, hoverService, menuService, contextMenuService, contextKeyService, configurationService, environmentService, keybindingService);
+ super(ManageProfilesSubMenu, action, contextMenuActionsProvider, (action.activity).icon, colors, hoverOptions, themeService, hoverService, menuService, contextMenuService, contextKeyService, configurationService, environmentService, keybindingService);
}
- protected run(): Promise {
- return this.commandService.executeCommand(MANAGE_PROFILES_ACTION_ID);
+ override render(container: HTMLElement): void {
+ super.render(container);
+ this.container.classList.add('profile-activity-item');
}
protected override async resolveContextMenuActions(disposables: DisposableStore): Promise {
@@ -401,7 +401,7 @@ export class GlobalActivityActionViewItem extends MenuActivityActionViewItem {
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService,
@IKeybindingService keybindingService: IKeybindingService,
) {
- super(MenuId.GlobalActivity, action, contextMenuActionsProvider, colors, activityHoverOptions, themeService, hoverService, menuService, contextMenuService, contextKeyService, configurationService, environmentService, keybindingService);
+ super(MenuId.GlobalActivity, action, contextMenuActionsProvider, true, colors, activityHoverOptions, themeService, hoverService, menuService, contextMenuService, contextKeyService, configurationService, environmentService, keybindingService);
}
}
@@ -454,7 +454,7 @@ registerAction2(
super({
id: 'workbench.action.previousSideBarView',
title: { value: localize('previousSideBarView', "Previous Primary Side Bar View"), original: 'Previous Primary Side Bar View' },
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true
}, -1);
}
@@ -467,7 +467,7 @@ registerAction2(
super({
id: 'workbench.action.nextSideBarView',
title: { value: localize('nextSideBarView', "Next Primary Side Bar View"), original: 'Next Primary Side Bar View' },
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true
}, 1);
}
@@ -480,7 +480,7 @@ registerAction2(
super({
id: 'workbench.action.focusActivityBar',
title: { value: localize('focusActivityBar', "Focus Activity Bar"), original: 'Focus Activity Bar' },
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true
});
}
@@ -509,13 +509,24 @@ registerThemingParticipant((theme, collector) => {
`);
}
- const activityBarSettingsProfileHoveFgColor = theme.getColor(ACTIVITY_BAR_SETTINGS_PROFILE_HOVER_FOREGROUND);
- if (activityBarSettingsProfileHoveFgColor) {
+ const activityBarSettingsProfileBgColor = theme.getColor(ACTIVITY_BAR_SETTINGS_PROFILE_BACKGROUND);
+ if (activityBarSettingsProfileBgColor) {
+ collector.addRule(`
+ .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item .action-label.profile-activity-item,
+ .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item .action-label.profile-activity-item,
+ .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item .action-label.profile-activity-item {
+ background-color: ${activityBarSettingsProfileBgColor} !important;
+ }
+ `);
+ }
+
+ const activityBarSettingsProfileHoverFgColor = theme.getColor(ACTIVITY_BAR_SETTINGS_PROFILE_HOVER_FOREGROUND);
+ if (activityBarSettingsProfileHoverFgColor) {
collector.addRule(`
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.active .action-label.profile-activity-item,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:focus .action-label.profile-activity-item,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item:hover .action-label.profile-activity-item {
- color: ${activityBarSettingsProfileHoveFgColor} !important;
+ color: ${activityBarSettingsProfileHoverFgColor} !important;
}
`);
}
@@ -567,6 +578,10 @@ registerThemingParticipant((theme, collector) => {
z-index: 1;
}
+ .monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.profile-activity-item:before {
+ top: -6px;
+ }
+
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.active:before,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.active:hover:before,
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-item.checked:before,
diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts
index 1981ce23cc9..6e51d7a9257 100644
--- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts
+++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts
@@ -1064,7 +1064,7 @@ export class ActivitybarPart extends Part implements IPaneCompositeSelectorPart
}
private get profilesVisibilityPreference(): boolean {
- return this.userDataProfilesService.profiles.length > 1 && !this.userDataProfileService.currentProfile.isDefault && this.storageService.getBoolean(ProfilesActivityActionViewItem.PROFILES_VISIBILITY_PREFERENCE_KEY, StorageScope.PROFILE, true);
+ return this.storageService.getBoolean(ProfilesActivityActionViewItem.PROFILES_VISIBILITY_PREFERENCE_KEY, StorageScope.PROFILE, this.userDataProfilesService.profiles.length > 1);
}
private set profilesVisibilityPreference(value: boolean) {
diff --git a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css
index 292c36545bc..a7b7e543420 100644
--- a/src/vs/workbench/browser/parts/activitybar/media/activityaction.css
+++ b/src/vs/workbench/browser/parts/activitybar/media/activityaction.css
@@ -178,14 +178,14 @@
.monaco-workbench .activitybar > .content :not(.monaco-menu) > .monaco-action-bar .action-label.profile-activity-item {
height: 20px;
- width: 28px;
- margin: 9px;
+ width: 32px;
+ margin: 14px 8px;
padding: 0px;
justify-content: center;
align-items: center;
- font-size: 12px;
- line-height: 16px;
- border: 1.5px solid;
+ font-size: 11px;
+ font-weight: 600;
+ border-radius: 10px;
}
/* Right aligned */
diff --git a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarActions.ts b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarActions.ts
index 4603210c471..0a8890728c3 100644
--- a/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarActions.ts
+++ b/src/vs/workbench/browser/parts/auxiliarybar/auxiliaryBarActions.ts
@@ -10,7 +10,8 @@ import { MenuId, MenuRegistry, SyncActionDescriptor } from 'vs/platform/actions/
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { Registry } from 'vs/platform/registry/common/platform';
import { registerIcon } from 'vs/platform/theme/common/iconRegistry';
-import { CATEGORIES, Extensions as WorkbenchExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions';
+import { Extensions as WorkbenchExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { AuxiliaryBarVisibleContext } from 'vs/workbench/common/contextkeys';
import { ViewContainerLocation, ViewContainerLocationToString } from 'vs/workbench/common/views';
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
@@ -134,5 +135,5 @@ MenuRegistry.appendMenuItems([
]);
const actionRegistry = Registry.as(WorkbenchExtensions.WorkbenchActions);
-actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleAuxiliaryBarAction), 'View: Toggle Secondary Side Bar Visibility', CATEGORIES.View.value);
-actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(FocusAuxiliaryBarAction), 'View: Focus into Secondary Side Bar', CATEGORIES.View.value);
+actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleAuxiliaryBarAction), 'View: Toggle Secondary Side Bar Visibility', Categories.View.value);
+actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(FocusAuxiliaryBarAction), 'View: Focus into Secondary Side Bar', Categories.View.value);
diff --git a/src/vs/workbench/browser/parts/banner/bannerPart.ts b/src/vs/workbench/browser/parts/banner/bannerPart.ts
index 667296666ae..0bb128fd96e 100644
--- a/src/vs/workbench/browser/parts/banner/bannerPart.ts
+++ b/src/vs/workbench/browser/parts/banner/bannerPart.ts
@@ -22,7 +22,7 @@ import { IBannerItem, IBannerService } from 'vs/workbench/services/banner/browse
import { MarkdownRenderer } from 'vs/editor/contrib/markdownRenderer/browser/markdownRenderer';
import { BANNER_BACKGROUND, BANNER_FOREGROUND, BANNER_ICON_FOREGROUND } from 'vs/workbench/common/theme';
import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { KeyCode } from 'vs/base/common/keyCodes';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
@@ -318,7 +318,7 @@ class FocusBannerAction extends Action2 {
super({
id: FocusBannerAction.ID,
title: { value: FocusBannerAction.LABEL, original: 'Focus Banner' },
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true
});
}
diff --git a/src/vs/workbench/browser/parts/compositePart.ts b/src/vs/workbench/browser/parts/compositePart.ts
index af7db9400e1..18a4d42ea90 100644
--- a/src/vs/workbench/browser/parts/compositePart.ts
+++ b/src/vs/workbench/browser/parts/compositePart.ts
@@ -329,6 +329,7 @@ export abstract class CompositePart extends Part {
private collectCompositeActions(composite?: Composite): () => void {
// From Composite
+ const menuIds = composite?.getMenuIds();
const primaryActions: IAction[] = composite?.getActions().slice(0) || [];
const secondaryActions: IAction[] = composite?.getSecondaryActions().slice(0) || [];
@@ -337,7 +338,7 @@ export abstract class CompositePart extends Part {
toolBar.context = this.actionsContextProvider();
// Return fn to set into toolbar
- return () => toolBar.setActions(prepareActions(primaryActions), prepareActions(secondaryActions));
+ return () => toolBar.setActions(prepareActions(primaryActions), prepareActions(secondaryActions), menuIds);
}
protected getActiveComposite(): IComposite | undefined {
diff --git a/src/vs/workbench/browser/parts/dialogs/dialog.web.contribution.ts b/src/vs/workbench/browser/parts/dialogs/dialog.web.contribution.ts
index 2781c45869f..4fa42a97578 100644
--- a/src/vs/workbench/browser/parts/dialogs/dialog.web.contribution.ts
+++ b/src/vs/workbench/browser/parts/dialogs/dialog.web.contribution.ts
@@ -75,4 +75,4 @@ export class DialogHandlerContribution extends Disposable implements IWorkbenchC
}
const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench);
-workbenchRegistry.registerWorkbenchContribution(DialogHandlerContribution, 'DialogHandlerContribution', LifecyclePhase.Starting);
+workbenchRegistry.registerWorkbenchContribution(DialogHandlerContribution, LifecyclePhase.Starting);
diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbs.ts b/src/vs/workbench/browser/parts/editor/breadcrumbs.ts
index f2a44d8b1db..af5bdc2b61f 100644
--- a/src/vs/workbench/browser/parts/editor/breadcrumbs.ts
+++ b/src/vs/workbench/browser/parts/editor/breadcrumbs.ts
@@ -10,7 +10,7 @@ import { IDisposable } from 'vs/base/common/lifecycle';
import { localize } from 'vs/nls';
import { IConfigurationOverrides, IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { Extensions, IConfigurationRegistry, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { Registry } from 'vs/platform/registry/common/platform';
import { GroupIdentifier, IEditorPartOptions } from 'vs/workbench/common/editor';
@@ -48,7 +48,7 @@ export class BreadcrumbsService implements IBreadcrumbsService {
}
}
-registerSingleton(IBreadcrumbsService, BreadcrumbsService, true);
+registerSingleton(IBreadcrumbsService, BreadcrumbsService, InstantiationType.Delayed);
//#region config
diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts
index 120b7c0343a..657bea0cea4 100644
--- a/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts
+++ b/src/vs/workbench/browser/parts/editor/breadcrumbsControl.ts
@@ -36,7 +36,7 @@ import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editor
import { IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor';
import { PixelRatio } from 'vs/base/browser/browser';
import { ILabelService } from 'vs/platform/label/common/label';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { ITreeNode } from 'vs/base/browser/ui/tree/tree';
import { IOutline } from 'vs/workbench/services/outline/browser/outline';
import { registerIcon } from 'vs/platform/theme/common/iconRegistry';
@@ -504,15 +504,20 @@ registerAction2(class ToggleBreadcrumb extends Action2 {
id: 'breadcrumbs.toggle',
title: {
value: localize('cmd.toggle', "Toggle Breadcrumbs"),
- mnemonicTitle: localize('miBreadcrumbs', "&&Breadcrumbs"),
+ mnemonicTitle: localize('miBreadcrumbs', "Toggle &&Breadcrumbs"),
original: 'Toggle Breadcrumbs',
},
- category: CATEGORIES.View,
- toggled: ContextKeyExpr.equals('config.breadcrumbs.enabled', true),
+ category: Categories.View,
+ toggled: {
+ condition: ContextKeyExpr.equals('config.breadcrumbs.enabled', true),
+ title: localize('cmd.toggle2', "Breadcrumbs"),
+ mnemonicTitle: localize('miBreadcrumbs2', "&&Breadcrumbs")
+ },
menu: [
{ id: MenuId.CommandPalette },
{ id: MenuId.MenubarViewMenu, group: '5_editor', order: 3 },
- { id: MenuId.NotebookToolbar, group: 'notebookLayout', order: 2 }
+ { id: MenuId.NotebookToolbar, group: 'notebookLayout', order: 2 },
+ { id: MenuId.StickyScrollContext }
]
});
}
diff --git a/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts b/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts
index e6535720005..28894f417fe 100644
--- a/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts
+++ b/src/vs/workbench/browser/parts/editor/breadcrumbsPicker.ts
@@ -381,6 +381,7 @@ export class BreadcrumbsFilePicker extends BreadcrumbsPicker {
identityProvider: new FileIdentityProvider(),
keyboardNavigationLabelProvider: new FileNavigationLabelProvider(),
accessibilityProvider: this._instantiationService.createInstance(FileAccessibilityProvider),
+ showNotFoundMessage: false,
overrideStyles: {
listBackground: breadcrumbsPickerBackground
},
@@ -474,6 +475,7 @@ export class BreadcrumbsOutlinePicker extends BreadcrumbsPicker {
collapseByDefault: true,
expandOnlyOnTwistieClick: true,
multipleSelectionSupport: false,
+ showNotFoundMessage: false
}
);
}
diff --git a/src/vs/workbench/browser/parts/editor/editor.contribution.ts b/src/vs/workbench/browser/parts/editor/editor.contribution.ts
index 8651d5bfbe2..82ca36f22a6 100644
--- a/src/vs/workbench/browser/parts/editor/editor.contribution.ts
+++ b/src/vs/workbench/browser/parts/editor/editor.contribution.ts
@@ -22,7 +22,8 @@ import { TextResourceEditorInput } from 'vs/workbench/common/editor/textResource
import { TextDiffEditor } from 'vs/workbench/browser/parts/editor/textDiffEditor';
import { BinaryResourceDiffEditor } from 'vs/workbench/browser/parts/editor/binaryDiffEditor';
import { ChangeEncodingAction, ChangeEOLAction, ChangeLanguageAction, EditorStatus } from 'vs/workbench/browser/parts/editor/editorStatus';
-import { IWorkbenchActionRegistry, Extensions as ActionExtensions, CATEGORIES } from 'vs/workbench/common/actions';
+import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { SyncActionDescriptor, MenuRegistry, MenuId, IMenuItem, registerAction2 } from 'vs/platform/actions/common/actions';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
@@ -122,10 +123,10 @@ Registry.as(EditorExtensions.EditorFactory).registerEdit
//#region Workbench Contributions
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(EditorAutoSave, 'EditorAutoSave', LifecyclePhase.Ready);
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(EditorStatus, 'EditorStatus', LifecyclePhase.Ready);
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(UntitledTextEditorWorkingCopyEditorHandler, 'UntitledTextEditorWorkingCopyEditorHandler', LifecyclePhase.Ready);
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DynamicEditorConfigurations, 'DynamicEditorConfigurations', LifecyclePhase.Ready);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(EditorAutoSave, LifecyclePhase.Ready);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(EditorStatus, LifecyclePhase.Ready);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(UntitledTextEditorWorkingCopyEditorHandler, LifecyclePhase.Ready);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DynamicEditorConfigurations, LifecyclePhase.Ready);
registerEditorContribution(FloatingClickMenu.ID, FloatingClickMenu);
@@ -172,78 +173,78 @@ registry.registerWorkbenchAction(SyncActionDescriptor.from(ChangeEOLAction), 'Ch
registry.registerWorkbenchAction(SyncActionDescriptor.from(ChangeEncodingAction), 'Change File Encoding');
// Editor Management
-registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenNextEditor, { primary: KeyMod.CtrlCmd | KeyCode.PageDown, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.RightArrow, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.BracketRight] } }), 'View: Open Next Editor', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenPreviousEditor, { primary: KeyMod.CtrlCmd | KeyCode.PageUp, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.LeftArrow, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.BracketLeft] } }), 'View: Open Previous Editor', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenNextEditorInGroup, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.PageDown), mac: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.RightArrow) } }), 'View: Open Next Editor in Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenPreviousEditorInGroup, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.PageUp), mac: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.LeftArrow) } }), 'View: Open Previous Editor in Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenNextRecentlyUsedEditorAction), 'View: Open Next Recently Used Editor', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenPreviousRecentlyUsedEditorAction), 'View: Open Previous Recently Used Editor', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenNextRecentlyUsedEditorInGroupAction), 'View: Open Next Recently Used Editor In Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenPreviousRecentlyUsedEditorInGroupAction), 'View: Open Previous Recently Used Editor In Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenFirstEditorInGroup), 'View: Open First Editor in Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenLastEditorInGroup, { primary: KeyMod.Alt | KeyCode.Digit0, secondary: [KeyMod.CtrlCmd | KeyCode.Digit9], mac: { primary: KeyMod.WinCtrl | KeyCode.Digit0, secondary: [KeyMod.CtrlCmd | KeyCode.Digit9] } }), 'View: Open Last Editor in Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(ReopenClosedEditorAction, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyT }), 'View: Reopen Closed Editor', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(ShowAllEditorsByAppearanceAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyP), mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Tab } }), 'View: Show All Editors By Appearance', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(ShowAllEditorsByMostRecentlyUsedAction), 'View: Show All Editors By Most Recently Used', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(ShowEditorsInActiveGroupByMostRecentlyUsedAction), 'View: Show Editors in Active Group By Most Recently Used', CATEGORIES.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenNextEditor, { primary: KeyMod.CtrlCmd | KeyCode.PageDown, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.RightArrow, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.BracketRight] } }), 'View: Open Next Editor', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenPreviousEditor, { primary: KeyMod.CtrlCmd | KeyCode.PageUp, mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.LeftArrow, secondary: [KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.BracketLeft] } }), 'View: Open Previous Editor', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenNextEditorInGroup, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.PageDown), mac: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.RightArrow) } }), 'View: Open Next Editor in Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenPreviousEditorInGroup, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.PageUp), mac: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.LeftArrow) } }), 'View: Open Previous Editor in Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenNextRecentlyUsedEditorAction), 'View: Open Next Recently Used Editor', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenPreviousRecentlyUsedEditorAction), 'View: Open Previous Recently Used Editor', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenNextRecentlyUsedEditorInGroupAction), 'View: Open Next Recently Used Editor In Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenPreviousRecentlyUsedEditorInGroupAction), 'View: Open Previous Recently Used Editor In Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenFirstEditorInGroup), 'View: Open First Editor in Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(OpenLastEditorInGroup, { primary: KeyMod.Alt | KeyCode.Digit0, secondary: [KeyMod.CtrlCmd | KeyCode.Digit9], mac: { primary: KeyMod.WinCtrl | KeyCode.Digit0, secondary: [KeyMod.CtrlCmd | KeyCode.Digit9] } }), 'View: Open Last Editor in Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(ReopenClosedEditorAction, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyT }), 'View: Reopen Closed Editor', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(ShowAllEditorsByAppearanceAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyP), mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.Tab } }), 'View: Show All Editors By Appearance', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(ShowAllEditorsByMostRecentlyUsedAction), 'View: Show All Editors By Most Recently Used', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(ShowEditorsInActiveGroupByMostRecentlyUsedAction), 'View: Show Editors in Active Group By Most Recently Used', Categories.View.value);
registry.registerWorkbenchAction(SyncActionDescriptor.from(ClearRecentFilesAction), 'File: Clear Recently Opened', localize('file', "File"));
-registry.registerWorkbenchAction(SyncActionDescriptor.from(CloseAllEditorsAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyW) }), 'View: Close All Editors', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(CloseAllEditorGroupsAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyW) }), 'View: Close All Editor Groups', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(CloseLeftEditorsInGroupAction), 'View: Close Editors to the Left in Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(CloseEditorsInOtherGroupsAction), 'View: Close Editors in Other Groups', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(CloseEditorInAllGroupsAction), 'View: Close Editor in All Groups', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorAction, { primary: KeyMod.CtrlCmd | KeyCode.Backslash }), 'View: Split Editor', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorOrthogonalAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.Backslash) }), 'View: Split Editor Orthogonal', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorLeftAction), 'View: Split Editor Left', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorRightAction), 'View: Split Editor Right', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorUpAction), 'View: Split Editor Up', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorDownAction), 'View: Split Editor Down', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(JoinTwoGroupsAction), 'View: Join Editor Group with Next Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(JoinAllGroupsAction), 'View: Join All Editor Groups', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateBetweenGroupsAction), 'View: Navigate Between Editor Groups', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(ResetGroupSizesAction), 'View: Reset Editor Group Sizes', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleGroupSizesAction), 'View: Toggle Editor Group Sizes', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(MaximizeGroupAction), 'View: Maximize Editor Group and Hide Side Bars', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(MinimizeOtherGroupsAction), 'View: Maximize Editor Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorLeftInGroupAction, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.PageUp, mac: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.LeftArrow) } }), 'View: Move Editor Left', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorRightInGroupAction, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.PageDown, mac: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.RightArrow) } }), 'View: Move Editor Right', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveGroupLeftAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.LeftArrow) }), 'View: Move Editor Group Left', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveGroupRightAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.RightArrow) }), 'View: Move Editor Group Right', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveGroupUpAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.UpArrow) }), 'View: Move Editor Group Up', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveGroupDownAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.DownArrow) }), 'View: Move Editor Group Down', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(DuplicateGroupLeftAction), 'View: Duplicate Editor Group Left', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(DuplicateGroupRightAction), 'View: Duplicate Editor Group Right', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(DuplicateGroupUpAction), 'View: Duplicate Editor Group Up', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(DuplicateGroupDownAction), 'View: Duplicate Editor Group Down', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToPreviousGroupAction, { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.LeftArrow, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.LeftArrow } }), 'View: Move Editor into Previous Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToNextGroupAction, { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.RightArrow, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.RightArrow } }), 'View: Move Editor into Next Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToFirstGroupAction, { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.Digit1, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.Digit1 } }), 'View: Move Editor into First Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToLastGroupAction, { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.Digit9, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.Digit9 } }), 'View: Move Editor into Last Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToLeftGroupAction), 'View: Move Editor into Left Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToRightGroupAction), 'View: Move Editor into Right Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToAboveGroupAction), 'View: Move Editor into Group Above', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToBelowGroupAction), 'View: Move Editor into Group Below', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorToPreviousGroupAction), 'View: Split Editor into Previous Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorToNextGroupAction), 'View: Split Editor into Next Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorToFirstGroupAction), 'View: Split Editor into First Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorToLastGroupAction), 'View: Split Editor into Last Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorToLeftGroupAction), 'View: Split Editor into Left Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorToRightGroupAction), 'View: Split Editor into Right Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorToAboveGroupAction), 'View: Split Editor into Group Above', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorToBelowGroupAction), 'View: Split Editor into Group Below', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusActiveGroupAction), 'View: Focus Active Editor Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusFirstGroupAction, { primary: KeyMod.CtrlCmd | KeyCode.Digit1 }), 'View: Focus First Editor Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusLastGroupAction), 'View: Focus Last Editor Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusPreviousGroup), 'View: Focus Previous Editor Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusNextGroup), 'View: Focus Next Editor Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusLeftGroup, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.LeftArrow) }), 'View: Focus Left Editor Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusRightGroup, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.RightArrow) }), 'View: Focus Right Editor Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusAboveGroup, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.UpArrow) }), 'View: Focus Editor Group Above', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusBelowGroup, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.DownArrow) }), 'View: Focus Editor Group Below', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(NewEditorGroupLeftAction), 'View: New Editor Group to the Left', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(NewEditorGroupRightAction), 'View: New Editor Group to the Right', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(NewEditorGroupAboveAction), 'View: New Editor Group Above', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(NewEditorGroupBelowAction), 'View: New Editor Group Below', CATEGORIES.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(CloseAllEditorsAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.KeyW) }), 'View: Close All Editors', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(CloseAllEditorGroupsAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KeyW) }), 'View: Close All Editor Groups', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(CloseLeftEditorsInGroupAction), 'View: Close Editors to the Left in Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(CloseEditorsInOtherGroupsAction), 'View: Close Editors in Other Groups', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(CloseEditorInAllGroupsAction), 'View: Close Editor in All Groups', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorAction, { primary: KeyMod.CtrlCmd | KeyCode.Backslash }), 'View: Split Editor', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorOrthogonalAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.Backslash) }), 'View: Split Editor Orthogonal', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorLeftAction), 'View: Split Editor Left', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorRightAction), 'View: Split Editor Right', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorUpAction), 'View: Split Editor Up', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorDownAction), 'View: Split Editor Down', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(JoinTwoGroupsAction), 'View: Join Editor Group with Next Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(JoinAllGroupsAction), 'View: Join All Editor Groups', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateBetweenGroupsAction), 'View: Navigate Between Editor Groups', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(ResetGroupSizesAction), 'View: Reset Editor Group Sizes', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleGroupSizesAction), 'View: Toggle Editor Group Sizes', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(MaximizeGroupAction), 'View: Maximize Editor Group and Hide Side Bars', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(MinimizeOtherGroupsAction), 'View: Maximize Editor Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorLeftInGroupAction, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.PageUp, mac: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.LeftArrow) } }), 'View: Move Editor Left', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorRightInGroupAction, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.PageDown, mac: { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.RightArrow) } }), 'View: Move Editor Right', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveGroupLeftAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.LeftArrow) }), 'View: Move Editor Group Left', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveGroupRightAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.RightArrow) }), 'View: Move Editor Group Right', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveGroupUpAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.UpArrow) }), 'View: Move Editor Group Up', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveGroupDownAction, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyCode.DownArrow) }), 'View: Move Editor Group Down', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(DuplicateGroupLeftAction), 'View: Duplicate Editor Group Left', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(DuplicateGroupRightAction), 'View: Duplicate Editor Group Right', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(DuplicateGroupUpAction), 'View: Duplicate Editor Group Up', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(DuplicateGroupDownAction), 'View: Duplicate Editor Group Down', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToPreviousGroupAction, { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.LeftArrow, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.LeftArrow } }), 'View: Move Editor into Previous Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToNextGroupAction, { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.RightArrow, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.RightArrow } }), 'View: Move Editor into Next Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToFirstGroupAction, { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.Digit1, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.Digit1 } }), 'View: Move Editor into First Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToLastGroupAction, { primary: KeyMod.Shift | KeyMod.Alt | KeyCode.Digit9, mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.Digit9 } }), 'View: Move Editor into Last Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToLeftGroupAction), 'View: Move Editor into Left Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToRightGroupAction), 'View: Move Editor into Right Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToAboveGroupAction), 'View: Move Editor into Group Above', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveEditorToBelowGroupAction), 'View: Move Editor into Group Below', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorToPreviousGroupAction), 'View: Split Editor into Previous Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorToNextGroupAction), 'View: Split Editor into Next Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorToFirstGroupAction), 'View: Split Editor into First Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorToLastGroupAction), 'View: Split Editor into Last Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorToLeftGroupAction), 'View: Split Editor into Left Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorToRightGroupAction), 'View: Split Editor into Right Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorToAboveGroupAction), 'View: Split Editor into Group Above', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(SplitEditorToBelowGroupAction), 'View: Split Editor into Group Below', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusActiveGroupAction), 'View: Focus Active Editor Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusFirstGroupAction, { primary: KeyMod.CtrlCmd | KeyCode.Digit1 }), 'View: Focus First Editor Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusLastGroupAction), 'View: Focus Last Editor Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusPreviousGroup), 'View: Focus Previous Editor Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusNextGroup), 'View: Focus Next Editor Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusLeftGroup, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.LeftArrow) }), 'View: Focus Left Editor Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusRightGroup, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.RightArrow) }), 'View: Focus Right Editor Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusAboveGroup, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.UpArrow) }), 'View: Focus Editor Group Above', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(FocusBelowGroup, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KeyK, KeyMod.CtrlCmd | KeyCode.DownArrow) }), 'View: Focus Editor Group Below', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(NewEditorGroupLeftAction), 'View: New Editor Group to the Left', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(NewEditorGroupRightAction), 'View: New Editor Group to the Right', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(NewEditorGroupAboveAction), 'View: New Editor Group Above', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(NewEditorGroupBelowAction), 'View: New Editor Group Below', Categories.View.value);
registry.registerWorkbenchAction(SyncActionDescriptor.from(NavigatePreviousAction), 'Go Previous');
registry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateForwardInEditsAction), 'Go Forward in Edit Locations');
registry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateBackwardsInEditsAction), 'Go Back in Edit Locations');
@@ -254,21 +255,21 @@ registry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateBackwardsInNa
registry.registerWorkbenchAction(SyncActionDescriptor.from(NavigatePreviousInNavigationsAction), 'Go Previous in Navigation Locations');
registry.registerWorkbenchAction(SyncActionDescriptor.from(NavigateToLastNavigationLocationAction), 'Go to Last Navigation Location');
registry.registerWorkbenchAction(SyncActionDescriptor.from(ClearEditorHistoryAction), 'Clear Editor History');
-registry.registerWorkbenchAction(SyncActionDescriptor.from(RevertAndCloseEditorAction), 'View: Revert and Close Editor', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutSingleAction), 'View: Single Column Editor Layout', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutTwoColumnsAction), 'View: Two Columns Editor Layout', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutThreeColumnsAction), 'View: Three Columns Editor Layout', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutTwoRowsAction), 'View: Two Rows Editor Layout', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutThreeRowsAction), 'View: Three Rows Editor Layout', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutTwoByTwoGridAction), 'View: Grid Editor Layout (2x2)', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutTwoRowsRightAction), 'View: Two Rows Right Editor Layout', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutTwoColumnsBottomAction), 'View: Two Columns Bottom Editor Layout', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleEditorTypeAction), 'View: Toggle Editor Type', CATEGORIES.View.value, ActiveEditorAvailableEditorIdsContext);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(ReOpenInTextEditorAction), 'View: Reopen Editor With Text Editor', CATEGORIES.View.value, ActiveEditorAvailableEditorIdsContext);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessPreviousRecentlyUsedEditorAction), 'View: Quick Open Previous Recently Used Editor', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessLeastRecentlyUsedEditorAction), 'View: Quick Open Least Recently Used Editor', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessPreviousRecentlyUsedEditorInGroupAction, { primary: KeyMod.CtrlCmd | KeyCode.Tab, mac: { primary: KeyMod.WinCtrl | KeyCode.Tab } }, ActiveEditorGroupEmptyContext.toNegated()), 'View: Quick Open Previous Recently Used Editor in Group', CATEGORIES.View.value);
-registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessLeastRecentlyUsedEditorInGroupAction, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Tab, mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.Tab } }, ActiveEditorGroupEmptyContext.toNegated()), 'View: Quick Open Least Recently Used Editor in Group', CATEGORIES.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(RevertAndCloseEditorAction), 'View: Revert and Close Editor', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutSingleAction), 'View: Single Column Editor Layout', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutTwoColumnsAction), 'View: Two Columns Editor Layout', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutThreeColumnsAction), 'View: Three Columns Editor Layout', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutTwoRowsAction), 'View: Two Rows Editor Layout', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutThreeRowsAction), 'View: Three Rows Editor Layout', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutTwoByTwoGridAction), 'View: Grid Editor Layout (2x2)', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutTwoRowsRightAction), 'View: Two Rows Right Editor Layout', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(EditorLayoutTwoColumnsBottomAction), 'View: Two Columns Bottom Editor Layout', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleEditorTypeAction), 'View: Toggle Editor Type', Categories.View.value, ActiveEditorAvailableEditorIdsContext);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(ReOpenInTextEditorAction), 'View: Reopen Editor With Text Editor', Categories.View.value, ActiveEditorAvailableEditorIdsContext);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessPreviousRecentlyUsedEditorAction), 'View: Quick Open Previous Recently Used Editor', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessLeastRecentlyUsedEditorAction), 'View: Quick Open Least Recently Used Editor', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessPreviousRecentlyUsedEditorInGroupAction, { primary: KeyMod.CtrlCmd | KeyCode.Tab, mac: { primary: KeyMod.WinCtrl | KeyCode.Tab } }, ActiveEditorGroupEmptyContext.toNegated()), 'View: Quick Open Previous Recently Used Editor in Group', Categories.View.value);
+registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessLeastRecentlyUsedEditorInGroupAction, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.Tab, mac: { primary: KeyMod.WinCtrl | KeyMod.Shift | KeyCode.Tab } }, ActiveEditorGroupEmptyContext.toNegated()), 'View: Quick Open Least Recently Used Editor in Group', Categories.View.value);
registry.registerWorkbenchAction(SyncActionDescriptor.from(QuickAccessPreviousEditorFromHistoryAction), 'Quick Open Previous Editor from History');
registerAction2(NavigateForwardAction);
@@ -547,17 +548,17 @@ appendEditorToolItem(
);
// Editor Commands for Command Palette
-MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: KEEP_EDITOR_COMMAND_ID, title: { value: localize('keepEditor', "Keep Editor"), original: 'Keep Editor' }, category: CATEGORIES.View }, when: ContextKeyExpr.has('config.workbench.editor.enablePreview') });
-MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: PIN_EDITOR_COMMAND_ID, title: { value: localize('pinEditor', "Pin Editor"), original: 'Pin Editor' }, category: CATEGORIES.View } });
-MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: UNPIN_EDITOR_COMMAND_ID, title: { value: localize('unpinEditor', "Unpin Editor"), original: 'Unpin Editor' }, category: CATEGORIES.View } });
-MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: CLOSE_EDITOR_COMMAND_ID, title: { value: localize('closeEditor', "Close Editor"), original: 'Close Editor' }, category: CATEGORIES.View } });
-MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: CLOSE_PINNED_EDITOR_COMMAND_ID, title: { value: localize('closePinnedEditor', "Close Pinned Editor"), original: 'Close Pinned Editor' }, category: CATEGORIES.View } });
-MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: { value: localize('closeEditorsInGroup', "Close All Editors in Group"), original: 'Close All Editors in Group' }, category: CATEGORIES.View } });
-MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: CLOSE_SAVED_EDITORS_COMMAND_ID, title: { value: localize('closeSavedEditors', "Close Saved Editors in Group"), original: 'Close Saved Editors in Group' }, category: CATEGORIES.View } });
-MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID, title: { value: localize('closeOtherEditors', "Close Other Editors in Group"), original: 'Close Other Editors in Group' }, category: CATEGORIES.View } });
-MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: CLOSE_EDITORS_TO_THE_RIGHT_COMMAND_ID, title: { value: localize('closeRightEditors', "Close Editors to the Right in Group"), original: 'Close Editors to the Right in Group' }, category: CATEGORIES.View }, when: ActiveEditorLastInGroupContext.toNegated() });
-MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: CLOSE_EDITORS_AND_GROUP_COMMAND_ID, title: { value: localize('closeEditorGroup', "Close Editor Group"), original: 'Close Editor Group' }, category: CATEGORIES.View }, when: MultipleEditorGroupsContext });
-MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: REOPEN_WITH_COMMAND_ID, title: { value: localize('reopenWith', "Reopen Editor With..."), original: 'Reopen Editor With...' }, category: CATEGORIES.View }, when: ActiveEditorAvailableEditorIdsContext });
+MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: KEEP_EDITOR_COMMAND_ID, title: { value: localize('keepEditor', "Keep Editor"), original: 'Keep Editor' }, category: Categories.View }, when: ContextKeyExpr.has('config.workbench.editor.enablePreview') });
+MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: PIN_EDITOR_COMMAND_ID, title: { value: localize('pinEditor', "Pin Editor"), original: 'Pin Editor' }, category: Categories.View } });
+MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: UNPIN_EDITOR_COMMAND_ID, title: { value: localize('unpinEditor', "Unpin Editor"), original: 'Unpin Editor' }, category: Categories.View } });
+MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: CLOSE_EDITOR_COMMAND_ID, title: { value: localize('closeEditor', "Close Editor"), original: 'Close Editor' }, category: Categories.View } });
+MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: CLOSE_PINNED_EDITOR_COMMAND_ID, title: { value: localize('closePinnedEditor', "Close Pinned Editor"), original: 'Close Pinned Editor' }, category: Categories.View } });
+MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: { value: localize('closeEditorsInGroup', "Close All Editors in Group"), original: 'Close All Editors in Group' }, category: Categories.View } });
+MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: CLOSE_SAVED_EDITORS_COMMAND_ID, title: { value: localize('closeSavedEditors', "Close Saved Editors in Group"), original: 'Close Saved Editors in Group' }, category: Categories.View } });
+MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID, title: { value: localize('closeOtherEditors', "Close Other Editors in Group"), original: 'Close Other Editors in Group' }, category: Categories.View } });
+MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: CLOSE_EDITORS_TO_THE_RIGHT_COMMAND_ID, title: { value: localize('closeRightEditors', "Close Editors to the Right in Group"), original: 'Close Editors to the Right in Group' }, category: Categories.View }, when: ActiveEditorLastInGroupContext.toNegated() });
+MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: CLOSE_EDITORS_AND_GROUP_COMMAND_ID, title: { value: localize('closeEditorGroup', "Close Editor Group"), original: 'Close Editor Group' }, category: Categories.View }, when: MultipleEditorGroupsContext });
+MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: REOPEN_WITH_COMMAND_ID, title: { value: localize('reopenWith', "Reopen Editor With..."), original: 'Reopen Editor With...' }, category: Categories.View }, when: ActiveEditorAvailableEditorIdsContext });
// File menu
MenuRegistry.appendMenuItem(MenuId.MenubarRecentMenu, {
diff --git a/src/vs/workbench/browser/parts/editor/editorCommands.ts b/src/vs/workbench/browser/parts/editor/editorCommands.ts
index 69f5e571700..31d6bb4bf3f 100644
--- a/src/vs/workbench/browser/parts/editor/editorCommands.ts
+++ b/src/vs/workbench/browser/parts/editor/editorCommands.ts
@@ -25,7 +25,7 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { CommandsRegistry, ICommandHandler, ICommandService } from 'vs/platform/commands/common/commands';
import { MenuRegistry, MenuId, registerAction2, Action2 } from 'vs/platform/actions/common/actions';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { ActiveGroupEditorsByMostRecentlyUsedQuickAccess } from 'vs/workbench/browser/parts/editor/editorQuickAccess';
import { IOpenerService, matchesScheme } from 'vs/platform/opener/common/opener';
import { EditorResolution, IEditorOptions, IResourceEditorInput, ITextEditorOptions } from 'vs/platform/editor/common/editor';
@@ -1058,7 +1058,7 @@ function registerSplitEditorInGroupCommands(): void {
super({
id: SPLIT_EDITOR_IN_GROUP,
title: { value: localize('splitEditorInGroup', "Split Editor in Group"), original: 'Split Editor in Group' },
- category: CATEGORIES.View,
+ category: Categories.View,
precondition: ActiveEditorCanSplitInGroupContext,
f1: true,
keybinding: {
@@ -1104,7 +1104,7 @@ function registerSplitEditorInGroupCommands(): void {
super({
id: JOIN_EDITOR_IN_GROUP,
title: { value: localize('joinEditorInGroup', "Join Editor in Group"), original: 'Join Editor in Group' },
- category: CATEGORIES.View,
+ category: Categories.View,
precondition: SideBySideEditorActiveContext,
f1: true,
keybinding: {
@@ -1124,7 +1124,7 @@ function registerSplitEditorInGroupCommands(): void {
super({
id: TOGGLE_SPLIT_EDITOR_IN_GROUP,
title: { value: localize('toggleJoinEditorInGroup', "Toggle Split Editor in Group"), original: 'Toggle Split Editor in Group' },
- category: CATEGORIES.View,
+ category: Categories.View,
precondition: ContextKeyExpr.or(ActiveEditorCanSplitInGroupContext, SideBySideEditorActiveContext),
f1: true
});
@@ -1146,7 +1146,7 @@ function registerSplitEditorInGroupCommands(): void {
super({
id: TOGGLE_SPLIT_EDITOR_IN_GROUP_LAYOUT,
title: { value: localize('toggleSplitEditorInGroupLayout', "Toggle Layout of Split Editor in Group"), original: 'Toggle Layout of Split Editor in Group' },
- category: CATEGORIES.View,
+ category: Categories.View,
precondition: SideBySideEditorActiveContext,
f1: true
});
@@ -1174,7 +1174,7 @@ function registerFocusSideEditorsCommands(): void {
super({
id: FOCUS_FIRST_SIDE_EDITOR,
title: { value: localize('focusLeftSideEditor', "Focus First Side in Active Editor"), original: 'Focus First Side in Active Editor' },
- category: CATEGORIES.View,
+ category: Categories.View,
precondition: ContextKeyExpr.or(SideBySideEditorActiveContext, TextCompareEditorActiveContext),
f1: true
});
@@ -1197,7 +1197,7 @@ function registerFocusSideEditorsCommands(): void {
super({
id: FOCUS_SECOND_SIDE_EDITOR,
title: { value: localize('focusRightSideEditor', "Focus Second Side in Active Editor"), original: 'Focus Second Side in Active Editor' },
- category: CATEGORIES.View,
+ category: Categories.View,
precondition: ContextKeyExpr.or(SideBySideEditorActiveContext, TextCompareEditorActiveContext),
f1: true
});
@@ -1220,7 +1220,7 @@ function registerFocusSideEditorsCommands(): void {
super({
id: FOCUS_OTHER_SIDE_EDITOR,
title: { value: localize('focusOtherSideEditor', "Focus Other Side in Active Editor"), original: 'Focus Other Side in Active Editor' },
- category: CATEGORIES.View,
+ category: Categories.View,
precondition: ContextKeyExpr.or(SideBySideEditorActiveContext, TextCompareEditorActiveContext),
f1: true
});
@@ -1283,7 +1283,7 @@ function registerOtherEditorCommands(): void {
super({
id: TOGGLE_LOCK_GROUP_COMMAND_ID,
title: { value: localize('toggleEditorGroupLock', "Toggle Editor Group Lock"), original: 'Toggle Editor Group Lock' },
- category: CATEGORIES.View,
+ category: Categories.View,
precondition: MultipleEditorGroupsContext,
f1: true
});
@@ -1298,7 +1298,7 @@ function registerOtherEditorCommands(): void {
super({
id: LOCK_GROUP_COMMAND_ID,
title: { value: localize('lockEditorGroup', "Lock Editor Group"), original: 'Lock Editor Group' },
- category: CATEGORIES.View,
+ category: Categories.View,
precondition: ContextKeyExpr.and(MultipleEditorGroupsContext, ActiveEditorGroupLockedContext.toNegated()),
f1: true
});
@@ -1314,7 +1314,7 @@ function registerOtherEditorCommands(): void {
id: UNLOCK_GROUP_COMMAND_ID,
title: { value: localize('unlockEditorGroup', "Unlock Editor Group"), original: 'Unlock Editor Group' },
precondition: ContextKeyExpr.and(MultipleEditorGroupsContext, ActiveEditorGroupLockedContext),
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true
});
}
diff --git a/src/vs/workbench/browser/parts/editor/editorGroupView.ts b/src/vs/workbench/browser/parts/editor/editorGroupView.ts
index 3049500d7f8..2495583b51f 100644
--- a/src/vs/workbench/browser/parts/editor/editorGroupView.ts
+++ b/src/vs/workbench/browser/parts/editor/editorGroupView.ts
@@ -36,9 +36,9 @@ import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IAction } from 'vs/base/common/actions';
import { NoTabsTitleControl } from 'vs/workbench/browser/parts/editor/noTabsTitleControl';
-import { IMenuService, MenuId, IMenu } from 'vs/platform/actions/common/actions';
+import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
-import { createAndFillInActionBarActions, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
+import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { hash } from 'vs/base/common/hash';
@@ -364,13 +364,11 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
}
private createContainerContextMenu(): void {
- const menu = this._register(this.menuService.createMenu(MenuId.EmptyEditorGroupContext, this.contextKeyService));
-
- this._register(addDisposableListener(this.element, EventType.CONTEXT_MENU, e => this.onShowContainerContextMenu(menu, e)));
- this._register(addDisposableListener(this.element, TouchEventType.Contextmenu, () => this.onShowContainerContextMenu(menu)));
+ this._register(addDisposableListener(this.element, EventType.CONTEXT_MENU, e => this.onShowContainerContextMenu(e)));
+ this._register(addDisposableListener(this.element, TouchEventType.Contextmenu, () => this.onShowContainerContextMenu()));
}
- private onShowContainerContextMenu(menu: IMenu, e?: MouseEvent): void {
+ private onShowContainerContextMenu(e?: MouseEvent): void {
if (!this.isEmpty) {
return; // only for empty editor groups
}
@@ -382,14 +380,11 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
anchor = { x: event.posx, y: event.posy };
}
- // Fill in contributed actions
- const actions: IAction[] = [];
- createAndFillInContextMenuActions(menu, undefined, actions);
-
// Show it
this.contextMenuService.showContextMenu({
+ menuId: MenuId.EmptyEditorGroupContext,
+ contextKeyService: this.contextKeyService,
getAnchor: () => anchor,
- getActions: () => actions,
onHide: () => {
this.focus();
}
diff --git a/src/vs/workbench/browser/parts/editor/titleControl.ts b/src/vs/workbench/browser/parts/editor/titleControl.ts
index 57fae3e0bc1..2ff9d39896b 100644
--- a/src/vs/workbench/browser/parts/editor/titleControl.ts
+++ b/src/vs/workbench/browser/parts/editor/titleControl.ts
@@ -12,8 +12,8 @@ import { ActionsOrientation, IActionViewItem, prepareActions } from 'vs/base/bro
import { IAction, SubmenuAction, ActionRunner } from 'vs/base/common/actions';
import { ResolvedKeybinding } from 'vs/base/common/keybindings';
import { dispose, DisposableStore } from 'vs/base/common/lifecycle';
-import { createActionViewItem, createAndFillInActionBarActions, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
-import { IMenu, IMenuService, MenuId } from 'vs/platform/actions/common/actions';
+import { createActionViewItem, createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
+import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
@@ -108,7 +108,6 @@ export abstract class TitleControl extends Themable {
private readonly editorToolBarMenuDisposables = this._register(new DisposableStore());
- private contextMenu: IMenu;
private renderDropdownAsChildElement: boolean;
constructor(
@@ -140,7 +139,6 @@ export abstract class TitleControl extends Themable {
this.groupLockedContext = ActiveEditorGroupLockedContext.bindTo(contextKeyService);
- this.contextMenu = this._register(this.menuService.createMenu(MenuId.EditorTitleContext, this.contextKeyService));
this.renderDropdownAsChildElement = false;
this.create(parent);
@@ -374,14 +372,12 @@ export abstract class TitleControl extends Themable {
anchor = { x: event.posx, y: event.posy };
}
- // Fill in contributed actions
- const actions: IAction[] = [];
- createAndFillInContextMenuActions(this.contextMenu, { shouldForwardArgs: true, arg: this.resourceContext.get() }, actions);
-
// Show it
this.contextMenuService.showContextMenu({
getAnchor: () => anchor,
- getActions: () => actions,
+ menuId: MenuId.EditorTitleContext,
+ menuActionOptions: { shouldForwardArgs: true, arg: this.resourceContext.get() },
+ contextKeyService: this.contextKeyService,
getActionsContext: () => ({ groupId: this.group.id, editorIndex: this.group.getIndexOfEditor(editor) }),
getKeyBinding: action => this.getKeybinding(action),
onHide: () => {
diff --git a/src/vs/workbench/browser/parts/paneCompositePart.ts b/src/vs/workbench/browser/parts/paneCompositePart.ts
index c0ee4b101f3..dd035d916fb 100644
--- a/src/vs/workbench/browser/parts/paneCompositePart.ts
+++ b/src/vs/workbench/browser/parts/paneCompositePart.ts
@@ -5,7 +5,7 @@
import { Event } from 'vs/base/common/event';
import { assertIsDefined } from 'vs/base/common/types';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IProgressIndicator } from 'vs/platform/progress/common/progress';
import { PaneCompositeDescriptor } from 'vs/workbench/browser/panecomposite';
@@ -159,4 +159,4 @@ export class PaneCompositeParts extends Disposable implements IPaneCompositePart
}
}
-registerSingleton(IPaneCompositePartService, PaneCompositeParts, true);
+registerSingleton(IPaneCompositePartService, PaneCompositeParts, InstantiationType.Delayed);
diff --git a/src/vs/workbench/browser/parts/panel/panelActions.ts b/src/vs/workbench/browser/parts/panel/panelActions.ts
index 074fafd9d61..f68ea5c90e3 100644
--- a/src/vs/workbench/browser/parts/panel/panelActions.ts
+++ b/src/vs/workbench/browser/parts/panel/panelActions.ts
@@ -9,7 +9,8 @@ import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { Action } from 'vs/base/common/actions';
import { Registry } from 'vs/platform/registry/common/platform';
import { SyncActionDescriptor, MenuId, MenuRegistry, registerAction2, Action2, IAction2Options } from 'vs/platform/actions/common/actions';
-import { IWorkbenchActionRegistry, Extensions as WorkbenchExtensions, CATEGORIES } from 'vs/workbench/common/actions';
+import { IWorkbenchActionRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { IWorkbenchLayoutService, PanelAlignment, Parts, Position, positionToString } from 'vs/workbench/services/layout/browser/layoutService';
import { ActivityAction, ToggleCompositePinnedAction, ICompositeBar } from 'vs/workbench/browser/parts/compositeBarActions';
import { IActivity } from 'vs/workbench/common/activity';
@@ -159,7 +160,7 @@ PositionPanelActionConfigs.forEach(positionPanelAction => {
super({
id,
title,
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true
});
}
@@ -193,7 +194,7 @@ AlignPanelActionConfigs.forEach(alignPanelAction => {
super({
id,
title: title,
- category: CATEGORIES.View,
+ category: Categories.View,
toggled: when.negate(),
f1: true
});
@@ -322,10 +323,10 @@ export class NextPanelViewAction extends SwitchPanelViewAction {
}
const actionRegistry = Registry.as(WorkbenchExtensions.WorkbenchActions);
-actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(TogglePanelAction, { primary: KeyMod.CtrlCmd | KeyCode.KeyJ }), 'View: Toggle Panel Visibility', CATEGORIES.View.value);
-actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(FocusPanelAction), 'View: Focus into Panel', CATEGORIES.View.value);
-actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(PreviousPanelViewAction), 'View: Previous Panel View', CATEGORIES.View.value);
-actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(NextPanelViewAction), 'View: Next Panel View', CATEGORIES.View.value);
+actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(TogglePanelAction, { primary: KeyMod.CtrlCmd | KeyCode.KeyJ }), 'View: Toggle Panel Visibility', Categories.View.value);
+actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(FocusPanelAction), 'View: Focus into Panel', Categories.View.value);
+actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(PreviousPanelViewAction), 'View: Previous Panel View', Categories.View.value);
+actionRegistry.registerWorkbenchAction(SyncActionDescriptor.from(NextPanelViewAction), 'View: Next Panel View', Categories.View.value);
registerAction2(class extends Action2 {
constructor() {
@@ -333,7 +334,7 @@ registerAction2(class extends Action2 {
id: 'workbench.action.toggleMaximizedPanel',
title: { value: localize('toggleMaximizedPanel', "Toggle Maximized Panel"), original: 'Toggle Maximized Panel' },
tooltip: localize('maximizePanel', "Maximize Panel Size"),
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true,
icon: maximizeIcon,
// the workbench grid currently prevents us from supporting panel maximization with non-center panel alignment
@@ -374,7 +375,7 @@ registerAction2(class extends Action2 {
super({
id: 'workbench.action.closePanel',
title: { value: localize('closePanel', "Close Panel"), original: 'Close Panel' },
- category: CATEGORIES.View,
+ category: Categories.View,
icon: closeIcon,
menu: [{
id: MenuId.CommandPalette,
@@ -396,7 +397,7 @@ registerAction2(class extends Action2 {
super({
id: 'workbench.action.closeAuxiliaryBar',
title: { value: localize('closeSecondarySideBar', "Close Secondary Side Bar"), original: 'Close Secondary Side Bar' },
- category: CATEGORIES.View,
+ category: Categories.View,
icon: closeIcon,
menu: [{
id: MenuId.CommandPalette,
@@ -500,7 +501,7 @@ class MovePanelToSidePanelAction extends MoveViewsBetweenPanelsAction {
value: localize('movePanelToSecondarySideBar', "Move Panel Views To Secondary Side Bar"),
original: 'Move Panel Views To Secondary Side Bar'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: false
});
}
@@ -515,7 +516,7 @@ export class MovePanelToSecondarySideBarAction extends MoveViewsBetweenPanelsAct
value: localize('movePanelToSecondarySideBar', "Move Panel Views To Secondary Side Bar"),
original: 'Move Panel Views To Secondary Side Bar'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true
});
}
@@ -536,7 +537,7 @@ class MoveSidePanelToPanelAction extends MoveViewsBetweenPanelsAction {
value: localize('moveSidePanelToPanel', "Move Secondary Side Bar Views To Panel"),
original: 'Move Secondary Side Bar Views To Panel'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: false
});
}
@@ -552,7 +553,7 @@ export class MoveSecondarySideBarToPanelAction extends MoveViewsBetweenPanelsAct
value: localize('moveSidePanelToPanel', "Move Secondary Side Bar Views To Panel"),
original: 'Move Secondary Side Bar Views To Panel'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true
});
}
diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts
index d3dfaf39c5f..6b8e20f84f4 100644
--- a/src/vs/workbench/browser/parts/panel/panelPart.ts
+++ b/src/vs/workbench/browser/parts/panel/panelPart.ts
@@ -45,7 +45,7 @@ import { IPartOptions } from 'vs/workbench/browser/part';
import { StringSHA1 } from 'vs/base/common/hash';
import { URI } from 'vs/base/common/uri';
import { Extensions, IProfileStorageRegistry } from 'vs/workbench/services/userDataProfile/common/userDataProfileStorageRegistry';
-import { WorkbenchToolBar } from 'vs/platform/actions/browser/toolbar';
+import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
interface ICachedPanel {
id: string;
@@ -110,7 +110,7 @@ export abstract class BasePanelPart extends CompositePart impleme
private compositeBar: CompositeBar;
private readonly compositeActions = new Map();
- private globalToolBar: WorkbenchToolBar | undefined;
+ private globalToolBar: ToolBar | undefined;
private globalActions: CompositeMenuActions;
private readonly panelDisposables: Map = new Map();
@@ -549,13 +549,12 @@ export abstract class BasePanelPart extends CompositePart impleme
const globalTitleActionsContainer = element.appendChild($('.global-actions'));
// Global Actions Toolbar
- this.globalToolBar = this._register(this.instantiationService.createInstance(WorkbenchToolBar, globalTitleActionsContainer, {
+ this.globalToolBar = this._register(new ToolBar(globalTitleActionsContainer, this.contextMenuService, {
actionViewItemProvider: action => this.actionViewItemProvider(action),
orientation: ActionsOrientation.HORIZONTAL,
getKeyBinding: action => this.keybindingService.lookupKeybinding(action.id),
anchorAlignmentProvider: () => this.getTitleAreaDropDownAnchorAlignment(),
- toggleMenuTitle: localize('moreActions', "More Actions..."),
- resetMenu: this.globalActions.menuId
+ toggleMenuTitle: localize('moreActions', "More Actions...")
}));
this.updateGlobalToolbarActions();
diff --git a/src/vs/workbench/browser/parts/sidebar/sidebarActions.ts b/src/vs/workbench/browser/parts/sidebar/sidebarActions.ts
index 9ebb1e99eb7..974349fe5b3 100644
--- a/src/vs/workbench/browser/parts/sidebar/sidebarActions.ts
+++ b/src/vs/workbench/browser/parts/sidebar/sidebarActions.ts
@@ -10,7 +10,7 @@ import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/bro
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
import { ViewContainerLocation } from 'vs/workbench/common/views';
@@ -20,7 +20,7 @@ export class FocusSideBarAction extends Action2 {
super({
id: 'workbench.action.focusSideBar',
title: { value: localize('focusSideBar', "Focus into Primary Side Bar"), original: 'Focus into Primary Side Bar' },
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true,
keybinding: {
weight: KeybindingWeight.WorkbenchContrib,
diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarActions.ts b/src/vs/workbench/browser/parts/statusbar/statusbarActions.ts
index 1af3a67ebc2..d484e5a0ad2 100644
--- a/src/vs/workbench/browser/parts/statusbar/statusbarActions.ts
+++ b/src/vs/workbench/browser/parts/statusbar/statusbarActions.ts
@@ -11,7 +11,7 @@ import { KeyCode } from 'vs/base/common/keyCodes';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { StatusbarViewModel } from 'vs/workbench/browser/parts/statusbar/statusbarModel';
import { StatusBarFocused } from 'vs/workbench/common/contextkeys';
@@ -114,7 +114,7 @@ class FocusStatusBarAction extends Action2 {
super({
id: 'workbench.action.focusStatusBar',
title: { value: localize('focusStatusBar', "Focus Status Bar"), original: 'Focus Status Bar' },
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true
});
}
diff --git a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts
index 90cb274b662..29b322622bd 100644
--- a/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts
+++ b/src/vs/workbench/browser/parts/titlebar/titlebarPart.ts
@@ -11,7 +11,6 @@ import { getZoomFactor } from 'vs/base/browser/browser';
import { MenuBarVisibility, getTitleBarStyle, getMenuBarVisibility } from 'vs/platform/window/common/window';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
-import { IAction } from 'vs/base/common/actions';
import { IConfigurationService, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
import { DisposableStore } from 'vs/base/common/lifecycle';
import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService';
@@ -25,8 +24,8 @@ import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiati
import { Emitter, Event } from 'vs/base/common/event';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { Parts, IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
-import { createActionViewItem, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
-import { Action2, IMenuService, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
+import { createActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
+import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { Codicon } from 'vs/base/common/codicons';
@@ -35,7 +34,7 @@ import { WindowTitle } from 'vs/workbench/browser/parts/titlebar/windowTitle';
import { CommandCenterControl } from 'vs/workbench/browser/parts/titlebar/commandCenterControl';
import { IHoverDelegate } from 'vs/base/browser/ui/iconLabel/iconHoverDelegate';
import { IHoverService } from 'vs/workbench/services/hover/browser/hover';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { MenuWorkbenchToolBar } from 'vs/platform/actions/browser/toolbar';
export class TitlebarPart extends Part implements ITitleService {
@@ -92,7 +91,6 @@ export class TitlebarPart extends Part implements ITitleService {
@IThemeService themeService: IThemeService,
@IStorageService storageService: IStorageService,
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
- @IMenuService private readonly menuService: IMenuService,
@IContextKeyService private readonly contextKeyService: IContextKeyService,
@IHostService private readonly hostService: IHostService,
@IHoverService hoverService: IHoverService,
@@ -322,7 +320,7 @@ export class TitlebarPart extends Part implements ITitleService {
super({
id: `workbench.action.focusTitleBar`,
title: { value: localize('focusTitleBar', "Focus Title Bar"), original: 'Focus Title Bar' },
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true,
});
}
@@ -382,16 +380,11 @@ export class TitlebarPart extends Part implements ITitleService {
const event = new StandardMouseEvent(e);
const anchor = { x: event.posx, y: event.posy };
- // Fill in contributed actions
- const menu = this.menuService.createMenu(menuId, this.contextKeyService);
- const actions: IAction[] = [];
- createAndFillInContextMenuActions(menu, undefined, actions);
- menu.dispose();
-
// Show it
this.contextMenuService.showContextMenu({
getAnchor: () => anchor,
- getActions: () => actions,
+ menuId,
+ contextKeyService: this.contextKeyService,
domForShadowRoot: isMacintosh && isNative ? event.target : undefined
});
}
diff --git a/src/vs/workbench/browser/parts/views/viewsService.ts b/src/vs/workbench/browser/parts/views/viewsService.ts
index 18670e883ad..4e2b8c64478 100644
--- a/src/vs/workbench/browser/parts/views/viewsService.ts
+++ b/src/vs/workbench/browser/parts/views/viewsService.ts
@@ -27,7 +27,7 @@ import { PaneCompositeDescriptor, PaneCompositeRegistry, Extensions as PaneCompo
import { IWorkbenchLayoutService, Parts } from 'vs/workbench/services/layout/browser/layoutService';
import { URI } from 'vs/base/common/uri';
import { IProgressIndicator } from 'vs/platform/progress/common/progress';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { FilterViewPaneContainer } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite';
@@ -139,7 +139,7 @@ export class ViewsService extends Disposable implements IViewsService {
for (const viewDescriptor of views) {
const disposables = new DisposableStore();
disposables.add(this.registerOpenViewAction(viewDescriptor));
- disposables.add(this.registerFocusViewAction(viewDescriptor, composite?.name && composite.name !== composite.id ? composite.name : CATEGORIES.View));
+ disposables.add(this.registerFocusViewAction(viewDescriptor, composite?.name && composite.name !== composite.id ? composite.name : Categories.View));
disposables.add(this.registerResetViewLocationAction(viewDescriptor));
this.viewDisposable.set(viewDescriptor, disposables);
}
@@ -354,7 +354,7 @@ export class ViewsService extends Disposable implements IViewsService {
return { value: localize('toggle view', "Toggle {0}", localizedTitle), original: `Toggle ${originalTitle}` };
}
},
- category: CATEGORIES.View,
+ category: Categories.View,
precondition: ContextKeyExpr.has(getEnabledViewContainerContextKey(viewContainer.id)),
keybinding: keybindings ? { ...keybindings, weight: KeybindingWeight.WorkbenchContrib } : undefined,
f1: true
@@ -422,7 +422,7 @@ export class ViewsService extends Disposable implements IViewsService {
return { value: localize('toggle view', "Toggle {0}", localizedTitle), original: `Toggle ${originalTitle}` };
}
},
- category: CATEGORIES.View,
+ category: Categories.View,
precondition: ContextKeyExpr.has(`${viewDescriptor.id}.active`),
keybinding: viewDescriptor.openCommandActionDescriptor!.keybindings ? { ...viewDescriptor.openCommandActionDescriptor!.keybindings, weight: KeybindingWeight.WorkbenchContrib } : undefined,
f1: true
diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts
index e50d4867a52..11806254df3 100644
--- a/src/vs/workbench/browser/web.main.ts
+++ b/src/vs/workbench/browser/web.main.ts
@@ -52,7 +52,7 @@ import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecy
import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { localize } from 'vs/nls';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
@@ -436,7 +436,7 @@ export class BrowserMain extends Disposable {
super({
id: 'workbench.action.resetUserData',
title: { original: 'Reset User Data', value: localize('reset', "Reset User Data") },
- category: CATEGORIES.Developer,
+ category: Categories.Developer,
menu: {
id: MenuId.CommandPalette
}
diff --git a/src/vs/workbench/browser/window.ts b/src/vs/workbench/browser/window.ts
index 52dcef61e86..724e130fcd0 100644
--- a/src/vs/workbench/browser/window.ts
+++ b/src/vs/workbench/browser/window.ts
@@ -26,6 +26,7 @@ import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/envir
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { BrowserLifecycleService } from 'vs/workbench/services/lifecycle/browser/lifecycleService';
import { ILifecycleService } from 'vs/workbench/services/lifecycle/common/lifecycle';
+import { IHostService } from 'vs/workbench/services/host/browser/host';
export class BrowserWindow extends Disposable {
@@ -36,7 +37,8 @@ export class BrowserWindow extends Disposable {
@ILabelService private readonly labelService: ILabelService,
@IProductService private readonly productService: IProductService,
@IBrowserWorkbenchEnvironmentService private readonly environmentService: IBrowserWorkbenchEnvironmentService,
- @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService
+ @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService,
+ @IHostService private readonly hostService: IHostService
) {
super();
@@ -204,29 +206,45 @@ export class BrowserWindow extends Disposable {
invokeProtocolHandler();
const showProtocolUrlOpenedDialog = async () => {
+ const { downloadUrl } = this.productService;
+ let detail = localize(
+ 'openExternalDialogDetail.v2',
+ "We launched {0} on your computer.\n\nIf {1} did not launch, try again or install it below.",
+ this.productService.nameLong,
+ this.productService.nameLong
+ );
+ const options = [
+ localize('openExternalDialogButtonClose', "Close tab"),
+ localize('openExternalDialogButtonRetry', "Try again"),
+ localize('openExternalDialogButtonInstall.v3', "Install"),
+ localize('openExternalDialogButtonCancel', "Cancel")
+ ];
+ if (downloadUrl === undefined) {
+ options.splice(2, 1);
+ detail = localize(
+ 'openExternalDialogDetailNoInstall',
+ "We launched {0} on your computer.\n\nIf {1} did not launch, try again below.",
+ this.productService.nameLong,
+ this.productService.nameLong
+ );
+ }
+
const showResult = await this.dialogService.show(
Severity.Info,
localize('openExternalDialogTitle', "All done. You can close this tab now."),
- [
- localize('openExternalDialogButtonRetry', "Try again"),
- localize('openExternalDialogButtonInstall', "Install {0}", this.productService.nameLong),
- localize('openExternalDialogButtonContinue', "Continue here")
- ],
+ options,
{
- cancelId: 2,
- detail: localize('openExternalDialogDetail', "We tried opening {0} on your computer.", this.productService.nameLong)
+ cancelId: downloadUrl === undefined ? 2 : 3,
+ detail
},
);
if (showResult.choice === 0) {
- invokeProtocolHandler();
+ this.hostService.close();
} else if (showResult.choice === 1) {
- // Route the user to the appropriate install link
- await this.openerService.open(URI.parse(
- this.productService.quality === 'stable'
- ? `http://aka.ms/vscode-install`
- : `http://aka.ms/vscode-install-insiders`
- ));
+ invokeProtocolHandler();
+ } else if (showResult.choice === 2 && downloadUrl !== undefined) {
+ await this.openerService.open(URI.parse(downloadUrl));
// Re-show the dialog so that the user can come back after installing and try again
showProtocolUrlOpenedDialog();
diff --git a/src/vs/workbench/browser/workbench.contribution.ts b/src/vs/workbench/browser/workbench.contribution.ts
index 4ebd6498e72..9ebe6ca8ed7 100644
--- a/src/vs/workbench/browser/workbench.contribution.ts
+++ b/src/vs/workbench/browser/workbench.contribution.ts
@@ -18,7 +18,7 @@ const registry = Registry.as(ConfigurationExtensions.Con
(function registerConfiguration(): void {
// Migration support
- Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(ConfigurationMigrationWorkbenchContribution, 'ConfigurationMigrationWorkbenchContribution', LifecyclePhase.Eventually);
+ Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(ConfigurationMigrationWorkbenchContribution, LifecyclePhase.Eventually);
// Workbench
registry.registerConfiguration({
diff --git a/src/vs/workbench/common/actions.ts b/src/vs/workbench/common/actions.ts
index 64742f9555f..3b2148055a5 100644
--- a/src/vs/workbench/common/actions.ts
+++ b/src/vs/workbench/common/actions.ts
@@ -3,7 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import { localize } from 'vs/nls';
import { Registry } from 'vs/platform/registry/common/platform';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ICommandHandler, CommandsRegistry } from 'vs/platform/commands/common/commands';
@@ -121,11 +120,3 @@ Registry.add(Extensions.WorkbenchActions, new class implements IWorkbenchActionR
}
}
});
-
-export const CATEGORIES = {
- View: { value: localize('view', "View"), original: 'View' },
- Help: { value: localize('help', "Help"), original: 'Help' },
- Test: { value: localize('test', "Test"), original: 'Test' },
- Preferences: { value: localize('preferences', "Preferences"), original: 'Preferences' },
- Developer: { value: localize({ key: 'developer', comment: ['A developer on Code itself or someone diagnosing issues in Code'] }, "Developer"), original: 'Developer' }
-};
diff --git a/src/vs/workbench/common/contributions.ts b/src/vs/workbench/common/contributions.ts
index afa24265570..592f64c9f89 100644
--- a/src/vs/workbench/common/contributions.ts
+++ b/src/vs/workbench/common/contributions.ts
@@ -9,6 +9,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
import { runWhenIdle, IdleDeadline } from 'vs/base/common/async';
import { mark } from 'vs/base/common/performance';
import { ILogService } from 'vs/platform/log/common/log';
+import { IEnvironmentService } from 'vs/platform/environment/common/environment';
/**
* A workbench contribution that will be loaded when the workbench starts and disposed when the workbench shuts down.
@@ -23,21 +24,15 @@ export namespace Extensions {
type IWorkbenchContributionSignature = new (...services: Service) => IWorkbenchContribution;
-interface IWorkbenchContributionRegistration {
- readonly id: string;
- readonly ctor: IConstructorSignature;
-}
-
export interface IWorkbenchContributionsRegistry {
/**
* Registers a workbench contribution to the platform that will be loaded when the workbench starts and disposed when
* the workbench shuts down.
*
- * @param id the identifier of the contribution.
* @param phase the lifecycle phase when to instantiate the contribution.
*/
- registerWorkbenchContribution(contribution: IWorkbenchContributionSignature, id: string, phase: LifecyclePhase): void;
+ registerWorkbenchContribution(contribution: IWorkbenchContributionSignature, phase: LifecyclePhase): void;
/**
* Starts the registry by providing the required services.
@@ -50,15 +45,15 @@ class WorkbenchContributionsRegistry implements IWorkbenchContributionsRegistry
private instantiationService: IInstantiationService | undefined;
private lifecycleService: ILifecycleService | undefined;
private logService: ILogService | undefined;
+ private environmentService: IEnvironmentService | undefined;
- private readonly toBeInstantiated = new Map();
+ private readonly toBeInstantiated = new Map[]>();
- registerWorkbenchContribution(ctor: IConstructorSignature, id: string, phase: LifecyclePhase = LifecyclePhase.Starting): void {
- const contribution = { id, ctor };
+ registerWorkbenchContribution(ctor: IConstructorSignature, phase: LifecyclePhase = LifecyclePhase.Starting): void {
// Instantiate directly if we are already matching the provided phase
- if (this.instantiationService && this.lifecycleService && this.logService && this.lifecycleService.phase >= phase) {
- this.safeCreateInstance(this.instantiationService, this.logService, contribution, phase);
+ if (this.instantiationService && this.lifecycleService && this.logService && this.environmentService && this.lifecycleService.phase >= phase) {
+ this.safeCreateInstance(this.instantiationService, this.logService, this.environmentService, ctor, phase);
}
// Otherwise keep contributions by lifecycle phase
@@ -69,7 +64,7 @@ class WorkbenchContributionsRegistry implements IWorkbenchContributionsRegistry
this.toBeInstantiated.set(phase, toBeInstantiated);
}
- toBeInstantiated.push(contribution);
+ toBeInstantiated.push(ctor as IConstructorSignature);
}
}
@@ -77,26 +72,27 @@ class WorkbenchContributionsRegistry implements IWorkbenchContributionsRegistry
const instantiationService = this.instantiationService = accessor.get(IInstantiationService);
const lifecycleService = this.lifecycleService = accessor.get(ILifecycleService);
const logService = this.logService = accessor.get(ILogService);
+ const environmentService = this.environmentService = accessor.get(IEnvironmentService);
for (const phase of [LifecyclePhase.Starting, LifecyclePhase.Ready, LifecyclePhase.Restored, LifecyclePhase.Eventually]) {
- this.instantiateByPhase(instantiationService, lifecycleService, logService, phase);
+ this.instantiateByPhase(instantiationService, lifecycleService, logService, environmentService, phase);
}
}
- private instantiateByPhase(instantiationService: IInstantiationService, lifecycleService: ILifecycleService, logService: ILogService, phase: LifecyclePhase): void {
+ private instantiateByPhase(instantiationService: IInstantiationService, lifecycleService: ILifecycleService, logService: ILogService, environmentService: IEnvironmentService, phase: LifecyclePhase): void {
// Instantiate contributions directly when phase is already reached
if (lifecycleService.phase >= phase) {
- this.doInstantiateByPhase(instantiationService, logService, phase);
+ this.doInstantiateByPhase(instantiationService, logService, environmentService, phase);
}
// Otherwise wait for phase to be reached
else {
- lifecycleService.when(phase).then(() => this.doInstantiateByPhase(instantiationService, logService, phase));
+ lifecycleService.when(phase).then(() => this.doInstantiateByPhase(instantiationService, logService, environmentService, phase));
}
}
- private doInstantiateByPhase(instantiationService: IInstantiationService, logService: ILogService, phase: LifecyclePhase): void {
+ private doInstantiateByPhase(instantiationService: IInstantiationService, logService: ILogService, environmentService: IEnvironmentService, phase: LifecyclePhase): void {
const toBeInstantiated = this.toBeInstantiated.get(phase);
if (toBeInstantiated) {
this.toBeInstantiated.delete(phase);
@@ -108,7 +104,7 @@ class WorkbenchContributionsRegistry implements IWorkbenchContributionsRegistry
mark(`code/willCreateWorkbenchContributions/${phase}`);
for (const ctor of toBeInstantiated) {
- this.safeCreateInstance(instantiationService, logService, ctor, phase); // catch error so that other contributions are still considered
+ this.safeCreateInstance(instantiationService, logService, environmentService, ctor, phase); // catch error so that other contributions are still considered
}
mark(`code/didCreateWorkbenchContributions/${phase}`);
@@ -123,7 +119,7 @@ class WorkbenchContributionsRegistry implements IWorkbenchContributionsRegistry
const instantiateSome = (idle: IdleDeadline) => {
while (i < toBeInstantiated.length) {
const ctor = toBeInstantiated[i++];
- this.safeCreateInstance(instantiationService, logService, ctor, phase); // catch error so that other contributions are still considered
+ this.safeCreateInstance(instantiationService, logService, environmentService, ctor, phase); // catch error so that other contributions are still considered
if (idle.timeRemaining() < 1) {
// time is up -> reschedule
runWhenIdle(instantiateSome, forcedTimeout);
@@ -136,19 +132,19 @@ class WorkbenchContributionsRegistry implements IWorkbenchContributionsRegistry
}
}
- private safeCreateInstance(instantiationService: IInstantiationService, logService: ILogService, contribution: IWorkbenchContributionRegistration, phase: LifecyclePhase): void {
+ private safeCreateInstance(instantiationService: IInstantiationService, logService: ILogService, environmentService: IEnvironmentService, ctor: IConstructorSignature, phase: LifecyclePhase): void {
const now: number | undefined = phase < LifecyclePhase.Restored ? Date.now() : undefined;
try {
- instantiationService.createInstance(contribution.ctor);
+ instantiationService.createInstance(ctor);
} catch (error) {
- logService.error(`Unable to instantiate workbench contribution ${contribution.id}.`, error);
+ logService.error(`Unable to instantiate workbench contribution ${ctor.name}.`, error);
}
- if (typeof now === 'number') {
+ if (typeof now === 'number' && !environmentService.isBuilt /* only log out of sources where we have good ctor names */) {
const time = Date.now() - now;
- if (time > 5) {
- logService.warn(`Workbench contribution ${contribution.id} blocked restore phase by ${time}ms.`);
+ if (time > 20) {
+ logService.warn(`Workbench contribution ${ctor.name} blocked restore phase by ${time}ms.`);
}
}
}
diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts
index b89e7d795d6..8c49d1bf96b 100644
--- a/src/vs/workbench/common/theme.ts
+++ b/src/vs/workbench/common/theme.ts
@@ -639,6 +639,13 @@ export const ACTIVITY_BAR_SETTINGS_PROFILE_HOVER_FOREGROUND = registerColor('act
hcLight: ACTIVITY_BAR_FOREGROUND
}, localize('activityBarItem.settingsProfilesHoverForeground', "Foreground color for the settings profile entry on the activity bar when hovering."));
+export const ACTIVITY_BAR_SETTINGS_PROFILE_BACKGROUND = registerColor('activityBarItem.settingsProfilesBackground', {
+ dark: lighten(ACTIVITY_BAR_BACKGROUND, 0.5),
+ light: darken(ACTIVITY_BAR_BACKGROUND, 0.12),
+ hcDark: null,
+ hcLight: null
+}, localize('statusBarItemSettingsProfileBackground', "Background color for the settings profile entry on the activity bar."));
+
// < --- Remote --- >
export const STATUS_BAR_HOST_NAME_BACKGROUND = registerColor('statusBarItem.remoteBackground', {
diff --git a/src/vs/workbench/contrib/audioCues/browser/audioCueService.ts b/src/vs/workbench/contrib/audioCues/browser/audioCueService.ts
index 1c26424410f..ce7a4d8a1b0 100644
--- a/src/vs/workbench/contrib/audioCues/browser/audioCueService.ts
+++ b/src/vs/workbench/contrib/audioCues/browser/audioCueService.ts
@@ -152,7 +152,8 @@ export class Sound {
public static readonly foldedArea = Sound.register({ fileName: 'foldedAreas.mp3' });
public static readonly break = Sound.register({ fileName: 'break.mp3' });
public static readonly quickFixes = Sound.register({ fileName: 'quickFixes.mp3' });
- public static readonly taskEnded = Sound.register({ fileName: 'taskEnded.mp3' });
+ public static readonly taskCompleted = Sound.register({ fileName: 'taskCompleted.mp3' });
+ public static readonly taskFailed = Sound.register({ fileName: 'taskFailed.mp3' });
public static readonly terminalBell = Sound.register({ fileName: 'terminalBell.mp3' });
private constructor(public readonly fileName: string) { }
@@ -201,6 +202,12 @@ export class AudioCue {
settingsKey: 'audioCues.lineHasInlineSuggestion',
});
+ public static readonly terminalQuickFix = AudioCue.register({
+ name: localize('audioCues.terminalQuickFix.name', 'Terminal Quick Fix'),
+ sound: Sound.quickFixes,
+ settingsKey: 'audioCues.terminalQuickFix',
+ });
+
public static readonly onDebugBreak = AudioCue.register({
name: localize('audioCues.onDebugBreak.name', 'Debugger Stopped on Breakpoint'),
sound: Sound.break,
@@ -213,10 +220,16 @@ export class AudioCue {
settingsKey: 'audioCues.noInlayHints'
});
- public static readonly taskEnded = AudioCue.register({
- name: localize('audioCues.taskEnded', 'Task Ended'),
- sound: Sound.taskEnded,
- settingsKey: 'audioCues.taskEnded'
+ public static readonly taskCompleted = AudioCue.register({
+ name: localize('audioCues.taskCompleted', 'Task Completed'),
+ sound: Sound.taskCompleted,
+ settingsKey: 'audioCues.taskCompleted'
+ });
+
+ public static readonly taskFailed = AudioCue.register({
+ name: localize('audioCues.taskFailed', 'Task Failed'),
+ sound: Sound.taskFailed,
+ settingsKey: 'audioCues.taskFailed'
});
public static readonly terminalBell = AudioCue.register({
diff --git a/src/vs/workbench/contrib/audioCues/browser/audioCues.contribution.ts b/src/vs/workbench/contrib/audioCues/browser/audioCues.contribution.ts
index facb74870e4..74b817d6c1a 100644
--- a/src/vs/workbench/contrib/audioCues/browser/audioCues.contribution.ts
+++ b/src/vs/workbench/contrib/audioCues/browser/audioCues.contribution.ts
@@ -17,8 +17,8 @@ import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle
registerSingleton(IAudioCueService, AudioCueService, false);
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(AudioCueLineFeatureContribution, 'AudioCueLineFeatureContribution', LifecyclePhase.Restored);
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(AudioCueLineDebuggerContribution, 'AudioCueLineDebuggerContribution', LifecyclePhase.Restored);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(AudioCueLineFeatureContribution, LifecyclePhase.Restored);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(AudioCueLineDebuggerContribution, LifecyclePhase.Restored);
const audioCueFeatureBase: IConfigurationPropertySchema = {
'type': 'string',
@@ -72,8 +72,16 @@ Registry.as(ConfigurationExtensions.Configuration).regis
'description': localize('audioCues.noInlayHints', "Plays a sound when trying to read a line with inlay hints that has no inlay hints."),
...audioCueFeatureBase,
},
- 'audioCues.taskEnded': {
- 'description': localize('audioCues.taskEnded', "Plays a sound when a task ends."),
+ 'audioCues.taskCompleted': {
+ 'description': localize('audioCues.taskCompleted', "Plays a sound when a task completed."),
+ ...audioCueFeatureBase,
+ },
+ 'audioCues.taskFailed': {
+ 'description': localize('audioCues.taskFailed', "Plays a sound when a task fails (non-zero exit code)."),
+ ...audioCueFeatureBase,
+ },
+ 'audioCues.terminalQuickFix': {
+ 'description': localize('audioCues.terminalQuickFix', "Plays a sound when a terminal quick fixes are available"),
...audioCueFeatureBase,
},
}
diff --git a/src/vs/workbench/contrib/audioCues/browser/media/taskCompleted.mp3 b/src/vs/workbench/contrib/audioCues/browser/media/taskCompleted.mp3
new file mode 100644
index 00000000000..dd3fecbef57
Binary files /dev/null and b/src/vs/workbench/contrib/audioCues/browser/media/taskCompleted.mp3 differ
diff --git a/src/vs/workbench/contrib/audioCues/browser/media/taskEnded.mp3 b/src/vs/workbench/contrib/audioCues/browser/media/taskEnded.mp3
deleted file mode 100644
index 37b832b02b5..00000000000
Binary files a/src/vs/workbench/contrib/audioCues/browser/media/taskEnded.mp3 and /dev/null differ
diff --git a/src/vs/workbench/contrib/audioCues/browser/media/taskFailed.mp3 b/src/vs/workbench/contrib/audioCues/browser/media/taskFailed.mp3
new file mode 100644
index 00000000000..7a155fa67d3
Binary files /dev/null and b/src/vs/workbench/contrib/audioCues/browser/media/taskFailed.mp3 differ
diff --git a/src/vs/workbench/contrib/bracketPairColorizer2Telemetry/browser/bracketPairColorizer2Telemetry.contribution.ts b/src/vs/workbench/contrib/bracketPairColorizer2Telemetry/browser/bracketPairColorizer2Telemetry.contribution.ts
index af4f63a1d65..c1051e9d4cf 100644
--- a/src/vs/workbench/contrib/bracketPairColorizer2Telemetry/browser/bracketPairColorizer2Telemetry.contribution.ts
+++ b/src/vs/workbench/contrib/bracketPairColorizer2Telemetry/browser/bracketPairColorizer2Telemetry.contribution.ts
@@ -51,5 +51,5 @@ class BracketPairColorizer2TelemetryContribution {
}
}
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(BracketPairColorizer2TelemetryContribution, 'BracketPairColorizer2TelemetryContribution', LifecyclePhase.Restored);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(BracketPairColorizer2TelemetryContribution, LifecyclePhase.Restored);
diff --git a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts
index ae0212db0c5..00a833511b0 100644
--- a/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts
+++ b/src/vs/workbench/contrib/bulkEdit/browser/bulkEditService.ts
@@ -16,7 +16,7 @@ import { localize } from 'vs/nls';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ILogService } from 'vs/platform/log/common/log';
import { IProgress, IProgressStep, Progress } from 'vs/platform/progress/common/progress';
@@ -184,7 +184,7 @@ export class BulkEditService implements IBulkEditService {
let edits = liftEdits(Array.isArray(editsIn) ? editsIn : editsIn.edits);
if (edits.length === 0) {
- return { ariaSummary: localize('nothing', "Made no edits") };
+ return { ariaSummary: localize('nothing', "Made no edits"), isApplied: false };
}
if (this._previewHandler && (options?.showPreview || edits.some(value => value.metadata?.needsConfirmation))) {
@@ -244,11 +244,11 @@ export class BulkEditService implements IBulkEditService {
// when enabled (option AND setting) loop over all dirty working copies and trigger save
// for those that were involved in this bulk edit operation.
- if (options?.respectAutoSaveConfig && this._configService.getValue(autoSaveSetting) === true && resources.length > 1) {
+ if (options?.respectAutoSaveConfig && this._configService.getValue(autoSaveSetting) === true) {
await this._saveAll(resources);
}
- return { ariaSummary: bulkEdit.ariaMessage() };
+ return { ariaSummary: bulkEdit.ariaMessage(), isApplied: edits.length > 0 };
} catch (err) {
// console.log('apply FAILED');
// console.log(err);
@@ -289,7 +289,7 @@ export class BulkEditService implements IBulkEditService {
}
}
-registerSingleton(IBulkEditService, BulkEditService, true);
+registerSingleton(IBulkEditService, BulkEditService, InstantiationType.Delayed);
const autoSaveSetting = 'files.refactoring.autoSave';
diff --git a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts
index 19164716538..4d51be59e2f 100644
--- a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts
+++ b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEdit.contribution.ts
@@ -323,9 +323,7 @@ registerAction2(class ToggleGrouping extends Action2 {
});
Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(
- BulkEditPreviewContribution,
- 'BulkEditPreviewContribution',
- LifecyclePhase.Ready
+ BulkEditPreviewContribution, LifecyclePhase.Ready
);
const refactorPreviewViewIcon = registerIcon('refactor-preview-view-icon', Codicon.lightbulb, localize('refactorPreviewViewIcon', 'View icon of the refactor preview view.'));
diff --git a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts
index cb829e3eb0b..33aae4de46f 100644
--- a/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts
+++ b/src/vs/workbench/contrib/bulkEdit/browser/preview/bulkEditPane.ts
@@ -26,9 +26,7 @@ import { ResourceLabels, IResourceLabelsContainer } from 'vs/workbench/browser/l
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import Severity from 'vs/base/common/severity';
import { basename, dirname } from 'vs/base/common/resources';
-import { IMenuService, MenuId } from 'vs/platform/actions/common/actions';
-import { IAction } from 'vs/base/common/actions';
-import { createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
+import { MenuId } from 'vs/platform/actions/common/actions';
import { ITreeContextMenuEvent } from 'vs/base/browser/ui/tree/tree';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
@@ -78,10 +76,9 @@ export class BulkEditPane extends ViewPane {
@ILabelService private readonly _labelService: ILabelService,
@ITextModelService private readonly _textModelService: ITextModelService,
@IDialogService private readonly _dialogService: IDialogService,
- @IMenuService private readonly _menuService: IMenuService,
@IContextMenuService private readonly _contextMenuService: IContextMenuService,
- @IContextKeyService private readonly _contextKeyService: IContextKeyService,
@IStorageService private readonly _storageService: IStorageService,
+ @IContextKeyService contextKeyService: IContextKeyService,
@IViewDescriptorService viewDescriptorService: IViewDescriptorService,
@IKeybindingService keybindingService: IKeybindingService,
@IContextMenuService contextMenuService: IContextMenuService,
@@ -92,13 +89,13 @@ export class BulkEditPane extends ViewPane {
) {
super(
{ ...options, titleMenuId: MenuId.BulkEditTitle },
- keybindingService, contextMenuService, configurationService, _contextKeyService, viewDescriptorService, _instaService, openerService, themeService, telemetryService
+ keybindingService, contextMenuService, configurationService, contextKeyService, viewDescriptorService, _instaService, openerService, themeService, telemetryService
);
this.element.classList.add('bulk-edit-panel', 'show-file-icons');
- this._ctxHasCategories = BulkEditPane.ctxHasCategories.bindTo(_contextKeyService);
- this._ctxGroupByFile = BulkEditPane.ctxGroupByFile.bindTo(_contextKeyService);
- this._ctxHasCheckedChanges = BulkEditPane.ctxHasCheckedChanges.bindTo(_contextKeyService);
+ this._ctxHasCategories = BulkEditPane.ctxHasCategories.bindTo(contextKeyService);
+ this._ctxGroupByFile = BulkEditPane.ctxGroupByFile.bindTo(contextKeyService);
+ this._ctxHasCheckedChanges = BulkEditPane.ctxHasCheckedChanges.bindTo(contextKeyService);
}
override dispose(): void {
@@ -380,16 +377,11 @@ export class BulkEditPane extends ViewPane {
}
private _onContextMenu(e: ITreeContextMenuEvent): void {
- const menu = this._menuService.createMenu(MenuId.BulkEditContext, this._contextKeyService);
- const actions: IAction[] = [];
- createAndFillInContextMenuActions(menu, undefined, actions);
this._contextMenuService.showContextMenu({
- getActions: () => actions,
- getAnchor: () => e.anchor,
- onHide: () => {
- menu.dispose();
- }
+ menuId: MenuId.BulkEditContext,
+ contextKeyService: this.contextKeyService,
+ getAnchor: () => e.anchor
});
}
}
diff --git a/src/vs/workbench/contrib/codeActions/browser/codeActions.contribution.ts b/src/vs/workbench/contrib/codeActions/browser/codeActions.contribution.ts
index f3d4de633ba..afcf9915643 100644
--- a/src/vs/workbench/contrib/codeActions/browser/codeActions.contribution.ts
+++ b/src/vs/workbench/contrib/codeActions/browser/codeActions.contribution.ts
@@ -30,4 +30,4 @@ class WorkbenchConfigurationContribution {
}
Registry.as(WorkbenchExtensions.Workbench)
- .registerWorkbenchContribution(WorkbenchConfigurationContribution, 'WorkbenchConfigurationContribution', LifecyclePhase.Eventually);
+ .registerWorkbenchContribution(WorkbenchConfigurationContribution, LifecyclePhase.Eventually);
diff --git a/src/vs/workbench/contrib/codeEditor/browser/inspectKeybindings.ts b/src/vs/workbench/contrib/codeEditor/browser/inspectKeybindings.ts
index 73808153cd7..dc493bf295c 100644
--- a/src/vs/workbench/contrib/codeEditor/browser/inspectKeybindings.ts
+++ b/src/vs/workbench/contrib/codeEditor/browser/inspectKeybindings.ts
@@ -8,7 +8,7 @@ import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
class InspectKeyMap extends Action2 {
@@ -17,7 +17,7 @@ class InspectKeyMap extends Action2 {
super({
id: 'workbench.action.inspectKeyMappings',
title: { value: localize('workbench.action.inspectKeyMap', "Inspect Key Mappings"), original: 'Inspect Key Mappings' },
- category: CATEGORIES.Developer,
+ category: Categories.Developer,
f1: true
});
}
@@ -38,7 +38,7 @@ class InspectKeyMapJSON extends Action2 {
super({
id: 'workbench.action.inspectKeyMappingsJSON',
title: { value: localize('workbench.action.inspectKeyMapJSON', "Inspect Key Mappings (JSON)"), original: 'Inspect Key Mappings (JSON)' },
- category: CATEGORIES.Developer,
+ category: Categories.Developer,
f1: true
});
}
diff --git a/src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts b/src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts
index 3cbf02252d0..5f44dc67e26 100644
--- a/src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts
+++ b/src/vs/workbench/contrib/codeEditor/browser/outline/documentSymbolsOutline.ts
@@ -432,4 +432,4 @@ class DocumentSymbolsOutlineCreator implements IOutlineCreator(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DocumentSymbolsOutlineCreator, 'DocumentSymbolsOutlineCreator', LifecyclePhase.Eventually);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DocumentSymbolsOutlineCreator, LifecyclePhase.Eventually);
diff --git a/src/vs/workbench/contrib/codeEditor/browser/saveParticipants.ts b/src/vs/workbench/contrib/codeEditor/browser/saveParticipants.ts
index 2049f12a728..4b966ec9bd1 100644
--- a/src/vs/workbench/contrib/codeEditor/browser/saveParticipants.ts
+++ b/src/vs/workbench/contrib/codeEditor/browser/saveParticipants.ts
@@ -402,4 +402,4 @@ export class SaveParticipantsContribution extends Disposable implements IWorkben
}
const workbenchContributionsRegistry = Registry.as(WorkbenchContributionsExtensions.Workbench);
-workbenchContributionsRegistry.registerWorkbenchContribution(SaveParticipantsContribution, 'SaveParticipantsContribution', LifecyclePhase.Restored);
+workbenchContributionsRegistry.registerWorkbenchContribution(SaveParticipantsContribution, LifecyclePhase.Restored);
diff --git a/src/vs/workbench/contrib/codeEditor/browser/toggleMinimap.ts b/src/vs/workbench/contrib/codeEditor/browser/toggleMinimap.ts
index f0ea2a89e33..33be24d8270 100644
--- a/src/vs/workbench/contrib/codeEditor/browser/toggleMinimap.ts
+++ b/src/vs/workbench/contrib/codeEditor/browser/toggleMinimap.ts
@@ -7,7 +7,7 @@ import { localize } from 'vs/nls';
import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
export class ToggleMinimapAction extends Action2 {
@@ -22,7 +22,7 @@ export class ToggleMinimapAction extends Action2 {
original: 'Toggle Minimap',
mnemonicTitle: localize({ key: 'miMinimap', comment: ['&& denotes a mnemonic'] }, "&&Minimap")
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true,
toggled: ContextKeyExpr.equals('config.editor.minimap.enabled', true),
menu: {
diff --git a/src/vs/workbench/contrib/codeEditor/browser/toggleMultiCursorModifier.ts b/src/vs/workbench/contrib/codeEditor/browser/toggleMultiCursorModifier.ts
index 58424f5f37c..fea60d0515a 100644
--- a/src/vs/workbench/contrib/codeEditor/browser/toggleMultiCursorModifier.ts
+++ b/src/vs/workbench/contrib/codeEditor/browser/toggleMultiCursorModifier.ts
@@ -64,7 +64,7 @@ class MultiCursorModifierContextKeyController implements IWorkbenchContribution
}
}
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(MultiCursorModifierContextKeyController, 'MultiCursorModifierContextKeyController', LifecyclePhase.Restored);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(MultiCursorModifierContextKeyController, LifecyclePhase.Restored);
registerAction2(ToggleMultiCursorModifierAction);
diff --git a/src/vs/workbench/contrib/codeEditor/browser/toggleRenderControlCharacter.ts b/src/vs/workbench/contrib/codeEditor/browser/toggleRenderControlCharacter.ts
index 0990dd2f454..9bc7a2b18ed 100644
--- a/src/vs/workbench/contrib/codeEditor/browser/toggleRenderControlCharacter.ts
+++ b/src/vs/workbench/contrib/codeEditor/browser/toggleRenderControlCharacter.ts
@@ -7,7 +7,7 @@ import { localize } from 'vs/nls';
import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
-import { CATEGORIES, } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
export class ToggleRenderControlCharacterAction extends Action2 {
@@ -22,7 +22,7 @@ export class ToggleRenderControlCharacterAction extends Action2 {
mnemonicTitle: localize({ key: 'miToggleRenderControlCharacters', comment: ['&& denotes a mnemonic'] }, "Render &&Control Characters"),
original: 'Toggle Control Characters'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true,
toggled: ContextKeyExpr.equals('config.editor.renderControlCharacters', true),
menu: {
diff --git a/src/vs/workbench/contrib/codeEditor/browser/toggleRenderWhitespace.ts b/src/vs/workbench/contrib/codeEditor/browser/toggleRenderWhitespace.ts
index c8bab9f321f..297c10d0cbb 100644
--- a/src/vs/workbench/contrib/codeEditor/browser/toggleRenderWhitespace.ts
+++ b/src/vs/workbench/contrib/codeEditor/browser/toggleRenderWhitespace.ts
@@ -7,7 +7,7 @@ import { localize } from 'vs/nls';
import { Action2, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
-import { CATEGORIES, } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
class ToggleRenderWhitespaceAction extends Action2 {
@@ -22,7 +22,7 @@ class ToggleRenderWhitespaceAction extends Action2 {
mnemonicTitle: localize({ key: 'miToggleRenderWhitespace', comment: ['&& denotes a mnemonic'] }, "&&Render Whitespace"),
original: 'Toggle Render Whitespace'
},
- category: CATEGORIES.View,
+ category: Categories.View,
f1: true,
toggled: ContextKeyExpr.notEquals('config.editor.renderWhitespace', 'none'),
menu: {
diff --git a/src/vs/workbench/contrib/codeEditor/browser/toggleWordWrap.ts b/src/vs/workbench/contrib/codeEditor/browser/toggleWordWrap.ts
index 947a3d1cfb4..56e5219cb2b 100644
--- a/src/vs/workbench/contrib/codeEditor/browser/toggleWordWrap.ts
+++ b/src/vs/workbench/contrib/codeEditor/browser/toggleWordWrap.ts
@@ -269,7 +269,7 @@ class EditorWordWrapContextKeyTracker implements IWorkbenchContribution {
}
const workbenchRegistry = Registry.as(Extensions.Workbench);
-workbenchRegistry.registerWorkbenchContribution(EditorWordWrapContextKeyTracker, 'EditorWordWrapContextKeyTracker', LifecyclePhase.Ready);
+workbenchRegistry.registerWorkbenchContribution(EditorWordWrapContextKeyTracker, LifecyclePhase.Ready);
registerEditorContribution(ToggleWordWrapController.ID, ToggleWordWrapController);
diff --git a/src/vs/workbench/contrib/codeEditor/electron-sandbox/displayChangeRemeasureFonts.ts b/src/vs/workbench/contrib/codeEditor/electron-sandbox/displayChangeRemeasureFonts.ts
index 4a2368a13a1..4d53ac15383 100644
--- a/src/vs/workbench/contrib/codeEditor/electron-sandbox/displayChangeRemeasureFonts.ts
+++ b/src/vs/workbench/contrib/codeEditor/electron-sandbox/displayChangeRemeasureFonts.ts
@@ -23,4 +23,4 @@ class DisplayChangeRemeasureFonts extends Disposable implements IWorkbenchContri
}
}
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DisplayChangeRemeasureFonts, 'DisplayChangeRemeasureFonts', LifecyclePhase.Eventually);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DisplayChangeRemeasureFonts, LifecyclePhase.Eventually);
diff --git a/src/vs/workbench/contrib/codeEditor/electron-sandbox/selectionClipboard.ts b/src/vs/workbench/contrib/codeEditor/electron-sandbox/selectionClipboard.ts
index 2801c0cb4c0..b0c66b9acb9 100644
--- a/src/vs/workbench/contrib/codeEditor/electron-sandbox/selectionClipboard.ts
+++ b/src/vs/workbench/contrib/codeEditor/electron-sandbox/selectionClipboard.ts
@@ -135,7 +135,7 @@ class PasteSelectionClipboardAction extends EditorAction {
}
registerEditorContribution(SelectionClipboardContributionID, SelectionClipboard);
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(SelectionClipboardPastePreventer, 'SelectionClipboardPastePreventer', LifecyclePhase.Ready);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(SelectionClipboardPastePreventer, LifecyclePhase.Ready);
if (platform.isLinux) {
registerEditorAction(PasteSelectionClipboardAction);
}
diff --git a/src/vs/workbench/contrib/codeEditor/electron-sandbox/sleepResumeRepaintMinimap.ts b/src/vs/workbench/contrib/codeEditor/electron-sandbox/sleepResumeRepaintMinimap.ts
index 78219ebf9ef..f0e5225baa5 100644
--- a/src/vs/workbench/contrib/codeEditor/electron-sandbox/sleepResumeRepaintMinimap.ts
+++ b/src/vs/workbench/contrib/codeEditor/electron-sandbox/sleepResumeRepaintMinimap.ts
@@ -24,4 +24,4 @@ class SleepResumeRepaintMinimap extends Disposable implements IWorkbenchContribu
}
}
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(SleepResumeRepaintMinimap, 'SleepResumeRepaintMinimap', LifecyclePhase.Eventually);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(SleepResumeRepaintMinimap, LifecyclePhase.Eventually);
diff --git a/src/vs/workbench/contrib/codeEditor/electron-sandbox/startDebugTextMate.ts b/src/vs/workbench/contrib/codeEditor/electron-sandbox/startDebugTextMate.ts
index 5d6f3d31359..032f263903d 100644
--- a/src/vs/workbench/contrib/codeEditor/electron-sandbox/startDebugTextMate.ts
+++ b/src/vs/workbench/contrib/codeEditor/electron-sandbox/startDebugTextMate.ts
@@ -6,7 +6,7 @@
import * as nls from 'vs/nls';
import { Range } from 'vs/editor/common/core/range';
import { Action2, registerAction2 } from 'vs/platform/actions/common/actions';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { ITextMateService } from 'vs/workbench/services/textMate/browser/textMate';
import { IModelService } from 'vs/editor/common/services/model';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
@@ -30,7 +30,7 @@ class StartDebugTextMate extends Action2 {
super({
id: 'editor.action.startDebugTextMate',
title: { value: nls.localize('startDebugTextMate', "Start Text Mate Syntax Grammar Logging"), original: 'Start Text Mate Syntax Grammar Logging' },
- category: CATEGORIES.Developer,
+ category: Categories.Developer,
f1: true
});
}
diff --git a/src/vs/workbench/contrib/comments/browser/commentMenus.ts b/src/vs/workbench/contrib/comments/browser/commentMenus.ts
index 79e647f9121..dae9f44956f 100644
--- a/src/vs/workbench/contrib/comments/browser/commentMenus.ts
+++ b/src/vs/workbench/contrib/comments/browser/commentMenus.ts
@@ -35,10 +35,6 @@ export class CommentMenus implements IDisposable {
return this.getMenu(MenuId.CommentThreadTitleContext, contextKeyService);
}
- getCommentThreadCommentContextActions(contextKeyService: IContextKeyService): IMenu {
- return this.getMenu(MenuId.CommentThreadCommentContext, contextKeyService);
- }
-
private getMenu(menuId: MenuId, contextKeyService: IContextKeyService): IMenu {
const menu = this.menuService.createMenu(menuId, contextKeyService);
diff --git a/src/vs/workbench/contrib/comments/browser/commentNode.ts b/src/vs/workbench/contrib/comments/browser/commentNode.ts
index df7f71d462a..8ca985d8f43 100644
--- a/src/vs/workbench/contrib/comments/browser/commentNode.ts
+++ b/src/vs/workbench/contrib/comments/browser/commentNode.ts
@@ -26,7 +26,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
import { ToggleReactionsAction, ReactionAction, ReactionActionViewItem } from './reactionsAction';
import { ICommentThreadWidget } from 'vs/workbench/contrib/comments/common/commentThreadWidget';
-import { MenuItemAction, SubmenuItemAction, IMenu } from 'vs/platform/actions/common/actions';
+import { MenuItemAction, SubmenuItemAction, IMenu, MenuId } from 'vs/platform/actions/common/actions';
import { MenuEntryActionViewItem, SubmenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { CommentFormActions } from 'vs/workbench/contrib/comments/browser/commentFormActions';
@@ -574,13 +574,11 @@ export class CommentNode extends Disposable {
private onContextMenu(e: MouseEvent) {
- const actions = this._commentMenus.getCommentThreadCommentContextActions(this._contextKeyService).getActions({ shouldForwardArgs: true }).map((value) => value[1]).flat();
- if (!actions.length) {
- return;
- }
this.contextMenuService.showContextMenu({
getAnchor: () => e,
- getActions: () => actions,
+ menuId: MenuId.CommentThreadCommentContext,
+ menuActionOptions: { shouldForwardArgs: true },
+ contextKeyService: this._contextKeyService,
actionRunner: new ActionRunner(),
getActionsContext: () => {
return this.commentNodeContext;
diff --git a/src/vs/workbench/contrib/comments/browser/commentsViewActions.ts b/src/vs/workbench/contrib/comments/browser/commentsViewActions.ts
index 4445e3a05b0..420029d895e 100644
--- a/src/vs/workbench/contrib/comments/browser/commentsViewActions.ts
+++ b/src/vs/workbench/contrib/comments/browser/commentsViewActions.ts
@@ -412,6 +412,7 @@ registerAction2(class extends ViewAction {
registerAction2(class extends Action2 {
constructor() {
super({
+ _isFakeAction: true,
id: `workbench.actions.treeView.${COMMENTS_VIEW_ID}.filter`,
title: localize('filter', "Filter"),
menu: {
diff --git a/src/vs/workbench/contrib/configExporter/electron-sandbox/configurationExportHelper.contribution.ts b/src/vs/workbench/contrib/configExporter/electron-sandbox/configurationExportHelper.contribution.ts
index 9a0c2be015a..127283add02 100644
--- a/src/vs/workbench/contrib/configExporter/electron-sandbox/configurationExportHelper.contribution.ts
+++ b/src/vs/workbench/contrib/configExporter/electron-sandbox/configurationExportHelper.contribution.ts
@@ -23,4 +23,4 @@ export class ExtensionPoints implements IWorkbenchContribution {
}
}
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(ExtensionPoints, 'ExtensionPoints', LifecyclePhase.Restored);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(ExtensionPoints, LifecyclePhase.Restored);
diff --git a/src/vs/workbench/contrib/contextmenu/browser/contextmenu.contribution.ts b/src/vs/workbench/contrib/contextmenu/browser/contextmenu.contribution.ts
index 79cf442038e..ee27b0aefa9 100644
--- a/src/vs/workbench/contrib/contextmenu/browser/contextmenu.contribution.ts
+++ b/src/vs/workbench/contrib/contextmenu/browser/contextmenu.contribution.ts
@@ -25,4 +25,4 @@ class ContextMenuContribution implements IWorkbenchContribution {
}
Registry.as(WorkbenchExtensions.Workbench)
- .registerWorkbenchContribution(ContextMenuContribution, 'ContextMenuContribution', LifecyclePhase.Eventually);
+ .registerWorkbenchContribution(ContextMenuContribution, LifecyclePhase.Eventually);
diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditor.contribution.ts b/src/vs/workbench/contrib/customEditor/browser/customEditor.contribution.ts
index f7ce07c9213..f8673805e33 100644
--- a/src/vs/workbench/contrib/customEditor/browser/customEditor.contribution.ts
+++ b/src/vs/workbench/contrib/customEditor/browser/customEditor.contribution.ts
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { Registry } from 'vs/platform/registry/common/platform';
import { EditorPaneDescriptor, IEditorPaneRegistry } from 'vs/workbench/browser/editor';
import { Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
@@ -16,7 +16,7 @@ import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle
import { CustomEditorInput } from './customEditorInput';
import { CustomEditorService } from './customEditors';
-registerSingleton(ICustomEditorService, CustomEditorService, false);
+registerSingleton(ICustomEditorService, CustomEditorService, InstantiationType.Delayed);
Registry.as(EditorExtensions.EditorPane)
.registerEditorPane(
@@ -34,4 +34,4 @@ Registry.as(EditorExtensions.EditorFactory)
CustomEditorInputSerializer);
Registry.as(WorkbenchExtensions.Workbench)
- .registerWorkbenchContribution(ComplexCustomWorkingCopyEditorHandler, 'ComplexCustomWorkingCopyEditorHandler', LifecyclePhase.Starting);
+ .registerWorkbenchContribution(ComplexCustomWorkingCopyEditorHandler, LifecyclePhase.Starting);
diff --git a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts
index 414b1b2494e..42b8cbf0f94 100644
--- a/src/vs/workbench/contrib/debug/browser/breakpointsView.ts
+++ b/src/vs/workbench/contrib/debug/browser/breakpointsView.ts
@@ -294,7 +294,7 @@ export class BreakpointsView extends ViewPane {
return langId && dbg.interestedInLanguage(langId);
});
- if (message && debuggerHasUnverifiedBps?.length) {
+ if (message && debuggerHasUnverifiedBps?.length && this.debugService.getModel().areBreakpointsActivated()) {
if (delayed) {
const mdown = new MarkdownString(undefined, { isTrusted: true }).appendMarkdown(message);
this.hintContainer.setLabel('$(warning)', undefined, { title: { markdown: mdown, markdownNotSupportedFallback: message } });
diff --git a/src/vs/workbench/contrib/debug/browser/callStackView.ts b/src/vs/workbench/contrib/debug/browser/callStackView.ts
index 7643f1a8057..74631ace0ca 100644
--- a/src/vs/workbench/contrib/debug/browser/callStackView.ts
+++ b/src/vs/workbench/contrib/debug/browser/callStackView.ts
@@ -229,7 +229,7 @@ export class CallStackView extends ViewPane {
this.instantiationService.createInstance(ThreadsRenderer),
this.instantiationService.createInstance(StackFramesRenderer),
new ErrorsRenderer(),
- new LoadAllRenderer(this.themeService),
+ new LoadMoreRenderer(this.themeService),
new ShowMoreRenderer(this.themeService)
], this.dataSource, {
accessibilityProvider: new CallStackAccessibilityProvider(),
@@ -259,7 +259,7 @@ export class CallStackView extends ViewPane {
return e;
}
if (e instanceof ThreadAndSessionIds) {
- return LoadAllRenderer.LABEL;
+ return LoadMoreRenderer.LABEL;
}
return localize('showMoreStackFrames2', "Show More Stack Frames");
@@ -804,14 +804,14 @@ class ErrorsRenderer implements ICompressibleTreeRenderer {
- static readonly ID = 'loadAll';
- static readonly LABEL = localize('loadAllStackFrames', "Load All Stack Frames");
+class LoadMoreRenderer implements ICompressibleTreeRenderer {
+ static readonly ID = 'loadMore';
+ static readonly LABEL = localize('loadAllStackFrames', "Load More Stack Frames");
constructor(private readonly themeService: IThemeService) { }
get templateId(): string {
- return LoadAllRenderer.ID;
+ return LoadMoreRenderer.ID;
}
renderTemplate(container: HTMLElement): ILabelTemplateData {
@@ -826,7 +826,7 @@ class LoadAllRenderer implements ICompressibleTreeRenderer, index: number, data: ILabelTemplateData): void {
- data.label.textContent = LoadAllRenderer.LABEL;
+ data.label.textContent = LoadMoreRenderer.LABEL;
}
renderCompressedElements(node: ITreeNode, FuzzyScore>, index: number, templateData: ILabelTemplateData, height: number | undefined): void {
@@ -904,7 +904,7 @@ class CallStackDelegate implements IListVirtualDelegate {
return ErrorsRenderer.ID;
}
if (element instanceof ThreadAndSessionIds) {
- return LoadAllRenderer.ID;
+ return LoadMoreRenderer.ID;
}
// element instanceof Array
@@ -1067,7 +1067,7 @@ class CallStackAccessibilityProvider implements IListAccessibilityProvider(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DebugStatusContribution, 'DebugStatusContribution', LifecyclePhase.Eventually);
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DebugProgressContribution, 'DebugProgressContribution', LifecyclePhase.Eventually);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DebugStatusContribution, LifecyclePhase.Eventually);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DebugProgressContribution, LifecyclePhase.Eventually);
if (isWeb) {
- Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DebugTitleContribution, 'DebugTitleContribution', LifecyclePhase.Eventually);
+ Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DebugTitleContribution, LifecyclePhase.Eventually);
}
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DebugToolBar, 'DebugToolBar', LifecyclePhase.Restored);
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DebugContentProvider, 'DebugContentProvider', LifecyclePhase.Eventually);
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(StatusBarColorProvider, 'StatusBarColorProvider', LifecyclePhase.Eventually);
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DisassemblyViewContribution, 'DisassemblyViewContribution', LifecyclePhase.Eventually);
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DebugLifecycle, 'DebugLifecycle', LifecyclePhase.Eventually);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DebugToolBar, LifecyclePhase.Restored);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DebugContentProvider, LifecyclePhase.Eventually);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(StatusBarColorProvider, LifecyclePhase.Eventually);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DisassemblyViewContribution, LifecyclePhase.Eventually);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DebugLifecycle, LifecyclePhase.Eventually);
// Register Quick Access
Registry.as(QuickAccessExtensions.Quickaccess).registerQuickAccessProvider({
diff --git a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts
index 3c2568989db..fe3d0e29842 100644
--- a/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts
+++ b/src/vs/workbench/contrib/debug/browser/debugConfigurationManager.ts
@@ -3,41 +3,41 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
-import * as nls from 'vs/nls';
-import { dispose, IDisposable, DisposableStore } from 'vs/base/common/lifecycle';
-import { Event, Emitter } from 'vs/base/common/event';
-import * as objects from 'vs/base/common/objects';
-import * as json from 'vs/base/common/json';
-import { URI as uri } from 'vs/base/common/uri';
-import * as resources from 'vs/base/common/resources';
-import { IJSONSchema } from 'vs/base/common/jsonSchema';
-import { IEditorPane } from 'vs/workbench/common/editor';
-import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
-import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
-import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
-import { IFileService } from 'vs/platform/files/common/files';
-import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace';
-import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
-import { IDebugConfigurationProvider, ICompound, IConfig, IGlobalConfig, IConfigurationManager, ILaunch, CONTEXT_DEBUG_CONFIGURATION_TYPE, IConfigPresentation, DebugConfigurationProviderTriggerKind } from 'vs/workbench/contrib/debug/common/debug';
-import { IEditorService, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
-import { launchSchemaId } from 'vs/workbench/services/configuration/common/configuration';
-import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
-import { Registry } from 'vs/platform/registry/common/platform';
-import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
-import { launchSchema } from 'vs/workbench/contrib/debug/common/debugSchemas';
-import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
-import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
-import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
-import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
-import { withUndefinedAsNull } from 'vs/base/common/types';
+import { distinct, flatten } from 'vs/base/common/arrays';
import { sequence } from 'vs/base/common/async';
-import { IHistoryService } from 'vs/workbench/services/history/common/history';
-import { flatten, distinct } from 'vs/base/common/arrays';
-import { getVisibleAndSorted } from 'vs/workbench/contrib/debug/common/debugUtils';
+import { CancellationToken, CancellationTokenSource } from 'vs/base/common/cancellation';
+import { Emitter, Event } from 'vs/base/common/event';
+import * as json from 'vs/base/common/json';
+import { IJSONSchema } from 'vs/base/common/jsonSchema';
+import { DisposableStore, dispose, IDisposable } from 'vs/base/common/lifecycle';
+import * as objects from 'vs/base/common/objects';
+import * as resources from 'vs/base/common/resources';
+import { withUndefinedAsNull } from 'vs/base/common/types';
+import { URI as uri } from 'vs/base/common/uri';
+import * as nls from 'vs/nls';
+import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration';
+import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
+import { IFileService } from 'vs/platform/files/common/files';
+import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
+import { Extensions as JSONExtensions, IJSONContributionRegistry } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
+import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
+import { Registry } from 'vs/platform/registry/common/platform';
+import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
+import { ThemeIcon } from 'vs/platform/theme/common/themeService';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
+import { IWorkspaceContextService, IWorkspaceFolder, IWorkspaceFoldersChangeEvent, WorkbenchState } from 'vs/platform/workspace/common/workspace';
+import { IEditorPane } from 'vs/workbench/common/editor';
import { AdapterManager } from 'vs/workbench/contrib/debug/browser/debugAdapterManager';
import { debugConfigure } from 'vs/workbench/contrib/debug/browser/debugIcons';
-import { ThemeIcon } from 'vs/platform/theme/common/themeService';
+import { CONTEXT_DEBUG_CONFIGURATION_TYPE, DebugConfigurationProviderTriggerKind, ICompound, IConfig, IConfigPresentation, IConfigurationManager, IDebugConfigurationProvider, IGlobalConfig, ILaunch } from 'vs/workbench/contrib/debug/common/debug';
+import { launchSchema } from 'vs/workbench/contrib/debug/common/debugSchemas';
+import { getVisibleAndSorted } from 'vs/workbench/contrib/debug/common/debugUtils';
+import { launchSchemaId } from 'vs/workbench/services/configuration/common/configuration';
+import { ACTIVE_GROUP, IEditorService } from 'vs/workbench/services/editor/common/editorService';
+import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
+import { IHistoryService } from 'vs/workbench/services/history/common/history';
+import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
+import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
const jsonRegistry = Registry.as(JSONExtensions.JSONContribution);
jsonRegistry.registerSchema(launchSchemaId, launchSchema);
@@ -56,6 +56,7 @@ export class ConfigurationManager implements IConfigurationManager {
private selectedLaunch: ILaunch | undefined;
private getSelectedConfig: () => Promise = () => Promise.resolve(undefined);
private selectedType: string | undefined;
+ private selectedDynamic = false;
private toDispose: IDisposable[];
private readonly _onDidSelectConfigurationName = new Emitter();
private configProviders: IDebugConfigurationProvider[];
@@ -279,7 +280,7 @@ export class ConfigurationManager implements IConfigurationManager {
removeRecentDynamicConfigurations(name: string, type: string) {
const remaining = this.getRecentDynamicConfigurations().filter(c => c.name !== name || c.type !== type);
this.storageService.store(DEBUG_RECENT_DYNAMIC_CONFIGURATIONS, JSON.stringify(remaining), StorageScope.WORKSPACE, StorageTarget.USER);
- if (this.selectedConfiguration.name === name && this.selectedType === type) {
+ if (this.selectedConfiguration.name === name && this.selectedType === type && this.selectedDynamic) {
this.selectConfiguration(undefined, undefined);
} else {
this._onDidSelectConfigurationName.fire();
@@ -377,6 +378,7 @@ export class ConfigurationManager implements IConfigurationManager {
const previousLaunch = this.selectedLaunch;
const previousName = this.selectedName;
+ const previousSelectedDynamic = this.selectedDynamic;
this.selectedLaunch = launch;
if (this.selectedLaunch) {
@@ -436,6 +438,7 @@ export class ConfigurationManager implements IConfigurationManager {
}
this.selectedType = dynamicConfig?.type || config?.type;
+ this.selectedDynamic = !!dynamicConfig;
// Only store the selected type if we are having a dynamic configuration. Otherwise restoring this configuration from storage might be misindentified as a dynamic configuration
this.storageService.store(DEBUG_SELECTED_TYPE, dynamicConfig ? this.selectedType : undefined, StorageScope.WORKSPACE, StorageTarget.MACHINE);
@@ -445,7 +448,7 @@ export class ConfigurationManager implements IConfigurationManager {
this.debugConfigurationTypeContext.reset();
}
- if (this.selectedLaunch !== previousLaunch || this.selectedName !== previousName) {
+ if (this.selectedLaunch !== previousLaunch || this.selectedName !== previousName || previousSelectedDynamic !== this.selectedDynamic) {
this._onDidSelectConfigurationName.fire();
}
}
diff --git a/src/vs/workbench/contrib/debug/browser/extensionHostDebugService.ts b/src/vs/workbench/contrib/debug/browser/extensionHostDebugService.ts
index a3fda1a7045..435d3fac617 100644
--- a/src/vs/workbench/contrib/debug/browser/extensionHostDebugService.ts
+++ b/src/vs/workbench/contrib/debug/browser/extensionHostDebugService.ts
@@ -9,7 +9,7 @@ import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { IExtensionHostDebugService, IOpenExtensionWindowResult } from 'vs/platform/debug/common/extensionHostDebug';
import { ExtensionHostDebugBroadcastChannel, ExtensionHostDebugChannelClient } from 'vs/platform/debug/common/extensionHostDebugIpc';
import { IFileService } from 'vs/platform/files/common/files';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { ILogService } from 'vs/platform/log/common/log';
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
import { isFolderToOpen, isWorkspaceToOpen } from 'vs/platform/window/common/window';
@@ -172,4 +172,4 @@ class BrowserExtensionHostDebugService extends ExtensionHostDebugChannelClient i
}
}
-registerSingleton(IExtensionHostDebugService, BrowserExtensionHostDebugService, true);
+registerSingleton(IExtensionHostDebugService, BrowserExtensionHostDebugService, InstantiationType.Delayed);
diff --git a/src/vs/workbench/contrib/debug/browser/repl.ts b/src/vs/workbench/contrib/debug/browser/repl.ts
index dfcdd381ef0..971f1e341f8 100644
--- a/src/vs/workbench/contrib/debug/browser/repl.ts
+++ b/src/vs/workbench/contrib/debug/browser/repl.ts
@@ -879,6 +879,7 @@ function getReplView(viewsService: IViewsService): Repl | undefined {
registerAction2(class extends Action2 {
constructor() {
super({
+ _isFakeAction: true,
id: FILTER_ACTION_ID,
title: localize('filter', "Filter"),
f1: false,
@@ -887,7 +888,7 @@ registerAction2(class extends Action2 {
group: 'navigation',
when: ContextKeyExpr.equals('view', REPL_VIEW_ID),
order: 10
- }
+ },
});
}
diff --git a/src/vs/workbench/contrib/debug/browser/replViewer.ts b/src/vs/workbench/contrib/debug/browser/replViewer.ts
index 94b7ecd5b13..9c4adf953f3 100644
--- a/src/vs/workbench/contrib/debug/browser/replViewer.ts
+++ b/src/vs/workbench/contrib/debug/browser/replViewer.ts
@@ -312,18 +312,21 @@ export class ReplDelegate extends CachedListVirtualDelegate {
return super.getHeight(element);
}
+ /**
+ * With wordWrap enabled, this is an estimate. With wordWrap disabled, this is the real height that the list will use.
+ */
protected estimateHeight(element: IReplElement, ignoreValueLength = false): number {
const lineHeight = this.replOptions.replConfiguration.lineHeight;
- const countNumberOfLines = (str: string) => Math.max(1, (str && str.match(/\r\n|\n/g) || []).length);
+ const countNumberOfLines = (str: string) => str.match(/\n/g)?.length ?? 0;
const hasValue = (e: any): e is { value: string } => typeof e.value === 'string';
- // Calculate a rough overestimation for the height
- // For every 70 characters increase the number of lines needed beyond the first
if (hasValue(element) && !isNestedVariable(element)) {
const value = element.value;
- const valueRows = countNumberOfLines(value) + (ignoreValueLength ? 0 : Math.floor(value.length / 70));
+ const valueRows = countNumberOfLines(value)
+ + (ignoreValueLength ? 0 : Math.floor(value.length / 70)) // Make an estimate for wrapping
+ + (element instanceof SimpleReplElement ? 0 : 1); // A SimpleReplElement ends in \n if it's a complete line
- return valueRows * lineHeight;
+ return Math.max(valueRows, 1) * lineHeight;
}
return lineHeight;
diff --git a/src/vs/workbench/contrib/deprecatedExtensionMigrator/browser/deprecatedExtensionMigrator.contribution.ts b/src/vs/workbench/contrib/deprecatedExtensionMigrator/browser/deprecatedExtensionMigrator.contribution.ts
index 2a91d82f0d8..3abb2f55315 100644
--- a/src/vs/workbench/contrib/deprecatedExtensionMigrator/browser/deprecatedExtensionMigrator.contribution.ts
+++ b/src/vs/workbench/contrib/deprecatedExtensionMigrator/browser/deprecatedExtensionMigrator.contribution.ts
@@ -100,4 +100,4 @@ interface State {
}[];
}
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DeprecatedExtensionMigratorContribution, 'DeprecatedExtensionMigratorContribution', LifecyclePhase.Restored);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(DeprecatedExtensionMigratorContribution, LifecyclePhase.Restored);
diff --git a/src/vs/workbench/contrib/editSessions/browser/editSessions.contribution.ts b/src/vs/workbench/contrib/editSessions/browser/editSessions.contribution.ts
index 146864b176f..af450bcd68e 100644
--- a/src/vs/workbench/contrib/editSessions/browser/editSessions.contribution.ts
+++ b/src/vs/workbench/contrib/editSessions/browser/editSessions.contribution.ts
@@ -10,7 +10,7 @@ import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecyc
import { Action2, IAction2Options, MenuRegistry, registerAction2 } from 'vs/platform/actions/common/actions';
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { localize } from 'vs/nls';
-import { IEditSessionsStorageService, Change, ChangeType, Folder, EditSession, FileType, EDIT_SESSION_SYNC_CATEGORY, EDIT_SESSIONS_CONTAINER_ID, EditSessionSchemaVersion, IEditSessionsLogService, EDIT_SESSIONS_VIEW_ICON, EDIT_SESSIONS_TITLE, EDIT_SESSIONS_SHOW_VIEW, EDIT_SESSIONS_SIGNED_IN, EDIT_SESSIONS_DATA_VIEW_ID, decodeEditSessionFileContent } from 'vs/workbench/contrib/editSessions/common/editSessions';
+import { IEditSessionsStorageService, Change, ChangeType, Folder, EditSession, FileType, EDIT_SESSION_SYNC_CATEGORY, EDIT_SESSIONS_CONTAINER_ID, EditSessionSchemaVersion, IEditSessionsLogService, EDIT_SESSIONS_VIEW_ICON, EDIT_SESSIONS_TITLE, EDIT_SESSIONS_SHOW_VIEW, EDIT_SESSIONS_DATA_VIEW_ID, decodeEditSessionFileContent } from 'vs/workbench/contrib/editSessions/common/editSessions';
import { ISCMRepository, ISCMService } from 'vs/workbench/contrib/scm/common/scm';
import { IFileService } from 'vs/platform/files/common/files';
import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState } from 'vs/platform/workspace/common/workspace';
@@ -131,6 +131,7 @@ export class EditSessionsContribution extends Disposable implements IWorkbenchCo
this._register(this.fileService.registerProvider(EditSessionsFileSystemProvider.SCHEMA, new EditSessionsFileSystemProvider(this.editSessionsStorageService)));
this.lifecycleService.onWillShutdown((e) => e.join(this.autoStoreEditSession(), { id: 'autoStoreEditSession', label: localize('autoStoreEditSession', 'Storing current edit session...') }));
this._register(this.editSessionsStorageService.onDidSignIn(() => this.updateAccountsMenuBadge()));
+ this._register(this.editSessionsStorageService.onDidSignOut(() => this.updateAccountsMenuBadge()));
}
private autoResumeEditSession() {
@@ -143,22 +144,33 @@ export class EditSessionsContribution extends Disposable implements IWorkbenchCo
};
this.telemetryService.publicLog2('editSessions.continue.resume');
+ const shouldAutoResumeOnReload = this.configurationService.getValue('workbench.editSessions.autoResume') === 'onReload';
+
if (this.environmentService.editSessionId !== undefined) {
this.logService.info(`Resuming edit session, reason: found editSessionId ${this.environmentService.editSessionId} in environment service...`);
await this.resumeEditSession(this.environmentService.editSessionId).finally(() => this.environmentService.editSessionId = undefined);
- } else if (
- this.configurationService.getValue('workbench.editSessions.autoResume') === 'onReload' &&
- this.editSessionsStorageService.isSignedIn
- ) {
+ } else if (shouldAutoResumeOnReload && this.editSessionsStorageService.isSignedIn) {
this.logService.info('Resuming edit session, reason: edit sessions enabled...');
// Attempt to resume edit session based on edit workspace identifier
// Note: at this point if the user is not signed into edit sessions,
// we don't want them to be prompted to sign in and should just return early
await this.resumeEditSession(undefined, true);
- } else {
+ } else if (shouldAutoResumeOnReload) {
// The application has previously launched via a protocol URL Continue On flow
const hasApplicationLaunchedFromContinueOnFlow = this.storageService.getBoolean(EditSessionsContribution.APPLICATION_LAUNCHED_VIA_CONTINUE_ON_STORAGE_KEY, StorageScope.APPLICATION, false);
+ const handlePendingEditSessions = () => {
+ // display a badge in the accounts menu but do not prompt the user to sign in again
+ this.updateAccountsMenuBadge();
+ // attempt a resume if we are in a pending state and the user just signed in
+ const disposable = this.editSessionsStorageService.onDidSignIn(async () => {
+ disposable.dispose();
+ this.resumeEditSession(undefined, true);
+ this.storageService.remove(EditSessionsContribution.APPLICATION_LAUNCHED_VIA_CONTINUE_ON_STORAGE_KEY, StorageScope.APPLICATION);
+ this.environmentService.continueOn = undefined;
+ });
+ };
+
if ((this.environmentService.continueOn !== undefined) &&
!this.editSessionsStorageService.isSignedIn &&
// and user has not yet been prompted to sign in on this machine
@@ -169,17 +181,14 @@ export class EditSessionsContribution extends Disposable implements IWorkbenchCo
if (this.editSessionsStorageService.isSignedIn) {
await this.resumeEditSession(undefined, true);
} else {
- this.updateAccountsMenuBadge();
+ handlePendingEditSessions();
}
// store the fact that we prompted the user
} else if (!this.editSessionsStorageService.isSignedIn &&
// and user has been prompted to sign in on this machine
hasApplicationLaunchedFromContinueOnFlow === true
) {
- // display a badge in the accounts menu but do not prompt the user to sign in again
- this.updateAccountsMenuBadge();
- // attempt a resume if we are in a pending state and the user just signed in
- this._register(this.editSessionsStorageService.onDidSignIn(async () => this.resumeEditSession(undefined, true)));
+ handlePendingEditSessions();
}
}
@@ -255,8 +264,7 @@ export class EditSessionsContribution extends Disposable implements IWorkbenchCo
id: 'workbench.editSessions.actions.showEditSessions',
title: { value: localize('show edit session', "Show Edit Sessions"), original: 'Show Edit Sessions' },
category: EDIT_SESSION_SYNC_CATEGORY,
- f1: true,
- precondition: EDIT_SESSIONS_SIGNED_IN
+ f1: true
});
}
@@ -378,6 +386,10 @@ export class EditSessionsContribution extends Disposable implements IWorkbenchCo
this.logService.info(ref !== undefined ? `Resuming edit session with ref ${ref}...` : 'Resuming edit session...');
+ if (silent && !(await this.editSessionsStorageService.initialize(false, true))) {
+ return;
+ }
+
const data = await this.editSessionsStorageService.read(ref);
if (!data) {
if (ref === undefined && !silent) {
@@ -398,6 +410,9 @@ export class EditSessionsContribution extends Disposable implements IWorkbenchCo
try {
const { changes, conflictingChanges } = await this.generateChanges(editSession, ref);
+ if (changes.length === 0) {
+ return;
+ }
// TODO@joyceerhl Provide the option to diff files which would be overwritten by edit session contents
if (conflictingChanges.length > 0) {
@@ -407,13 +422,12 @@ export class EditSessionsContribution extends Disposable implements IWorkbenchCo
const result = await this.dialogService.show(
Severity.Warning,
- changes.length > 1 ?
- localize('resume edit session warning many', 'Resuming your edit session will overwrite the following {0} files. Do you want to proceed?', changes.length) :
- localize('resume edit session warning 1', 'Resuming your edit session will overwrite {0}. Do you want to proceed?', basename(changes[0].uri)),
+ conflictingChanges.length > 1 ?
+ localize('resume edit session warning many', 'Resuming your edit session will overwrite the following {0} files. Do you want to proceed?', conflictingChanges.length) :
+ localize('resume edit session warning 1', 'Resuming your edit session will overwrite {0}. Do you want to proceed?', basename(conflictingChanges[0].uri)),
[cancel, yes],
{
- custom: true,
- detail: changes.length > 1 ? getFileNamesMessage(conflictingChanges.map((c) => c.uri)) : undefined,
+ detail: conflictingChanges.length > 1 ? getFileNamesMessage(conflictingChanges.map((c) => c.uri)) : undefined,
cancelId: 0
});
@@ -794,7 +808,7 @@ const continueEditSessionExtPoint = ExtensionsRegistry.registerExtensionPoint(WorkbenchExtensions.Workbench);
-workbenchRegistry.registerWorkbenchContribution(EditSessionsContribution, 'EditSessionsContribution', LifecyclePhase.Restored);
+workbenchRegistry.registerWorkbenchContribution(EditSessionsContribution, LifecyclePhase.Restored);
Registry.as(ConfigurationExtensions.Configuration).registerConfiguration({
...workbenchConfigurationNodeBase,
diff --git a/src/vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts b/src/vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts
index 7637ef73355..fcdcc89dcce 100644
--- a/src/vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts
+++ b/src/vs/workbench/contrib/editSessions/browser/editSessionsStorageService.ts
@@ -56,6 +56,11 @@ export class EditSessionsWorkbenchService extends Disposable implements IEditSes
return this._didSignIn.event;
}
+ private _didSignOut = new Emitter();
+ get onDidSignOut() {
+ return this._didSignOut.event;
+ }
+
constructor(
@IFileService private readonly fileService: IFileService,
@IStorageService private readonly storageService: IStorageService,
@@ -162,11 +167,11 @@ export class EditSessionsWorkbenchService extends Disposable implements IEditSes
return [];
}
- public async initialize(fromContinueOn: boolean) {
+ public async initialize(fromContinueOn: boolean, silent: boolean = false) {
if (this.initialized) {
return true;
}
- this.initialized = await this.doInitialize(fromContinueOn);
+ this.initialized = await this.doInitialize(fromContinueOn, silent);
this.signedInContext.set(this.initialized);
if (this.initialized) {
this._didSignIn.fire();
@@ -181,7 +186,7 @@ export class EditSessionsWorkbenchService extends Disposable implements IEditSes
* meaning that authentication is configured and it
* can be used to communicate with the remote storage service
*/
- private async doInitialize(fromContinueOn: boolean): Promise {
+ private async doInitialize(fromContinueOn: boolean, silent: boolean): Promise {
// Wait for authentication extensions to be registered
await this.extensionService.whenInstalledExtensionsRegistered();
@@ -206,7 +211,7 @@ export class EditSessionsWorkbenchService extends Disposable implements IEditSes
return true;
}
- const authenticationSession = await this.getAuthenticationSession(fromContinueOn);
+ const authenticationSession = await this.getAuthenticationSession(fromContinueOn, silent);
if (authenticationSession !== undefined) {
this.#authenticationInfo = authenticationSession;
this.storeClient.setAuthToken(authenticationSession.token, authenticationSession.providerId);
@@ -239,7 +244,7 @@ export class EditSessionsWorkbenchService extends Disposable implements IEditSes
return currentMachineId;
}
- private async getAuthenticationSession(fromContinueOn: boolean) {
+ private async getAuthenticationSession(fromContinueOn: boolean, silent: boolean) {
// If the user signed in previously and the session is still available, reuse that without prompting the user again
if (this.existingSessionId) {
this.logService.info(`Searching for existing authentication session with ID ${this.existingSessionId}`);
@@ -247,6 +252,8 @@ export class EditSessionsWorkbenchService extends Disposable implements IEditSes
if (existingSession) {
this.logService.info(`Found existing authentication session with ID ${existingSession.session.id}`);
return { sessionId: existingSession.session.id, token: existingSession.session.idToken ?? existingSession.session.accessToken, providerId: existingSession.session.providerId };
+ } else {
+ this._didSignOut.fire();
}
}
@@ -261,6 +268,12 @@ export class EditSessionsWorkbenchService extends Disposable implements IEditSes
}
}
+ // If we aren't supposed to prompt the user because
+ // we're in a silent flow, just return here
+ if (silent) {
+ return;
+ }
+
// Ask the user to pick a preferred account
const authenticationSession = await this.getAccountPreference(fromContinueOn);
if (authenticationSession !== undefined) {
diff --git a/src/vs/workbench/contrib/editSessions/browser/editSessionsViews.ts b/src/vs/workbench/contrib/editSessions/browser/editSessionsViews.ts
index 7a70b872e41..92e368b719a 100644
--- a/src/vs/workbench/contrib/editSessions/browser/editSessionsViews.ts
+++ b/src/vs/workbench/contrib/editSessions/browser/editSessionsViews.ts
@@ -10,7 +10,7 @@ import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiati
import { Registry } from 'vs/platform/registry/common/platform';
import { TreeView, TreeViewPane } from 'vs/workbench/browser/parts/views/treeView';
import { Extensions, ITreeItem, ITreeViewDataProvider, ITreeViewDescriptor, IViewsRegistry, TreeItemCollapsibleState, TreeViewItemHandleArg, ViewContainer } from 'vs/workbench/common/views';
-import { EDIT_SESSIONS_DATA_VIEW_ID, EDIT_SESSIONS_SCHEME, EDIT_SESSIONS_SHOW_VIEW, EDIT_SESSIONS_SIGNED_IN, EDIT_SESSIONS_SIGNED_IN_KEY, EDIT_SESSIONS_TITLE, IEditSessionsStorageService } from 'vs/workbench/contrib/editSessions/common/editSessions';
+import { EDIT_SESSIONS_DATA_VIEW_ID, EDIT_SESSIONS_SCHEME, EDIT_SESSIONS_SHOW_VIEW, EDIT_SESSIONS_TITLE, IEditSessionsStorageService } from 'vs/workbench/contrib/editSessions/common/editSessions';
import { URI } from 'vs/base/common/uri';
import { fromNow } from 'vs/base/common/date';
import { Codicon } from 'vs/base/common/codicons';
@@ -54,7 +54,7 @@ export class EditSessionsDataViews extends Disposable {
canMoveView: false,
treeView,
collapsed: false,
- when: ContextKeyExpr.and(EDIT_SESSIONS_SIGNED_IN, EDIT_SESSIONS_SHOW_VIEW),
+ when: ContextKeyExpr.and(EDIT_SESSIONS_SHOW_VIEW),
order: 100,
hideByDefault: true,
}], container);
@@ -69,7 +69,7 @@ export class EditSessionsDataViews extends Disposable {
localize('storeEditSessionTitle', 'Store Edit Session')
)
),
- when: ContextKeyExpr.and(ContextKeyExpr.equals(EDIT_SESSIONS_SIGNED_IN_KEY, true), ContextKeyExpr.equals(EDIT_SESSIONS_COUNT_KEY, 0)),
+ when: ContextKeyExpr.equals(EDIT_SESSIONS_COUNT_KEY, 0),
order: 1
});
@@ -208,7 +208,8 @@ class EditSessionDataViewDataProvider implements ITreeViewDataProvider {
const sessionData = await this.editSessionsStorageService.read(session.ref);
const label = sessionData?.editSession.folders.map((folder) => folder.name).join(', ') ?? session.ref;
const machineId = sessionData?.editSession.machine;
- const description = machineId === undefined ? fromNow(session.created, true) : `${fromNow(session.created, true)}\u00a0\u00a0\u2022\u00a0\u00a0${await this.editSessionsStorageService.getMachineById(machineId)}`;
+ const machineName = machineId ? await this.editSessionsStorageService.getMachineById(machineId) : undefined;
+ const description = machineName === undefined ? fromNow(session.created, true) : `${fromNow(session.created, true)}\u00a0\u00a0\u2022\u00a0\u00a0${machineName}`;
editSessions.push({
handle: resource.toString(),
diff --git a/src/vs/workbench/contrib/editSessions/common/editSessions.ts b/src/vs/workbench/contrib/editSessions/common/editSessions.ts
index f9b84cf5bc0..99e5c8a16cc 100644
--- a/src/vs/workbench/contrib/editSessions/common/editSessions.ts
+++ b/src/vs/workbench/contrib/editSessions/common/editSessions.ts
@@ -25,8 +25,9 @@ export interface IEditSessionsStorageService {
readonly isSignedIn: boolean;
readonly onDidSignIn: Event;
+ readonly onDidSignOut: Event;
- initialize(fromContinueOn: boolean): Promise;
+ initialize(fromContinueOn: boolean, silent?: boolean): Promise;
read(ref: string | undefined): Promise<{ ref: string; editSession: EditSession } | undefined>;
write(editSession: EditSession): Promise;
delete(ref: string | null): Promise;
diff --git a/src/vs/workbench/contrib/editSessions/test/browser/editSessions.test.ts b/src/vs/workbench/contrib/editSessions/test/browser/editSessions.test.ts
index a766a535095..3bcd8b1d946 100644
--- a/src/vs/workbench/contrib/editSessions/test/browser/editSessions.test.ts
+++ b/src/vs/workbench/contrib/editSessions/test/browser/editSessions.test.ts
@@ -68,6 +68,7 @@ suite('Edit session sync', () => {
instantiationService.stub(INotificationService, new TestNotificationService());
instantiationService.stub(IEditSessionsStorageService, new class extends mock() {
override onDidSignIn = Event.None;
+ override onDidSignOut = Event.None;
});
instantiationService.stub(IProgressService, ProgressService);
instantiationService.stub(ISCMService, SCMService);
diff --git a/src/vs/workbench/contrib/experiments/browser/experiments.contribution.ts b/src/vs/workbench/contrib/experiments/browser/experiments.contribution.ts
index 2dc9b0f9303..c2d36360806 100644
--- a/src/vs/workbench/contrib/experiments/browser/experiments.contribution.ts
+++ b/src/vs/workbench/contrib/experiments/browser/experiments.contribution.ts
@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
-import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
+import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IExperimentService, ExperimentService } from 'vs/workbench/contrib/experiments/common/experimentService';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
@@ -13,9 +13,9 @@ import { ExperimentalPrompts } from 'vs/workbench/contrib/experiments/browser/ex
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration';
-registerSingleton(IExperimentService, ExperimentService, true);
+registerSingleton(IExperimentService, ExperimentService, InstantiationType.Delayed);
-Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(ExperimentalPrompts, 'ExperimentalPrompts', LifecyclePhase.Eventually);
+Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(ExperimentalPrompts, LifecyclePhase.Eventually);
const registry = Registry.as(ConfigurationExtensions.Configuration);
diff --git a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts
index e9d58bface0..6eb6663c74c 100644
--- a/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts
+++ b/src/vs/workbench/contrib/extensions/browser/abstractRuntimeExtensionsEditor.ts
@@ -35,7 +35,7 @@ import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/common/runtimeExtensionsInput';
import { Action2, MenuId } from 'vs/platform/actions/common/actions';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
interface IExtensionProfileInformation {
@@ -491,7 +491,7 @@ export class ShowRuntimeExtensionsAction extends Action2 {
super({
id: 'workbench.action.showRuntimeExtensions',
title: { value: nls.localize('showRuntimeExtensions', "Show Running Extensions"), original: 'Show Running Extensions' },
- category: CATEGORIES.Developer,
+ category: Categories.Developer,
f1: true,
menu: {
id: MenuId.ViewContainerTitle,
diff --git a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts
index 96449b7b363..65d0cc03d7e 100644
--- a/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts
+++ b/src/vs/workbench/contrib/extensions/browser/extensionEditor.ts
@@ -29,7 +29,7 @@ import {
UpdateAction, ReloadAction, EnableDropDownAction, DisableDropDownAction, ExtensionStatusLabelAction, SetFileIconThemeAction, SetColorThemeAction,
RemoteInstallAction, ExtensionStatusAction, LocalInstallAction, ToggleSyncExtensionAction, SetProductIconThemeAction,
ActionWithDropDownAction, InstallDropdownAction, InstallingLabelAction, UninstallAction, ExtensionActionWithDropdownActionViewItem, ExtensionDropDownAction,
- InstallAnotherVersionAction, ExtensionEditorManageExtensionAction, WebInstallAction, SwitchToPreReleaseVersionAction, SwitchToReleasedVersionAction, MigrateDeprecatedExtensionAction, SetLanguageAction, ClearLanguageAction
+ InstallAnotherVersionAction, ExtensionEditorManageExtensionAction, WebInstallAction, SwitchToPreReleaseVersionAction, SwitchToReleasedVersionAction, MigrateDeprecatedExtensionAction, SetLanguageAction, ClearLanguageAction, SkipUpdateAction
} from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
@@ -322,7 +322,8 @@ export class ExtensionEditor extends EditorPane {
const actions = [
this.instantiationService.createInstance(ReloadAction),
this.instantiationService.createInstance(ExtensionStatusLabelAction),
- this.instantiationService.createInstance(UpdateAction),
+ this.instantiationService.createInstance(ActionWithDropDownAction, 'extensions.updateActions', '',
+ [[this.instantiationService.createInstance(UpdateAction)], [this.instantiationService.createInstance(SkipUpdateAction)]]),
this.instantiationService.createInstance(SetColorThemeAction),
this.instantiationService.createInstance(SetFileIconThemeAction),
this.instantiationService.createInstance(SetProductIconThemeAction),
@@ -674,7 +675,7 @@ export class ExtensionEditor extends EditorPane {
private async openMarkdown(cacheResult: CacheResult, noContentCopy: string, container: HTMLElement, webviewIndex: WebviewIndex, token: CancellationToken): Promise {
try {
- const body = await this.renderMarkdown(cacheResult, container);
+ const body = await this.renderMarkdown(cacheResult, container, token);
if (token.isCancellationRequested) {
return Promise.resolve(null);
}
@@ -741,13 +742,21 @@ export class ExtensionEditor extends EditorPane {
}
}
- private async renderMarkdown(cacheResult: CacheResult, container: HTMLElement) {
+ private async renderMarkdown(cacheResult: CacheResult, container: HTMLElement, token?: CancellationToken): Promise {
const contents = await this.loadContents(() => cacheResult, container);
- const content = await renderMarkdownDocument(contents, this.extensionService, this.languageService);
+ if (token?.isCancellationRequested) {
+ return '';
+ }
+
+ const content = await renderMarkdownDocument(contents, this.extensionService, this.languageService, true, false, token);
+ if (token?.isCancellationRequested) {
+ return '';
+ }
+
return this.renderBody(content);
}
- private async renderBody(body: string): Promise {
+ private renderBody(body: string): string {
const nonce = generateUuid();
const colorMap = TokenizationRegistry.getColorMap();
const css = colorMap ? generateTokensCSSForColorMap(colorMap) : '';
@@ -1171,7 +1180,14 @@ export class ExtensionEditor extends EditorPane {
} else if (configuration) {
properties = configuration.properties;
}
- const contrib = properties ? Object.keys(properties) : [];
+
+ let contrib = properties ? Object.keys(properties) : [];
+
+ // filter deprecated settings
+ contrib = contrib.filter(key => {
+ const config = properties[key];
+ return !config.deprecationMessage && !config.markdownDeprecationMessage;
+ });
if (!contrib.length) {
return false;
@@ -1186,7 +1202,7 @@ export class ExtensionEditor extends EditorPane {
$('th', undefined, localize('default', "Default"))
),
...contrib.map(key => {
- let description: (Node | string) = properties[key].description;
+ let description: (Node | string) = properties[key].description || '';
if (properties[key].markdownDescription) {
const { element, dispose } = renderMarkdown({ value: properties[key].markdownDescription }, { actionHandler: { callback: (content) => this.openerService.open(content).catch(onUnexpectedError), disposables: this.contentDisposables } });
description = element;
diff --git a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts
index 41169964b15..1519416d891 100644
--- a/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts
+++ b/src/vs/workbench/contrib/extensions/browser/extensions.contribution.ts
@@ -14,7 +14,7 @@ import { IExtensionIgnoredRecommendationsService, IExtensionRecommendationsServi
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IOutputChannelRegistry, Extensions as OutputExtensions } from 'vs/workbench/services/output/common/output';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
-import { VIEWLET_ID, IExtensionsWorkbenchService, IExtensionsViewPaneContainer, TOGGLE_IGNORE_EXTENSION_ACTION_ID, INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID, WORKSPACE_RECOMMENDATIONS_VIEW_ID, IWorkspaceRecommendedExtensionsView, AutoUpdateConfigurationKey, HasOutdatedExtensionsContext, SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID, LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID, ExtensionEditorTab, THEME_ACTIONS_GROUP, INSTALL_ACTIONS_GROUP } from 'vs/workbench/contrib/extensions/common/extensions';
+import { VIEWLET_ID, IExtensionsWorkbenchService, IExtensionsViewPaneContainer, TOGGLE_IGNORE_EXTENSION_ACTION_ID, INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID, WORKSPACE_RECOMMENDATIONS_VIEW_ID, IWorkspaceRecommendedExtensionsView, AutoUpdateConfigurationKey, HasOutdatedExtensionsContext, SELECT_INSTALL_VSIX_EXTENSION_COMMAND_ID, LIST_WORKSPACE_UNSUPPORTED_EXTENSIONS_COMMAND_ID, ExtensionEditorTab, THEME_ACTIONS_GROUP, INSTALL_ACTIONS_GROUP, OUTDATED_EXTENSIONS_VIEW_ID } from 'vs/workbench/contrib/extensions/common/extensions';
import { ReinstallAction, InstallSpecificVersionOfExtensionAction, ConfigureWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction, PromptExtensionInstallFailureAction, SearchExtensionsAction, SwitchToPreReleaseVersionAction, SwitchToReleasedVersionAction, SetColorThemeAction, SetFileIconThemeAction, SetProductIconThemeAction, ClearLanguageAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
import { ExtensionEditor } from 'vs/workbench/contrib/extensions/browser/extensionEditor';
@@ -46,7 +46,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { MultiCommand } from 'vs/editor/browser/editorExtensions';
import { IWebview } from 'vs/workbench/contrib/webview/browser/webview';
import { ExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/browser/extensionsWorkbenchService';
-import { CATEGORIES } from 'vs/workbench/common/actions';
+import { Categories } from 'vs/platform/action/common/actionCommonCategories';
import { IExtensionRecommendationNotificationService } from 'vs/platform/extensionRecommendations/common/extensionRecommendations';
import { ExtensionRecommendationNotificationService } from 'vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService';
import { IExtensionService, toExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
@@ -81,7 +81,7 @@ import { IStringDictionary } from 'vs/base/common/collections';
// Singletons
registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService, InstantiationType.Eager /* Auto updates extensions */);
-registerSingleton(IExtensionRecommendationNotificationService, ExtensionRecommendationNotificationService, true);
+registerSingleton(IExtensionRecommendationNotificationService, ExtensionRecommendationNotificationService, InstantiationType.Delayed);
registerSingleton(IExtensionRecommendationsService, ExtensionRecommendationsService, InstantiationType.Eager /* Prompts recommendations in the background */);
Registry.as(OutputExtensions.OutputChannels)
@@ -653,15 +653,23 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
title: { value: localize('updateAll', "Update All Extensions"), original: 'Update All Extensions' },
category: ExtensionsLocalizedLabel,
precondition: HasOutdatedExtensionsContext,
- menu: [{
- id: MenuId.CommandPalette,
- when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER))
- }, {
- id: MenuId.ViewContainerTitle,
- when: ContextKeyExpr.and(ContextKeyExpr.equals('viewContainer', VIEWLET_ID), ContextKeyExpr.or(ContextKeyExpr.has(`config.${AutoUpdateConfigurationKey}`).negate(), ContextKeyExpr.equals(`config.${AutoUpdateConfigurationKey}`, 'onlyEnabledExtensions'))),
- group: '1_updates',
- order: 2
- }],
+ menu: [
+ {
+ id: MenuId.CommandPalette,
+ when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER, CONTEXT_HAS_WEB_SERVER))
+ }, {
+ id: MenuId.ViewContainerTitle,
+ when: ContextKeyExpr.and(ContextKeyExpr.equals('viewContainer', VIEWLET_ID), ContextKeyExpr.or(ContextKeyExpr.has(`config.${AutoUpdateConfigurationKey}`).negate(), ContextKeyExpr.equals(`config.${AutoUpdateConfigurationKey}`, 'onlyEnabledExtensions'))),
+ group: '1_updates',
+ order: 2
+ }, {
+ id: MenuId.ViewTitle,
+ when: ContextKeyExpr.equals('view', OUTDATED_EXTENSIONS_VIEW_ID),
+ group: 'navigation',
+ order: 1
+ }
+ ],
+ icon: installWorkspaceRecommendedIcon,
run: () => {
return Promise.all(this.extensionsWorkbenchService.outdated.map(async extension => {
try {
@@ -830,7 +838,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
this.registerExtensionAction({
id: 'workbench.extensions.action.installWebExtensionFromLocation',
title: { value: localize('installWebExtensionFromLocation', "Install Web Extension..."), original: 'Install Web Extension...' },
- category: CATEGORIES.Developer,
+ category: Categories.Developer,
menu: [{
id: MenuId.CommandPalette,
when: ContextKeyExpr.or(CONTEXT_HAS_WEB_SERVER)
@@ -1182,7 +1190,7 @@ class ExtensionsContributions extends Disposable implements IWorkbenchContributi
this.registerExtensionAction({
id: ReinstallAction.ID,
title: { value: ReinstallAction.LABEL, original: 'Reinstall Extension...' },
- category: CATEGORIES.Developer,
+ category: Categories.Developer,
menu: {
id: MenuId.CommandPalette,
when: ContextKeyExpr.and(CONTEXT_HAS_GALLERY, ContextKeyExpr.or(CONTEXT_HAS_LOCAL_SERVER, CONTEXT_HAS_REMOTE_SERVER))
@@ -1580,18 +1588,18 @@ class ExtensionStorageCleaner implements IWorkbenchContribution {
}
const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench);
-workbenchRegistry.registerWorkbenchContribution(ExtensionsContributions, 'ExtensionsContributions', LifecyclePhase.Restored);
-workbenchRegistry.registerWorkbenchContribution(StatusUpdater, 'StatusUpdater', LifecyclePhase.Restored);
-workbenchRegistry.registerWorkbenchContribution(MaliciousExtensionChecker, 'MaliciousExtensionChecker', LifecyclePhase.Eventually);
-workbenchRegistry.registerWorkbenchContribution(KeymapExtensions, 'KeymapExtensions', LifecyclePhase.Restored);
-workbenchRegistry.registerWorkbenchContribution(ExtensionsViewletViewsContribution, 'ExtensionsViewletViewsContribution', LifecyclePhase.Restored);
-workbenchRegistry.registerWorkbenchContribution(ExtensionActivationProgress, 'ExtensionActivationProgress', LifecyclePhase.Eventually);
-workbenchRegistry.registerWorkbenchContribution(ExtensionDependencyChecker, 'ExtensionDependencyChecker', LifecyclePhase.Eventually);
-workbenchRegistry.registerWorkbenchContribution(ExtensionEnablementWorkspaceTrustTransitionParticipant, 'ExtensionEnablementWorkspaceTrustTransitionParticipant', LifecyclePhase.Restored);
-workbenchRegistry.registerWorkbenchContribution(ExtensionsCompletionItemsProvider, 'ExtensionsCompletionItemsProvider', LifecyclePhase.Restored);
-workbenchRegistry.registerWorkbenchContribution(UnsupportedExtensionsMigrationContrib, 'UnsupportedExtensionsMigrationContrib', LifecyclePhase.Eventually);
+workbenchRegistry.registerWorkbenchContribution(ExtensionsContributions, LifecyclePhase.Restored);
+workbenchRegistry.registerWorkbenchContribution(StatusUpdater, LifecyclePhase.Restored);
+workbenchRegistry.registerWorkbenchContribution(MaliciousExtensionChecker, LifecyclePhase.Eventually);
+workbenchRegistry.registerWorkbenchContribution(KeymapExtensions, LifecyclePhase.Restored);
+workbenchRegistry.registerWorkbenchContribution(ExtensionsViewletViewsContribution, LifecyclePhase.Restored);
+workbenchRegistry.registerWorkbenchContribution(ExtensionActivationProgress, LifecyclePhase.Eventually);
+workbenchRegistry.registerWorkbenchContribution(ExtensionDependencyChecker, LifecyclePhase.Eventually);
+workbenchRegistry.registerWorkbenchContribution(ExtensionEnablementWorkspaceTrustTransitionParticipant, LifecyclePhase.Restored);
+workbenchRegistry.registerWorkbenchContribution(ExtensionsCompletionItemsProvider, LifecyclePhase.Restored);
+workbenchRegistry.registerWorkbenchContribution(UnsupportedExtensionsMigrationContrib, LifecyclePhase.Eventually);
if (isWeb) {
- workbenchRegistry.registerWorkbenchContribution(ExtensionStorageCleaner, 'ExtensionStorageCleaner', LifecyclePhase.Eventually);
+ workbenchRegistry.registerWorkbenchContribution(ExtensionStorageCleaner, LifecyclePhase.Eventually);
}
diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
index 634dd88be4e..102fec7ea15 100644
--- a/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
+++ b/src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
@@ -802,18 +802,18 @@ export class UninstallAction extends ExtensionAction {
}
}
-export class UpdateAction extends ExtensionAction {
+abstract class AbstractUpdateAction extends ExtensionAction {
private static readonly EnabledClass = `${ExtensionAction.LABEL_ACTION_CLASS} prominent update`;
- private static readonly DisabledClass = `${UpdateAction.EnabledClass} disabled`;
+ private static readonly DisabledClass = `${AbstractUpdateAction.EnabledClass} disabled`;
private readonly updateThrottler = new Throttler();
constructor(
- @IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
- @IInstantiationService private readonly instantiationService: IInstantiationService,
+ id: string, label: string | undefined,
+ protected readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
) {
- super(`extensions.update`, '', UpdateAction.DisabledClass, false);
+ super(id, label, AbstractUpdateAction.DisabledClass, false);
this.update();
}
@@ -824,7 +824,6 @@ export class UpdateAction extends ExtensionAction {
private async computeAndUpdateEnablement(): Promise {
this.enabled = false;
this.class = UpdateAction.DisabledClass;
- this.label = this.getLabel();
if (!this.extension) {
return;
@@ -838,8 +837,17 @@ export class UpdateAction extends ExtensionAction {
const isInstalled = this.extension.state === ExtensionState.Installed;
this.enabled = canInstall && isInstalled && this.extension.outdated;
- this.class = this.enabled ? UpdateAction.EnabledClass : UpdateAction.DisabledClass;
- this.label = this.getLabel(this.extension);
+ this.class = this.enabled ? AbstractUpdateAction.EnabledClass : AbstractUpdateAction.DisabledClass;
+ }
+}
+
+export class UpdateAction extends AbstractUpdateAction {
+
+ constructor(
+ @IExtensionsWorkbenchService override readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
+ @IInstantiationService protected readonly instantiationService: IInstantiationService,
+ ) {
+ super(`extensions.update`, localize('update', "Update"), extensionsWorkbenchService);
}
override async run(): Promise {
@@ -858,15 +866,35 @@ export class UpdateAction extends ExtensionAction {
this.instantiationService.createInstance(PromptExtensionInstallFailureAction, extension, extension.latestVersion, InstallOperation.Update, undefined, err).run();
}
}
+}
- private getLabel(extension?: IExtension): string {
- if (!extension?.outdated) {
- return localize('updateAction', "Update");
+export class SkipUpdateAction extends AbstractUpdateAction {
+
+ constructor(
+ @IExtensionsWorkbenchService override readonly extensionsWorkbenchService: IExtensionsWorkbenchService
+ ) {
+ super(`extensions.ignoreUpdates`, localize('ignoreUpdates', "Ignore Updates"), extensionsWorkbenchService);
+ }
+
+ override update() {
+ if (!this.extension) {
+ return;
}
- if (extension.outdatedTargetPlatform) {
- return localize('updateToTargetPlatformVersion', "Update to {0} version", TargetPlatformToString(extension.gallery!.properties.targetPlatform));
+ if (this.extension.isBuiltin) {
+ this.enabled = false;
+ return;
}
- return localize('updateToLatestVersion', "Update to {0}", extension.latestVersion);
+ super.update();
+ this._checked = this.extensionsWorkbenchService.isExtensionIgnoresUpdates(this.extension);
+ }
+
+ override async run(): Promise {
+ if (!this.extension) {
+ return;
+ }
+ alert(localize('ignoreExtensionUpdate', "Ignoring {0} updates", this.extension.displayName));
+ const newIgnoresAutoUpdates = !this.extensionsWorkbenchService.isExtensionIgnoresUpdates(this.extension);
+ this.extensionsWorkbenchService.setExtensionIgnoresUpdate(this.extension, newIgnoresAutoUpdates);
}
}
diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsList.ts b/src/vs/workbench/contrib/extensions/browser/extensionsList.ts
index 931710ee3d5..7c9a3c17f22 100644
--- a/src/vs/workbench/contrib/extensions/browser/extensionsList.ts
+++ b/src/vs/workbench/contrib/extensions/browser/extensionsList.ts
@@ -13,7 +13,7 @@ import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { IPagedRenderer } from 'vs/base/browser/ui/list/listPaging';
import { Event } from 'vs/base/common/event';
import { IExtension, ExtensionContainers, ExtensionState, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
-import { UpdateAction, ManageExtensionAction, ReloadAction, ExtensionStatusLabelAction, RemoteInstallAction, ExtensionStatusAction, LocalInstallAction, ActionWithDropDownAction, InstallDropdownAction, InstallingLabelAction, ExtensionActionWithDropdownActionViewItem, ExtensionDropDownAction, WebInstallAction, SwitchToPreReleaseVersionAction, SwitchToReleasedVersionAction, MigrateDeprecatedExtensionAction, SetLanguageAction, ClearLanguageAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
+import { ManageExtensionAction, ReloadAction, ExtensionStatusLabelAction, RemoteInstallAction, ExtensionStatusAction, LocalInstallAction, ActionWithDropDownAction, InstallDropdownAction, InstallingLabelAction, ExtensionActionWithDropdownActionViewItem, ExtensionDropDownAction, WebInstallAction, SwitchToPreReleaseVersionAction, SwitchToReleasedVersionAction, MigrateDeprecatedExtensionAction, SetLanguageAction, ClearLanguageAction, UpdateAction, SkipUpdateAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { RatingsWidget, InstallCountWidget, RecommendationWidget, RemoteBadgeWidget, ExtensionPackCountWidget as ExtensionPackBadgeWidget, SyncIgnoredWidget, ExtensionHoverWidget, ExtensionActivationStatusWidget, PreReleaseBookmarkWidget, extensionVerifiedPublisherIconColor } from 'vs/workbench/contrib/extensions/browser/extensionsWidgets';
import { IExtensionService, toExtension } from 'vs/workbench/services/extensions/common/extensions';
@@ -120,7 +120,8 @@ export class Renderer implements IPagedRenderer {
this.instantiationService.createInstance(ExtensionStatusLabelAction),
this.instantiationService.createInstance(MigrateDeprecatedExtensionAction, true),
reloadAction,
- this.instantiationService.createInstance(UpdateAction),
+ this.instantiationService.createInstance(ActionWithDropDownAction, 'extensions.updateActions', '',
+ [[this.instantiationService.createInstance(UpdateAction)], [this.instantiationService.createInstance(SkipUpdateAction)]]),
this.instantiationService.createInstance(InstallDropdownAction),
this.instantiationService.createInstance(InstallingLabelAction),
this.instantiationService.createInstance(SetLanguageAction),
diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts
index fb9c4ee55ab..b986e34b545 100644
--- a/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts
+++ b/src/vs/workbench/contrib/extensions/browser/extensionsViewlet.ts
@@ -16,7 +16,7 @@ import { append, $, Dimension, hide, show, DragAndDropObserver } from 'vs/base/b
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
-import { IExtensionsWorkbenchService, IExtensionsViewPaneContainer, VIEWLET_ID, CloseExtensionDetailsOnViewChangeKey, INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID, WORKSPACE_RECOMMENDATIONS_VIEW_ID, AutoCheckUpdatesConfigurationKey } from '../common/extensions';
+import { IExtensionsWorkbenchService, IExtensionsViewPaneContainer, VIEWLET_ID, CloseExtensionDetailsOnViewChangeKey, INSTALL_EXTENSION_FROM_VSIX_COMMAND_ID, WORKSPACE_RECOMMENDATIONS_VIEW_ID, AutoCheckUpdatesConfigurationKey, OUTDATED_EXTENSIONS_VIEW_ID } from '../common/extensions';
import { InstallLocalExtensionsInRemoteAction, InstallRemoteExtensionsInLocalAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IWorkbenchExtensionEnablementService, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
@@ -328,7 +328,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
* View used for searching outdated extensions
*/
viewDescriptors.push({
- id: 'workbench.views.extensions.searchOutdated',
+ id: OUTDATED_EXTENSIONS_VIEW_ID,
name: localize('availableUpdates', "Available Updates"),
ctorDescriptor: new SyncDescriptor(OutdatedExtensionsView, [{}]),
when: ContextKeyExpr.or(SearchExtensionUpdatesContext, ContextKeyExpr.has('searchOutdatedExtensions')),
@@ -800,14 +800,14 @@ export class StatusUpdater extends Disposable implements IWorkbenchContribution
@IWorkbenchExtensionEnablementService private readonly extensionEnablementService: IWorkbenchExtensionEnablementService
) {
super();
- this._register(extensionsWorkbenchService.onChange(this.onServiceChange, this));
+ this._register(Event.debounce(extensionsWorkbenchService.onChange, () => undefined, 100, undefined, undefined, this._store)(this.onServiceChange, this));
}
private onServiceChange(): void {
this.badgeHandle.clear();
const extensionsReloadRequired = this.extensionsWorkbenchService.installed.filter(e => e.reloadRequiredStatus !== undefined);
- const outdated = this.extensionsWorkbenchService.outdated.reduce((r, e) => r + (this.extensionEnablementService.isEnabled(e.local!) && !extensionsReloadRequired.includes(e) ? 1 : 0), 0);
+ const outdated = this.extensionsWorkbenchService.outdated.reduce((r, e) => r + (this.extensionEnablementService.isEnabled(e.local!) && !this.extensionsWorkbenchService.isExtensionIgnoresUpdates(e) && !extensionsReloadRequired.includes(e) ? 1 : 0), 0);
const newBadgeNumber = outdated + extensionsReloadRequired.length;
if (newBadgeNumber > 0) {
let msg = '';
diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts
index ec3821e1885..575a220bc18 100644
--- a/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts
+++ b/src/vs/workbench/contrib/extensions/browser/extensionsViews.ts
@@ -512,16 +512,18 @@ export class ExtensionsListView extends ViewPane {
value = value.replace(/@installed/g, '').replace(/@sort:(\w+)(-\w*)?/g, '').trim().toLowerCase();
- let result = local
- .filter(e => !e.isBuiltin
- && (e.name.toLowerCase().indexOf(value) > -1 || e.displayName.toLowerCase().indexOf(value) > -1)
- && (!categories.length || categories.some(category => (e.local && e.local.manifest.categories || []).some(c => c.toLowerCase() === category))));
+ const matchingText = (e: IExtension) => (e.name.toLowerCase().indexOf(value) > -1 || e.displayName.toLowerCase().indexOf(value) > -1)
+ && (!categories.length || categories.some(category => (e.local && e.local.manifest.categories || []).some(c => c.toLowerCase() === category)));
+ let result;
if (options.sortBy !== undefined) {
+ result = local.filter(e => !e.isBuiltin && matchingText(e));
result = this.sortExtensions(result, options);
} else {
+ result = local.filter(e => (!e.isBuiltin || e.outdated || e.reloadRequiredStatus !== undefined) && matchingText(e));
const runningExtensionsById = runningExtensions.reduce((result, e) => { result.set(ExtensionIdentifier.toKey(e.identifier.value), e); return result; }, new Map());
- result = result.sort((e1, e2) => {
+
+ const defaultSort = (e1: IExtension, e2: IExtension) => {
const running1 = runningExtensionsById.get(ExtensionIdentifier.toKey(e1.identifier.id));
const isE1Running = !!running1 && this.extensionManagementServerService.getExtensionManagementServer(toExtension(running1)) === e1.server;
const running2 = runningExtensionsById.get(ExtensionIdentifier.toKey(e2.identifier.id));
@@ -544,7 +546,24 @@ export class ExtensionsListView extends ViewPane {
return e1.displayName.localeCompare(e2.displayName);
}
return isE1Running ? -1 : 1;
+ };
+
+ const outdated: IExtension[] = [];
+ const reloadRequired: IExtension[] = [];
+ const noActionRequired: IExtension[] = [];
+ result.forEach(e => {
+ if (e.outdated && !this.extensionsWorkbenchService.isExtensionIgnoresUpdates(e)) {
+ outdated.push(e);
+ }
+ else if (e.reloadRequiredStatus) {
+ reloadRequired.push(e);
+ }
+ else {
+ noActionRequired.push(e);
+ }
});
+
+ result = [...outdated.sort(defaultSort), ...reloadRequired.sort(defaultSort), ...noActionRequired.sort(defaultSort)];
}
return result;
}
@@ -663,7 +682,7 @@ export class ExtensionsListView extends ViewPane {
private filterRecentlyUpdatedExtensions(local: IExtension[], query: Query, options: IQueryOptions): IExtension[] {
let { value, categories } = this.parseCategories(query.value);
const currentTime = Date.now();
- local = local.filter(e => !e.isBuiltin && e.local?.installedTimestamp !== undefined && currentTime - e.local.installedTimestamp < ExtensionsListView.RECENT_UPDATE_DURATION);
+ local = local.filter(e => !e.isBuiltin && !e.outdated && e.local?.updated && e.local?.installedTimestamp !== undefined && currentTime - e.local.installedTimestamp < ExtensionsListView.RECENT_UPDATE_DURATION);
value = value.replace(/@recentlyUpdated/g, '').replace(/@sort:(\w+)(-\w*)?/g, '').trim().toLowerCase();
diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
index 4dda6675f73..542534bada3 100644
--- a/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
+++ b/src/vs/workbench/contrib/extensions/browser/extensionsWorkbenchService.ts
@@ -1587,14 +1587,15 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
for (const extension of toCheck) {
checked.push(extension);
}
- const extensionsToDisable = installed.filter(i => {
+ const extensionsToEanbleOrDisable = installed.filter(i => {
if (checked.indexOf(i) !== -1) {
return false;
}
- if (i.enablementState === enablementState) {
+ const enable = enablementState === EnablementState.EnabledGlobally || enablementState === EnablementState.EnabledWorkspace;
+ const isExtensionEnabled = i.enablementState === EnablementState.EnabledGlobally || i.enablementState === EnablementState.EnabledWorkspace;
+ if (enable === isExtensionEnabled) {
return false;
}
- const enable = enablementState === EnablementState.EnabledGlobally || enablementState === EnablementState.EnabledWorkspace;
return (enable || !i.isBuiltin) // Include all Extensions for enablement and only non builtin extensions for disablement
&& (options.dependencies || options.pack)
&& extensions.some(extension =>
@@ -1602,10 +1603,10 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
|| (options.pack && extension.extensionPack.some(id => areSameExtensions({ id }, i.identifier)))
);
});
- if (extensionsToDisable.length) {
- extensionsToDisable.push(...this.getExtensionsRecursively(extensionsToDisable, installed, enablementState, options, checked));
+ if (extensionsToEanbleOrDisable.length) {
+ extensionsToEanbleOrDisable.push(...this.getExtensionsRecursively(extensionsToEanbleOrDisable, installed, enablementState, options, checked));
}
- return extensionsToDisable;
+ return extensionsToEanbleOrDisable;
}
return [];
}
@@ -1770,6 +1771,24 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
}
}
+ setExtensionIgnoresUpdate(extension: IExtension, ignoreAutoUpate: boolean): void {
+ const extensionKey = new ExtensionKey(extension.identifier, extension.version);
+ if (ignoreAutoUpate) {
+ this.ignoreAutoUpdate(extensionKey);
+ }
+ else if (this.isAutoUpdateIgnored(extensionKey)) {
+ this.ignoredAutoUpdateExtensions = this.ignoredAutoUpdateExtensions.filter(extensionId => extensionId !== extensionKey.toString());
+ }
+ else {
+ return;
+ }
+ this._onChange.fire(extension);
+ }
+
+ isExtensionIgnoresUpdates(extension: IExtension): boolean {
+ return this.isAutoUpdateIgnored(new ExtensionKey(extension.identifier, extension.version));
+ }
+
private isAutoUpdateIgnored(extensionKey: ExtensionKey): boolean {
return this.ignoredAutoUpdateExtensions.indexOf(extensionKey.toString()) !== -1;
}
diff --git a/src/vs/workbench/contrib/extensions/common/extensions.ts b/src/vs/workbench/contrib/extensions/common/extensions.ts
index 9b6ca4e0345..e01cdeee918 100644
--- a/src/vs/workbench/contrib/extensions/common/extensions.ts
+++ b/src/vs/workbench/contrib/extensions/common/extensions.ts
@@ -111,6 +111,8 @@ export interface IExtensionsWorkbenchService {
canSetLanguage(extension: IExtension): boolean;
setLanguage(extension: IExtension): Promise;
setEnablement(extensions: IExtension | IExtension[], enablementState: EnablementState): Promise;
+ setExtensionIgnoresUpdate(extension: IExtension, ignoreAutoUpate: boolean): void;
+ isExtensionIgnoresUpdates(extension: IExtension): boolean;
open(extension: IExtension, options?: IExtensionEditorOptions): Promise